自动微分方法简介

假设我们定义了一个方程: f(x,y)=x2y+y+2 f ( x , y ) = x 2 y + y + 2 ,我们需要对 x x y 求偏导,此时通常由以下几种做法:

  • 手动求导
  • 符号微分
  • 数值微分
  • 前向自动微分
  • 反向自动微分

1. 手动求导

拿起纸笔应用链式法则逐层求导即可。缺点是易于出错。

2. 符号微分

下图是符号微分方法在函数 g(x,y) g ( x , y ) 上的运算示例。

symbolic

链式法则的运算过程与右边这棵树的生成过程对应。计算时首先从叶节点开始,逐层向上。

当函数比较复杂时,由该方法生成的树规模十分庞大,且难以进行简化。另外,符号微分无法无法对一些迭代计算的表达式进行计算:

def my_func(a, b): z=0
    for i in range(100):
        z = a * np.cos(z + i) + z * np.sin(b - i)
    return z

3. 数值微分

最简单的方法就是对偏导数进行数值近似。函数 h(x) h ( x ) x0 x 0 点处的导数为:

h(x)=limxx0h(x)h(x0)xx0=limϵ0h(x0+ϵ)h(x0)ϵ h ′ ( x ) = lim x → x 0 h ( x ) − h ( x 0 ) x − x 0 = lim ϵ → 0 h ( x 0 + ϵ ) − h ( x 0 ) ϵ

在计算微分的时候,取一个很小的 ϵ ϵ 代入计算即可。但由此得到的结果不够准确,当函数比较复杂时尤为如此。

4. 前向自动微分

前向自动微分结合了符号微分与数值微分的思想,主要依赖 dual numbers ϵ ϵ 实现, ϵ ϵ 是一个无穷小的数, ϵ0 ϵ ≠ 0 但是 ϵ2=0 ϵ 2 = 0

注意,因为有:

h(a+bϵ)=h(a)+b×h(a)ϵ h ( a + b ϵ ) = h ( a ) + b × h ′ ( a ) ϵ

因此,我们可以通过计算 h(a+ϵ) h ( a + ϵ ) 来求解 h(a) h ′ ( a )

下图为对 f(x,y) f ( x , y ) 在点 x=3,y=4 x = 3 , y = 4 处求偏导的计算过程。要求 f(3+ϵ,4) f ( 3 + ϵ , 4 ) ,所得 dual number 的第一部分对应于 f(3,4) f ( 3 , 4 ) ,第二部分对应于  f x(3,4) ∂   f ∂   x ( 3 , 4 )

forward

需要说明的是,如果要求解  f y(3,4) ∂   f ∂   y ( 3 , 4 ) ,我们必须按照流程从头到尾再计算一遍。

总的来说,前向自动微分要比数值微分精确得多。但真如上一段所说,每对一个变量求解微分,我们就需要从叶子节点开始计算到根节点,当变量数很大时,前向自动微分方法就不够实用了。

5. 反向自动微分

反向自动微分正是TensorFlow采用的自动微分方法。该方法共分为两个阶段完成:

  • 依照 forward direction (输入->输出,叶节点->根节点) 计算图中每个节点的取值
  • 依照 reverse direction 计算所有的导数取值

下图为 reverse direction 的计算过程示意。

reverse

  • n7 n 7 : 输出节点, f=n7 f = n 7 =>  f n7=1 ∂   f ∂   n 7 = 1
  • n5 n 5 :  f n5= f n7× n7 n5 ∂   f ∂   n 5 = ∂   f ∂   n 7 × ∂   n 7 ∂   n 5 ,我们知道  f n7=1 ∂   f ∂   n 7 = 1 ,而 n7=n5+n6 n 7 = n 5 + n 6 ,因此  n7 n5=1 ∂   n 7 ∂   n 5 = 1 =>  f n5=1×1=1 ∂   f ∂   n 5 = 1 × 1 = 1
  • n4 n 4 :  f n4= f n5× n5 n4 ∂   f ∂   n 4 = ∂   f ∂   n 5 × ∂   n 5 ∂   n 4 ,因为 n5=n4×n2 n 5 = n 4 × n 2 ,所以  n5 n4=n2 ∂   n 5 ∂   n 4 = n 2 =>  f n4=1×n2=4 ∂   f ∂   n 4 = 1 × n 2 = 4

总的来说,反向自动微分法是一个非常清大且精确的技术,当输入输出维度较大时,优势尤为明显。具体来说

  • 该方法只需要 forward pass + reverse pass 两次计算就可以求得所有输出对所有输入的导数
  • 能够处理 functions defined by arbitrary code (如,上面的代码示例)
  • 可计算不完全可导的函数在可导处的导数值

autodiff

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值