【刘二大人】pytorch深度学习实践(三):如何实现线性模型的反向传播+代码实现详解(Tensor、backward函数)

参考资料

一、反向传播流程

1.1 问题

求loss函数对于w和x的偏导。

1.2 方法

基于导数的链式法则,依次求导。
在这里插入图片描述

1.3 步骤

  1. 首先根据前向传播,可以得到 x = 2 , w = 3 , z = f ( x , w ) = x ∗ w = 6 , x =2 ,w = 3, z= f(x,w) = x*w = 6, x=2,w=3,z=f(x,w)=xw=6, 那么就可以求得z关于w和z的导数: ∂ z ∂ w = x = 2 , ∂ z ∂ x = w = 3 \frac{\partial z}{\partial w} =x=2,\frac{\partial z}{\partial x} =w=3 wz=x=2,xz=w=3
  2. 继续前向传播, l o s s = ( y − y p r e d ) 2 loss = (y-y_{pred})^2 loss=(yypred)2,直到计算出loss函数
  3. 根据反向传播,程序可以计算出 ∂ L o s s ∂ z = 5 \frac{\partial Loss}{\partial z} =5 zLoss=5
  4. 根据链式法则,我们知道 ∂ L o s s ∂ w = ∂ L o s s ∂ z ∗ ∂ z ∂ w \frac{\partial Loss}{\partial w}=\frac{\partial Loss}{\partial z}*\frac{\partial z}{\partial w} wLoss=zLosswz, 而我们已经计算出 ∂ z ∂ w = x = 2 \frac{\partial z}{\partial w} =x=2 wz=x=2,所以 ∂ L o s s ∂ w = 2 ∗ 5 = 10 \frac{\partial Loss}{\partial w}=2*5=10 wLoss=25=10,同理可以计算出 ∂ L o s s ∂ x = 3 ∗ 5 = 15 \frac{\partial Loss}{\partial x}=3*5=15 xLoss=35=15
  5. 由此我们便完成了 ∂ z ∂ w , ∂ z ∂ x \frac{\partial z}{\partial w},\frac{\partial z}{\partial x} wz,xz的计算。
    在这里插入图片描述

1.4 例题

求loss函数关于w的偏导数
在这里插入图片描述

前向传播求出局部梯度,再反向传播求得最终梯度

二、Pytorch中前向传播和反馈的计算

2.1 tensor数据类型

pytorch官方文档 - tensor

Tensor中有两个重要的数据变量

  • data:该节点的数据值,为Tensor类
  • grad:该节点的梯度值,为Tensor类
    在这里插入图片描述

对w使用Tensor数据类型进行定义:设置requires_grad = True表明在计算过程中需要保留该值的梯度;

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

2.2 定义线性模型并且计算损失

y ′ = w ∗ x y' =w*x y=wx

l o s s = ( y ′ − y ) 2 = ( x ∗ w − y ) 2 loss = (y'-y)^2 =(x*w-y)^2 loss=(yy)2=(xwy)2

这段代码是在构建如下的计算图,前向传播并且求出loss值
在这里插入图片描述

此处的 l l l是一个张量(因为w是一个张量),所以后续需要 l l l的值时要使用 l . i t e m ( ) l.item() l.item()的方法进行取值

2.2.1 torch.tensor.item()

item()是将一个张量的值以一个python数字形式返回;
在这里插入图片描述
使用item()将Tensor张量转换为数字

在这里插入图片描述

2.2.2 代码

def forward(x):
    return x*w

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

2.3 反向传播

2.3.1 torch.tensor.backward()

该函数计算当前张量相对于计算图中所有叶子节点的梯度
在这里插入图片描述

2.3.2 tensor.zero_( )

把Tensor的数值清零。
在这里插入图片描述

2.3.3 代码实现

  1. 使用for循环设置训练10个epoch
  2. 使用loss函数构建计算图,计算损失值
  3. 调用backward函数计算计算图上叶子节点的梯度值
  4. 根据w的梯度值更新w( w − = w ∗ 学习率 w-=w*学习率 w=w学习率
  5. 清空w的梯度,准备下一轮计算
print("predicted(before training)",4,forward(4).item())
# 训练10个epoch
for epoch in range(10):
    for x,y in zip(x_data,y_data):
    # 计算损失值
        l = loss(x,y)
        # 反向传播
        l.backward()
        print("\tgrad:",x,y,w.grad.item())
        # 更新w
        w.data=w.data-0.01*w.grad
# 清空w的梯度
        w.grad.zero_()
    print("progress:",epoch,l.item())
print("predict(after training)",4,forward(4).item())

三、代码实现

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

def forward(x):
    return x*w

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

print("predicted(before training)",4,forward(4).item())

for epoch in range(10):
    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

        w.grad.zero_()
    print("progress:",epoch,l.item())
print("predict(after training)",4,forward(4).item())


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45662399/article/details/134079224