天天看點

機器學習之線性回歸筆記1 目錄2 回歸的了解3 線性回歸4 使用最大似然解釋最小二乘5 梯度下降法6 程式分析7 分析sklearn線性回歸的官方例程8 參考書目

平台:windows10 64位

IDE:Pycharm

Python版本:Python3.5

github代碼:源代碼

1 目錄

  • 1 目錄
  • 2 回歸的了解
  • 3 線性回歸
  • 4 使用最大似然解釋最小二乘
    • 4.1 基本形式
    • 4.2 高斯的對數似然與最小二乘
    • 4.3 向量表示下的求解
    • 4.4 L2正則化(ℓ2−normℓ2−norm\ell2-norm)
    • 4.5 L1正則化(ℓ1−normℓ1−norm\ell1-norm)
    • 4.6 lastic Net
    • 4.7 L1和L2正則的差別
  • 5 梯度下降法
  • 6 程式分析
  • 7 分析sklearn線性回歸的官方例程
    • 7.1 官方例程分析
    • 7.2 使用sklearn方法訓練自己生成的資料
  • 8 參考書目

2 回歸的了解

回歸是由高爾頓最先在生物遺傳上提出的,線上性回歸中,與其說其為回歸,不如說線性拟合更合适,而為了紀念高爾頓還是保留了回歸這一名詞

而對數幾率回歸(Logistic regression)解決的卻是一個分類問題,其實就是2分類,如果需要解決多分類那麼就做多次2分類或直接用Softmax回歸。

3 線性回歸

線性回歸試圖建立的一個線性模型以盡可能準确的預測輸出标記。考慮最簡單的模型,給定若幹對 (x,y) ( x , y ) 的資料,将其在坐标軸上表示如下:

機器學習之線性回歸筆記1 目錄2 回歸的了解3 線性回歸4 使用最大似然解釋最小二乘5 梯度下降法6 程式分析7 分析sklearn線性回歸的官方例程8 參考書目

線性回歸就是要尋找一條直線來使得這些所有的點都盡量符合直線上的點,其中盡量符合指的就是使損失最小,在這裡以點到直線的距離的平方來作為‘損失’,使用線性回歸可以來預測資料,這在機器學習裡面是一個非常重要的概念——預測,不管是什麼模型,最後做出來都是需要用來預測資料,來判斷這個模型到底實不實用,線性回歸就是這些模型中最簡單的一種模型。

機器學習之線性回歸筆記1 目錄2 回歸的了解3 線性回歸4 使用最大似然解釋最小二乘5 梯度下降法6 程式分析7 分析sklearn線性回歸的官方例程8 參考書目

4 使用最大似然解釋最小二乘

4.1 基本形式

首先對于線性回歸,所求得就是一條直線,設其方程為:

y(i)=θTx(i)+ε(i) y ( i ) = θ T x ( i ) + ε ( i )

其中 θ θ 和 ε ε 為這條直線的斜率和截距, x,y x , y 分别為圖上的一系列散點,用極大似然法估計時,我們認為 ε ε 符合正太分布,且期望為0,那麼根據大學的知識可以得到 ε ε 的機率為:

p(ε(i))=1s2πσ−−−√exp(−(ε(i))22σ2) p ( ε ( i ) ) = 1 s 2 π σ e x p ( − ( ε ( i ) ) 2 2 σ 2 )

把直線方程移項帶入上式得到在 θ θ 參數下,已知 x x 的情況下yy的機率密度函數為:

p(y(i)|x(i);θ)=12πσ−−−√exp(−(y(i)−θTx(i))22σ2) p ( y ( i ) | x ( i ) ; θ ) = 1 2 π σ e x p ( − ( y ( i ) − θ T x ( i ) ) 2 2 σ 2 )

這裡的機率密度函數為條件機率密度函數,直接求解是無法解出來的,假設樣本之間是獨立的,那麼就得到:

L(θ)=∐i=1mp(y(i)|x(i);θ)=∐i=1m12πσ−−−√exp(−(y(i)−θTx(i))22σ2) L ( θ ) = ∐ i = 1 m p ( y ( i ) | x ( i ) ; θ ) = ∐ i = 1 m 1 2 π σ e x p ( − ( y ( i ) − θ T x ( i ) ) 2 2 σ 2 )

4.2 高斯的對數似然與最小二乘

這裡用的是對數似然,即需要對 L(θ) L ( θ ) 取對數,則可以化簡得到如下方程:

ℓ(θ)=logL(θ)=log∐i=1m12πσ−−−√exp(−(y(i)−θTx(i))22σ2)=∑i=1mlog12πσ−−−√exp(−(y(i)−θTx(i))22σ2)=mlog12πσ−−−√−1σ2⋅12∑i=1m(y(i)−θTx(i)) ℓ ( θ ) = log ⁡ L ( θ ) = log ⁡ ∐ i = 1 m 1 2 π σ e x p ( − ( y ( i ) − θ T x ( i ) ) 2 2 σ 2 ) = ∑ i = 1 m log ⁡ 1 2 π σ e x p ( − ( y ( i ) − θ T x ( i ) ) 2 2 σ 2 ) = m log ⁡ 1 2 π σ − 1 σ 2 ⋅ 1 2 ∑ i = 1 m ( y ( i ) − θ T x ( i ) )

現在,需要求 L(θ) L ( θ ) 為最大值時 θ θ 的值,前面一項為常數,可以省略掉,隻保留後方一項得到函數:

J(θ)=12∑i=1m(y(i)−θTx(i)) J ( θ ) = 1 2 ∑ i = 1 m ( y ( i ) − θ T x ( i ) )

即求 J(θ) J ( θ ) 的最小值,括号裡的一項就是預測值和實際值之間的差,這個就成為目标函數或成為損失函數,這其實就是最小二乘估計,整個推導過程其實就是利用高斯分布推導最小二乘。

4.3 向量表示下的求解

設有 M M 個NN維樣本組成矩陣 X X ,即XX的行對應每個樣本, X X 的列對應樣本的次元,目标函數就可以表示為:

J(θ)=12∑i=1m(hθ(x(i))−y(i))2=12(Xθ−y)T(Xθ−y)J(θ)=12∑i=1m(hθ(x(i))−y(i))2=12(Xθ−y)T(Xθ−y)

即現在要求出 J(θ) J ( θ ) 最小值時 θ θ 的值,對目标函數求導,令其等于 0 0 ,求出θθ的值。

∇θJ(θ)=12∑i=1m(hθx(i)−y(i))2=∇θ{12(θTXTXθ−]thetaTXTy−yTXθ+hTy)}=12(2XTXθ−XTy−(yTX)T)=XTXθ−xTy ∇ θ J ( θ ) = 1 2 ∑ i = 1 m ( h θ x ( i ) − y ( i ) ) 2 = ∇ θ { 1 2 ( θ T X T X θ − ] t h e t a T X T y − y T X θ + h T y ) } = 1 2 ( 2 X T X θ − X T y − ( y T X ) T ) = X T X θ − x T y

得到最後的結果如下:

θ=(XTX)−1XTy θ = ( X T X ) − 1 X T y

4.4 L2正則化( ℓ2−norm ℓ 2 − n o r m )

而在現實中當特征比樣本點更多時,矩陣 X X 不是滿秩矩陣, XTXXTX不一定可逆,通常引入正則化(egularization)項,其實質是為了防止過拟合,

12∑i=1m(hθx(i)−y(i))2+λ∑j=1nθ2j 1 2 ∑ i = 1 m ( h θ x ( i ) − y ( i ) ) 2 + λ ∑ j = 1 n θ j 2

稱為 L2 L 2 正則( ℓ2−norm ℓ 2 − n o r m ),那麼加了 L2 L 2 正則的最小二乘稱為 嶺回歸,求解可得 θ θ 為:

θ=(XTX+λI)−1XTy θ = ( X T X + λ I ) − 1 X T y

4.5 L1正則化( ℓ1−norm ℓ 1 − n o r m )

既然有L2正則化,那麼也必然有L1正則化( ℓ1−norm ℓ 1 − n o r m ),将目标函數正則項中 θ θ 的平方替換為 θ θ 的絕對值,那麼就叫L1正則,即LASSO。

12∑i=1m(hθx(i)−y(i))2+λ∑j=1n|θj| 1 2 ∑ i = 1 m ( h θ x ( i ) − y ( i ) ) 2 + λ ∑ j = 1 n | θ j |

4.6 lastic Net

結合l1和l2正則,即為Elastic Net:

12∑i=1m(hθx(i)−y(i))2+λ(ρ⋅∑j=1n|θj|+(1−ρ)⋅∑j=1nθ2j) 1 2 ∑ i = 1 m ( h θ x ( i ) − y ( i ) ) 2 + λ ( ρ ⋅ ∑ j = 1 n | θ j | + ( 1 − ρ ) ⋅ ∑ j = 1 n θ j 2 )

4.7 L1和L2正則的差別

使用絕對值取代平方和,在 λ λ 最夠大時,高階的情況下高階項的系數會縮減到0

5 梯度下降法

求出目标函數了,就要根據目标函數來求的這條直線,這裡常用的一種方法就是梯度下降法,梯度下降法的公式如下:

θ=θ−α⋅∂J(θ)∂θ θ = θ − α ⋅ ∂ J ( θ ) ∂ θ

其中 α α 表示學習率, θ θ 為參數,具體做法就是初始化 θ θ ,然後沿着負梯度方向疊代,不斷更新 θ θ 使就 J(θ) J ( θ ) 最小。

6 程式分析

import numpy as np
import matplotlib.pyplot as plt

np.random.seed()
x = np.linspace(, , ) + np.random.randn()
x = np.sort(x)
y = x **  +  + np.random.randn()
           

首先生成随機點x,y,随機生成11個點,這11個點是根據y=x2+2這條曲線上生成的。

def optimizer():
    w = 
    b = 
    for i in range():
        w, b = compute_gradient(w, b, )
        # if i % 50 == 0:
            # plt.plot(x, x * w + b, 'b-')
            # plt.pause(0.5)
    y_pre = x * w + b
    print(w, b)
    return y_pre
           

這個函數是執行梯度下降法1000次,以此來找到最優的w,b,每執行一次,都将新的w,b帶入梯度中來求,最後求得最終的w,b,然後可以得到最終拟合的直線,即y_pre.

def compute_gradient(m_current, b_current, learning_rate):
    N = len(x)  # 資料的長度
    m_gradient = 
    b_gradient = 
    for i in range(N):
        m_gradient += -( / N) * x[i] * (y[i] - (m_current * x[i] + b_current))
        b_gradient += -( / N) * (y[i] - (m_current * x[i] + b_current))
    new_m = m_current - (learning_rate * m_gradient)
    new_b = b_current - (learning_rate * b_gradient)
    return new_m, new_b
           

在compute_gradient函數中,主要是傳回每次計算的 w,b w , b 以及

∂J(θ)∂θ ∂ J ( θ ) ∂ θ ,上面函數中for循環就是所求的偏導數,傳回值是計算一次梯度下降時的 w,b w , b 。

plt.plot(x, y, 'ro')
plt.plot(x, optimizer(), 'b-')
#optimizer()
plt.show()
           

在多次計算後,再将散點圖最終求得的直線圖畫出來即可。

7 分析sklearn線性回歸的官方例程

官方網站為:Linear Regression Example

7.1 官方例程分析

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
           

導入庫

導出資料集,其中diabetes是

sklearn.datasets.base.Bunch

類型,該類型和Python内置的字典類型相似

這個用法為sklearn中的用法,

datasets.data

dataset

對象中的

data

屬性,而

data

屬性對應的資料為一個二維數組,故

[:, np.newaxis,2]

為取data中的所有行,增加一個次元,第三列,故

diabetes_X

為一個二維數組,如下:

{'data': array([[ ,  ,  , ..., -,
          , -],
        [-, -, -, ..., -,
         -, -],
        [ ,  ,  , ..., -,
          , -],
        ..., 
        [ ,  , -, ..., -,
         -,  ],
        [-, -,  , ...,  ,
          , -],
        [-, -, - , ..., -,
         -,  ]]),
           

上面得到的diabetes_X的shape為(442, 1),再将其分為訓練集和測試集

diabetes_X_train = diabetes_X[:-]
diabetes_X_test = diabetes_X[-:]
           

該句中前0個到倒數第20個分為訓練集,倒數20個資料為測試集。

diabetes_y_train = diabetes.target[:-]
diabetes_y_test = diabetes.target[-20:]
           

同理,将diabetes中的target屬性也這樣劃分。

regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
diabetes_y_pred = regr.predict(diabetes_X_test)
           

然後建立一個線性模型的對象,并用訓練集來fit,最後得到預測的資料

# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print("Mean squared error: %.2f"
      % mean_squared_error(diabetes_y_test, diabetes_y_pred))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % r2_score(diabetes_y_test, diabetes_y_pred))
           

列印出相關系數和均方誤差以及差異分數

這裡相關系數為 R R ,回歸系數為R2R2,而回歸系數

R2=SSRegSST=1−SSESST R 2 = S S R e g S S T = 1 − S S E S S T

其中 SSReg S S R e g 為回歸平方和(sum of squares for regression),也叫做模型平方和,,SSE為殘差平方(sum of squares for error),SST為總平方和(SSReg+SSE),其中各公式如下:

SST=∑i=1n(yi−y¯)2 S S T = ∑ i = 1 n ( y i − y ¯ ) 2

SSReg=∑i(yi^−y¯)2 S S R e g = ∑ i ( y i ^ − y ¯ ) 2

SSE=∑i(yi−y^)2 S S E = ∑ i ( y i − y ^ ) 2

故在本次實驗中相關系數 R R 即為:

R=∑ni=1(xi−x¯)(yi−y¯)∑ni=1(xi−x¯)2∑ni=1(yi−y¯)2−−−−−−−−−−−−−−−−−−−−−−−√R=∑i=1n(xi−x¯)(yi−y¯)∑i=1n(xi−x¯)2∑i=1n(yi−y¯)2

yi^ y i ^ 表示的為回歸直線中 y y 的值,y¯y¯表示 y y <script type="math/tex" id="MathJax-Element-73">y</script>的平均值.最後結果如下:

機器學習之線性回歸筆記1 目錄2 回歸的了解3 線性回歸4 使用最大似然解釋最小二乘5 梯度下降法6 程式分析7 分析sklearn線性回歸的官方例程8 參考書目

7.2 使用sklearn方法訓練自己生成的資料

代碼如下:

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score

np.random.seed()
x = np.linspace(, , ) + np.random.randn()
x = np.sort(x)
y = x **  +  + np.random.randn()
x=x[:,np.newaxis]
print(x)
regr = linear_model.LinearRegression()
regr.fit(x,y)
y_pre = regr.predict(x)

plt.scatter(x,y)
plt.plot(x,y_pre)
plt.show()
           

預測結果:

機器學習之線性回歸筆記1 目錄2 回歸的了解3 線性回歸4 使用最大似然解釋最小二乘5 梯度下降法6 程式分析7 分析sklearn線性回歸的官方例程8 參考書目

可以看到,使用sklearn的預測結果和使用梯度下降法的線性回歸結果是一模一樣的。

8 參考書目

  • 機器學習實戰
  • 機器學習 周志華
  • 線性回歸了解(附純python實作)
  • sklaern官網例程

繼續閱讀