本文使用随机梯度下降,进行线性回归参数估计,多项式回归请参考多项式回归——梯度下降
梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。
代码如下(示例):
import numpy as np
import matplotlib.pyplot as plt
代码如下(示例):
# 建立训练集和测试集
data = [5.1, 8.2, 11.5, 13.9, 15.1, 16.2]
target = [2.14, 4.62, 8.24, 11.24, 13.99, 16.33]
test = [19.6, 23.3]
test_target = [19.23, 28.74]
该处使用的自定义数据集。
代码如下(示例):
# 使用曲线y = wx +b 拟合
w = 0 # 权重设置为0
b = 0 # 截距设置为0
esum = 100 # 训练集样本误差之和,初始值100
n = 1 # 训练次数
代码如下(示例):
# 计算最优权重
while(abs(esum)>1.5): # 当训练集误差之和的绝对值小于1.5时跳出循环
i = np.random.randint(0,5)
e = (data[i]*w+b)-target[i] # 计算误差
w= w - e*data[i]*0.0002 # 随机下降梯度步长设置为0.0002
b = b-e*0.0002
for i in range(len(data)): # 计算样本误差之和
esum = w*data[i] +b - target[i]
# if n%100 == 0: # 结果呈现
# print("第{:}次".format(n))
# print("此时训练集误差之和为:%.2f"%esum)
n+=1
代码如下(示例):
err = []
scount = []
err_train = []
scount_train=[]
# 计算训练样本误差
for i in range(len(data)):
e = (data[i]*data[i]*w1 + data[i]*w2 +b1)-target[i]
p = e/target[i]
err_train.append(e)
scount_train.append(p)
# 计算测试样本误差
for i in range(len(test)):
e = (test[i]*test[i]*w1 + test[i]*w2 +b1)-test_target[i] # 计算误差量
p = e/test_target[i] # 计算误差率
err.append(e)
scount.append(p)
代码如下(示例):
sst = 0
sse = 0
sum =0
# 求target平均值
for i in range(len(test_target)):
sum += test_target[i]
avg = sum/len(test_target)
# 评价模型
for i in range(len(test_target)):
sst += (test_target[i] - avg)**2
sse += (w*test[i] +b - test_target[i])**2
代码如下(示例):
# 结果输出
print("随机梯度下降:线性回归")
print(w, b) # 输出参数
print("测试集评价模型{}".format(1-sse/sst))
print('训练结束,共运行{}次,最后一次训练集总误差{}'.format(n, esum))
print('训练集样本误差和误差百分比:', end='')
print( err_train, scount_train)
print('测试集样本误差和误差百分比:', end='')
print( err, scount)
# 图像显示
x = data + test
x = np.reshape(x, newshape=(len(x), 1))
y = target + test_target
y = np.reshape(y, newshape=(len(y), 1))
plt.scatter(x, y)
plt.plot(x, w*x+b)
plt.show()
运行实现
结果分析:
没有跑出最佳结果。在循环0~150000次时训练集总误差下降明显,在150000次之后基本上在2.0上下浮动,出现此状况可能的原因有两个:1、训练结束的条件——训练集总误差的阈值选取有问题,本次程序代码中的训练集总误差阈值设置为1。2、评判模型有问题,我采用的是将目前得到的w,b带入到回归直线中计算。
结果分析:证明我们第一次选取的阈值并不合理。该回归线对于测试集的最后一个点的拟合效果并不好,但由于测试集样本太少,也并不能说明此次拟合的直线并不好,通过计算训练样本误差之和小于2
对原因1改进,将阈值设置为1.5, 步长设置为0.0002
运行实现:
结果分析:采用更小阈值和更大的步长,发现当步长增大时,训练集样本的总误差更小,所以在阈值设为2时陷入了局部最优解。
以上主要是进行了梯度下降的实现,具体的最优步长,阈值选择仍需要继续研究。