對於機器學習來說,最簡單的模型就是線性迴歸,線性迴歸往往作爲機器學習的入門模型來學習,線性迴歸,顧名思義就是數據集合的分佈可以用一條直線(二維)或者一個平面(三維)或者更多維度的線性方程 來進行劃分界限的分佈,舉個很直觀的例子:
上面是二維和三維的線性迴歸的界限分隔示意圖,線性迴歸最典型的例子就是房價的問題,如上面圖中,左邊的圖顯示了 房屋的大小對房價的影響,只關注一個變量(房屋大小)對房價的影響。
上面圖中右面的圖中是顯示了兩個變量:房屋大小、附近學校的質量 對房價的影響。
那麼怎麼能得出這個劃分的界限的方程的係數呢?計算機是怎麼學習出來的?
以最簡單的二維數據爲例,如果 數據分隔的界限 是直線 y = w1 * x + w2,那麼線性迴歸的最終目標是通過對已知數據集的學習來算出 直線y = w1 * x + w2的參數值 w1 和w2
那麼怎麼才能算出這兩個參數呢?具體學習的過程是如何的呢?
一、線性迴歸擬合數據
首先,計算機會隨機生成w1 和w2,也就生成了一條直線,然後看下各個數據點與這條直線的距離,看看如何對這條直線進行調整使得各個點與這個直線的距離達到最優的狀態,就得到了最終的模擬曲線,具體過程見下圖:
如上圖所示,在隨機生成了一條直線後,各個點都想讓直線離得更近一點更近一點,具體如何調整呢?這裏有調整的策略及算法:
(1) 絕對值技巧
從圖中看出,絕對值技巧是這樣的,當一個點(p,q),如果想讓直線 y = w1 *x +w2,離得更近一點,那麼需要將直線變成
y = (w1+p)x +(w2 +1 ),這個步驟循環進行,直到達到最優爲止。
爲了讓這個調整的過程更細緻,更細膩,引入了學習率α,至此公式調整爲: y = (w1+pα)x +(w2 +α)
(2) 平方技巧
平方技巧的策略與絕對值技巧不同的是:當直線距離點遠的時候調整的幅度就比較大,如果直線距離點的距離比較近的時候,調整的幅度就比較小,這是絕對值技巧所沒有的特性,調整的過程如下圖所示,調整策略的公式爲:y = (w1+pα(q-y))x + w2 + α(q-y),由公式可以看出,調整參數僅僅與點(p,q)的橫座標有關係,還與縱座標與直線上的縱座標的差(q-y)有關係。
二、誤差函數
下面來說一下線性迴歸的誤差,線性迴歸的誤差分爲兩種:
(1)平均絕對值誤差
(2)平均平方誤差
(3)梯度下降
下面來談談梯度下降,梯度下降更多的是一種思想,他體現在各個學習的模型,他的最重要的思想是使誤差值沿着最快的速度下降,就是沿着導數的反方向,來進行調整參數 就得到誤差快速的下降
由上面圖中可以看出對於參數的調整
由公式可以看出,梯度下降的具體算法取決於 誤差函數的公式,例如 誤差函數是均方誤差函數,y-hat 表示預測的值,那麼對w1 和w2求導的結果如下圖右側方程,那麼 採用梯度下降的思路帶入之後 確實和之前的平方技巧是相同的
同樣的,如下圖,如果誤差函數採用的是平均絕對值誤差,那麼誤差函數對w1,w2 的導數如下圖所示,帶入梯度下降的公式後可以看出,與絕對值技巧是一樣的
三、scikit-learn 中的線性迴歸
(1)最小二乘法
最後我們來說一下python 中 scikit-learn 中的線性迴歸,在scikit-learn 中的線性迴歸 LinearRegression 中採用的是最小二乘法,在最小二乘法中 誤差函數是:
他的目標是 使得誤差達到最小值:即 導數爲0 時候,求得的參數值
(2)梯度下降法
梯度下降法是一種迭代的方法,是一個逐步調整的過程
其代價函數(誤差函數)如下:
稍微有一點有一點不一樣的地方是取得誤差的平均數 並加了個係數1 /2
經過幾次迭代 獲得最後的係數值
四、python 中 scikit-learn 中的線性迴歸代碼實現
import pandas as pd
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import numpy as np
bmi_life_data = pd.read_csv("bmi_and_life_expectancy.csv")
bmi_life_model = LinearRegression()
bmi_life_model.fit(bmi_life_data[['BMI']],bmi_life_data[['Life expectancy']])
laos_life_exp = bmi_life_model.predict([ [21.07931]])
print(laos_life_exp)
ax = plt.scatter(bmi_life_data[['BMI']], bmi_life_data[['Life expectancy']])
plt.title('bmi_and_life_expectancy(LinearRegression)')
plt.xlabel("BMI")
plt.ylabel("Life expectancy")
print("coef_:",bmi_life_model.coef_)
print("intercept_:",bmi_life_model.intercept_)
x = np.linspace(18, 30, 1000)
y = bmi_life_model.coef_[0][0] *x+ bmi_life_model.intercept_[0]
A = [0,bmi_life_model.intercept_[0]]
B = [-bmi_life_model.intercept_[0]/bmi_life_model.coef_[0][0],0]
plt.plot(x,y,c='r')
上面代碼中採用的一個BMI的數據集,代碼中的 bmi_life_model.coef_[0][0] 和 bmi_life_model.intercept_[0] 就是我們得到的迴歸直線的係數,迴歸曲線及數據集的可視化如下圖:
詳細的代碼及數據集請到 github 上下載: 線性迴歸-BMI
此外,我測試了python 和R 兩個版本的情況,兩種語言版本都是採用最小二乘法,而得出的結構基本相同:(左邊Python,右邊 R)