梯度下降法求解线性回归
import numpy as np
x ⃗ ∈ R m × 1 \vec x \in R^{m \times 1} x∈Rm×1是用来训练的一个数据点
X ∈ R m × n X \in R^{m \times n} X∈Rm×n是所有数据点组成的数据集,也就是训练集
Y ∈ R n × 1 Y \in R^{n \times 1} Y∈Rn×1是训练集的标签
X = 2*np.random.rand(2, 50) #创建一个2*50矩阵
Y = np.random.uniform(10, 11, (50, 1)) #创建一个50*1矩阵,值在10到11随机选取
ω ⃗ ∈ R m × 1 \vec \omega \in R^{m \times 1} ω∈Rm×1是权重矩阵
b b b是偏置量
k k k是训练步长
w = np.random.rand(2, 1) #初始化权重矩阵,创建一个2*1矩阵,值为随机值
b = 1.3 #偏置量随便取一个值
k = 0.001
在线性回归中,定义:
输出值: y ^ : = ω ⃗ ⋅ x ⃗ + b \hat y := \vec \omega \cdot \vec x + b y^:=ω⋅x+b
损失函数: l o s s ( y , y ^ ) : = 1 2 ( y − y ^ ) 2 loss(y,\hat y) := \frac{1}{2}(y - \hat y)^2 loss(y,y^):=21(y−y^)2
成本函数: c o s t ( ω ⃗ , b ) : = ∑ i = 1 N l o s s ( y i , y ^ i ) cost(\vec\omega,b) := \sum_{i=1}^N loss(y_i, \hat y_i) cost(ω,b):=∑i=1Nloss(yi,y^i)
其中 y ^ \hat y y^和 c o s t cost cost的向量化表示是:
Y ^ : = ω ⃗ T × X + b ⃗ \hat Y := \vec\omega^T \times X + \vec b Y^:=ωT×X+b
c o s t ( ω ⃗ , b ) = 1 2 ( Y ^ T − Y ) 2 cost(\vec \omega,b) = \frac{1}{2}(\hat Y^T- Y)^2 cost(ω,b)=21(Y^T−Y)2
更新权重 ω ⃗ \vec \omega ω是:
ω ⃗ ← ω ⃗ − k ∇ ω ⃗ c o s t ( ω ⃗ , b ) \vec \omega \leftarrow \vec \omega - k\nabla _{\vec \omega} cost(\vec\omega,b) ω←ω−k∇ωcost(ω,b)
更新权重 b b b是:
b ← b − k ∂ ∂ b c o s t ( ω ⃗ , b ) b \leftarrow b - k\frac{\partial}{\partial b} cost(\vec\omega,b) b←b−k∂b∂cost(ω,b)
可以证明(证明过程就是:
1、先把梯度运算符展开,写成求和号的形式
2、用复合导数的公式化简
3、再把求和号写成向量化的形式):
∇ ω ⃗ c o s t ( ω ⃗ , b ) = X × ( Y ^ T − Y ) \nabla _{\vec \omega} cost(\vec\omega,b) = X \times (\hat Y^T - Y) ∇ωcost(ω,b)=X×(Y^T−Y)
∂ ∂ b c o s t ( ω ⃗ , b ) = ( Y ^ T − Y ) . s u m ( ) \frac{\partial}{\partial b} cost(\vec\omega,b) = (\hat Y^T - Y).sum() ∂b∂cost(ω,b)=(Y^T−Y).sum()
#做1000步梯度下降
for i in range(1000):
Y_hat = np.dot(w.T, X)+b #Y_hat: 1*50
grad = [np.dot(X, Y_hat.T - Y), (Y_hat.T - Y).sum()] #计算梯度
w -= k*grad[0] #更新权重
b -= k*grad[1] #更新偏置量
cost = 0.5*((Y_hat.T - Y)**2).sum() #误差
print("cost=", cost)
前10步cost函数递减如下:
cost= 1662.1840712832482
cost= 1198.9548401813956
cost= 879.8028186217688
cost= 659.7337015686602
cost= 507.8066005945032
cost= 402.7446103448193
cost= 329.91636760244586
cost= 279.26038807913466
cost= 243.85771439696683
cost= 218.9503821949377
import matplotlib.pyplot as plt
#画训练数据
ax = plt.axes(projection = '3d')
ax.set_zlim(5, 15) #设置Z轴的范围
ax.scatter(X[0], X[1], Y)
#画拟合好的平面
X1 = np.linspace(0,2,100)
Y1 = np.linspace(0,2,100)
X1, Y1 = np.meshgrid(X1, Y1)
Z = X1*w[0] + Y1*w[1] + b
ax.plot_surface(X1, Y1, Z,cmap='viridis')
plt.show()
贴个运行结果:
跑100步后的拟合结果:
跑1000步后的拟合结果: