反向传播梯度下降
1、在比较简单线性模型函数(y=wx+b),根据损失函数(loss=y_pred-y)**2)来写梯度下降算法是比较容易直接处理。
2、但在一些复杂的模型(如下图)包含复杂的函数模型、多层、多参数,直接手动计算梯度就困难了。这时候就需要一个非常方便的反向传播梯度下降算法。
3、使用反向传播梯度下降算法,就可以很方便直接对多个需要更新迭代的权重参数函数进行求对应的梯度,进而更新权重参数,实现梯度下降的效果。
例如,在前向传播中求损失值,需要不断更新权重值来是的损失值不断减少,(如下的y=wx+b,loss=(x*w + b - y)^2 )可以执行 loss.backward() 函数,自动计算各变量在各阶段的梯度(即若设置叶子x,w,b的require_grad的属性都为True),则x,w,b的梯度都会求得,并保存到各自的grad中。
4、实现的代码:
# 对应 y = wx + b 也同理可以求权重 w 、b
import torch
x_data = [1.0, 2.0, 3.0]
y_data = [2.5, 4.5, 6.5]
# 可随机设置权重 w、b
w = torch.Tensor([1000.0])
b = torch.Tensor([50.1])
w.requires_grad = True # 需要求梯度(默认不求)
b.requires_grad = True # 需要求梯度(默认不求)
# 定义一个模型函数
def forward(x):
return x * w + b
# 定义损失函数
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training)", forward(4).item())
# 训练过程(进行100次梯度更新迭代,迭代次数越大,训练结果越好)
for epoch in range(1000):
for x, y in zip(x_data, y_data):
loss_val = loss(x, y)
loss_val.backward() # loss_val.backward()会把loss_val计算链路上的所有需要梯度都会计算出来,把梯度存在对应本身(例如w梯度会存到w上)
print('\t grad:', x, y, w.grad.item(), b.grad.item())
w.data = w.data - 0.01 * w.grad.data # w.grad是一个张量,需通过(.data)得到标量,再进行权重更新
b.data = b.data - 0.01 * b.grad.data
w.grad.data.zero_() # 将权重里面的梯度进行清0,否则本次梯度会保存到下一次的求到梯度,进而梯度相加。(但有时候也需要保留梯度)
b.grad.data.zero_()
print("process: ", epoch, loss_val.item())
# w、b都经过100次的迭代更新,所以100后的预测值为:
print("predict (after training)", forward(4).item())
运行效果: