【353】線性回歸損失函數求導舉例


參考:【351】實數對向量求導公式

參考:【352】矩陣轉置性質

參考:機器學習實戰教程(十一):線性回歸基礎篇之預測鮑魚年齡

其他方法可參考 回歸算法之線性回歸

參考:通過一個例子快速上手矩陣求導


線性回歸的損失函數如下:
$$E_b = {(X b - y)^T (X b - y)}$$

將轉置打開,像是開平方一樣,運用到上面的性質:
$$
\begin{equation*}
\begin{split}
E_b &= (X b - y)^T (X b - y)\\\\
&=((Xb)^T - y^T)(Xb-y)\\\\
&=(b^T X^T - y^T)(Xb-y)\\\\
&=b^T X^T Xb - b^T X^T y - y^T Xb + y^T y
\end{split}
\end{equation*}
$$

根據實數對向量求導的公式,對上面的實數分別對向量 $b$ 求導。

$$
\begin{equation*}
\begin{split}
\nabla_b E_b &= \nabla_b (b^T X^T Xb - b^T X^T y - y^T Xb + y^T y)\\\\
&= \nabla_b (b^T X^T Xb) - \nabla_b (b^T X^T y) - \nabla_b (y^T Xb) + \nabla_b (y^T y)\\\\
&= \nabla_b (b^T (X^T X)b) - \nabla_b (b^T (X^T y)) - \nabla_b ((y^T X)b) + 0\\\\
&= (X^T X + (X^T X)^T)b - X^T y - (y^T X)^T\\\\
&= 2 X^T X b - 2 X^T y\\\\
&= 2 X^T (Xb-y)
\end{split}
\end{equation*}
$$


Python 實現算法

通過 sklearn 實現

from sklearn import linear_model

x = [
    [100.0, 4.0],
    [50.0, 3.0],
    [100.0, 4.0],
    [100.0, 2.0],
    [50.0, 2.0],
    [80.0, 2.0],
    [75.0, 3.0],
    [65.0, 4.0],
    [90.0, 3.0],
    [90.0, 2.0]
]

y = [9.3, 4.8, 8.9, 6.5, 4.2, 6.2, 7.4, 6.0, 7.6, 6.1]

test_row = [50, 3]
sk = linear_model.LinearRegression()
sk.fit(x, y)
print(sk.coef_)
print(sk.intercept_)
print(sk.predict([test_row]))

[0.0611346 0.92342537]
-0.868701466781709
[4.95830457] 

x1, x2 = sk.coef_
print(x1)
print(x2)

0.06113459879206212
0.9234253666954272 

得到的模型為:$y = -0.87 + 0.06 \cdot x_1 + 0.92 \cdot x_2 $

參考:Python:類屬性,實例屬性,私有屬性與靜態方法,類方法,實例方法

通過矩陣計算實現

參考:回歸算法之線性回歸

得到正規方程組:

說明:"$$" - 表示獨占一行。
參考:在Jupyter Notebook里面寫Python代碼和數學公式

$$
mb_0 + \sum_{i=1}^{m} x_{i1}b_1 + ... + \sum_{i=1}^{m} x_{in}b_n = \sum_{i=1}^{m} y_i
$$
$$
\sum_{i=1}^{m} x_{i1} b_0 + \sum_{i=1}^{m} x_{i1} x_{i1} b_1 + ... + \sum_{i=1}^{m} x_{i1} x_{in}b_n = \sum_{i=1}^{m} x_{i1} y_i
$$
$$...$$
$$
\sum_{i=1}^{m} x_{in} b_0 + \sum_{i=1}^{m} x_{in} x_{i1} b_1 + ... + \sum_{i=1}^{m} x_{in} x_{in}b_n = \sum_{i=1}^{m} x_{in} y_i
$$

寫成矩陣表示為:
$$
\mathbf{X}^T \mathbf{X}\mathbf{B}=\mathbf{X}^T \mathbf{Y}
$$
解得:
$$
\mathbf{B}=(\mathbf{X}^T \mathbf{X})^{-1} \mathbf{X}^T \mathbf{Y}
$$

這一步的結果,與上面通過求偏導得到的結果一致,只需讓導數為 0 即可。

import numpy as np
class MyLinearRegression(object):
    def __init__(self):
        # 添加屬性,並且初始化,b 為列表
        self.b = []
        self.intercept_ = 0.0
        self.coef_ = []
        
    def fit(self, x:list, y:list):
        # 為每條訓練數據前都添加 1,作為 b0 的系數
        point_num, future_num = np.shape(x)
        # 在原來 x 的維度基礎上增加一列
        tmpx = np.ones(shape=(point_num, future_num + 1))
        # 將索引為 1 的列往后的部分賦值與 x 相同
        tmpx[:, 1:] = x
        
        # 矩陣 X
        x_mat = np.mat(tmpx)
        # 矩陣 y
        y_mat = np.mat(y).T
        # 獲取矩陣 X 的轉置矩陣 xT
        xT = x_mat.T
        # 直接按照公式計算
        self.b = (xT * x_mat).I * xT * y_mat
        
        # 從 b 中截取相應部分
        self.intercept_ = self.b[0]
        self.coef_ = self.b[1:]
        
    def predict(self, x):
        # [1] + x 表示將兩個列表合並成一個連續的列表
        return np.mat([1] + x) * self.b

調用自定義的類:

linear = MyLinearRegression()
linear.fit(x,y)
print(linear.intercept_)
print(linear.coef_)
print(linear.predict(test_row))

[[-0.86870147]]
[[0.0611346 ]
[0.92342537]]
[[4.95830457]]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM