自动微分

计算机程序的求导机制分为四种

  1. 人工计算出导数,并写成代码形式
  2. 数值计算微分,即取极限求导数
  3. 符号微分,使用表达式来计算导数
  4. 自动微分

比如下面的程序所示

import numpy as np


def sigmoid(x):
    """
    Compute sigmoid Function
    """
    return 1 / (1+np.exp(-x))


def sigmoid_grad(x):
    return np.exp(-x) / np.square(1 + np.exp(-x))


def sigmoid_numerical_grad(x, eps=1e-6):
    return (sigmoid(x+eps) - sigmoid(x)) / eps


print("Handcraft Diff is: ", sigmoid_grad(0))
print("Numerical Diff is: ", sigmoid_numerical_grad(0))

Handcraft Diff is:  0.25
Numerical Diff is:  0.2500000000349445

这几种方法存在一定问题,比如人工计算微分,当模型变大时,微分计算耗时长,容易出错;而数值微分看起来简单,但由于浮点数特性,容易出现截断错误,另外它对于梯度缩放能力较差,而机器学习模型通常比较大。符号微分能很好避免前面两者的错误,但是容易受表达式膨胀的问题

自动微分技术,指的是通过在代码执行过程中,积累数值,来计算导数。

在深度学习中,模型通过反向传播算法来在网络空间中,寻找梯度下降方向,寻找目标函数,也就是我们常说的 loss function 的最小值。

section2

在这里插入图片描述

上图展示的是一个正向传播和反向传播的过程
在这里插入图片描述

自动微分并不是数值微分

自动微分具有数值微分和符号微分的特点,但是具有不同之处

数值微分的形式如数学定义
d f ( x ) d x ≈ f ( x + δ ) − f ( x ) δ \frac{df(x)}{dx} \approx \frac{f(x+\delta)-f(x)}{\delta} dxdf(x)δf(x+δ)f(x)
但是对于n维数组,则计算复杂度为 O(n),而且这个 δ \delta δ 选择需要十分小心,过大,则数值计算的梯度不够。

数值微分由于浮点数计算原因,存在截断和近似错误
其中forward计算diff的公式为上面的公式,center计算diff的公式为
d f ( x ) d x ≈ f ( x − δ ) − f ( x + δ ) 2 ∗ δ \frac{df(x)}{dx} \approx \frac{f(x-\delta)-f(x+\delta)}{2*\delta} dxdf(x)2δf(xδ)f(x+δ)
在这里插入图片描述

最大的痛处在于,现代深度学习模型参数量庞大,数值微分引入的计算复杂度会使整个反向传播,更新参数的过程十分低效

自动微分不是符号微分

符号微分,是对原始公式进行操作,从而得到对应导数的表达式,如
d ( f ( x ) + g ( x ) ) d x − > d ( f ( x ) ) d x + d ( g ( x ) ) d x \frac{d(f(x)+g(x))}{dx} ->\frac{d(f(x))}{dx} + \frac{d(g(x))}{dx} dxd(f(x)+g(x))>dxd(f(x))+dxd(g(x))
简单的表达式,符号微分很简单,直观。但随着表达式复杂起来,符号微分得到的表达式是会很复杂的,也是常说的表达式膨胀问题 expression swell
在这里插入图片描述

自动微分

自动微分的主要思想就是, 所有导数运算到最后,就是一组有限初等运算组合而成。此外,自动微分还能处理复杂的表达形式,比如分支,循环,回溯等

下面我们来看一个例子,这是函数
f ( x 1 , x 2 ) = l n ( x 1 ) + x 1 ∗ x 2 − s i n ( x 2 ) f(x1, x2) = ln(x1) + x1*x2 - sin(x2) f(x1,x2)=ln(x1)+x1x2sin(x2)
的计算图
在这里插入图片描述

在前向求导模式中,就是经过表达式运算得到对应的值,从左至右推得对应的导数

我们假设只对x1求导,那么就有如下的求导过程(右侧)
在这里插入图片描述

然后我们可以构造一个雅各比矩阵
在这里插入图片描述

对应每一步求导,就相当于雅各比矩阵乘上一个向量
在这里插入图片描述

雅各比矩阵补充

假设我们有一个三维的向量
X = [ x 1 , x 2 , x 3 ] Y = X 2 X = [x1 , x2,x3] \\Y = X^2 X=[x1,x2,x3]Y=X2
那么对Y 求导,结果不是 2 X ,因为X是一个向量,求导得到的是一个雅各比矩阵
在这里插入图片描述

可参考 https://zhuanlan.zhihu.com/p/65609544

DUAL NUMBERS 对偶数求导法

不清楚

反向模式

主要是利用链式法则的变换

在这里插入图片描述

在 大量输入 的情况下,前向求导模式每次计算都需要O(n)。而反向求导从后往前推,相比前向模式,其计算量小

所以 Pytorch 这类框架禁掉了 tensor 对 tensor的求导。它backward一定是从一个scalar开始backward。而scalar标量值就是1个,因此反向传播在计算量上更具优势!
在这里插入图片描述

反向传播的雅各比矩阵,则是转置后,乘上一个张量
在这里插入图片描述

根据前面的计算量比较,我们可以得知,当输入比较少的时候(即雅各比矩阵比较窄,但是比较高)则适合前向模式

当输入比较多的时候(即雅各比矩阵比较宽,但是比较矮)则适合后向模式

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值