Pytorch深度学习实践(3)反向传播

反向传播

反向传播是在神经网络中一种非常重要的算法

由于在实际的神经网络中,层数较多,梯度计算比较复杂,不可能每一步都要推出来梯度的公式,此时就要利用链式法则,通过反向传播,来计算梯度,更新参数

以两层神经网络为例,其最终的输出就是
y^=W2(W1X+b1)+b2 \hat y = W_2(W_1X + b_1) + b_2 y^=W2(W1X+b1)+b2
其计算图如下所示:
在这里插入图片描述

激活函数

对于线性模型,无论其增加多少层,最终都能化简为线性模型,即对于线性模型而言,增加层数对模型没有意义

以两层线性模型而言,
y^=W2(W1X+b1)+b2=W2W1X+(W2b1+b2)=WX+b \hat y = W_2(W_1X +b_1) + b_2 = W_2W_1X+(W_2b_1 + b_2) =WX + b y^=W2(W1X+b1)+b2=W2W1X+(W2b1+b2)=WX+b
因此,为了解决此问题,我们要在每一层的输出中添加一个非线性变化函数,即激活函数,对输出中张量的每一个值都非线性化,使得模型更加准确

在这里插入图片描述

反向传播过程

首先生成计算图

在这里插入图片描述

然后进行前馈计算 Forward,即沿着计算图边的方向进行计算,由输入求得losslossloss

同时在运算的过程中还要计算输出zzz关于xxxwww的导数,即∂z∂x\frac{\partial z}{\partial x }xz∂z∂w\frac{\partial z}{\partial w}wz
在这里插入图片描述

{再由损失losslossloss往回算,进行反向传播,计算∂L∂z\frac{\partial L}{\partial z}zL,通过链式法则,计算出梯度,即$\frac{\partial L}{\partial x} = \frac{\partial L}{\partial z}\frac{\partial z}{\partial x} 和和\frac{\partial L}{\partial w} = \frac{\partial L}{\partial z}\frac{\partial z}{\partial w} $

在这里插入图片描述

最后再通过梯度进行参数更新

以线性模型为例,整体流程如下图所示

在这里插入图片描述

Pytorch中使用前馈和反向传播

张量

Pytorch中,常用tensor保存这种数值

tensor是一个类,通常保存两种类型的数:

  • data
  • grad
import torch  # 导入Pytorch

## 数据准备
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   # 标明需要计算梯度

其中:

  • torch.tensor()用法和np.array()用法一致
  • 要显示标明需要计算梯度,即w.requires_grad = True
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()) # .item()将tensor转化为标量 即拿出具体数值
        w.data = w.data - 0.01*w.grad.data  # 具体计算时要使用.data

        w.grad.zero_()  # 梯度清零 !!!

    print("progress:", epoch, l.item())
    cost_history.append(l.item())

print("predict (after training)", 4, forward(4).item())

注意:

  • 每一步更新梯度时,要使用.data来更新,这样不会影响计算图的改变
  • .item().data有区别
    • .item()是把tensor类型中的数值拿出来,最终是一个标量数值
    • .data返回的仍然是tensor类型,使用,data进行运算时,不会构建相应的计算图

作业

在这里插入图片描述

import torch

x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]

w1 = torch.tensor([1.0])
w1.requires_grad = True
w2 = torch.tensor([1.0])
w2.requires_grad = True
b = torch.tensor([1.0])
b.requires_grad = True

def forward(x):
    return w1*x**2 + w2*x + b
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, w1.grad.item(), w2.grad.item(), b.grad.item())
        w1.data = w1.data - 0.01 * w1.grad.data
        w2.data = w2.data - 0.01 * w2.grad.data
        b.data = b.data - 0.01 * b.grad.data
        w1.grad.data.zero_()
        w2.grad.data.zero_()
        b.grad.data.zero_()
    print("progress", epoch, l.item())

print("predict (before training)", 4, forward(4).item())
print("w1=",w1.item(), "\tw2=", w2.item(), "\tb=",b.item())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值