1. 程式人生 > >[ch04-02] 用梯度下降法解決線性迴歸問題

[ch04-02] 用梯度下降法解決線性迴歸問題

系列部落格,原文在筆者所維護的github上:https://aka.ms/beginnerAI,
點選star加星不要吝嗇,星越多筆者越努力。

4.2 梯度下降法

有了上一節的最小二乘法做基準,我們這次用梯度下降法求解w和b,從而可以比較二者的結果。

4.2.1 數學原理

在下面的公式中,我們規定x是樣本特徵值(單特徵),y是樣本標籤值,z是預測值,下標 \(i\) 表示其中一個樣本。

預設函式(Hypothesis Function)

為一個線性函式:

\[z_i = x_i \cdot w + b \tag{1}\]

損失函式(Loss Function)

為均方差函式:

\[loss(w,b) = \frac{1}{2} (z_i-y_i)^2 \tag{2}\]

與最小二乘法比較可以看到,梯度下降法和最小二乘法的模型及損失函式是相同的,都是一個線性模型加均方差損失函式,模型用於擬合,損失函式用於評估效果。

區別在於,最小二乘法從損失函式求導,直接求得數學解析解,而梯度下降以及後面的神經網路,都是利用導數傳遞誤差,再通過迭代方式一步一步逼近近似解。

4.2.2 梯度計算

計算z的梯度

根據公式2:
\[ {\partial loss \over \partial z_i}=z_i - y_i \tag{3} \]

計算w的梯度

我們用loss的值作為誤差衡量標準,通過求w對它的影響,也就是loss對w的偏導數,來得到w的梯度。由於loss是通過公式2->公式1間接地聯絡到w的,所以我們使用鏈式求導法則,通過單個樣本來求導。

根據公式1和公式3:

\[ {\partial{loss} \over \partial{w}} = \frac{\partial{loss}}{\partial{z_i}}\frac{\partial{z_i}}{\partial{w}}=(z_i-y_i)x_i \tag{4} \]

計算b的梯度

\[ \frac{\partial{loss}}{\partial{b}} = \frac{\partial{loss}}{\partial{z_i}}\frac{\partial{z_i}}{\partial{b}}=z_i-y_i \tag{5} \]

4.2.3 程式碼實現

if __name__ == '__main__':

    reader = SimpleDataReader()
    reader.ReadData()
    X,Y = reader.GetWholeTrainSamples()

    eta = 0.1
    w, b = 0.0, 0.0
    for i in range(reader.num_train):
        # get x and y value for one sample
        xi = X[i]
        yi = Y[i]
        # 公式1
        zi = xi * w + b
        # 公式3
        dz = zi - yi
        # 公式4
        dw = dz * xi
        # 公式5
        db = dz
        # update w,b
        w = w - eta * dw
        b = b - eta * db

    print("w=", w)    
    print("b=", b)

大家可以看到,在程式碼中,我們完全按照公式推導實現了程式碼,所以,大名鼎鼎的梯度下降,其實就是把推導的結果轉化為數學公式和程式碼,直接放在迭代過程裡!另外,我們並沒有直接計算損失函式值,而只是把它融入在公式推導中。

4.2.4 執行結果

w= [1.71629006]
b= [3.19684087]

讀者可能會注意到,上面的結果和最小二乘法的結果(w1=2.056827, b1=2.965434)相差比較多,這個問題我們留在本章稍後的地方解決。

程式碼位置

ch04, Level2