代码引用自:
https://blog.csdn.net/weixin_39228381/article/details/108310520
import torch
def test_sgd():
# 定义一个可学习参数w,初值是100
w = torch.tensor(data=[[[100, 100, 100, 100, 100],
[100, 100, 100, 100, 100]],
[[100, 100, 100, 100, 100],
[100, 100, 100, 100, 100]],
[[100, 100, 100, 100, 100],
[100, 100, 100, 100, 100]]], dtype=torch.float32, requires_grad=True)
# 定义SGD优化器,nesterov=False,其余参数都有效
optimizer = torch.optim.SGD(params=[w], lr=0.1, momentum=0.9, dampening=0.5, weight_decay=0.01, nesterov=False)
# 进行5次优化
gradient = torch.ones_like(w)
for i in range(5):
y = w ** 2 # 优化的目标是让w的平方,即y尽可能小
optimizer.zero_grad() # 让w的偏导数置零
y.backward(gradient) # 反向传播,计算w的偏导数
optimizer.step() # 根据上述两个公式,计算一个v,然后作用到w
# print('grad=%.2f, w=%.2f' % (w.grad, w.data)) # 查看w的梯度和更新后的值
res = [x.grad for x in optimizer.param_groups[0]['params']]
print(res)
test_sgd()
'''
输入日志如下:
grad=201.00000, w=79.90000
grad=160.59900, w=53.78005
grad=108.09791, w=24.86720
grad=49.98307, w=-3.65352
grad=-7.34357, w=-28.95499
'''
梯度下降和随机梯度下降的代码详解参考自:
http://sofasofa.io/tutorials/python_gradient_descent/4.php
对于SGD的随机性,我的理解是这样的:
假设有是个样本(1,1),(2,2),…,(10,10),我要用线性回归y=wx+b和最小二乘法MSE去学习w和b。
那么在传统的梯度下降方法中,由于MSE计算损失会用到所有的样本,那么计算w梯度时也会用到所有的样本,因此当数据量很大时,速度会很慢;
在随机梯度下降中,会随机选择一个样本来计算w的梯度,这样时间复杂度瞬间就从O(n)降低为O(1),速度大大提高。