自动微分(Automatic Differentiation):算法篇
source link: https://lotabout.me/2023/Auto-Differentiation-Part-1-Algorithm/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
自动微分(Automatic Differentiation,下面简称 AD)是用来计算偏导的一种手段,在深度学习框架中广泛使用(如 Pytorh, Tensorflow)。最近想学习这些框架的实现,先从 AD 入手,框架的具体实现比较复杂,我们主要是理解 AD 的思想并做个简单的实现。
AD 能干什么?
AD 能用来求偏导值的。
例如有一个 R2↦RR2↦R 的函数(函数有 2
个输入,1
个输出):f(x,y)f(x,y) ,对于 xx、yy 的偏导分别计为
∂f∂x∂f∂x 和 ∂f∂y∂f∂y。通常我们不关心偏导的解析式,只关心具体某个 xixi, yiyi 取值下偏导
∂f∂x|x=xi,y=yi∂f∂x|x=xi,y=yi 和
∂f∂y|x=xi,y=yi∂f∂y|x=xi,y=yi 的值。
另外注意在神经网络在使用“梯度下降”学习时,我们关心的是“参数 ww”的偏导。而不是“输入 xx”的偏导。假设有 f(x)=ax2+bf(x)=ax2+b 这样的神经网络,损失函数是 l(f(x),y)l(f(x),y),现在给了一个样本标签对(x0,y0)(x0,y0),我们要计算的是 ∂l∂a|x=x0,y=y0,a=a0,b=b0∂l∂a|x=x0,y=y0,a=a0,b=b0 和 ∂l∂b|x=x0,y=y0,a=a0,b=b0∂l∂b|x=x0,y=y0,a=a0,b=b0。在对号入座时要牢记这点。
为什么用 AD?
求偏导有很多做法,例如 symbolic differentiation 使用“符号计算” 得到准确的偏导解析式,但对于复杂的函数,偏导解析式会特别复杂,占用大量内存且计算慢,并且通常应用也不需要解析式;再比如 numerical differentiation 通过引入很小的位移 hh,计算 f(x+h)−f(h)hf(x+h)−f(h)h 得到偏导,这种方法编码容易,但受 float 误差影响大,且计算慢(有几个输入就要算几次 ff)。
AD 认为所有的计算最终都可以拆解成基础操作(如加减乘除,exp
, log
, sin
,
cos
等基本函数)的组合。然后通过链式法则
逐步计算偏导。这样使用方只需要正常组合基础操作,就能自动计算偏导,且不受 float
误差的影响,还可以复用一些中间结果来减少计算量(等价于动态规划)。
链式法则回顾
AD 的数学基础就是链式法则(chain rule):
对于函数 z=h(x)z=h(x),如果有子函数 y=f(x)y=f(x),满足 z=h(x)=g(y)=g(f(x))z=h(x)=g(y)=g(f(x)),则求偏导有如下关系:
上述两种写法是一致的。另外如果涉及多个变量,例如 z=f(x,y)z=f(x,y),而 x=g(t),y=h(t)x=g(t),y=h(t),则有:
这里之所以成立,应该是因为 x,yx,y 是独立的(没有深究)。
AD 具体是怎么做的?
AD 其实就是链式法则的具体实现。它有两种模式:前向模式(Forward accumulation)和反向模式(Reverse accumulation),我们只考虑反向模式。那么具体是怎么工作的呢?考虑下面的复杂函数[1]
上述公式中,我们用了一些子函数来简化整个函数,画成图如下左图:
于是为了求偏导 ∂f∂x1∂f∂x1 与 ∂f∂x2∂f∂x2 的值,我们可以先定义中间值 vi¯=∂f∂vivi¯=∂f∂vi,根据链式法则,有
于是计算时需要先“前向”计算一次,得到 v1,v2,⋯,v5v1,v2,⋯,v5 的值,之后再“后向”计算 v5¯,v4¯,⋯,v1¯v5¯,v4¯,⋯,v1¯ 的值(参考上右图),最终得到的 v1¯,v2¯v1¯,v2¯ 就是我们要计算的结果。而需要先“前向”计算一次,是因为后向计算时会用到前向的值,例如 v2¯=v4¯v1v2¯=v4¯v1 就需要用到前向的v1v1。
注意图里 v1¯v1¯ 的计算依赖了链式法则中多变量的情况,等于它所有后继节点偏导(即图中的 va1¯,vb1¯v1a¯,v1b¯)的和。
多输出情形
多输出的情况偏理论,跳过也影响不大。神经网络的输出,在训练时最终都会接入损失函数,得到 loss
值,一般都是一个标量,可以认为神经网络的学习总是单输出的。
在多输出的情况下,链式法则依然生效。
刚才都假设函数是 Rn↦RRn↦R,即 n
个输入,1
个输出。考虑 m
个输出,即 Rn↦RmRn↦Rm 的情况。假设输入是
x1,x2,⋯,xnx1,x2,⋯,xn,而输出是
f1(x1,⋯,xn),f2(x1,⋯,xn),⋯,fm(x1,⋯,xn)f1(x1,⋯,xn),f2(x1,⋯,xn),⋯,fm(x1,⋯,xn)。此时我们要计算的偏导就不是 n
个值了,而是一个 m×n
的矩阵[2],每个元素 Jij=∂fi∂xjJij=∂fi∂xj。这个矩阵一般称为
Jacobian Matrix:
其中 ∇Tfi∇Tfi 代表 fifi 对于所有输入的偏导(行向量)的转置。
考虑函数 g:Rn↦Rkg:Rn↦Rk,h:Rk↦Rmh:Rk↦Rm,而函数 ff 是二者的组合: f(x)=h∘g(x)=h(g(x))f(x)=h∘g(x)=h(g(x)),则有
此时 JJ 中的每个元素:
可以看到和 Jh⋅JgJh⋅Jg 的结果是一致的。不过这些性质其实都是链式法则的内容,这里也只是扩充视野。
AD 把复杂的函数看成是许多小函数的组合,再利用链式法则来计算偏导。它有不同的模式,其中“后向模式”在计算偏导时先“前向”计算得到一些中间结果,之后再“反向”计算偏导。从工程的视角看,由于中间的偏导可以重复利用,能减少许多计算量。深度学习的反向传播算法(BP)是 AD 的一种特例。
所以回过头来,什么是 AD?AD 就是利用链式法则算偏导的一种实现。
- A Review of automatic differentiation and its efficient implementation 一篇综述,对 AD “是什么”、“为什么”的描述比较清晰
- What is Automatic Differentiation? Youtube 视频,回过头来看它介绍了 AD 的各个方面,但第一次直接看还是比较懵的,视频也有对应的综述论文,也是比较好的补充材料
- Lecture 4 - Automatic Differentiation 一个 DL 的课程,前面的内容和其它材料差不多,最后通过扩展计算图来计算 AD 的方式对理解一些框架的具体实现很有帮助
Recommend
-
30
I was playing with AutoGrad.jl and Zygote.jl , they both look awesome, and AutoGrad.jl is already applied to the m...
-
60
README.md ceviche
-
52
简介 机器学习工具包(PyTorch/TensorFlow)一般都具有自动微分(Automatic Differentiation)机制,自动微分方法包括
-
19
AutoDiff Automatic Differentiation via Contour Integration Motivation: There has previously been some back-and-forth among scientists about whether biological networks such as brains might comp...
-
14
If you have any experience with machine learning or its sub-discipline of deep learning, you probably know that we usually use gradient descent and its variants in the process of training our models and neural networks. I...
-
26
Continuing from my last post on implementing forward-mode automatic differentiation (AD) using C# operator overloading , th...
-
24
Automatic differentiation is the foundation upon which deep learning frameworks lie. Deep learning models are typically trained using gradient based techniques, and autodiff makes it easy to get gradients, even from enorm...
-
13
当前,PyTorch、TensorFlow等机器学习框架已经成为了人们开发的重要工具。计算反向传播、贝叶斯推理、不确定性量化和概率编程等算法的梯度时,我们需要把所有的代码以微分型写入框架内。这对于将机器学习引入新领域带来了问题:在物理模拟、游戏引...
-
6
自动微分(Automatic Differentiation):实现篇前情提要:在算法篇中,我们介绍了深度学习领域基本都是使用自动微分(Automati...
-
2
Understanding Automatic Differentiation in 30 lines...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK