Pytorch(5)-梯度反向传播
自动求梯度
- 1. 函数对自变量x求梯度--ax^2+b
- 2. 网络对参数w求梯度- loss(w,x)
- 3. 自动求梯度的底层支持--torch.autograd
- 3.1 Variable
- 3.1.1 Variable构造函数
- 3.1.2 Variable链式求导--backward()
- 3.1.3 Variable反向传播函数--grad_fn
- 3.2 计算图
- 3.2.1 动态创建计算图
- 3.2.2 非叶子节点的梯度--autograd.grad 与 hook
- 3.3 复杂自建函数,自动求导支持
1. 函数对自变量x求梯度–ax^2+b
torch提供了简便的求梯度方法:带入变量值x,求解目标函数f(x),将目标函数的值反向传播f.backward(),就能计算对应变量的导数。
- 以二次函数为例:f(x)=ax2+bf(x)=ax^2+bf(x)=ax2+b
- 其中a,b是已知的参数,对x 求导:f′(x)=2axf'(x)=2axf′(x)=2ax
- 当a=1,x=1时a=1,x=1时a=1,x=1时:f′(x)=2f'(x)=2f′(x)=2
import torch
from torch.autograd import Variable
def f(x):return x**2
x1 = Variable(torch.Tensor([1]),requires_grad=True) # 使用variable封装待求导的参数
print("初始化", x1.grad)y=f(x1)
y.backward()
print("一次传播", x1.grad)x1.grad.data.zero_()
print("梯度置零", x1.grad)y=f(x1)
y.backward()
y=f(x1) # #如果x1.grad 每次计算前梯度不归零,那么当前的梯度会与原来的梯度累加
y.backward() # #每次loss 反向传播前需要将梯度设置为0
print("二次传播", x1.grad)
输出
初始化 None
一次传播 tensor([2.])
梯度置零 tensor([0.])
二次传播 tensor([4.])
2. 网络对参数w求梯度- loss(w,x)
神经网络训练:通过调整神经网络参数使网络输出尽可能接近于想要的对象。具体通过损失函数的梯度下降实现的,即损失函数对网络参数求梯度,利用该梯度调整网络参数。
模型的损失函数实际是输入x 和模型参数w 的函数:loss(w,x)。依据part1demo流程,随机初始化w后,输入观测数据x(图像 或者 其他需要分类或者回归的数据)。loss(w, x).backward()就可以求出对应的网络参数w的梯度。再利用各种优化算法(SGD,admn)更新各个网络参数w即可。
pytorch 网络训练的流程
- 搭建好网络:net()
- 数据x输入网络:y=net(x,w)
- 网络输出y与标签label计算标量损失函数:loss(y,label,w)
- 损失函数loss()反向传播:loss.backward()->通过自动求导Adagrad实现
- 网络参数更新:net.parameters().step()->通过优化器实现
注意事项:在每次损失函数反向传播计算梯度时,原本的参数梯度必须设置为0。否则,各个参数的梯度会累加之前的梯度。网络参数梯度置0:
optimizer=torch.optim.SGD(net.parameters(),lr=0.001,momentum=0.1)
optimizer.zero_grad()
loss.backward()
3. 自动求梯度的底层支持–torch.autograd
torch.autograd 是一套自动求导引擎,能够根据输入和前向传播过程自动构建计算图,并执行反向传播. 计算图是深度学习框架的核心。
[本节为陈云<<深度学习框架-pytorch 入门与实践>>一书第3.2章的内容autograd 读书笔记.]
pytorch 中 autograd模块 实现了 计算图 相关功能. autograd 的核心数据结构Variable。
pytorch 中 autograd模块 底层采用 计算图 实现梯度计算。
3.1 Variable
Variable中封装了以下三个部分内容
- data : 保存数据tensor
- grad : 保存data对应的梯度,形状与data一致,也是一个Variable
- grad_fn : 指向一个Function,记录Variable操作历史,如果一个变量是由用户创建的,则他为叶子节点,对应的grad_fn为None.
3.1.1 Variable构造函数
Variable的构造函数–需要传入tensor,还有两个可选参数:
- requires_grad : bool 是否需要对该variable进行求导
- volatile : bool 为True , 那么基于该variable 构建的图都不会求导,转为推理阶段设计.
volatile优先级别比requires_grad高。在计算路径上同时存在requires_grad=True 和 volatile=True 的变量,那么其后的通过计算得出的变量的requires_grad 为False.
3.1.2 Variable链式求导–backward()
Variable支持大部分的tensor操作,但不支持部分inplace函数。如果想要计算各个Variable的梯度,只需要调用根节点variable的backward方法,autograd 会自动沿计算图反向传播,计算每一个叶子节点的梯度.
Variable.backward(grad_variables=None,retain_graph=None,create_graph=None)
grad_variables : 相当与链式法则∂z∂x=∂z∂y∂y∂x\frac{\partial z}{\partial x}=\frac{\partial z}{\partial y}\frac{\partial y}{\partial x}∂x∂z=∂y∂z∂x∂y中的∂z∂y\frac{\partial z}{\partial y}∂y∂z 。y.backward(grad_y) 等价于 z.backward()
retain_graph : 反向传播中会缓存一些中间结果,反向传播结束后缓存被清空。可以通过指定这个参数不清空缓存,用于多次反向传播。
create_graph : 反向传播过程中再次构建计算图,通过backward of backward实现高阶求导.
3.1.3 Variable反向传播函数–grad_fn
variable变量的grad_fn 属性可以用来查看反向传播函数, next_functions保存grad_fn的输入,是一个tuple。每个变量在图中的位置可以通过grad_fn 属性在图中的位置推测得到。每一个前向传播函数都有一个与之对应的反向传播函数,用来计算各个输入变量的梯度;这些函数以Backward结尾。
x=Variable(torch.ones(1))
b=Variable(torch.rand(1,requires_grad=True))
w=Variable(torch.rand(1),requires_grad=True)
y=w*x
z=y+b
z.grad_fn # 查看z的反向传播函数
Out[16]: <AddBackward0 at 0x7f84b0a0e3c8>z.grad_fn.next_functions # z 反向传播函数的输入,一个为y.grad_fn(为MulBackward0),另一个是b.grad_fn(为none)
Out[17]: ((<MulBackward0 at 0x7f84903a9588>, 0), (None, 0))y.grad_fn
Out[27]: <MulBackward0 at 0x7f84903a9588>
y.grad_fn.next_functions
Out[19]: ((<AccumulateGrad at 0x7f84b0a0ee10>, 0), (None, 0))z.backward(retain_graph=True) # 保留中间结果
w.grad
Out[23]: tensor([1.])z.backward(retain_graph=True) # 保留中间结果, 才能二次传播
w.grad
Out[26]:tensor([2.]) # 这个为2 不是保留中间结果的原因,而是两次梯度传播
3.2 计算图
pytorch 中 autograd模块 底层采用 计算图 实现梯度计算。计算图是一种特殊的有向无环图 , 用于记录算子 与 变量 之间的关系。
在pytorch 中autograd模块会随着用户操作,记录生成当前 variable 的所有操作。以此建立一个有向无环图(每个变量都有一个有向无环图?还以一个计算过程有一个?应该是一个计算过程有一个图)。用户每进行一次操作,计算图就会变化。对应的变化会通3.1.3 的grad_fn 记录
3.2.1 动态创建计算图
pytorch 的计算图在每次前向传播的时候都是从头开始构建的 , 所以能够利用python的控制语句(for,if) 根据需求 创建动态图.
少一个例子
3.2.2 非叶子节点的梯度–autograd.grad 与 hook
在反向传播的过程中,非叶子节点的导数在计算完成之后即被清空,若想查看这些变量的梯度,有两种方法:autograd.grad 与 hook。
torch.autograd.grad()
In [28]: x=Variable(torch.ones(3),requires_grad=True)
In [30]: w=Variable(torch.ones(3),requires_grad=True)
In [31]: y=x*w
In [32]: z=y.sum()
In [33]: z.backward()
In [34]: (x.grad,w.grad,y.grad)
Out[34]: (tensor([1., 1., 1.]), tensor([1., 1., 1.]), None) # y.grad的梯度计算完被释放掉了
# 使用torch.autograd.grad()计算中间节点的梯度
In [35]: torch.autograd.grad(z,y) # 求Z对Y的梯度
Out[35]: (tensor([1., 1., 1.]),)
hook 呢?
Pytorch(5)-梯度反向传播相关推荐
- pytorch 入门学习反向传播-4
pytorch 入门学习反向传播 反向传播 import numpy as np import matplotlib.pyplot as plt import torchdef forward(x): ...
- 梯度反向传播过程中,测试强行修改后的预测结果是否还会传递loss?
在深度学习计算损失函数的过程中,我一直有这样一个问题,如果Label是1.0,而预测结果是0.0,则BCE损失中理论上计算出的结果是无穷大的(当然pytorch并不会报错,而是将损失上限设在了100. ...
- 损失函数与优化器理解+【PyTorch】在反向传播前为什么要手动将梯度清零?optimizer.zero_grad()
目录 回答一: 回答二: 回答三: 传统的训练函数,一个batch是这么训练的: 使用梯度累加是这么写的: 回答一: 一句话,用来更新和计算影响模型训练和模型输出的网络参数,使其逼近或达到最优值,从而 ...
- 梯度反向传播求解示例
深度学习中进行网络的训练的时候,常常采用梯度反向传递的方式对网络中的参数进行调整,那么具体是怎么实现的呢?我用一个简单的例子进行推导求解. 如下图,这里采用的是两层网络,损失函数采用的是平方差损失函数 ...
- Pytorch专题实战——反向传播(Backpropagation)
文章目录 1.前言 2.初识如何更新梯度 3.手动更新梯度 4.自动更新梯度 1.前言 大体分为三步: (1)前向传播,计算loss (2)计算局部梯度 (3)反向传播,用链式求导法则计算梯度 2.初 ...
- 梯度反向传播(CS231n课程笔记翻译)
CS231n课程笔记翻译:反向传播笔记 - 杜客的文章 - 知乎 译者注:本文智能单元首发,译自斯坦福CS231n课程笔记Backprop Note,课程教师Andrej Karpathy授权翻译.本 ...
- pytorch 正向与反向传播的过程 获取模型的梯度(gradient),并绘制梯度的直方图
记录一下怎样pytorch框架下怎样获得模型的梯度 文章目录 引入所需要的库 一个简单的函数 模型梯度获取 先定义一个model 如下定义两个获取梯度的函数 定义一些过程与调用上述函数的方法 可视化一 ...
- 神经网络梯度反向传播公式
考虑三层网络: 输出层没有激活函数,只有中间层有: y=Wout⋅tanh(Win⋅x)y = W_{out}\cdot tanh(W_{in}\cdot x)y=Wout⋅tanh(Win⋅x) ...
- PyTorch 入坑四 梯度、链式法则、计算图与反向传播
PyTorch 一文入门 PyTorch 入坑四:计算图与反向传播 导数.梯度与最优化 方向导数与梯度 最优化 复合函数求梯度 计算图 PyTorch实战 PyTorch中的动态图机制 PyTorch ...
最新文章
- 解决Windows Git Bash中文乱码问题
- 多用户使用一台计算机可设置,《计算机应用基础》试卷(A)
- cython编码报错
- netty里集成spring注入mysq连接池(二)
- 通过这5个简单的技巧减少GC开销
- android Intent 全面点的介绍
- 农村大学生的出路或许是读个真才实学的博士
- 百倍加速!Python量化策略的算法性能提升指南
- AI进军B-Box界:输入20秒任意声音,还你一段定制的B-Box演奏
- python for mac下载_Python for Mac
- linux jdk11 64位下载安装
- 深度学习涉及到的线性代数知识点总结(二)
- 中文论文检索证明怎么开_SCI论文检索后收录证明怎么开?
- 计划预算(PV)、实际完成工作预算(EV)、实际成本(AC)
- 前端实现GIF图片压缩上传
- MODBUS-RTU协议主机和从机代码STM32 包含2个程序代码,主机和从机
- java 将字符串集合转换成字符串并以顿号隔开
- 月份对比_2020年5月份,四款主流游戏电脑配置横向对比,你会选择哪款呢?
- 计算机网络之五层体系结构
- matlab 三维相交面,MATLAB画三维图时如何画相交部分
热门文章
- C语言的putpiel函数,C语言graphics.h函数介绍
- mysql修改语句_序言:MySQL与Navicat安装Tips
- python中如何标识语句块_如何用python在一个块中编写多个try语句?
- php公交查询系统源代码,基于Smarty公交查询系统的设计与实现(PHP,MySQL)
- g5420 win7集显驱动_台式机装WIN7?雷我已经趟完了
- C#多线程编程系列(二)- 线程基础
- 关于w3wp.exe
- ROS机器人导航仿真(kinetic版本)
- 与gps优缺点_长缨在手,敢缚苍龙,中国北斗三号圆满收官,相比美国GPS怎样?...
- 【POJ - 2965】The Pilots Brothers' refrigerator(暴力枚举,思维)