目錄
在下自我介紹
本文講述 單一變量的直線迴歸!!!!!!
Hello,你們可以叫我弛仔,這算是人生中第一篇正式的分享博客。我呢是大一的學生,對機器學習(Machine Learning)感興趣。
hhh,也是剛剛接觸這方面的學習,想在這裏分享初學者的經驗,並且給出一些踩過的坑。
還有,我不是大佬哈!!!歡迎各位跟我一起學習!!!
最終的迴歸結果!
一些概念
擬合是什麼?
在我看來,擬合就是把平面上一系列的點,用一條光滑的曲線連接起來。
因爲點很複雜,我們可以用各種函數去組合來達到我們的目的。
泛化能力是什麼?
訓練集在訓練後,能夠預測位置數據的能力。
簡單的瞭解下即可。
過擬合是什麼?
過擬合,可能我們選擇模型時過於複雜,在訓練時表現極好,實戰卻不行了~
欠擬合是什麼?
與過擬合相反,即訓練時的效果就不佳~那就更不要說實戰拉!
線性迴歸
假設函數(hypothesis)
假設函數(Hypothesis),這個函數可以是簡單的直線,也可以是複雜的多項式組合。(我認爲他就是數學模型,可能不對,若有出入望指正)
代價函數(cost function)
我的圖應該很形象的解釋了他的意義了吧?我們可以由此計算出所有點的預測值y 與 假設函數h(x)的差,通過平方(平方是爲了化負爲正)後取均值再除以2,吳恩達老師的課程上就是這麼講噠,通常下除以2,爲了能更進一步的將代價最小化吧??
線性迴歸目標(Goal)
我們的目標:爲了讓預測值與函數值的誤差最小化
即 minimizeJ(theta)
所以引入了梯度下降(Gradient Descent)
梯度下降也可以簡單理解,多維也使很好理解的,我先再次梳理下最基礎的梯度下降
這只是舉了個例子,對J函數求導後,我們發現局部上,導數永遠指向最小值處。
所以有了梯度下降的公式:
這需要用到高數中的偏導知識,如果你已經學過導數,那麼偏導也是很簡單的~
具體推導過程,可以自己動手算一算!
上代碼
import sklearn as sk
"""
單變量的線性迴歸基礎
單變量:一個特徵哈!!!
"""
from sklearn.datasets import load_boston
import numpy as np
#輸出數據的結構
def print_data(data):
print("Shape:",data.shape,"\n")
print("Feature:",data['feature_names'], "\n")
print("Keys:",data.keys(), "\n")
"""
# 計算CostFunction 代價函數
# X爲特徵矩陣
# y爲目標
# theta爲theta係數 1 X n 的矩陣
"""
def computerCost(X ,y ,theta):
num = len(y)
y = y.reshape(num,1)
result = np.power((X.dot(theta.transpose()) - y),2)
return np.sum(result) /(2* num)
"""
梯度下降函數
# Param X train Feature
# Param y train Target
# Param theta h(x)=theta(0)+theta(1)*x1
# Param times 迭代的次數
"""
def gridientDescent(X,y,theta,times,learn_rate):
number = len(y) #獲取訓練數據的數量
X[:,1] = X[:,1]/100 #特徵縮放
temp = np.zeros(theta.shape) #用於更新theta
cost = np.zeros(times) #記錄每次迭代後代價函數的值
paramters = len(theta[0]) #參數的個數
for i in range(times):
y = y.reshape(number,1)
H = X.dot(theta.transpose())
E = H - y
#print("Y SHAPE:",y.shape)
#print("H SHAPE:",H.shape)
#print("E SHAPE:",E.shape)
for j in range(paramters):#更新theta
XT = X.transpose()
XT = XT[j,:]
XT = XT.reshape(1,len(XT))
#print("XT",XT.shape)
term = XT.dot(E)
temp[0, j] = theta[0, j] - ((1 / number) * learn_rate * term)
theta = temp
print(computerCost(X,y,theta))
return theta
if __name__ == '__main__':
"""
準備好了嗎?我們開始操作咯!
# 首先獲取我們的數據
"""
Boston = load_boston()
BostonData = Boston.data ##特徵數據
BostonTarget = Boston.target ##房價
BostonFeatureName = Boston.feature_names
print(BostonFeatureName)
"""我們使用AGE 這個特徵做本次的單特徵迴歸"""
BostonAge = BostonData[:10,6]
BostonAgeTarget = BostonTarget[:10]
print('TARGET SHAPE :',BostonAgeTarget.shape)
print("DATA SHAPE:",BostonAge.shape)
"""發現一共有506條數據,我們獲取其中前10行"""
print("DATA:\n",BostonAge)
#給X加入一列,因爲theta0 是一個常數項
X = np.column_stack((np.ones(len(BostonAgeTarget)),BostonAge))
theta = np.array([[0,0]]) #參數矩陣
times = 100000 #迭代次數
step = 0.02 #步長
g = gridientDescent(X,BostonAgeTarget,theta,times,step)
"""將數據可視化"""
import matplotlib.pyplot as plt
font = {
'family': 'SimHei',
'weight': 'bold',
'size': '10'
}
plt.rc('font', **font)
plt.rc('axes', unicode_minus=False)
plt.xlabel("Feature Age")
plt.ylabel("House Price")
plt.title("Boston Price Data By Age")
plt.scatter(x=BostonAge,
y=BostonAgeTarget,
c='b',
alpha=.8,
label='訓練數據')
#畫出擬合直線
x = np.linspace(BostonAge.min(), BostonAge.max(), 100)
f = g[0, 0] + (g[0, 1] * x /100) #注意除以100,因爲我們做過特徵縮放
plt.plot(x, f, 'r', label='預測函數')
plt.legend(loc=2)
plt.show()
編碼中遇到的坑
- 爲了每一步都簡介明瞭,代碼中加入了很多不必要的中間變量,真正實踐的時候不需要這麼複雜哦~
- 矩陣的shape,比如讀入target y 後,他的shape 是一維的,但是矩陣是二維的,所以會出現無法做運算。
- 儘量輸出Shape,通過矩陣運算法則 ,這樣可以更快的找到編碼可能出錯的位置
- 矩陣運算的乘法 * 和 np.dot() 是不同的
- 最後矩陣的求解:這是矩陣哦!!大家用學過的線性代數推導一下就明白拉(提示:由見到推複雜,由一個元素推整個矩陣)
感謝
謝謝大家看完~繼續鑽研吧!