目录

  • 1 Manual Differentiation (手动微分)
    • 1.1 计算方法
    • 1.2 缺陷
  • 2 Symbolic Differentiation (符号微分)
    • 2.1 计算方法
    • 2.2 缺陷
  • 3 Numerical Differentiation (数值微分)
    • 3.1 计算方法
    • 3.2 缺陷
  • 4 Automatic Differentiation (自动微分)
    • 4.1 Forward-Mode (前向模式)
    • 4.2 Reverse-Mode (反向模式)
    • 4.3 小结
  • 5 参考

1 Manual Differentiation (手动微分)

1.1 计算方法

手动求导,顾名思义,通过求导的一些公式,我们提前算好导数表达式,再带入公式求解。
假设我们以一个输入为3个变量的函数fff为例:
f(x1,x2,x3)=3∗(x12+x2∗x3)f(x_1, x_2, x_3) = 3*(x_1^2+x_2*x_3) f(x1​,x2​,x3​)=3∗(x12​+x2​∗x3​)
我们定义输入的三个值为(x1=2,x2=3,x3=4)(x_1=2, x_2=3, x_3=4)(x1​=2,x2​=3,x3​=4),那手动微分是怎么计算?首先,分别对x1,x2,x3x_1, x_2, x_3x1​,x2​,x3​求导,再带入输入值,得到如下结果:
∂f(x1,x2,x3)∂x1=3∗2∗x1=12\frac{\partial f(x_1, x_2, x_3)}{\partial x_1} = 3*2*x_1 = 12 ∂x1​∂f(x1​,x2​,x3​)​=3∗2∗x1​=12
∂f(x1,x2,x3)∂x2=3∗x3=12\frac{\partial f(x_1, x_2, x_3)}{\partial x_2} = 3*x_3 = 12 ∂x2​∂f(x1​,x2​,x3​)​=3∗x3​=12
∂f(x1,x2,x3)∂x3=3∗x2=9\frac{\partial f(x_1, x_2, x_3)}{\partial x_3} = 3*x_2 = 9 ∂x3​∂f(x1​,x2​,x3​)​=3∗x2​=9

1.2 缺陷

  • 当计算较复杂的函数时,求导结果表达式将会十分繁琐
  • 每次给定不同的目标函数,都需要重新计算求导表达式,定义函数公式,效率低,无法大规模复用

2 Symbolic Differentiation (符号微分)

2.1 计算方法

符号微分通过求导规则来计算导数值,给定一个函数,通过规则一步一步求解,常见的求导规则有如下:

  • 加法求导规则:

d(f+g)dx=dfdx+dgdx\frac{d(f+g)}{dx} = \frac{df}{dx} + \frac{dg}{dx} dxd(f+g)​=dxdf​+dxdg​

  • 乘法求导规则:
    d(fg)dx=dfdxg+fdgdx\frac{d(fg)}{dx} = \frac{df}{dx}g + f \frac{dg}{dx} dxd(fg)​=dxdf​g+fdxdg​
  • 链式法则:
    d(f(g(x)))dx=df(g(x))dg(x)dg(x)dx\frac{d(f(g(x)))}{dx} = \frac{df(g(x))}{dg(x)}\frac{dg(x)}{dx} dxd(f(g(x)))​=dg(x)df(g(x))​dxdg(x)​

2.2 缺陷

符号微分的主要缺陷就是:

  • 对于复杂的函数,求导结果表达式十分繁琐,如下图所示:
  • 为了计算最终的数值梯度,中间符号表达式都需要存储,很浪费资源
  • 计算过程中容易出错

3 Numerical Differentiation (数值微分)

3.1 计算方法

数值微分主要基于导数的极限定义,例如给定一个多元函数 f:Rn→Rf: R^n \to Rf:Rn→R,我们可以估计函数梯度∇f=(∂f∂x1,...,∂f∂xn)\nabla f = (\frac{\partial f}{\partial x_1}, ..., \frac{\partial f}{\partial x_n})∇f=(∂x1​∂f​,...,∂xn​∂f​)公式如下:
∂f(x)∂xi≈lim⁡h→0f(x+hei)−f(x)h\frac{\partial f(x)}{\partial x_i} \approx \lim_{h \to 0} \frac{f(x+he_i)-f(x)}{h} ∂xi​∂f(x)​≈h→0lim​hf(x+hei​)−f(x)​
为了避免截断误差,一般使用中心差分,如下公式:
∂f(x)∂xi≈lim⁡h→0f(x+hei)−f(x−hei)2h\frac{\partial f(x)}{\partial x_i} \approx \lim_{h \to 0}\frac{f(x+he_i)-f(x-he_i)}{2h} ∂xi​∂f(x)​≈h→0lim​2hf(x+hei​)−f(x−hei​)​
hhh是一个很小的数,一般设置为h=1e−6h=1e-6h=1e−6

3.2 缺陷

  • 计算nnn维度的梯度,需要计算函数O(n)O(n)O(n)次对fff函数的计算,效率较慢
  • 每一步需要很小心的选择hhh,梯度计算存在舍入误差

4 Automatic Differentiation (自动微分)

自动微分是一个有效的计算偏导方法,对任意函数的一点,自动微分可以自动计算偏导数。自动微分有两种计算方式:前向模式和反向模式,接下来我们用函数f(x1,x2)=ln(x1)+x1x2−sin(x2)f(x_1, x_2) = ln(x_1) + x_1x_2 - sin(x_2)f(x1​,x2​)=ln(x1​)+x1​x2​−sin(x2​)为例,分别对自动微分的前向模式和方向模式做一个对比。

4.1 Forward-Mode (前向模式)

对函数f(x1,x2)=ln(x1)+x1x2−sin(x2)f(x_1, x_2) = ln(x_1) + x_1x_2 - sin(x_2)f(x1​,x2​)=ln(x1​)+x1​x2​−sin(x2​)构造图如下:

每个中间变量viv_ivi​,计算对x1x_1x1​的偏导数记做:
v˙=∂vi∂x1v˙= \frac{\partial v_i}{\partial x_1} v˙=∂x1​∂vi​​
接下来,我们看自动微分的前向模式计算细节,我们按照输入(x1,x2)=(2,5)(x_1, x_2)=(2,5)(x1​,x2​)=(2,5)为例:

  • step 1: 前向计算各中间变量值

    通过函数fff定义形式,将输入的值带入求解,计算各中间的变量值viv_ivi​
  • step 2 : 从前往后计算偏导数
    因为定义v˙=∂vi∂x1v˙= \frac{\partial v_i}{\partial x_1}v˙=∂x1​∂vi​​,所以x˙1=∂x1∂x1=1x˙_1 = \frac{\partial x_1}{\partial x_1}=1x˙1​=∂x1​∂x1​​=1,则计算结果如下:

    根据前向计算的结果和求导的链式法则,很容易得出上述结果,得到最终的结果:y˙=˙v5=5.5y˙= ˙v_5 = 5.5y˙=˙v5​=5.5
    若给定一个函数方程: f:Rn→Rmf:R^n \to R^mf:Rn→Rm,输入是nnn个独立的变量xix_ixi​和mmm个非独立的输出变量yjy_jyj​,在x=ax=ax=a取值点,则计算的雅可比导数矩阵形式如下:
    Jf=[∂y1∂x1...∂y1∂xn.........∂ym∂x1...∂ym∂xn]x=aJ_f = \begin{bmatrix} \frac{\partial y_1}{\partial x_1} & ... & \frac{\partial y_1}{\partial x_n} \\.&.&.\\.&.&.\\.&.&. \\ \frac{\partial y_m}{\partial x_1} & ... & \frac{\partial y_m}{\partial x_n} \end{bmatrix}_{x=a} Jf​=⎣⎢⎢⎢⎢⎡​∂x1​∂y1​​...∂x1​∂ym​​​.........​∂xn​∂y1​​...∂xn​∂ym​​​⎦⎥⎥⎥⎥⎤​x=a​
    自动微分的前向模式十分有效,对于函数方程f:R→Rmf : R \to R^mf:R→Rm,对于所有的偏导数计算dyidx\frac{dy_i}{dx}dxdyi​​只需要一次前向计算,但如果函数方程是f:Rn→Rf: R^n \to Rf:Rn→R,则前向模式需要计算nnn个等式计算梯度:
    ∇f=(∂y∂x1,...,∂y∂xn)\nabla f = (\frac{\partial y}{\partial x_1},...,\frac{\partial y}{\partial x_n}) ∇f=(∂x1​∂y​,...,∂xn​∂y​)
    而当函数f:Rn→Rmf: R^n \to R^mf:Rn→Rm其中 n≫mn ≫ mn≫m,则前向模式效率将会十分低,特别是目前DL模型有上亿级别的参数,所以需要更快的方式计算,这就是接下来要讲的反向模式。

4.2 Reverse-Mode (反向模式)

自动微分的反向模式通过从输出反向计算各变量的偏导数,我们定义变量v‾i=∂yj∂vi\overline{v}_i = \frac{\partial y_j}{\partial v_i}vi​=∂vi​∂yj​​,还是回到例子y=f(x1,x2)=ln(x1)+x1x2−sin(x2)y=f(x_1,x_2)=ln(x_1) + x_1x_2 - sin(x_2)y=f(x1​,x2​)=ln(x1​)+x1​x2​−sin(x2​),从上述构造的图可以看出,变量v0v_0v0​通过影响v2和v3v_2和v_3v2​和v3​来影响yyy,所以,v0v_0v0​对yyy影响可以通过如下公式计算:
∂y∂v0=∂y∂v2∂v2∂v0+∂y∂v3∂v3∂v0\frac{\partial y}{\partial v_0} = \frac{\partial y}{\partial v_2}\frac{\partial v_2}{\partial v_0}+\frac{\partial y}{\partial v_3}\frac{\partial v_3}{\partial v_0} ∂v0​∂y​=∂v2​∂y​∂v0​∂v2​​+∂v3​∂y​∂v0​∂v3​​
或者
v0‾=v2‾∂v2∂v0+v3‾∂v3∂v0\overline{v_0} = \overline{v_2}\frac{\partial v_2}{\partial v_0}+\overline{v_3}\frac{\partial v_3}{\partial v_0} v0​​=v2​​∂v0​∂v2​​+v3​​∂v0​∂v3​​
在反向模式里,我们首先以v5‾=y‾=∂y∂y=1\overline{v_5}=\overline{y}=\frac{\partial y}{\partial y}=1v5​​=y​=∂y∂y​=1开始,在最后我们得到∂y∂x1=x1‾和∂y∂x2=x2‾\frac{\partial y}{\partial x_1}=\overline{x_1} 和 \frac{\partial y}{\partial x_2}=\overline{x_2}∂x1​∂y​=x1​​和∂x2​∂y​=x2​​,只需要一次反向计算。
相对前向模式,反向模式最大的优势是需要更少的计算,对于函数f:Rn→Rf: R^n \to Rf:Rn→R这样有nnn个输入,反向模式只需要一次计算就可以得到所有的梯度∇f=(∂y∂x1,...,∂y∂xn)\nabla f = (\frac{\partial y}{\partial x_1},...,\frac{\partial y}{\partial x_n})∇f=(∂x1​∂y​,...,∂xn​∂y​),而前向计算需要算nnn次前向计算。我们来看下在反向计算函数f(x1,x2)f(x_1,x_2)f(x1​,x2​)过程

  • step 1: 前向计算各变量的值
    和自动微分的前向模式一样,首先前向计算出每个变量的值
  • step 2: 反向计算各变量的梯度值

从下往上计算,其中v5‾,v4‾,v3‾,v1‾,v2‾\overline{v_5}, \overline{v_4}, \overline{v_3}, \overline{v_1}, \overline{v_2}v5​​,v4​​,v3​​,v1​​,v2​​计算很容易求解得到,接下来我们来看v0‾\overline{v_0}v0​​的计算,首先从构造的图来看,v0v_0v0​作用于v3v_3v3​和v2v_2v2​, 而v3=sin⁡v0v_3 = \sin{v_0}v3​=sinv0​,所以在反向模式里,如上图所示,标红的第一次计算v0‾=∂y∂v3∂v3∂v0=v3‾∂v3∂v0\overline{v_0}=\frac{\partial y}{\partial v_3}\frac{\partial v_3}{\partial v_0}=\overline{v_3}\frac{\partial v_3}{\partial v_0}v0​​=∂v3​∂y​∂v0​∂v3​​=v3​​∂v0​∂v3​​,第二次计算v0‾=∂y∂v3∂v3∂v0+∂y∂v2∂v2∂v0=v0‾+v2‾∂v2∂v0\overline{v_0}=\frac{\partial y}{\partial v_3}\frac{\partial v_3}{\partial v_0}+\frac{\partial y}{\partial v_2}\frac{\partial v_2}{\partial v_0}=\overline{v_0}+\overline{v_2}\frac{\partial v_2}{\partial v_0}v0​​=∂v3​∂y​∂v0​∂v3​​+∂v2​∂y​∂v0​∂v2​​=v0​​+v2​​∂v0​∂v2​​,同理,可得到v‾−1\overline{v}_{-1}v−1​的结果

4.3 小结

对于一个函数f:Rn→Rmf : R^n \to R^mf:Rn→Rm,假设计算函数fff的所有operation操作总和记做ops(f)ops(f)ops(f),则计算一个m×nm×nm×n的雅可比导数矩阵,自动微分的前向计算需要ncncnc次ops(f)ops(f)ops(f)操作,反向模式需要mcmcmc次ops(f)ops(f)ops(f)操作,其中c<6c < 6c<6,通常c∼[2,3]c ∼ [2, 3]c∼[2,3],所以当m≪nm ≪ nm≪n的时候,反向模式更加有效,相反,则前向模式更加有效,但是一般对于DL模型,输入变量参数都有上亿级别的变量,则反向模式效率更高。

5 参考

https://arxiv.org/pdf/1502.05767.pdf
http://dlsys.cs.washington.edu/pdf/lecture4.pdf

计算机求导方法:自动微分(Automatic Differentiation)相关推荐

  1. 如何在python中表示微分_Python实现自动微分(Automatic Differentiation)

    什么是自动微分 自动微分(Automatic Differentiation)是什么?微分是函数在某一处的导数值,自动微分就是使用计算机程序自动求解函数在某一处的导数值.自动微分可用于计算神经网络反向 ...

  2. 自动微分(Automatic Differentiation)

    目录 什么是自动微分 手动求解法 数值微分法 符号微分法 自动微分法 自动微分Forward Mode 自动微分Reverse Mode 参考引用 现代深度学习系统中(比如MXNet, TensorF ...

  3. 自动微分(Automatic Differentiation)简介

    现代深度学习系统中(比如MXNet, TensorFlow等)都用到了一种技术--自动微分.在此之前,机器学习社区中很少发挥这个利器,一般都是用Backpropagation进行梯度求解,然后进行SG ...

  4. 自动微分 ​​​​​​​​​​​​​​Automatic Differentiation

    目录 一.概述 二.原理 2.1 前向模式 2.2 后向模式 2.3 前向 VS 反向 三.Pytorch自动微分举例 四.Ref 记录自动微分的知识点. 一.概述 计算机实现微分功能, 有以下四种方 ...

  5. 自动微分(Auto differentiation)

    1.自动微分是干什么的: 自动微分现在已经是深度学习框架的标配,我们写的任何模型都需要靠自动微分机制分配模型损失信息,从而更新模型.简言之,就是在模型更新计算梯度的时候会用到自动微分. 在数学和计算机 ...

  6. 矩阵论思维导图_矩阵求导与矩阵微分

    矩阵求导与矩阵微分 符号定义 ​ 使用大写的粗体字母表示矩阵 ​ 使用小写的粗体字母表示向量 ,这里默认为列向量 ​ 使用小写的正体字母表示标量 需要明白的是,矩阵求导的意义在哪来,我们回想一下函数求 ...

  7. 二元函数对xy同时求导_矩阵求导与矩阵微分

    矩阵求导与矩阵微分 符号定义 ​ 使用大写的粗体字母表示矩阵 ​ 使用小写的粗体字母表示向量 ,这里默认为列向量 ​ 使用小写的正体字母表示标量 需要明白的是,矩阵求导的意义在哪来,我们回想一下函数求 ...

  8. 机器学习 标量、向量、矩阵的求导 PyTorch自动求导

    1 说明 本文是学习Dive into Deep Learning中相应内容做出的总结和一些实现代码,原文链接:矩阵计算. 2 求导 学习PyTorch的自动求导之前首先需要知道求导的过程. 注意:可 ...

  9. 高等数学——复杂函数的求导方法

    本文始发于个人公众号:TechFlow,原创不易,求个关注 上一篇文章我们复习了函数求导的定义和一些常见函数的导数,今天这篇文章我们回顾一下复杂函数的求导方法.先强调一下,今天的文章很重要,想要看懂机 ...

最新文章

  1. Linux之软件卸载 apt-get
  2. 【专家观点】张亚勤、张宏江:人工智能的未来是什么?
  3. java nio ssl_java连接MQTT+SSL服务器
  4. ue默认高亮mysql_UE设置打开文件的默认高亮语言
  5. MS的完整形式是什么?
  6. 当翻译变成了文本编辑。。。
  7. Flex手机开发系列一:新建Flex手机项目并打包
  8. Real World Haskell 第四章 函数式编程
  9. 【Android学习笔记】【Android开发环境搭建】安装JDK
  10. unity中程序的延时
  11. 教你快速使用VSCode编写HTML文件
  12. 车金融|合同中心系统的前世今生
  13. 老外用VB6写的Windows驱动备份软件
  14. 开心农场最新外挂助手下载
  15. 本地打印后台处理程序服务没有运行
  16. 电脑显示网络2连接服务器失败,崩坏学园2连接服务器失败 连接不上网络怎么办...
  17. ZGF建筑事务所公布波特兰国际机场新航站楼设计方案,木构屋顶展现自然景观
  18. Qt QTextStream
  19. OpenMV:17笑脸检测
  20. public static void 可以写成 static public void

热门文章

  1. STM32人脸识别系统设计(程序代码+论文)
  2. “5G通达,AI赋能“ AI在网络规划中的应用实践(人工智能应用案例)
  3. 解决JPEGImageEncoder生成的图片全黑的问题
  4. 计算机科学与技术毕业论文格式,计算机科学与技术毕业论文格式示例.docx
  5. Python环境搭建(一)
  6. JavaOOP(面向对象)学习体会
  7. C语言核心知识点大汇总
  8. 有效 360 度反馈系统的关键
  9. zte手机android手机怎么刷机,ZTE中兴U880手机刷机详细图文教程
  10. 5G安全的全球统一认证体系和标准演进