线性回归——梯度下降


前言

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


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

梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(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评价模型

在这里插入图片描述

代码如下(示例):

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()

三、实验过程

第一次实验

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

第二次实验

对原因1改进,将阈值设置为2
运行实现
在这里插入图片描述
在这里插入图片描述

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

第三次实验

对原因1改进,将阈值设置为1.5, 步长设置为0.0002
运行实现:
在这里插入图片描述
在这里插入图片描述

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


总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值