雷锋网按:本文原作者Aaron Yang,原载于知乎专栏。雷锋网已获得作者授权。
导读:首先我想在这里声明的是,本篇文章针对的是一些已经具备一定神经网络知识的人。意在帮助大家梳理神经网络中涉及的数学知识,以及理解其物理含义。希望大家读过之后,可以使大家对于神经网络有更多角度的理解,帮助大家推导以及理解其中的数学公式。(本篇文章在叙述方式上多以白话为主,意在让大多数人有形象的概念,所以在严谨性与通俗性上难免会出现失衡问题,希望大家理解。分享的目的即分享,非教授!)
1. 线性代数
矩阵乘以向量的物理含义
矩阵乘法我更喜欢称作线性转换。一个矩阵乘以向量中,矩阵相当于一个转换函数,而向量是一个输入,已知了输入和函数,我们就可以知道输出。这里需要强调的是,向量共有两种形式,一种为列向量,一种为行向量。在默认情况下,向量是指列向量。大部分的国内教材中,并没有特意提到这一点。很多人接触到编写代码时,都是以行向量的形式开始学习,导致后续有很多概念产生混淆。在本文中,若无特殊说明,向量的形式默认为列向量。
首先我们先看以下的 2 道热身题:
1. 假设读者并不知道矩阵乘法的运算准则,能否在假想的几何空间中,快速地反应出答案是多少呢?给大家 30s。(记住,不可以通过运算法则来进行计算)
2. 同样地,利用假想的几何空间想象,是否可以立即解答出矩阵是什么?
如果读者可以快速解答出上面的问题,那么恭喜您,您已经了解了线性代数空间转换的本质;如果没有解答出,那就是我写这篇文章的意义。
先抛开上面两道题,这里来介绍一下矩阵。
线性代数与空间几何是存在紧密的联系的。基本所有的线性代数都有其对应的几何表示方法。理解几何,是理解线性代数的核心所在。以二维空间作为例子,与是二维空间的单位基向量。任何的向量都是由这两个单位基向量线性组合而成,并表示出来,例如。
现在,我们来看一张动图:
更多动图的信息请关注 3Blue1Brown主页,里面有大量冲破你数学世界观的知识。3Blue1Brown 还有视频集。B 站有做了很赞的汉化,不过更鼓励大家去看英文原版视频。
YouTube 视频集链接
B 站汉化视频集链接
在这张动图的开始的阶段,绿色向量代表 ,而红色向量代表 。我们盯住这两个基向量,观察到在动图的末尾,这两个向量分别落在了 与 ,那么,这两个基向量组成的坐标系也随着这两个基向量的变换而线性变换,形成了动图末尾中蓝色直线组成的二维坐标。假设经历了上图的坐标变换,原来的向量 ,现在到了何处呢?
通过仔细观察动图 (一点一点数格子) 我们可以看到,原来的向量 变换为向量 。
我们来继续看看表示方法:
原来: ,变换后: 。
这其中的区别就是基向量不一样了,而线性组合的系数 与 保持固定不变。
我们把变换后的基向量放在一起,变为矩阵:
这就是矩阵的由来,其实质就是将坐标整体线性变换。向量 在经过线性变换 变为向量 表示形式为:
(注意:这里的表示顺序为变换矩阵在左,向量为列向量在右侧。)
我们在来看另一幅动图来实践一下,找到这幅动图的线性变换矩阵是什么?
根据上面的方法,锁定绿色与红色基向量末尾的位置,这幅动图的线性变换矩阵为 :
而其原来所有坐标系上的向量都随之变换发生改变。
现在再回头看看上面的两道题?是否能够通过想象的空间去快速找到答案?
上面我们讲的是方阵,那么如果不是方阵呢?比如一个 的矩阵,或者一个 的矩阵呢? (以下我们只用中括号来代表具体矩阵的形状,具体数字并不重要。)
我们来以 矩阵形式举例,如下所示:
的矩阵的物理含义就是把一个向量从二维表示方法转换到三维表示。而转换矩阵的每一列就代表:将二维空间对应的基向量转换到三维的样子。将这种变换规律映射到其他变换的二维向量;同样地, 矩阵物理含义就是将一个向量从三维表示转换成二维表示。转换矩阵每一列代表:三维空间的基向量映射到二维空间之后的样子。将这种变换规律映射到其他变换的三维向量。
现在,我们再进行下一步操作。如果我们假设让一个 4 维向量,先转化为 3 维向量,在转化为二维向量,那么它的形式是什么样子的呢?
第一步: 第二步:
将两步合并到一起为:
通过以上形式,我们可以发现如果将一个列向量经过多次线性转换,他的顺序应该是从右至左的顺序。这就是标准的线性代数书中所讲到的连续线性变换的形式,从右至左也是线性代数数学家习惯的顺序。
但是,在很多神经网络包括深度学习网络的课程中我们可以看到,更符合我们阅读的顺序是将一个输入数据拿进来之后经过一次矩阵转换,从左至右得到输出结果。他们之间有什么联系呢?
通过观察我们可以知道,这其中最大的原因在于数据的形式,也就是上文中提到的每一个样本表示方法是列向量还是行向量。如果是列向量,变换的顺序就是从右至左;如果是行向量,变换顺序就是从左至右。而相应的矩阵形状也发生反转。
对比
所有形式为矩阵乘以矩阵
神经网络中,大家都希望最终的形式为矩阵乘以矩阵,不希望中间有任何向量的存在,这样显得更酷,实际上计算也更快。这很简单,现在我们只差最后一步。当我们把所有数据放在一起,还是如上方有 个 维行向量形式的数据,我们将这些行向量数据堆叠在一起形成 的矩阵,经过多个矩阵的变换之后输出为一个 的矩阵。这样,在计算过程中,全部为不同形状的矩阵。当然,大家也可以想想如果是列向量该是什么形式。
以上内容想说明的就是,无论是上方哪一种形式,都是正确的。关键看输入的数据是什么形式,形式决定了数据变换的顺序,以及设计矩阵的形状。
通过以上的形式,其实神经网络前向传导和向量在不同维度间的连续线性变换及其相似。唯一不同的一点就在于,在每次线性转换后,神经网络可以加一个非线性激活函数,使线性转换变为非线性转换。实际上,也就这么点区别。而非线性激活函数并不会改变数据的形状,对后续矩阵乘法不造成任何影响。
小结一下上面线性代数部分我们发现了什么:
线性代数中的向量默认形式是列向量。
矩阵的实质就是将坐标整体线性变换。
矩阵的组合以列向量组合在一起,其代表各自的基向量变换之后的新向量是什么。
矩阵与向量相乘,矩阵与矩阵相乘,顺序很重要,其决定权在于实际问题中样本的表达形式,是行向量还是列向量。
神经网络的前向传导与线性代数中连续对于向量的线性变换过程极其相似,只是在层与层之间多了非线性激活函数。
神经网络求的是什么?其实就是上方这么多矩阵中每一个位置的数字是多少?这就是我们最终的目的。那么如何求?这就需要微积分中链式法则的知识了。
2. 微积分
链式反向推导之所以很头大,很大原因在于它将微积分求导和矩阵知识揉在一起。我尽量用尽量少的公式,记住极少的关键点,帮助大家去顺利的推导神经网络中运用到的链式推导。这样对于公司的面试,还是实际科研过程中均不会发蒙。
明确目标
我们都知道,神经网络的目的是训练网络中的参数,即矩阵中每一个位置的数值。我们通过构建对于这些参数的损失函数,最终找到损失函数 最小值时的参数。最初的想法就是高中学习的求导的思路,只要导数等于 (这里涉及矩阵求导),就找到了极值,也就找到了答案。但是由于网络巨大(输入数据维度大,每层网络节点多,网络层数多),计算资源消耗的也巨大(涉及矩阵求逆),以现在的设备,我们并不能一步到位的求出最小值,这也是为什么我们在神经网络中使用梯度下降法一步一步逼近最小值的原因。其公式如下:
这就是梯度下降的公式。 就是我们要所求的参数,它是一个转换矩阵。而 是一个标量,即一个数字(以下用 来表示)。 是通过迭代一步一步优化出来的,在初始的时候随机赋值。所以我们的目标就是搞清楚 是如何求出来的。
细化在神经网络每一层,目标就是:
目标明确了,那么我们是如何牵扯到链式求导呢?
明确几个定义
先上图,一个前馈神经网络如下所示:
这里展示了一个非常简单的三层神经网络,更多的层次大家可以开脑洞。图中的的公式大家应该已经非常熟悉。 代表神将网络每层的输出值,是一个向量(一般是行向量);第一层的输出值就是输入值 ; 代表线性输出; 代表激活函数; 为最终的输出值;每一个字符的上表代表其层数。
这里需要特别注意地是对于不同变量的上标层数对应关系一定不要弄混淆。比如 是神经网络第 层与第 层之间的转换矩阵,即 为第 层与第 层的转换矩阵。
接下来,主角登场。我们要想知道神经网络如何反向推导,只需记住这里的唯一定义的变量 即可。
定义:
在一些翻译的变量名中叫做 “残差”。但是它是什么名字并不重要,但建议不要根据这个名字去揣测它的物理含义。如果想明白了那当然很好,但是若想不透彻很容易与其他概念弄混淆,最后云里雾里地以为自己懂了,但是自己推的时候仍然会错。总而言之,只把它当做一个定义就好,背下来了就是了。而且,在链式推导中,只需要记住这个,其他的都好推。(注意: 也是向量,其形状与 一致。)
开始真正的推导
我们的目标:逐层计算出
将目标展开:
我们看到,我们把目标分为前后两部分。
第一部分,根据 的定义可得到
第二部分,根据 的定义可以得到
所以,我们的目标 或者
到这里,我们很轻松地导出了我们目标的通项公式,是不是很简单?就是做了个分解,然后分别求导,再组合在一起,就可以了。在这里,我们可以得到另外一条很有意思的结论,那就是我们求每一层转换矩阵的导数(参数的导数)与最终目标函数 的具体形式无关,这点是不是很神奇?
(注意:我们需要验证分解的两项是否可以进行矩阵乘法运算,并且最终矩阵的形状符合规定。这里又与变量自身的形状有关。我们观察发现,在分解的第一部分中,最后一项多出了一个字符 ,这里代表转置。这个是矩阵求导的法则,通过最后公式的法则也可以验证。这部分有些复杂。但是,我们可以完全绕过去这样复杂的关系。这里有个小技巧:若记不住这两项矩阵相乘谁在前,谁在后,谁转置,谁不动。只要记住 与 的形状是一致的,在求出 与 之后,根据矩阵乘法的法则,随便试出最后相乘的形状符合 的形状即可,很快就可以试出正确答案。)
只剩最后一步
所谓反向推导,就是根据后一项的结果去计算前一项。我们 “通项公式” 搞到手了,那么最后一层的 “残差” 是多少呢?
我们用 来代表最后一层。根据 的公式,我们可以依然进行如下分解:
从这个公式中我们可以看出我们将最后一层 “残差” 又分解为两部分。下面,我们分别看看在一般的回归问题与二分类问题中 到底长什么样子。
1. 回归问题
损失函数:
求解分解后的第一部分:因为在回归问题中,最后一层是没有激活函数的,或者说激活函数为 乘以其输入值。所以,激活函数的导数就为 。则有:
求解分解后的第二部分:
所以最终,我们求得:
2. 二分类问题
损失函数:
求解分解后的第一部分:二分类问题中,激活函数 ,其导数为 。则有:
求解分解后的第二部分:
所以最终,我们求得:
我们惊奇地发现,在对于回归问题与二分类问题中,虽然损失函数与最后一层的激活函数均不一样,但是其结果居然是同一个值。这是否是巧合?也许只有深入了解为何这样设计损失函数与激活函数之后,我们才会知道答案。大家还可以想想,多分类问题的结果呢?
上述的推导中,我们也可以得到结论:在最后一层 “残差” 中,是与损失函数 和最后一层的激活函数 两项有关的。
小结一下神经网络部分的一些要点:
记住前馈网络中各个变量上标层数表达方式。各个教科书上表达可能会存在不同,一定要认真观察清楚。
牢记 的定义,是推导整个链式推导中最重要的一环。
在神经网络 层的链式推导中,我们的目标是 ,将其利用带有 项进行展开;而在最后一层 层中我们主要推导的目标是 ,利用其定义将其展开。
在经典的回归与二分类问题中,其 结果完全相同,但计算过程却完全不同。
总结
希望经过上述自己的梳理,大家对于神经网络中涉及到的数学知识有了更进一步形象化的了解。当然,本文中加入大量自己的理解,若有不同意见,欢迎大家来共享 idea。