0
点赞
收藏
分享

微信扫一扫

从零实现深度学习框架——常见运算的计算图


引言

本着“凡我不能创造的,我就不能理解”的思想,​​本系列​​文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导。

要深入理解深度学习,从零开始创建的经验非常重要,从自己可以理解的角度出发,尽量不适用外部完备的框架前提下,实现我们想要的模型。​​本系列​​​文章的宗旨就是通过这样的过程,让大家切实掌握深度学习底层实现,而不是仅做一个调包侠。
本系列文章首发于微信公众号:JavaNLP

本文介绍常见运算的计算图。

计算图直观地表示了计算过程。通过观察反向传播的梯度流动,可以帮助我们理解反向传播的推导过程。

我们会利用计算图来实现自动求导工具。首先我们看一下常见运算操作的计算图。

加法

从零实现深度学习框架——常见运算的计算图_反向传播

从零实现深度学习框架——常见运算的计算图_深度学习_02求这个运算的梯度比较简单,易得从零实现深度学习框架——常见运算的计算图_矩阵乘法_03

从零实现深度学习框架——常见运算的计算图_反向传播_04为经过反向传播传递到从零实现深度学习框架——常见运算的计算图_矩阵乘法_05节点上的梯度。

减法

从零实现深度学习框架——常见运算的计算图_深度学习_06

从零实现深度学习框架——常见运算的计算图_反向传播_07 可得从零实现深度学习框架——常见运算的计算图_机器学习_08

乘法

从零实现深度学习框架——常见运算的计算图_反向传播_09

从零实现深度学习框架——常见运算的计算图_机器学习_10 的梯度也比较简单,易得从零实现深度学习框架——常见运算的计算图_pytorch_11

此时,反向传播时会将上游传来的梯度乘以当前路径上计算出来的梯度。

除法

从零实现深度学习框架——常见运算的计算图_pytorch_12

从零实现深度学习框架——常见运算的计算图_深度学习_13的梯度稍微有点复杂,从零实现深度学习框架——常见运算的计算图_机器学习_14

我们现在看到的都是单变量,其实也可以是多变量(向量、张量或矩阵)。在多变量时,只需要独立计算向量中各个元素,即,向量的各个元素独立于其他元素进行对应元素的计算。在下文的矩阵乘法时会详细介绍。

分支

严格来说,分支并不是我们常见运算的一种。但是有些情况下很有用,比如进行广播操作时。

从零实现深度学习框架——常见运算的计算图_深度学习_15

分支是最简单的复制形式,它的反向传播是上游传来的梯度之和。

Repeat

上面的分支操作有两个副本(或者分支),也可以扩展为从零实现深度学习框架——常见运算的计算图_机器学习_16个副本,此时称为复制(Repeat)。

从零实现深度学习框架——常见运算的计算图_反向传播_17

如上图,将长度为从零实现深度学习框架——常见运算的计算图_机器学习_18的数组复制了从零实现深度学习框架——常见运算的计算图_机器学习_16份,这个复制操作可以看成是从零实现深度学习框架——常见运算的计算图_机器学习_16个分支操作,所以它的反向传播可以通过从零实现深度学习框架——常见运算的计算图_机器学习_16个梯度的总和。

从零实现深度学习框架——常见运算的计算图_矩阵乘法_22

如果通过Numpy实现的化:

import numpy as np

D, N = 8, 7
x = np.random.randn(1,D)
y = np.repeat(x, N, axis=0) # axis=0 沿着行的方向复制N份,变成了(N,D)
# 上面是正向传播
# 下面是梯度
dy = np.random.randn(N,D) # y的梯度一定和y的维度保持一致
dx = np.sum(dy, axis=0, keepdims=True) # 同理,x的梯度也和x保持一致,这里变成了(1,D)

从零实现深度学习框架——常见运算的计算图_机器学习_23

上图是简单介绍一下Numpy中axis的概念。当数组是1D的时候,只有一个轴,所以0轴的方向和2D的不同,要注意一下。

Numpy中的广播会复制数组的元素,可以通过这里的复制操作来表示。

Sum

Sum(求和)也是我们在深度学习中常用的运算。加法操作可以看成是求和的特殊形式。

考虑对一个从零实现深度学习框架——常见运算的计算图_深度学习_24对数组沿着第行的方向求和,此时正向传播和反向传播如下所示。

从零实现深度学习框架——常见运算的计算图_pytorch_25

和加法一样,反向传播时将梯度(拷贝)分配到所有的箭头上,Sum操作是上面介绍的复制操作的逆向操作。即Sum的正向传播相当于复制操作的反向传播;Sum的反向传播相当于复制操作的正向传播。

我们也看一下通过Numpy实现的例子。

D, N = 8, 7
# 正向传播
x = np.random.randn(N, D)
y = np.sum(x, axis=0, keepdims=True) # 变成了(1,D)
# 反向传播
dy = np.random.randn(1, D) # 维度和y保持一致
dx = np.repeat(dy, N, axis=0) # 复制成了(N,D)

Matmul

Matmul是矩阵乘法(Matrix Multiply),比如,考虑从零实现深度学习框架——常见运算的计算图_pytorch_26这个运算。从零实现深度学习框架——常见运算的计算图_pytorch_27的形状分别是从零实现深度学习框架——常见运算的计算图_机器学习_28从零实现深度学习框架——常见运算的计算图_深度学习_29从零实现深度学习框架——常见运算的计算图_反向传播_30

从零实现深度学习框架——常见运算的计算图_深度学习_31

它的反向传播稍微有点复杂。我们先来了解下雅可比矩阵(Jacobian matrix)。

从零实现深度学习框架——常见运算的计算图_反向传播_32

用每个从零实现深度学习框架——常见运算的计算图_机器学习_33对每个从零实现深度学习框架——常见运算的计算图_反向传播_34计算偏微分,计算得到的矩阵高度是从零实现深度学习框架——常见运算的计算图_机器学习_33的个数,宽度是从零实现深度学习框架——常见运算的计算图_反向传播_34的个数。

从零实现深度学习框架——常见运算的计算图_pytorch_26展开得:
从零实现深度学习框架——常见运算的计算图_pytorch_38

这里假设我们要计算从零实现深度学习框架——常见运算的计算图_pytorch_39从零实现深度学习框架——常见运算的计算图_反向传播_34的导数从零实现深度学习框架——常见运算的计算图_机器学习_41

我们先计算从零实现深度学习框架——常见运算的计算图_机器学习_42

接着计算从零实现深度学习框架——常见运算的计算图_机器学习_33从零实现深度学习框架——常见运算的计算图_反向传播_34的导数从零实现深度学习框架——常见运算的计算图_pytorch_45,根据雅克比矩阵,有
从零实现深度学习框架——常见运算的计算图_深度学习_46
看起来挺复杂,但是如果我们先把从零实现深度学习框架——常见运算的计算图_机器学习_33中第从零实现深度学习框架——常见运算的计算图_反向传播_48个元素从零实现深度学习框架——常见运算的计算图_pytorch_49的等式写出来,就会很简单,如:
从零实现深度学习框架——常见运算的计算图_pytorch_50
所以 从零实现深度学习框架——常见运算的计算图_pytorch_51,把从零实现深度学习框架——常见运算的计算图_pytorch_45完整的写出来,有
从零实现深度学习框架——常见运算的计算图_深度学习_53
所以从零实现深度学习框架——常见运算的计算图_反向传播_54 ,这就解释了为什么计算矩阵乘法的反向传播时,有个参数需要转置的。

从零实现深度学习框架——常见运算的计算图_反向传播_55

从零实现深度学习框架——常见运算的计算图_反向传播_34的形状是从零实现深度学习框架——常见运算的计算图_机器学习_28从零实现深度学习框架——常见运算的计算图_机器学习_41的形状和它保持一致,也是从零实现深度学习框架——常见运算的计算图_机器学习_28

从零实现深度学习框架——常见运算的计算图_机器学习_60的形状和从零实现深度学习框架——常见运算的计算图_机器学习_33一样,是从零实现深度学习框架——常见运算的计算图_反向传播_30

从零实现深度学习框架——常见运算的计算图_机器学习_63的形状是从零实现深度学习框架——常见运算的计算图_反向传播_64

在推导上面的公式时,不要被写法的复杂所迷惑了,只要我们展开把等式写出来,或者用一个简单的比如从零实现深度学习框架——常见运算的计算图_矩阵乘法_65的矩阵自己去推,就可以知道规律。

上面把从零实现深度学习框架——常见运算的计算图_机器学习_66写出来后,计算从零实现深度学习框架——常见运算的计算图_pytorch_67就很简单了,因为此时只与从零实现深度学习框架——常见运算的计算图_反向传播_68有关,对于从零实现深度学习框架——常见运算的计算图_深度学习_69剩下的元素的导数都是0,变成了从零实现深度学习框架——常见运算的计算图_pytorch_70

下面介绍几个简单的一元操作。

Pow

计算从零实现深度学习框架——常见运算的计算图_机器学习_71,我们把从零实现深度学习框架——常见运算的计算图_反向传播_34看成是变量,从零实现深度学习框架——常见运算的计算图_矩阵乘法_73看成是常数。只有一个变量,因此定义为一元操作。从零实现深度学习框架——常见运算的计算图_反向传播_74,一元操作比较简单,因此正向传播和反向传播画到一张图里面。

从零实现深度学习框架——常见运算的计算图_pytorch_75

Log

取对数(Log),一般指的是以指数从零实现深度学习框架——常见运算的计算图_机器学习_76为底。从零实现深度学习框架——常见运算的计算图_反向传播_77,那么从零实现深度学习框架——常见运算的计算图_反向传播_78

从零实现深度学习框架——常见运算的计算图_pytorch_79

Exp

指数函数最简单了从零实现深度学习框架——常见运算的计算图_深度学习_80从零实现深度学习框架——常见运算的计算图_矩阵乘法_81,原样返回。

从零实现深度学习框架——常见运算的计算图_机器学习_82

Neg

Neg是取负数的意思,从零实现深度学习框架——常见运算的计算图_反向传播_83从零实现深度学习框架——常见运算的计算图_深度学习_84,可以理解为从零实现深度学习框架——常见运算的计算图_矩阵乘法_85

从零实现深度学习框架——常见运算的计算图_pytorch_86


举报

相关推荐

0 条评论