- 第五节:自动微分

Posted 海轰Pro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了- 第五节:自动微分相关的知识,希望对你有一定的参考价值。

目录

前言

Hello!
非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~
 
自我介绍 ଘ(੭ˊᵕˋ)੭
昵称:海轰
标签:程序猿|C++选手|学生
简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研。
学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!
 
唯有努力💪
 

知其然 知其所以然!

 
本文仅记录自己感兴趣的内容

2.5. 自动微分

2.5.1. 标量变量的反向传播

求函数 f ( x ) = 2 x T x f(x) = 2 x^Tx f(x)=2xTx对列向量 x x x求导后的梯度

  1. 初始化向量 x x x
  2. 设置x可计算梯度

requires_grad: 如果需要为张量计算梯度,则为True,否则为False

  1. 计算 y = 2 x T x y = 2x^Tx y=2xTx

dot用来计算两个向量之间内积(对应元素相乘,再累加,最终得到一个标量)

grad_fn: grad_fn用来记录变量是怎么来的,方便计算梯度(比如这里便于使用反向传播计算梯度)

  1. 使用反向传播法计算梯度

理论上 f ( x ) = 2 x T x f(x) = 2 x^Tx f(x)=2xTx x x x求导后结果为 4 x 4x 4x
初始时 x = [ 0 , 1 , 2 , 3 ] x = [0,1,2,3] x=[0,1,2,3]
利用 x x x x = [ 0 , 1 , 2 , 3 ] x = [0,1,2,3] x=[0,1,2,3]时的梯度为 4 x = [ 0 , 4 , 8 , 12 ] 4x = [0, 4, 8, 12] 4x=[0,4,8,12]
计算得出的结果和理论值一样

  1. 判断计算得出的结果和理论值是否一样


现在设 y = x 1 + x 2 + x 3 + x 4 y = x_1 + x_2 + x_3 + x_4 y=x1+x2+x3+x4,其中 x = [ x 1 , x 2 , x 3 , x 4 ] x = [x_1, x_2, x_3, x_4] x=[x1,x2,x3,x4],求 x x x的梯度

import torch

x = torch.arange(4.0, requires_grad = True)
y = x.sum() # 相当于 x_1 + x_2 + ... + x_n = y
y.backward()
x.grad

# tensor([1., 1., 1., 1.])

解释:对 x 1 x_1 x1求偏导,结果为1,同理,对 x 2 、 x 3 、 x 4 x_2、x_3、x_4 x2x3x4求偏导,结果都为1

注意:在默认情况下,PyTorch会累积梯度

比如多次运行y.backward(),会有

  1. 第一次
  2. 第二次
  3. 第三次

解决办法:使用grad.zero_()清除梯度

这样多次运行,结果都是[1,1,1,1]

2.5.2. 非标量变量的反向传播

y = x ∗ x y = x * x y=xx x x x求偏导( x x x为一个向量)

说明:

  • y = x ∗ x y= x * x y=xx: 对应元素相乘,此时结果 y y y是一个非标量

x = [0, 1, 2, 3] ===> x * x = [0, 1 * 1 , 2 * 2 , 3 * 3] = [0, 1, 4, 9]

为了求 x x x的偏导,则需要先对 y y y进行累加求和,再使用反向传播

利用 y = x * x x x x求导后,结果为 2 x 2 x 2x
x = [0,1,2,3] ==> 2x = [0,2,4,6]

注:这里还是有点不懂 ??? 以下为书中原话:

2.5.3. 分离计算


若不丢弃计算图中如何计算y的任何信息,也就是不使用detach()函数

y = x ∗ x u = y z = u ∗ x y = x * x\\\\ u = y\\\\ z = u * x y=xxu=yz=ux

等效于

z = x ∗ x ∗ x z = x * x * x z=xxx

此时z关于x求导,梯度为(此时z为非标量,需要先求和)

得到梯度为[0,3,12,27] ,与理论值 3 x 2 3 x^2 3x2 吻合


使用detach()函数后

这里可以理解为:

  • u = y.detach()使得u仅仅是一个向量[0,1,4, 9]
  • z = u * x, u仅仅作为一个常向量,对x求导,得到结果为u

总结:

  • 不使用detach(), 那么y是由x计算出来的,也就是可以用x的算式进行替换
  • 使用detach(), u仅仅表示一个向量,仅有y的值,其它信息都无

2.5.4. Python控制流的梯度计算

大概意思:

  • f(a)函数是一个分段函数,其中每一段都是线性的(直线)
  • 输入a的值不同,对应不同的线段(需要经过while循环、if-else等)
  • 但是最后依然是可以算出来x的梯度,不受循环等的影响
  • 比如经过多次循环、if-else, 得到的a与d的对应关系为 d = 1231 * a,梯度依然可以算出来为1231
  • 也就是说经过多次Python控制流(例如,条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度

练习

import numpy as np
import torch
from d2l import torch as d2l
x = torch.arange(-4.0, 4.0, 0.1, requires_grad = True)
x

y = torch.sin(x)
y.sum().backward()
x.grad == torch.cos(x)

y2 = x.grad
y2

y2_np = y2.numpy()
y2_np

x_np = x.detach().numpy()
x_np

def f(x):
    return np.sin(x)
y1_np = f(x_np)
y1_np

d2l.plot(x_np, [y1_np, y2_np], 'x', 'f(x)', legend=['sin(x)', 'cos(x)'])

结语

学习资料:http://zh.d2l.ai/

文章仅作为个人学习笔记记录,记录从0到1的一个过程

希望对您有一点点帮助,如有错误欢迎小伙伴指正

以上是关于- 第五节:自动微分的主要内容,如果未能解决你的问题,请参考以下文章

自动化测试第五节-模块

第五节:从源码的角度理解各种Result(ActionResultJsonResultJavaScriptResult等)

BurpSuite学习第五节--Scanner

第五节——DockerFile

第五节——切片

第五节,计算机(电脑)简介