反向传播

使用反向传播的原因:

利用梯度下降来找到最优的权重,需要计算梯度,而计算每个中间结果的梯度又想当繁琐,所以利用反向传播的方式来取得最终值对于权重的梯度。

反向传播过程:

前向计算每个中间结果节点的梯度,前向传播生成计算图,然后利用链式法则,反向将最终结果关于权重的梯度表示出来。

代码来源:https://blog.csdn.net/qq_39804263/article/details/139685123?fromshare=blogdetail&sharetype=blogdetail&sharerId=139685123&sharerefer=PC&sharesource=m0_63829662&sharefrom=from_link

仅添加部分注释

代码如下:

# 如果是复杂的网络,没办法都自己写gradient的计算。
import torch
import matplotlib.pyplot as plt

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

def forward(x, w):
    return x * w

def loss(x, y, w):
    y_pred = forward(x, w)
    loss = (y - y_pred) ** 2
    return loss

print('predict (before training)', 4, forward(4, w.item()))

epoch_list = []
loss_list = []

for epoch in range(100):
    for x, y in zip(x_data, y_data):
        l = loss(x, y, w)
        l.backward()
        print('\tgrad:', x, y, w.grad.item())
        w.data = w.data - 0.01 * w.grad.data  #w.grad是张量tensor,w.grad.data是标量
        w.grad.data.zero_()  # 对梯度进行清零,否则梯度会进行累加
    print('process:', epoch, l.item())
    epoch_list.append(epoch)
    loss_list.append(l.item())

print('predict (after training)', 4, forward(4, w))

plt.plot(epoch_list, loss_list)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

【注意点】

(1)w.grad是张量,而w.grad.data是标量。张量w包含data和grad的,grad也是一个张量,grad.data才是它的标量值。

(2)每一个样本进行权重更新时,最后都需要将梯度值清零,利用w.grad.data.zero_(),不然,梯度值会累加到下一个样本梯度值中。

运行结果:

更多推荐