计算图与反向传播
- 本节主要需要理解计算图和基于链式法则的反向传播。
- 由于pytorch是基于动态计算图做梯度反向传播,因此理解了计算图的构建和反向传播,就已经入门pytorch了。
- 本小节针对反向传播的例子过于简单,没有加入激活函数的计算图是不完整的。实际上如果再能理解加入卷积层后的计算图,那就完美了。
- 本小结的计算图和反向传播例子如图:
使用pytorch实现自动梯度和反向传播
关键代码必知必会
- w = torch.Tensor([1.0],w.requires_grad = True),首先要知道pytorch的张量可以同时存储数值和梯度,而梯度默认是不计算的,等于True表示该节点需要计算梯度。需要计算梯度,那么后续使用到该张量w时,就会自动的构建计算图,比如forward,loss。
- l.backward(),前面计算loss的时候,计算图已经被构建完毕,调用backward(),会自动的沿着构建好的计算图进行梯度反向传播,也就是会把所有要求梯度的张量计算出来,并把该梯度值存储到该张量的属性grad当中。
- w.grad.data.zero_(),一次梯度更新后,要把该节点的梯度值清零,防止梯度累加。如下如所示:
本小结代码
import torch
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0])
w.requires_grad = True #默认是不计算的,等于True表示w是需要计算梯度的
#定义模型
def forward(x):
return x * w #x会自动进行类型转换,成tensor
#定义损失函数
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training)", 4, forward(4).item())
for epoch in range(100):
for x, y in zip(x_data, y_data):
l = loss(x, y)#前向传播,计算损失
l.backward()#向后传播,计算梯度
print('\tgrad:', x, y, w.grad.item())
w.data = w.data - 0.01 * w.grad.data #注意进行权重更新的时候不能使用tensor,否则会在这里又构建一次计算图
# backward()计算的梯度会累加,注意把梯度清零。为什么不默认清零?因为有些算法可能需要保留前一步的梯度
# 利用前一步节点的梯度做累加或累乘
w.grad.data.zero_()
print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())