参考:【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]]
原文地址:https://www.cnblogs.com/alex-bn-lee/p/10297893.html