自动微分

原理

pytorch 内置了常见 tensor 操作的求导解析解. 从 loss 到 parameter 是若干个 op 叠加起来的复合函数, 所以用链式法则逐个计算.
tensor.grad_fn 记录了一个 tensor 是由何种运算产出的, 以及相应的求导解析解. 注意并不是根据 y x ′ = Δ y Δ x y'_x=\frac {\Delta y} {\Delta x} yx′​=ΔxΔy​ 的定义去计算数值解.

相关 api

  • tensor.requires_grad :bool
    标识一个 tensor 是否需要计算梯度.
  • tensor.grad_fn
    标识不同运算对应的求导方法.
  • tensor.backward()
    loss 就是一个 tensor 标量, 该方法将当前 tensor 视为因变量, 计算它到叶子节点的梯度. 注意只是算梯度, 不更新.
    该方法会累积叶子节点的梯度, 所以一般要搭配 optimizer.zero_grad() 使用.
  • tensor.retain_grad()
    Enables this Tensor to have their :attr:grad populated during :func:backward. This is a no-op for leaf tensors.

例子

  • 令 x 1 = 2 , x 2 = 2 x_1=2,x_2=2 x1​=2,x2​=2
    u = ( u 1 , u 2 ) = f 1 ( x ) = ( 4 x 1 , 4 x 2 ) u=(u_1,u_2)=f_1(x)=(4x_1,4x_2) u=(u1​,u2​)=f1​(x)=(4x1​,4x2​)
    y = f 2 ( u ) = ( u 1 2 + u 2 2 ) 1 2 y=f_2(u)=(u_1^2+u_2^2)^{\frac12} y=f2​(u)=(u12​+u22​)21​,
  • 求 y 对 x1 的偏导数.

手算偏导

使用链式法则作复合函数的求导.
∂ y ∂ x 1 = ∂ y ∂ u 1 ⋅ ∂ u 1 ∂ x 1 (1) \frac{\partial y}{\partial x_1} = \frac{\partial y}{\partial u_1} \cdot \frac{\partial u_1}{\partial x_1} \tag1 ∂x1​∂y​=∂u1​∂y​⋅∂x1​∂u1​​(1)

分别计算两项各自的导数:
∂ y ∂ u 1 = ∂ ( u 1 2 + u 2 2 ) 1 2 ∂ u 1 = 1 2 × ( u 1 2 + u 2 2 ) − 1 2 × 2 u 1 = 1 2 × 1 64 + 64 × 2 × 8 = 0.7071 (2) \frac{\partial y}{\partial u_1}=\frac{{\partial}(u_1^2+u_2^2)^{\frac12}}{{\partial u_1}}\\ =\frac12 \times (u_1^2+u_2^2)^{-\frac12}\times 2u_1\\ =\frac12\times\frac1{\sqrt{64+64}}\times 2\times8\\ =0.7071 \\ \tag2 ∂u1​∂y​=∂u1​∂(u12​+u22​)21​​=21​×(u12​+u22​)−21​×2u1​=21​×64+64 ​1​×2×8=0.7071(2)
注意因为有 u 1 2 u_1^2 u12​ 的存在, 这里其实也是一个复合函数, 都用到了 ( x a ) ′ = a x a − 1 (x^a)'=ax^{a-1} (xa)′=axa−1 的求导公式.

∂ u 1 ∂ x 1 = 4 (3) \frac{\partial u_1}{\partial x_1} =4 \tag3 ∂x1​∂u1​​=4(3)

将 (2)(3)的结果代入式(1), 有
r e s = ∂ y ∂ u 1 ⋅ ∂ u 1 ∂ x 1 = 0.7071 × 4 = 2.8284 (4) res = \frac{\partial y}{\partial u_1} \cdot \frac{\partial u_1}{\partial x_1}\\ =0.7071\times 4\\ =2.8284 \tag4 res=∂u1​∂y​⋅∂x1​∂u1​​=0.7071×4=2.8284(4)

代码比对

import torchx = torch.tensor([2, 2], dtype=torch.float)  # input tensor
x.requires_grad = True
u = 4 * x
y: torch.Tensor = u.norm()
print('x.grad_fn', x.grad_fn)
print('y.grad_fn', y.grad_fn)
print('u.grad_fn', u.grad_fn)
print(f'before y.backward(), x.grad = {x.grad}, u.grad = {u.grad}')
y.backward()
print(f'after y.backward(), x.grad = {x.grad}, u.grad = {u.grad}')
"""
x.grad_fn None
y.grad_fn <NormBackward1 object at 0x0000027620F89A90>
u.grad_fn <MulBackward0 object at 0x0000027620F89A90>
before y.backward(), x.grad = None, u.grad = None
after y.backward(), x.grad = tensor([2.8284, 2.8284]), u.grad = None
D:\code_study\torch_study\test\auto_grad_test.py:10: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\build\aten\src\ATen/core/TensorBody.h:485.)print(f'before y.backward(), x.grad = {x.grad}, u.grad = {u.grad}')
"""

可以清晰看到 y对x1的偏导为 2.8284, 与手算结果一致.
有个 warning 信息, 是说 tensor u 不是叶子结点, 所以.grad attribute 不会被自动计算. 如果硬要算也可以, 调用 u.retain_grad() 即可.

不可微的 op 怎么搞?

一些分段函数带来的 第一类间断点等.
todo

梯度更新

相关api

  • Optimizer.zero_grad()
    将优化器负责的所有 tensor 的梯度置为0. 一般跟随在 loss.backward() 后使用.
  • torch.nn.modules.module.Module.zero_grad()
    Sets gradients of all model parameters to zero.
  • optimizer.step()
    根据各 parameter 的已有 grad , 和 优化器自己存储的 动量,步长,decay 等信息作 trainable tensor 值的更新.

手算tensor迭代

使用最简单的 SGD, 步长为 0.1, 那么一个 step 之后, x 新的值为
x=x+(-1)*gradient*learning_rate, 代入得 x=2-0.1*2.8284=1.7172.

代码比对

import torchx = torch.tensor([2, 2], dtype=torch.float)  # input tensor
x.requires_grad = Trueu: torch.Tensor = 4 * x
y: torch.Tensor = u.norm()
print('y.grad_fn = ', y.grad_fn)
print('u.grad_fn = ', u.grad_fn)
print('x.grad_fn = ', x.grad_fn)loss = y
optimizer = torch.optim.SGD(params=[x], lr=0.1)u.retain_grad()
optimizer.zero_grad()print(f'before loss.backward(), x.grad = {x.grad}, u.grad = {u.grad}')
loss.backward()
print(f'after loss.backward(), x.grad = {x.grad}, u.grad = {u.grad}')print(f'before optimizer.step(), x = {x}')
optimizer.step()
print(f'after optimizer.step(), x = {x}')"""
y.grad_fn <CopyBackwards object at 0x0000022F2CDA1BE0>
u.grad_fn <MulBackward0 object at 0x0000022F2CDA1BE0>
x.grad_fn Nonebefore loss.backward(), x.grad = None, u.grad = None
after loss.backward(), x.grad = tensor([2.8284, 2.8284]), u.grad = tensor([0.7071, 0.7071])before optimizer.step(), x = tensor([2., 2.], requires_grad=True)
after optimizer.step(), x = tensor([1.7172, 1.7172], requires_grad=True)
"""

pytorch autograd 自动微分与梯度更新相关推荐

  1. PyTorch深度学习60分钟闪电战:02 Autograd - 自动微分

    本系列是PyTorch官网Tutorial Deep Learning with PyTorch: A 60 Minute Blitz 的翻译和总结. PyTorch概览 Autograd - 自动微 ...

  2. 只知道TF和PyTorch还不够,快来看看怎么从PyTorch转向自动微分神器JAX

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转载自:机器之心 说到当前的深度学习框架,我们往往绕不开 Ten ...

  3. Pytorch Autograd (自动求导机制)

    Introduce Pytorch Autograd库 (自动求导机制) 是训练神经网络时,反向误差传播(BP)算法的核心. 本文通过logistic回归模型来介绍Pytorch的自动求导机制.首先, ...

  4. [PyTorch] autograd 自动求导

    文章目录 1. autograd 注意事项 backward() 梯度累加 2. 标量求导 3. 张量求导 例1 例2 1. autograd 注意事项 backward() backwad() 函数 ...

  5. pytorch基础-使用 TORCH.AUTOGRAD 进行自动微分(5)

    在训练神经网络时,最常用的算法是反向传播.PyTorch的反向传播(即tensor.backward())是通过autograd包来实现的,autograd包会根据tensor进行过的数学运算来自动计 ...

  6. 速成pytorch学习——3天自动微分机制

    神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情. 而深度学习框架可以帮助我们自动地完成这种求梯度运算. Pytorch一般通过反向传播 backward 方 ...

  7. 《20天吃透Pytorch》Pytorch自动微分机制学习

    自动微分机制 Pytorch一般通过反向传播 backward 方法 实现这种求梯度计算.该方法求得的梯度将存在对应自变量张量的grad属性下. 除此之外,也能够调用torch.autograd.gr ...

  8. PyTorch深度学习基础之Reduction归约和自动微分操作讲解及实战(附源码 超详细必看)

    创作不易 觉得有帮助请点赞关注收藏~~~ 一.PyTorch的Reduction操作 Reduction运算的特点是它往往对一个Tensor内的元素做归约操作,比如torch.max找极大值,torc ...

  9. 【Pytorch】用自动微分求sin(x)的导数

    目录 1. 问题分析 1.1 问题描述 1.2 解决思路 2. 代码实现 1. 问题分析 1.1 问题描述 其实这个问题很简单,本篇博客全当备忘录了.我们的需求是: 图片来源:李沐:<动手学深度 ...

最新文章

  1. python源码学习_【Python学习】Python源码阅读(一)
  2. 电子书下载:Learn Office 2011 for Mac OS X
  3. 安徽建筑大学计算机专业年新,2017年安徽建筑大学计算机技术909数据结构[专业硕士]考研题库...
  4. oss导出数据为空时怎么处理_sql数据库导出空库的搜索结果-阿里云开发者社区...
  5. C#——自定义泛型链表DEMO
  6. wordpress 表格文字对齐_Word文字对齐还用空格键?OUT了,这3个文字对齐方式你值得拥有!...
  7. 用C语言做一个横板过关类型的控制台游戏
  8. mysql -b -e_MySQL 的B+树索引.
  9. 6-6-1:STL之map和set——set的基本使用
  10. linux 常用SHELL
  11. 三人表决器_数电小实验之三人表决器
  12. PDF免费转word方法
  13. Javascript七种继承方式
  14. JSP→JSTL标准标签库简介与环境搭建、JSTL助手EL表达式EL隐式对象、标签→out、set、if、多选择配合、foreach、redirect、格式化、JSTL函数标签、自定义标签、标签类架构
  15. [2018.03.14 T2] 树(tree)
  16. PHP之GD图像处理
  17. iOS DevCamp Android DevCamp 课程集锦 为最喜爱的课程投票 获得CSDN社区会员专享特惠票...
  18. android系统怎么连不上wifi,为什么手机连接不上wifi wifi连不上怎么办
  19. mysqldump: Got error: 145:
  20. [错误解决]centos中使用kubeadm方式搭建一个单master的K8S集群

热门文章

  1. K7 GTX在SDI中的使用解析
  2. 中学 教育知识与能力 思维导图
  3. App 如何快速重启(编译)
  4. Sql case when 用法实例详解
  5. 【论文-目标追踪】BoT-SORT: Robust Associations Multi-Pedestrian Tracking
  6. 【第51天| 309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费 】
  7. macbook快捷键和使用技巧
  8. 逻辑回归原理简述及代码实现
  9. 网页上实现打印指定区域的方法实现
  10. STEVAL-MKI109V3评估板 PART2 - LPS27HHW传感器接口