标准方程法
标准方程法就是通过一些方法直接求出权值ω的值,以往的文章已将讲过了代价函数的相关内容,这里直接给出代价函数的公式:
J
(
ω
0
,
ω
1
,
ω
2
,
…
,
ω
n
)
=
∑
i
=
1
m
[
y
i
−
h
ω
(
x
i
)
]
2
J(ω_0,ω_1,ω_2,\dots,ω_n)=\sum_{i=1}^m[y_i-h_ω(x_i)]^2
J(ω0,ω1,ω2,…,ωn)=i=1∑m[yi−hω(xi)]2
其中
h
ω
(
x
)
h_ω(x)
hω(x)的公式如下:
h
ω
(
x
)
=
ω
0
+
ω
1
x
1
+
ω
2
x
2
+
⋯
+
ω
n
x
n
h_ω(x)=ω_0+ω_1x_1+ω_2x_2+\dots+ω_nx_n
hω(x)=ω0+ω1x1+ω2x2+⋯+ωnxn
如果数据集中只有一条数据,通过矩阵可以描述成一下形式:
X
=
[
x
0
x
1
x
2
…
x
n
]
,
其
中
x
0
=
1
X = \begin{bmatrix} x_0 & x_1 & x_2 & \dots & x_n \end{bmatrix},其中x_0=1
X=[x0x1x2…xn],其中x0=1
w = [ ω 0 ω 1 ω 2 ⋮ ω n ] w=\begin{bmatrix} ω_0 \\ ω_1 \\ ω_2 \\ \vdots \\ ω_n \end{bmatrix} w=⎣⎢⎢⎢⎢⎢⎡ω0ω1ω2⋮ωn⎦⎥⎥⎥⎥⎥⎤
h ω ( x ) = X ∗ w = [ x 0 x 1 x 2 … x n ] ∗ [ ω 0 ω 1 ω 2 ⋮ ω n ] = ω 0 + ω 1 x 1 + ω 2 x 2 + ⋯ + ω n x n \begin{aligned} h_ω(x)=X*w=\begin{bmatrix} x_0 & x_1 & x_2 & \dots & x_n \end{bmatrix} *\begin{bmatrix} ω_0 \\ ω_1 \\ ω_2 \\ \vdots \\ ω_n \end{bmatrix} \\ =ω_0+ω_1x_1+ω_2x_2+\dots+ω_nx_n \end{aligned} hω(x)=X∗w=[x0x1x2…xn]∗⎣⎢⎢⎢⎢⎢⎡ω0ω1ω2⋮ωn⎦⎥⎥⎥⎥⎥⎤=ω0+ω1x1+ω2x2+⋯+ωnxn
一般数据集中,会有很多条数据,每一条数据通过上述公式都会得到一个
h
ω
(
x
)
h_ω(x)
hω(x),故通过矩阵可以描述成以下形式:
x
0
x
1
x
2
…
x
n
X
=
[
1
a
1
a
2
…
a
n
1
b
1
b
2
…
b
n
…
…
…
…
…
1
n
1
n
2
…
n
n
]
n
∗
(
n
+
1
)
x_0\quad x_1\quad x_2 \quad \dots \quad x_n \\ X = \begin{bmatrix} 1 & a_1 & a_2 & \dots & a_n \\ 1 & b_1 & b_2 & \dots & b_n \\ \dots & \dots & \dots & \dots & \dots \\ 1 & n_1 & n_2 & \dots & n_n \end{bmatrix}_{n*(n+1)}
x0x1x2…xnX=⎣⎢⎢⎡11…1a1b1…n1a2b2…n2…………anbn…nn⎦⎥⎥⎤n∗(n+1)
w = [ ω 0 ω 1 ω 2 ⋮ ω n ] ( n + 1 ) ∗ 1 w=\begin{bmatrix} ω_0 \\ ω_1 \\ ω_2 \\ \vdots \\ ω_n \end{bmatrix}_{(n+1)*1} w=⎣⎢⎢⎢⎢⎢⎡ω0ω1ω2⋮ωn⎦⎥⎥⎥⎥⎥⎤(n+1)∗1
h ω ( x ) = X ∗ w = [ 1 a 1 a 2 … a n 1 b 1 b 2 … b n … … … … … 1 n 1 n 2 … n n ] ∗ [ ω 0 ω 1 ω 2 ⋮ ω n ] = [ ω 0 + ω 1 a 1 + ω 2 a 2 + ⋯ + ω n a n ω 0 + ω 1 b 1 + ω 2 b 2 + ⋯ + ω n b n ⋮ ω 0 + ω 1 n 1 + ω 2 n 2 + ⋯ + ω n n n ] = [ h ω ( x 1 ) h ω ( x 2 ) ⋮ h ω ( x n ) ] n ∗ 1 \begin{aligned} h_ω(x)=X*w&=\begin{bmatrix} 1 & a_1 & a_2 & \dots & a_n \\ 1 & b_1 & b_2 & \dots & b_n \\ \dots & \dots & \dots & \dots & \dots \\ 1 & n_1 & n_2 & \dots & n_n \end{bmatrix} *\begin{bmatrix} ω_0 \\ ω_1 \\ ω_2 \\ \vdots \\ ω_n \end{bmatrix} \\ &=\begin{bmatrix} ω_0+ω_1a_1+ω_2a_2+\dots+ω_na_n \\ ω_0+ω_1b_1+ω_2b_2+\dots+ω_nb_n \\ \vdots \\ ω_0+ω_1n_1+ω_2n_2+\dots+ω_nn_n \end{bmatrix} \\ &=\begin{bmatrix} h_ω(x_1) \\ h_ω(x_2) \\ \vdots \\ h_ω(x_n) \end{bmatrix}_{n*1} \end{aligned} hω(x)=X∗w=⎣⎢⎢⎡11…1a1b1…n1a2b2…n2…………anbn…nn⎦⎥⎥⎤∗⎣⎢⎢⎢⎢⎢⎡ω0ω1ω2⋮ωn⎦⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎡ω0+ω1a1+ω2a2+⋯+ωnanω0+ω1b1+ω2b2+⋯+ωnbn⋮ω0+ω1n1+ω2n2+⋯+ωnnn⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡hω(x1)hω(x2)⋮hω(xn)⎦⎥⎥⎥⎤n∗1
那么代价函数如何用这种形式表示呢?别急,看下面这个公式
∑
i
=
1
n
[
y
i
−
h
ω
(
x
i
)
]
2
=
(
y
i
−
X
w
)
T
(
y
i
−
X
w
)
\sum_{i=1}^n[y_i-h_ω(x_i)]^2=(y_i-Xw)^T(y_i-Xw)
i=1∑n[yi−hω(xi)]2=(yi−Xw)T(yi−Xw)
证明如下
y
i
−
X
w
=
[
y
1
−
h
ω
(
x
1
)
y
2
−
h
ω
(
x
2
)
⋮
y
n
−
h
ω
(
x
n
)
]
y_i-Xw=\begin{aligned} \begin{bmatrix} y_1-h_ω(x_1) \\ y_2-h_ω(x_2) \\ \vdots \\ y_n-h_ω(x_n) \end{bmatrix} \end{aligned}
yi−Xw=⎣⎢⎢⎢⎡y1−hω(x1)y2−hω(x2)⋮yn−hω(xn)⎦⎥⎥⎥⎤
( y i − X w ) T ( y i − X w ) = [ y 1 − h ω ( x 1 ) y 2 − h ω ( x 2 ) … y n − h ω ( x n ) ] ∗ [ y 1 − h ω ( x 1 ) y 2 − h ω ( x 2 ) ⋮ y n − h ω ( x n ) ] = ( y 1 − h ω ( x 1 ) ) 2 + ( y 2 − h ω ( x 2 ) ) 2 + ( y 1 − h ω ( x 1 ) ) 2 + ⋯ + ( y n − h ω ( x n ) ) 2 = ∑ i = 1 n [ y i − h ω ( x i ) ] 2 \begin{aligned} (y_i-Xw)^T(y_i-Xw)&=\begin{bmatrix} y_1-h_ω(x_1) & y_2-h_ω(x_2) & \dots & y_n-h_ω(x_n) \end{bmatrix}*\begin{bmatrix} y_1-h_ω(x_1) \\ y_2-h_ω(x_2) \\ \vdots \\ y_n-h_ω(x_n) \end{bmatrix} \\ &=(y_1-h_ω(x_1))^2+(y_2-h_ω(x_2))^2+(y_1-h_ω(x_1))^2+\dots+(y_n-h_ω(x_n))^2 \\ &=\sum_{i=1}^n[y_i-h_ω(x_i)]^2 \end{aligned} (yi−Xw)T(yi−Xw)=[y1−hω(x1)y2−hω(x2)…yn−hω(xn)]∗⎣⎢⎢⎢⎡y1−hω(x1)y2−hω(x2)⋮yn−hω(xn)⎦⎥⎥⎥⎤=(y1−hω(x1))2+(y2−hω(x2))2+(y1−hω(x1))2+⋯+(yn−hω(xn))2=i=1∑n[yi−hω(xi)]2
证明结束。
但是呢,到这里肯定是还没有结束的,我们知道了代价函数,接下来一步就是去求最小值。提到函数和最小值,用我为数不多的数学知识那就是求导了,我现在脑海中只剩了一顿求导,令其为零了。好了,接下来就让我们一起来求导吧!!!
∂
(
y
−
X
w
)
T
(
y
−
X
w
)
∂
w
=
∂
(
y
T
−
w
T
X
T
)
(
y
−
X
w
)
∂
w
=
∂
(
y
T
y
−
y
T
X
w
−
w
T
X
T
y
+
w
T
X
T
X
w
)
∂
w
=
∂
y
T
y
∂
w
−
∂
y
T
X
w
∂
w
−
∂
w
T
X
T
y
∂
w
+
∂
w
T
X
T
X
w
∂
w
\begin{aligned} &\frac{∂(y-Xw)^T(y-Xw)}{∂w} \\ &=\frac{∂(y^T-w^TX^T)(y-Xw)}{∂w} \\ &=\frac{∂(y^Ty-y^TXw-w^TX^Ty+w^TX^TXw)}{∂w} \\ &=\frac{∂y^Ty}{∂w}-\frac{∂y^TXw}{∂w}-\frac{∂w^TX^Ty}{∂w}+\frac{∂w^TX^TXw}{∂w} \end{aligned}
∂w∂(y−Xw)T(y−Xw)=∂w∂(yT−wTXT)(y−Xw)=∂w∂(yTy−yTXw−wTXTy+wTXTXw)=∂w∂yTy−∂w∂yTXw−∂w∂wTXTy+∂w∂wTXTXw
对其各自求偏导得:
∂
y
T
y
∂
w
=
0
∂
y
T
X
w
∂
w
=
X
T
y
∂
w
T
X
T
y
∂
w
=
(
∂
w
T
X
T
y
)
T
∂
w
=
∂
y
T
X
w
∂
w
=
X
T
y
∂
w
T
X
T
X
w
∂
w
=
2
X
T
X
w
\begin{aligned} \frac{∂y^Ty}{∂w}&=0 \\ \frac{∂y^TXw}{∂w}&=X^Ty \\ \frac{∂w^TX^Ty}{∂w}&=\frac{(∂w^TX^Ty)^T}{∂w}=\frac{∂y^TXw}{∂w}=X^Ty \\ \frac{∂w^TX^TXw}{∂w}&=2X^TXw \end{aligned}
∂w∂yTy∂w∂yTXw∂w∂wTXTy∂w∂wTXTXw=0=XTy=∂w(∂wTXTy)T=∂w∂yTXw=XTy=2XTXw
整合一下:
∂
y
T
y
∂
w
−
∂
y
T
X
w
∂
w
−
∂
w
T
X
T
y
∂
w
+
∂
w
T
X
T
X
w
∂
w
=
0
−
X
T
y
−
X
T
y
+
2
X
T
X
w
\frac{∂y^Ty}{∂w}-\frac{∂y^TXw}{∂w}-\frac{∂w^TX^Ty}{∂w}+\frac{∂w^TX^TXw}{∂w}=0-X^Ty-X^Ty+2X^TXw
∂w∂yTy−∂w∂yTXw−∂w∂wTXTy+∂w∂wTXTXw=0−XTy−XTy+2XTXw
令其为零:
−
2
X
T
y
+
2
X
T
X
w
=
0
X
T
X
w
=
X
T
y
(
X
T
X
)
−
1
X
T
X
w
=
(
X
T
X
)
−
1
X
T
y
w
=
(
X
T
X
)
−
1
X
T
y
\begin{aligned} -2X^Ty+2X^TXw&=0 \\ X^TXw&=X^Ty \\ (X^TX)^{-1}X^TXw&=(X^TX)^{-1}X^Ty \\ w&=(X^TX)^{-1}X^Ty \end{aligned}
−2XTy+2XTXwXTXw(XTX)−1XTXww=0=XTy=(XTX)−1XTy=(XTX)−1XTy
到这里
w
w
w就是我们苦苦寻求的值了,而其中
(
X
T
X
)
−
1
(X^TX)^{-1}
(XTX)−1是
X
T
X
)
X^TX)
XTX)的逆矩阵。
不可逆的情况
这里再给出两种不可逆的情况
- 线性相关特征(多重共线性)
- x1为房屋面积,单位是平方英尺
- x2为房屋面积,单位是平方米
- 特征数据太多(样本数m ≤ \le ≤特征数量n)
梯度下降和标准方程的比较
梯度下降法 | 标准方程法 | |
---|---|---|
优点 | 当特征值非常多的时候也可以很好的工作 | 不需要学习率 不需要迭代 可以得到全局最优解 |
缺点 | 需要选择合适的学习率 需要迭代很多个周期 最能得到最优解的近似值 | 需要计算
(
X
T
X
)
−
1
(X^TX)^{-1}
(XTX)−1 时间复杂度大约是 O ( n 3 ) O(n^3) O(n3) n是特征数量 |
代码实现
import numpy as np
from numpy import genfromtxt
import matplotlib.pyplot as plt
# 载入数据
data = np.genfromtxt("data.csv", delimiter=",")
x_data = data[:,0,np.newaxis]
y_data = data[:,1,np.newaxis]
plt.scatter(x_data,y_data)
plt.show()
print(np.mat(x_data).shape)
print(np.mat(y_data).shape)
# 给样本添加偏置项
X_data = np.concatenate((np.ones((100,1)),x_data),axis=1)
print(X_data.shape)
# 标准方程法求解回归参数
def weights(xArr, yArr):
xMat = np.mat(xArr)
yMat = np.mat(yArr)
xTx = xMat.T*xMat # 矩阵乘法
# 计算矩阵的值,如果值为0,说明该矩阵没有逆矩阵
if np.linalg.det(xTx) == 0.0:
print("This matrix cannot do inverse")
return
# xTx.I为xTx的逆矩阵
ws = xTx.I*xMat.T*yMat
return ws
#使用numpy本身函数求解
#相关函数可以点击链接查看
#https://www.numpy.org.cn/article/basics/numpy_matrices_vectors.html#%E7%94%A8numpy%E6%B1%82%E8%A7%A3%E6%96%B9%E7%A8%8B%E7%BB%84
def numpy_weights(xArr, yArr):
xMat = np.mat(xArr)
yMat = np.mat(yArr)
xT = np.transpose(xMat)#转置矩阵
xTx = np.dot(xT, xMat)#矩阵乘
if np.linalg.det(xTx) == 0.0:
print("This matrix cannot do inverse")
return
xTy = np.dot(xT, yMat)
ws = np.linalg.solve(xTx,xTy)
return ws
#调用函数
ws = weights(X_data,y_data)
ws1 = numpy_weights(X_data,y_data)
print(ws)
print(ws1)
# 画图
x_test = np.array([[20],[80]])
y_test = ws[0] + x_test*ws[1]
plt.plot(x_data, y_data, 'b.')
plt.plot(x_test, y_test, 'r')
plt.show()