数学原理
在下面的公式中,我们规定 x x x 是样本特征值(单特征), y y y 是样本标签值, z z z 是预测值,下标 i i i 表示其中一个样本。
预设函数(Hypothesis Function)
为一个线性函数:
z i = x i ⋅ w + b z_i=x_i⋅w+b zi=xi⋅w+b (1)
损失函数(Loss Function)
为均方差函数:
l o s s ( w , b ) = 1 2 ( z i − y i ) 2 loss(w,b)={1 \over 2}(z_i−y_i)^2 loss(w,b)=21(zi−yi)2 (2)
与最小二乘法比较可以看到,梯度下降法和最小二乘法的模型及损失函数是相同的,都是一个线性模型加均方差损失函数,模型用于拟合,损失函数用于评估效果。
区别在于,最小二乘法从损失函数求导,直接求得数学解析解,而梯度下降以及后面的神经网络,都是利用导数传递误差,再通过迭代方式一步一步(用近似解)逼近真实解。
梯度计算
计算 z z z 的梯度
根据公式 2:
∂ l o s s ∂ z i = z i − y i {∂loss \over ∂zi}=z_i−y_i ∂zi∂loss=zi−yi (3)
计算 w w w 的梯度
我们用loss的值作为误差衡量标准,通过求w对它的影响,也就是loss对w的偏导数,来得到w的梯度。由于loss是通过公式2->公式1间接地联系到w的,所以我们使用链式求导法则,通过单个样本来求导。
根据公式1和公式3:
∂ l o s s ∂ w = ∂ l o s s ∂ z i ∂ z i ∂ w = ( z i − y i ) x i {∂loss \over ∂w}={∂loss \over ∂zi} {∂zi \over ∂w}=(z_i−y_i)x_i ∂w∂loss=∂zi∂loss∂w∂zi=(zi−yi)xi (4)
计算 b b b 的梯度
∂ l o s s ∂ b = ∂ l o s s ∂ z i ∂ z i ∂ b = z i − y i {∂loss \over ∂b}={∂loss \over ∂z_i}{∂z_i \over ∂b}=z_i−y_i ∂b∂loss=∂zi∂loss∂b∂zi=zi−yi (5)
代码实现
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 13 23:01:28 2020
@author: lujia
"""
import numpy as np
import matplotlib.pyplot as plt
def GetWholeTrainSamples():
data = np.load('ch04.npz')
X = data['data']
Y = data['label']
num_train = X.shape[0] # 获取数据行数
return X,Y,num_train
def linear_equation(x,w,b):
return x * w + b
trainX,trainY,trainNum = GetWholeTrainSamples()
eta = 0.1
w, b = 0.0, 0.0
for i in range(trainNum):
# get x and y value for one sample
xi = trainX[i]
yi = trainY[i]
# 公式1
zi = xi * w + b
# 公式3
dz = zi - yi
# 公式4
dw = dz * xi
# 公式5
db = dz
# update w,b
w = w - eta * dw
b = b - eta * db
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制散点图
ax.scatter(trainX,trainY)
# 绘制线性回归
x = np.arange(0, 1, 0.01)
fun = np.vectorize(linear_equation, excluded=['x'])
plt.plot(x,fun(x,w,b),color='red')
#显示图表
plt.show()
print("w=", w)
print("b=", b)