文章目录

  • 前言
  • 一、随机梯度下降是什么?
  • 二、代码实现
  • 1.引入库
  • 2.建立训练集和测试集
  • 3.线性回归实现
  • 3.1初始参数
  • 3.2计算最优参数
  • 3.3计算训练集和测试集误差
  • 3.4评价模型
  • 3.4输出结果并显示图像
  • 三、实验过程
  • 第一次实验
  • 第二次实验
  • 第三次实验
  • 总结



前言

本文使用随机梯度下降,进行线性回归参数估计,多项式回归请参考多项式回归——梯度下降


一、随机梯度下降是什么?

梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。

二、代码实现

1.引入库

代码如下(示例):

import numpy as np
import matplotlib.pyplot as plt

2.建立训练集和测试集

代码如下(示例):

# 建立训练集和测试集
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]

该处使用的自定义数据集。

3.线性回归实现

3.1初始参数

代码如下(示例):

# 使用曲线y = wx +b 拟合
w = 0  # 权重设置为0
b = 0  # 截距设置为0
esum = 100  # 训练集样本误差之和,初始值100
n = 1 # 训练次数

3.2计算最优参数

代码如下(示例):

# 计算最优权重
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

3.3计算训练集和测试集误差

代码如下(示例):

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)

3.4评价模型

L1回归和梯度下降 线性回归梯度下降_L1回归和梯度下降

代码如下(示例):

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

3.4输出结果并显示图像

代码如下(示例):

# 结果输出
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()

三、实验过程

第一次实验

运行实现

L1回归和梯度下降 线性回归梯度下降_线性回归_02


结果分析:

没有跑出最佳结果。在循环0~150000次时训练集总误差下降明显,在150000次之后基本上在2.0上下浮动,出现此状况可能的原因有两个:1、训练结束的条件——训练集总误差的阈值选取有问题,本次程序代码中的训练集总误差阈值设置为1。2、评判模型有问题,我采用的是将目前得到的w,b带入到回归直线中计算。

第二次实验

对原因1改进,将阈值设置为2

运行实现

L1回归和梯度下降 线性回归梯度下降_线性回归_03


L1回归和梯度下降 线性回归梯度下降_机器学习_04

结果分析:证明我们第一次选取的阈值并不合理。该回归线对于测试集的最后一个点的拟合效果并不好,但由于测试集样本太少,也并不能说明此次拟合的直线并不好,通过计算训练样本误差之和小于2

第三次实验

对原因1改进,将阈值设置为1.5, 步长设置为0.0002

运行实现:

L1回归和梯度下降 线性回归梯度下降_机器学习_05


L1回归和梯度下降 线性回归梯度下降_L1回归和梯度下降_06

结果分析:采用更小阈值和更大的步长,发现当步长增大时,训练集样本的总误差更小,所以在阈值设为2时陷入了局部最优解。


总结

以上主要是进行了梯度下降的实现,具体的最优步长,阈值选择仍需要继续研究。