线性回归
一、原理
线性回归应该是最简单的机器学习算法了,我们以最小二乘法为基础来进行求解
1.1 数据输入
设数据表现形式为:
D a t a = ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) Data = {(x_1,y_1),(x_2,y_2),...,(x_N,y_N)} Data=(x1,y1),(x2,y2),...,(xN,yN)
其中 x i ∈ R p , y i ∈ R , i = 1 , 2 , . . . , N x_i∈R^p,\ y_i∈R,\ i=1,2,...,N xi∈Rp, yi∈R, i=1,2,...,N
就是说有N条数据,每条数据分为特征 x i x_i xi和对应的标签值 y i y_i yi,其中 x i x_i xi为 p ∗ 1 p*1 p∗1维,也就是说有 p p p个特征, x i x_i xi表现为列向量
用
X
X
X表示特征矩阵为
X
=
(
x
1
,
x
2
,
.
.
,
x
N
)
=
[
x
1
T
x
2
T
⋮
x
N
T
]
=
[
x
11
x
12
⋯
x
1
p
x
21
x
22
⋯
x
2
p
⋮
⋮
⋱
⋯
x
N
1
x
N
2
⋯
x
N
p
]
N
×
p
T
X = (x_1,x_2,..,x_N) = \left[\begin{matrix} x_1^T\\ x_2^T\\ \vdots\\ x_N^T\end{matrix}\right]=\left[\begin{matrix} x_{11}&x_{12}&\cdots&x_{1p} \\ x_{21}&x_{22}&\cdots&x_{2p}\\\vdots&\vdots&\ddots&\cdots\\ x_{N1}&x_{N2}&\cdots&x_{Np}\end{matrix}\right]_{N×p}^T
X=(x1,x2,..,xN)=⎣⎢⎢⎢⎡x1Tx2T⋮xNT⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡x11x21⋮xN1x12x22⋮xN2⋯⋯⋱⋯x1px2p⋯xNp⎦⎥⎥⎥⎤N×pT
用
Y
Y
Y表示标签矩阵为:
Y
=
[
y
1
y
2
⋮
y
N
]
N
×
1
Y =\left[\begin{matrix} y_1\\ y_2 \\ \vdots \\y_N \end{matrix}\right]_{N×1}
Y=⎣⎢⎢⎢⎡y1y2⋮yN⎦⎥⎥⎥⎤N×1
线性回归的目的在于拟合一个函数来根据特征值预测标签值,当数据为平面坐标点时( 横坐标为x纵坐标为y),拟合的函数表现为一条坐标平面直线。
我们需要拟合函数的权重
W
W
W,其维度为
p
×
1
p×1
p×1,当数据为平面坐标点时为一个数(
1
×
1
1×1
1×1的矩阵)
W
=
[
W
1
W
2
⋮
W
N
]
p
×
1
W =\left[\begin{matrix} W_1\\ W_2 \\ \vdots \\W_N \end{matrix}\right]_{p×1}
W=⎣⎢⎢⎢⎡W1W2⋮WN⎦⎥⎥⎥⎤p×1
1.2 最小二乘法一般解法
显然,用最小二乘法求解,其损失函数为
M
S
E
MSE
MSE :
L
(
W
)
=
∑
i
=
1
N
∣
∣
W
T
x
i
−
y
i
∣
∣
2
=
∑
i
=
1
N
(
W
T
x
i
−
y
i
)
2
=
[
W
T
x
1
−
y
1
,
W
T
x
2
−
y
2
,
.
.
.
,
W
T
x
N
−
y
N
]
[
W
T
x
1
−
y
1
W
T
x
2
−
y
2
⋮
W
T
x
N
−
y
B
]
=
(
W
T
X
T
−
Y
T
)
(
X
W
−
Y
)
=
W
T
X
T
X
W
−
W
T
X
T
Y
−
Y
T
X
W
+
Y
T
Y
=
W
T
X
T
X
W
−
2
W
T
X
T
Y
+
Y
T
Y
\begin{aligned} L(W) &= \displaystyle\sum_{i=1}^N||W^Tx_i-y_i||^2 \\&=\displaystyle\sum_{i=1}^N(W^Tx_i-y_i)^2 \\&=\left[W^Tx_1-y_1,W^Tx_2-y_2,...,W^Tx_N-y_N\right]\left[\begin{matrix} W^Tx_1-y_1\\ W^Tx_2-y_2\\ \vdots\\ W^Tx_N-y_B\end{matrix}\right]\\&=(W^TX^T-Y^T)(XW-Y)\\&=W^TX^TXW-W^TX^TY-Y^TXW+Y^TY\\&=W^TX^TXW-2W^TX^TY+Y^TY\\ \end{aligned}\\
L(W)=i=1∑N∣∣WTxi−yi∣∣2=i=1∑N(WTxi−yi)2=[WTx1−y1,WTx2−y2,...,WTxN−yN]⎣⎢⎢⎢⎡WTx1−y1WTx2−y2⋮WTxN−yB⎦⎥⎥⎥⎤=(WTXT−YT)(XW−Y)=WTXTXW−WTXTY−YTXW+YTY=WTXTXW−2WTXTY+YTY
使用损失函数对
W
W
W求导:
∂
L
(
W
)
∂
W
=
2
X
T
X
W
−
2
X
T
Y
=
0
\large \frac{\partial L(W)}{\partial W} = 2X^TXW-2X^TY=0
∂W∂L(W)=2XTXW−2XTY=0
可得
X
T
X
W
=
X
T
Y
W
=
(
X
T
X
)
−
1
X
T
Y
\begin{aligned} X^TXW &=X^TY \\ W&=(X^TX)^{-1}X^TY\\ \end{aligned}
XTXWW=XTY=(XTX)−1XTY
即求得参数
W
W
W,其中
(
X
T
X
)
−
1
X
T
(X^TX)^{-1}X^T
(XTX)−1XT被称为
X
X
X的伪逆矩阵
1.3 最小二乘法的几何理解
我们将 X X X理解为一种特征空间,比如说,现在由 x 1 、 x 2 x_1、x_2 x1、x2两个特征组成了一个平面,而使用 Y Y Y向该平面投影:
投影可以理解为在向量 x 1 、 x 2 x_1、x_2 x1、x2的线性组合,则可以找到一组 w w w用来表示这段线性组合的权重,即 [ x 1 , x 2 ] [ w 1 , w 2 ] T [x_1,x_2][w_1,w_2]^T [x1,x2][w1,w2]T
扩展到全部的 X X X和 Y Y Y,投影就是 X W XW XW,而根据向量的减法,垂直于平面的那一段可以描述为 Y − X W Y-XW Y−XW
垂直的向量内积为0,即:
X
T
(
Y
−
X
W
)
=
0
X
T
Y
=
X
T
X
W
W
=
(
X
T
X
)
−
1
X
T
Y
\begin{aligned} X^T(Y-XW) &= 0\\ X^TY&=X^TXW\\ W &= (X^TX)^{-1}X^TY \end{aligned}
XT(Y−XW)XTYW=0=XTXW=(XTX)−1XTY
与之前使用求导算得的
W
W
W一致
二、正则化与岭回归
对于上述问题,求得的线性回归损失函数及其
W
W
W为:
L
(
W
)
=
∑
i
=
1
N
∣
∣
W
T
x
i
−
y
i
∣
∣
2
W
=
(
X
T
X
)
−
1
X
T
Y
\begin{aligned} L(W) &= \displaystyle\sum_{i=1}^N||W^Tx_i-y_i||^2\\W&=(X^TX)^{-1}X^TY \end{aligned}
L(W)W=i=1∑N∣∣WTxi−yi∣∣2=(XTX)−1XTY
而在实际应用中,
(
X
T
X
)
(X^TX)
(XTX)可能是不可逆的,比如特征大于样本时,而且样本过少特征过多还容易造成过拟合,由此提出了正则化的解决方案。
正则化的框架为:
L
(
W
)
+
λ
P
(
W
)
L(W)+\lambda P(W)
L(W)+λP(W)
其中
λ
P
(
w
)
\lambda P(w)
λP(w)被称为惩罚项
一般正则化可以分为L1正则化和L2正则化:
- L1正则化:也被称作Lasso,此时 P ( W ) = ∣ ∣ W ∣ ∣ 1 P(W) = ||W||_1 P(W)=∣∣W∣∣1,即 W W W的一范式
- L2正则化:也被称作Ridge和岭回归,此时 P ( W ) = ∣ ∣ W ∣ ∣ 2 2 = W T W P(W)=||W||_2^2=W^TW P(W)=∣∣W∣∣22=WTW
在这里我们主要介绍L2正则化,也就是岭回归
在岭回归的情况下,损失函数就变为:
J
(
W
)
=
∑
i
=
1
N
∣
∣
W
T
x
i
−
y
i
∣
∣
2
+
λ
W
T
W
=
(
W
T
X
T
−
Y
T
)
(
X
W
−
Y
)
+
λ
W
T
W
=
W
T
X
T
X
W
−
2
W
T
X
T
Y
+
Y
T
Y
+
λ
W
T
W
=
W
T
(
X
T
X
+
λ
I
)
W
−
2
W
T
X
T
Y
+
Y
T
Y
\begin{aligned} J(W)&=\displaystyle\sum_{i=1}^N||W^Tx_i-y_i||^2+\lambda W^TW \\ &=(W^TX^T-Y^T)(XW-Y)+\lambda W^TW\\ &=W^TX^TXW-2W^TX^TY+Y^TY+\lambda W^TW\\ &=W^T(X^TX+\lambda I)W-2W^TX^TY+Y^TY \end{aligned}
J(W)=i=1∑N∣∣WTxi−yi∣∣2+λWTW=(WTXT−YT)(XW−Y)+λWTW=WTXTXW−2WTXTY+YTY+λWTW=WT(XTX+λI)W−2WTXTY+YTY
对
W
W
W进行求导:
∂
J
(
W
)
∂
W
=
2
(
X
T
X
+
λ
I
)
W
−
2
X
T
Y
=
0
\frac{\partial J(W)}{\partial W} = 2(X^TX+\lambda I)W - 2X^TY = 0
∂W∂J(W)=2(XTX+λI)W−2XTY=0
求得
W
=
(
X
T
X
+
λ
I
)
−
1
X
T
Y
W = (X^TX+\lambda I)^{-1}X^TY
W=(XTX+λI)−1XTY
此时
(
X
T
X
+
λ
I
)
(X^TX+\lambda I)
(XTX+λI)一定可逆,理由如下:
假设
X
T
X
X^TX
XTX不可逆,即不满秩,其可以变换为某一行或某一列为全0的矩阵:
X
T
X
=
[
a
11
a
12
a
13
⋯
a
1
n
0
a
22
a
23
⋯
a
2
n
0
0
a
33
⋯
a
3
n
⋮
⋮
⋮
⋱
⋮
0
0
0
⋯
0
]
X^TX = \left[\begin{matrix} a_{11}&a_{12} &a_{13} &\cdots & a_{1n} \\0&a_{22} &a_{23} &\cdots & a_{2n} \\0&0 &a_{33} &\cdots & a_{3n} \\ \vdots&\vdots &\vdots &\ddots & \vdots \\0&0 &0 &\cdots & 0 \end{matrix} \right]
XTX=⎣⎢⎢⎢⎢⎢⎡a1100⋮0a12a220⋮0a13a23a33⋮0⋯⋯⋯⋱⋯a1na2na3n⋮0⎦⎥⎥⎥⎥⎥⎤
X T X + λ I = [ a 11 + λ a 12 a 13 ⋯ a 1 n 0 a 22 + λ a 23 ⋯ a 2 n 0 0 a 33 + λ ⋯ a 3 n ⋮ ⋮ ⋮ ⋱ ⋮ 0 0 0 ⋯ λ ] X^TX+\lambda I = \left[\begin{matrix} a_{11}+\lambda&a_{12} &a_{13} &\cdots & a_{1n} \\0&a_{22}+\lambda &a_{23} &\cdots & a_{2n} \\0&0 &a_{33}+\lambda &\cdots & a_{3n} \\ \vdots&\vdots &\vdots &\ddots & \vdots \\0&0 &0 &\cdots & \lambda \end{matrix} \right] XTX+λI=⎣⎢⎢⎢⎢⎢⎡a11+λ00⋮0a12a22+λ0⋮0a13a23a33+λ⋮0⋯⋯⋯⋱⋯a1na2na3n⋮λ⎦⎥⎥⎥⎥⎥⎤
此时不存在全为0的行或列,矩阵满秩可逆,当然,还是有特殊清况,比如:
- λ = 0 \lambda=0 λ=0
- 原本矩阵中存在对象线上元素为 − λ -\lambda −λ,其他元素都为0的行或列
当然,这些情况可以通过调节 λ \lambda λ来解决
三、代码实现
梯度下降法,使用之前公式中损失函数 L L L对 W W W的求导作为梯度,每次乘上学习率进行衰减,即:
d W = 2 X T X W − 2 X T Y d_W = 2X^TXW-2X^TY dW=2XTXW−2XTY
W = W − l r ∗ d W W = W-lr*d_W W=W−lr∗dW
公式法则是直接用最后的公式计算 X X X的伪逆矩阵乘上 Y Y Y
岭回归只需要在原始基础上加上惩罚项
其实两种方法实现起来几乎是一模一样的:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
def get_points():
#获取坐标点
point = [[3,3],[4,3],[2,5],[6,7],[8,10]]
X = np.array([x[0] for x in point])
Y = np.array([x[1] for x in point])
X = X.reshape(X.shape[0],1)
Y = Y.reshape(Y.shape[0],1)
#另一组点,此时x为二维,画图函数无效,记得注释掉
# X = np.array([[1, 2], [3, 4], [3, 6]])
# Y = np.array([3, 6, 9])
# X = X.reshape(X.shape[0],2)
# Y = Y.reshape(Y.shape[0],1)
# return X,Y.reshape(Y.shape[0],1)
return X,Y
def get_house():
#波士顿房价数据集
data,target = load_boston(return_X_y=True)
return data,target.reshape(target.shape[0],1)
def cal_w(X,Y):
#公式直接计算W
w = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)
return w
def Ridge_w(X,Y):
#岭回归,可以通过调节lambda,此处为a来改变直线
a = 5
w = np.linalg.inv(X.T.dot(X)+a*np.eye(X.shape[1])).dot(X.T).dot(Y)
return w
def gradient(X,Y):
#梯度下降法
lr = 0.01
epochs = 2
w = np.zeros((X.shape[1],1))
for epoch in range(epochs):
dw = X.T.dot(X).dot(w)-X.T.dot(Y)
w -= lr*dw
return w
if __name__ == '__main__':
X,Y = get_points()
w1 = gradient(X,Y)
w2 = cal_w(X,Y)
w3 = Ridge_w(X,Y)
plt.scatter(X, Y, c='b',label = 'points')
plt.plot(np.arange(1, 9), w1[0][0] * np.arange(1, 9), c='r',label = 'line_gradient')
plt.plot(np.arange(1, 9), w2[0][0] * np.arange(1, 9), c='g',label = 'line_cal_w')
plt.plot(np.arange(1, 9), w3[0][0] * np.arange(1, 9), c='y',label = 'Ridge_cal_w')
plt.legend()
plt.show()
结果如下图所示:
注意,调节梯度下降的epochs,lr 以及岭回归的惩罚系数可以使三条直线完全吻合,但为了方便展示这里做了区分。
在实验中发现梯度下降法当学习率过大或者过小时会发生梯度消失或是梯度爆炸,原因可能是数据量太小。
同时,线性回归也可以尝试其他更复杂的点以及波士顿房价预测数据集,代码中已给出数据集,请自行尝试。
四、结语
参考内容:
- B站视频:https://www.bilibili.com/video/BV1aE411o7qd?from=search&seid=1227152557997491474&spm_id_from=333.337.0.0
- 博客:https://www.cnblogs.com/oten/p/13953220.html
如有问题欢迎评论区指出,有问题也可以联系我:
1759412770@qq.com