本篇是一个练手项目,目的在于:
1. 熟悉 pytorch
2. 实现 SGD 与 动量梯度下降,并对比收敛性
本教程环境 pytorch 1.3以上
手动实现线性回归模型,一个很简单的模型,不多介绍,直接上代码
import torch as t import matplotlib.pylab as plt ### 制造数据 def make_data(): # y = 2x+3 x = t.rand(1, 10) * 20 y = x * 2 + 3 + t.randn(1, 10) return x, y ### 初始化参数 t.manual_seed(10000) ### 随机种子 w = t.rand(1, 1) b = t.rand(1, 1) ### 动量梯度的初始值 w0 = 0 b0 = 0 lr = 0.001 loss_record = [] for i in range(10000): x_t, y_t = make_data() y_p = t.matmul(w, x_t) + b loss = t.pow(y_p - y_t, 2) * 0.5 loss = t.mean(loss) ### 可 sum 可 mean,一般和 下面的 grad_b 对应 loss_record.append(loss) ### 手动求导,计算梯度 ## 注意这里对 (yp-yt)^2 求导,是 (yp-yt)x,如果是对 (yt-yp)^2 求导,是 -(yt-yp)x grad_w = t.matmul(y_p - y_t, x_t.t()) ### t() 转置 grad_b = t.mean(y_p - y_t) ### SGD 参数更新 # w -= lr * grad_w # b -= lr * grad_b ### 动量梯度下降的参数更新,收敛效果比 SGD 好很多 grad_w_new = 0.8 * w0 + grad_w w.sub_(lr * grad_w) w0 = grad_w ### 记住本次梯度,作为下次的 w0,这里只是记了上次,可以自己设定计前几次,或者计之前全部 grad_b_new = 0.8 * b0 + grad_b b.sub_(lr * grad_b_new) b0 = grad_b print(w, b) plt.plot(loss_record) plt.show()
下面我把学习率变得很低,并且把 动量梯度下降中 的只记录上次 梯度改为 记录之前全部梯度
lr = 0.0000001 grad_w = 0.9 * w0 + grad_w w.sub_(lr * grad_w) w0 = grad_w ### 计之前全部 grad_b = 0.9 * b0 + grad_b b.sub_(lr * grad_b) b0 = grad_b
其他不变,对比下 SGD 与动量梯度的收敛性
左边 SGD, 右边 动量梯度下降
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)