目标值 y 是输入变量 x 的线性组合
如果 y^\hat{y}y^ 是预测值,那么有:
y^(w,x)=w0+w1x1+...+wpxp\hat{y}(w, x) = w_0 + w_1 x_1 + ... + w_p x_py^(w,x)=w0+w1x1+...+wpxp
在sklearn中,定义向量 w=(w1,...,wp)w = (w_1, ..., w_p)w=(w1,...,wp) 为系数(斜率) coef_
,定义 w0w_0w0 为截距 intercept_
在sklearn中,LinearRegression
拟合一个带有系数 w=(w1,...,wp)w = (w_1, ..., w_p)w=(w1,...,wp) 的线性模型,使得数据集实际观测数据和预测数据(估计值)之间的残差平方和最小。其数学表达式为:
minw∣∣Xw−y∣∣22\min\limits_{w} || X w - y||_2^2wmin∣∣Xw−y∣∣22
其系数的求解 - 正规方程:
w=(XTX)−1XTyw = (X^TX)^{-1}X^Tyw=(XTX)−1XTy
正规方程的推导令 f(w)=∣∣Xw−y∣∣22f(w) = ||Xw - y||_2^2f(w)=∣∣Xw−y∣∣22
由于向量2范数的公式为:
∣∣X∣∣2=∑i=1nxi2||X||_2 = \sqrt{\sum\limits_{i = 1}^nx_i^2}∣∣X∣∣2=i=1∑nxi2
再根据矩阵运算法则,可将原公式变形为:
f(w)=(Xw−y)T(Xw−y)f(w) = (Xw - y)^T(Xw - y)f(w)=(Xw−y)T(Xw−y)
展开:
f(w)=(wTXT−yT)(Xw−y)f(w) = (w^TX^T - y^T)(Xw - y)f(w)=(wTXT−yT)(Xw−y)
f(w)=wTXTXw−wTXTy−yTXw+yTyf(w) = w^TX^TXw - w^TX^Ty - y^TXw + y^Tyf(w)=wTXTXw−wTXTy−yTXw+yTy
f(w)=wTXTXw−2yTXw+yTyf(w) = w^TX^TXw - 2y^TXw + y^Ty f(w)=wTXTXw−2yTXw+yTy
目的是求原函数的最小值,所以对其求导,令导数等于0即可
根据矩阵求导法则求导结果:
f′(w)=2XTXw−2XTyf'(w) = 2X^TXw - 2X^Tyf′(w)=2XTXw−2XTy
令 f′(w)=0f'(w) = 0f′(w)=0 ,则:
2XTXw−2XTy=02X^TXw - 2X^Ty = 02XTXw−2XTy=0
移项化简:
XTXw=XTyX^TXw = X^TyXTXw=XTy
两边同时左乘逆矩阵 (XTX)−1(X^TX)^{-1}(XTX)−1:
(XTX)−1(XTX)w=(XTX)−1XTy(X^TX)^{-1}(X^TX)w = (X^TX)^{-1}X^Ty(XTX)−1(XTX)w=(XTX)−1XTy
最后可得正规方程:
w=(XTX)−1XTyw = (X^TX)^{-1}X^Tyw=(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
如果需要截距,我们用正规方程求解时,需要把截距 w0w_0w0 对应的特征 111 也加在数据 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数组
w0 = np.ones(X.shape[0])
X = np.c_[w0, 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模型的拟合原理正是最小二乘法。