线性模型 - 普通最小二乘法
广义线性模型
目标值 y 是输入变量 x 的线性组合
如果 y ^ \hat{y} y^ 是预测值,那么有:
y ^ ( w , x ) = w 0 + w 1 x 1 + . . . + w p x p \hat{y}(w, x) = w_0 + w_1 x_1 + ... + w_p x_p y^(w,x)=w0+w1x1+...+wpxp
在sklearn中,定义向量
w
=
(
w
1
,
.
.
.
,
w
p
)
w = (w_1, ..., w_p)
w=(w1,...,wp) 为系数(斜率) coef_
,定义
w
0
w_0
w0 为截距 intercept_
普通最小二乘法
在sklearn中,LinearRegression
拟合一个带有系数
w
=
(
w
1
,
.
.
.
,
w
p
)
w = (w_1, ..., w_p)
w=(w1,...,wp) 的线性模型,使得数据集实际观测数据和预测数据(估计值)之间的残差平方和最小。其数学表达式为:
min w ∣ ∣ X w − y ∣ ∣ 2 2 \min\limits_{w} || X w - y||_2^2 wmin∣∣Xw−y∣∣22
其系数的求解 - 正规方程:
w = ( X T X ) − 1 X T y w = (X^TX)^{-1}X^Ty w=(XTX)−1XTy
正规方程的推导
令 f ( w ) = ∣ ∣ X w − y ∣ ∣ 2 2 f(w) = ||Xw - y||_2^2 f(w)=∣∣Xw−y∣∣22
由于向量2范数的公式为:
∣ ∣ X ∣ ∣ 2 = ∑ i = 1 n x i 2 ||X||_2 = \sqrt{\sum\limits_{i = 1}^nx_i^2} ∣∣X∣∣2=i=1∑nxi2
再根据矩阵运算法则,可将原公式变形为:
f ( w ) = ( X w − y ) T ( X w − y ) f(w) = (Xw - y)^T(Xw - y) f(w)=(Xw−y)T(Xw−y)
展开:
f ( w ) = ( w T X T − y T ) ( X w − y ) f(w) = (w^TX^T - y^T)(Xw - y) f(w)=(wTXT−yT)(Xw−y)
f ( w ) = w T X T X w − w T X T y − y T X w + y T y f(w) = w^TX^TXw - w^TX^Ty - y^TXw + y^Ty f(w)=wTXTXw−wTXTy−yTXw+yTy
f ( w ) = w T X T X w − 2 y T X w + y T y f(w) = w^TX^TXw - 2y^TXw + y^Ty f(w)=wTXTXw−2yTXw+yTy
目的是求原函数的最小值,所以对其求导,令导数等于0即可
根据矩阵求导法则求导结果:
f ′ ( w ) = 2 X T X w − 2 X T y f'(w) = 2X^TXw - 2X^Ty f′(w)=2XTXw−2XTy
令 f ′ ( w ) = 0 f'(w) = 0 f′(w)=0 ,则:
2 X T X w − 2 X T y = 0 2X^TXw - 2X^Ty = 0 2XTXw−2XTy=0
移项化简:
X T X w = X T y X^TXw = X^Ty XTXw=XTy
两边同时左乘逆矩阵 ( X T X ) − 1 (X^TX)^{-1} (XTX)−1:
( X T X ) − 1 ( X T X ) w = ( X T X ) − 1 X T y (X^TX)^{-1}(X^TX)w = (X^TX)^{-1}X^Ty (XTX)−1(XTX)w=(XTX)−1XTy
最后可得正规方程:
w = ( X T X ) − 1 X T y w = (X^TX)^{-1}X^Ty w=(XTX)−1XTy
实例验证
import numpy as np
from sklearn import linear_model
from sklearn import datasets
X, y = datasets.load_boston(True)
reg = linear_model.LinearRegression(fit_intercept=False)
reg.fit(X, y)
print('sklearn封装好的LinearRegression模型计算的系数:', reg.coef_, sep='\n', end='\n\n')
coef = np.linalg.inv(X.T @ X) @ X.T @ y
print('自己用正规方程计算的系数:', coef, sep='\n')
结果:
sklearn封装好的LinearRegression模型计算的系数:
[-9.28965170e-02 4.87149552e-02 -4.05997958e-03 2.85399882e+00
-2.86843637e+00 5.92814778e+00 -7.26933458e-03 -9.68514157e-01
1.71151128e-01 -9.39621540e-03 -3.92190926e-01 1.49056102e-02
-4.16304471e-01]
自己用正规方程计算的系数:
[-9.28965170e-02 4.87149552e-02 -4.05997958e-03 2.85399882e+00
-2.86843637e+00 5.92814778e+00 -7.26933458e-03 -9.68514157e-01
1.71151128e-01 -9.39621540e-03 -3.92190926e-01 1.49056102e-02
-4.16304471e-01]
我们发现,sklearn的LinearRegression模型计算的系数和我们直接用正规方程计算的系数一致,说明该模型的拟合的确用的是最小二乘法
但是这是忽略截距的情况,即 fit_intercept=False
如果需要截距,我们用正规方程求解时,需要把截距
w
0
w_0
w0 对应的特征
1
1
1 也加在数据 X
中(见文章开头的广义线性模型)求解:
import numpy as np
from sklearn import linear_model
from sklearn import datasets
X, y = datasets.load_boston(True)
reg = linear_model.LinearRegression()
reg.fit(X, y)
print('sklearn封装好的LinearRegression模型计算的系数:', reg.coef_, sep='\n', end='\n\n')
print('sklearn封装好的LinearRegression模型计算的截距:', reg.intercept_, sep='\n', end='\n\n')
# 截距w0对应的特征为1,所以添加一列值全为1数组
x0 = np.ones(X.shape[0])
X = np.c_[x0, X]
intercept_coef = np.linalg.inv(X.T @ X) @ X.T @ y
print('自己用正规方程计算的系数:', intercept_coef[1:], sep='\n', end='\n\n')
print('自己用正规方程计算的截距:', intercept_coef[0], sep='\n')
结果:
sklearn封装好的LinearRegression模型计算的系数:
[-1.08011358e-01 4.64204584e-02 2.05586264e-02 2.68673382e+00
-1.77666112e+01 3.80986521e+00 6.92224640e-04 -1.47556685e+00
3.06049479e-01 -1.23345939e-02 -9.52747232e-01 9.31168327e-03
-5.24758378e-01]
sklearn封装好的LinearRegression模型计算的截距:
36.45948838509001
自己用正规方程计算的系数:
[-1.08011358e-01 4.64204584e-02 2.05586264e-02 2.68673382e+00
-1.77666112e+01 3.80986521e+00 6.92224640e-04 -1.47556685e+00
3.06049479e-01 -1.23345939e-02 -9.52747232e-01 9.31168327e-03
-5.24758378e-01]
自己用正规方程计算的截距:
36.459488385095966
我们发现,结果一致,说明sklearn中的LinearRegression模型的拟合原理正是最小二乘法。