1.2 数学基础
机器学习及深度学习的理论是建立在数学基础上的。本节主要介绍了线性代数和微积分的基础知识。本书的主题是深度学习及PaddlePaddle框架的使用,所以数学部分只简明扼要地介绍与主题紧密相关的内容。如果读者已经熟悉相关知识,可以跳过本节。
1.2.1 线性代数基础
线性代数对于机器学习及深度学习极为重要。机器学习的基础就是数据,没有大量的数据也就没有了机器学习。数据中蕴含了丰富的信息,这些信息可以通过多维的视角来看待,可以说数据就是很多个维度的信息的综合体。如果要存储和计算这些数据就需要用到线性代数中的知识,包括机器学习中最常用到的向量、矩阵、张量等。下面分别介绍这些基本概念及相关的常用运算。
1.向量
在线性代数中,最基本的概念是标量(Scalar)。标量就是一个实数。比标量更常用的一个概念是向量(Vector)。向量就是n个实数组成的有序数组,称为n维向量(如公式1-1所示)。如果没有特别说明,一个n维向量一般表示一个列向量。向量符号一般用黑体小写字母a, b, c来表示。这个有序数组中的每个元素都有对应的下标。数组中的第一个元素的下标是1,第二个元素的下标是2,以此类推。通常用a1表示第一个元素,a2表示第二个元素,ai表示第i个元素。数组中的每一个元素被称为一个分量。多个向量可以组成一个矩阵。
2.矩阵
矩阵(Matrix)是线性代数中应用非常广泛的一个概念。矩阵比向量更加复杂,向量是一个一维的概念而矩阵是一个二维的概念。一个矩阵的直观认识如公式1-2所示。式中矩阵由m×n个元素组成,这些元素被组织成m行和n列。本书中矩阵使用黑体大写字母表示,例如A。矩阵中每个元素使用a ij的形式表示,例如第一行第一列的元素为a11。
特别的,一个向量也可视为大小为n×1的矩阵,如公式1-3所示,既是一个n×1矩阵,又是一个n维向量。
单位矩阵(Identity Matrix)是一种特殊的矩阵,其主对角线(Leading Diagonal,连接矩阵左上角和右下角的连线)上元素为1,其余元素为0。n阶单位矩阵In是一个n×n的方形矩阵。可以记为In=diag(1,1, …,1)。
3.向量的运算
在机器学习及深度学习中向量不仅用来存储数据,也会参与操作。向量的运算主要有两个,一个是向量的加减法,一个是向量的点乘(内积)。
向量的加减法比较容易理解。无论是加法还是减法都需要参与运算的两个向量的长度相同,其运算规则是对应位置的元素求和或者求差。例如,向量a=[a1, a2, …an]和向量b=[b1, b2, …bn]都是长度为n的向量,求和就是生成向量c=[c1, c2, …cn], c中的每一个元素都是由a和b对应位置的元素求和得到ci=ai+bi。
向量的点乘相对复杂一些,两个长度相同的向量才能做点乘。假设存在两个长度相同都为n的向量a=[a1, a2, …an]和b=[b1, b2, …bn],它们的点乘结果为一个标量c。c的值为向量a和向量b对应位置的元素的乘积求和:c=a 1× b 1+a 2× b 2+…+an× bn。向量点乘记作c=ab或记作c=a · b。点乘使用公式表示,即。通过对公式的观察会发现点乘符合交换律,即ab=ba。
4.矩阵的运算
相比于普通的算术运算,矩阵运算更加复杂。最常见的矩阵运算主要有加、减、乘、转置,而乘又分为点乘和元素乘。矩阵的加减运算是相对简单的运算。加减运算涉及两个矩阵,运算的结果生成第三个矩阵。加减运算要求运算输入的两个矩阵的规模相同(即,两个矩阵都为m行×n列),其规则就是对应位置的元素加和减。例如,假设A和B都是m行n列的矩阵,则A和B的加和减分别为:
矩阵乘法是矩阵运算中最重要的操作之一。矩阵的乘法有两种运算,一种是点乘(Matrix Product),一种是元素乘(Element-Wise Product)。下面分别介绍。
点乘运算是一个常用矩阵操作。两个矩阵A和B经过点乘运算产生矩阵C。点乘运算的前提条件就是矩阵A的列数必须和矩阵B的行数相等。如果矩阵A的形状是m×n,矩阵B的形状是n×p,那么矩阵C的形状是m×p。点乘运算可以书写作C=A · B,通常更常用的写法是C=AB。点乘运算的规则稍复杂,A中的第i行点乘B中的第j列得到一个标量,这个标量就是C中的第i行第j个元素。例如,A的第一行点乘B的第一列得到C中的一个元素C11; A的第三行乘以B的第二列得到C的一个元素C32。其公式表示如下:
注意 点乘运算不具备交换律,即AB≠BA。甚至很多时候AB可以计算,但是BA不存在,因为点乘必须符合行数和列数的对应关系。
除了矩阵的点乘操作,机器学习和深度学习会使用到的另一个运算是元素乘。元素乘又称元素积、元素对应乘积。元素乘的运算条件更加严格一些,要求参与运算的两个矩阵的规模一样(即,都为m×n的矩阵)。两个m×n的矩阵A和B,经过元素乘后其运算结果为C,一般记为C=A⊙B。与点乘相同元素乘运算结果也是一个矩阵,只不过运算规则更加简单,只是对应位置的元素相乘即可。元素乘的公式为Cij= Aij⊙Bij。例如,一个2×3规模的元素乘为C2*3= A2*3⊙B2*3,运算过程如下所示:
矩阵的转置(transposition)是一个很容易理解的运算。转置就是将原来的行元素变成列元素。假设矩阵A是m×n的矩阵,经过转置后的矩阵变为n×m,记作AT。从公式的角度看(AT)ij=A ij。下面给出一个具体的例子。
注意 矩阵的操作将在介绍numpy时介绍,详见代码清单1-4。
除了数学概念上的运算外,计算机深度学习中常常会用到向量化的概念。向量化(Vectorization)是指将原本需要高复杂度的计算过程化为低复杂度的向量乘积的过程。深度学习过程常常都面临大量的向量和矩阵运算,如果采用传统的计算方法那么这些运算将消耗大量时间,而向量化可以有效降低其计算耗时。
注意 这一部分将在numpy章节直观展现,详见代码清单1-8。
假设程序员面对一个需求:求两个向量a和b的点乘。他可以选择的一个操作方法是把向量视为多个元素的有序数组,对a和b中的每一个分量做一次乘积运算,最后将乘积结果求和即。而他可以选择的另一个操作方法是把向量视作一个整体,直接调用Python语言现成的库函数完成两个向量的乘积。从数学角度看两个操作的复杂度是相同的,但是从程序的角度看,Python库内部对向量操作做了算法甚至硬件级别的优化,会使得计算机运算更加迅速。所以,向量化是深度学习过程可以提速的一大法宝。
5.向量的范数
在机器学习中衡量一个向量大小的时候会用到范数(Norm)的概念。范数可以理解为一个将向量映射到非负实数的函数。通俗来讲范数表示的是向量的“长度”。形式上范数的定义如下:
观察范数的定义很容易发现,范数事实上和p的取值是有关系的,所以范数的数学符号是Lp。
在机器学习和深度学习领域最常用到的两个范数是L1范数和L2范数。对于绝大多数读者来说,最熟悉的就是p=2的情况。L2范数(L2Norm)也被称为欧几里得范数,它表示从原点出发到向量x确定的点的欧几里得距离。向量的L2范数也被称作向量的模。L2在机器学习和深度学习中出现十分频繁,为了计算和使用方便,常常会对L2范数做平方运算。平方L2范数对每一个x的导数只取决于对应的元素,而L2范数对每个元素的导数却和整个向量相关。但是平方L2范数的一个缺点是它在原点附近增长得十分缓慢。在某些机器学习和深度学习应用中,区分值为零的元素和非零但值很小的元素是很重要的。在这些情况下,转而使用在各个位置斜率相同,同时保持简单的数学形式的函数:L1范数。当机器学习和深度学习问题中零和非零元素之间的差异非常重要时,通常会使用L1范数。L1范数即为向量中各个元素绝对值的和。每当x中某个元素从0增加є,对应的L1范数也会增加є。
Lp范数用来度量向量的大小,相应的度量矩阵的大小可以使用Frobenius范数(Frobenius Norm)。其类似于L2范数,可以将其理解为L2范数在矩阵上的推广。公式如下:
1.2.2 微积分基础
机器学习和深度学习除了需要线性代数的基础,还需要一定的微积分基础。在机器学习和深度学习计算过程中,逆向传播算法(第4章着重讲述)需要用到偏导数求解的知识,而梯度下降算法(第3章着重讲述)需要理解梯度的概念。
1.导数
首先介绍导数的相关知识。导数(Derivative)直观理解是反应瞬时变化率的量。如图1-1所示。考虑一个实际问题,纵坐标是车辆位移,横坐标是时间,如何知道t1时刻车辆的瞬时速度呢?
图1-1 斜率示意图
获得瞬时速度的核心思想是用平均速度去逼近瞬时速度。这里可以考虑t1和t2, t1在前,t2在后,它们之间有一定的时间间隔,这个时间间隔为Δt。在这段时间间隔内产生的位移为Δs。那么时间内的平均速度为。Δt不断缩小,也就是t2不断靠近t1,当t2与t1无限接近几乎重合时,便可以视作t1点的瞬时速率(如图1-1所示)。
导数是从瞬时速度的概念中类比抽象出来的。将瞬时速率拓展到更一般的情形,在更广的函数范围内,根据这种无限逼近的思路,知道任意变量在一点处的变化率(斜率),函数在这一点处的斜率就是导数。在高等数学中更为严谨的定义为:对于定义域和值域都是实域的函数y=f (x),若f (x)在点x0的某个邻域Δx内,极限
存在,则称函数y=f (x)在x0处可导,且导数为f '(x0)。
来看下面的例子,如图1-2所示是函数y=4a的曲线,当a=3时,y=12,而当a在a坐标轴向右移动很小的一段距离0.001时,a=3.001, y=12.004。
图1-2 导数推导计算示意图
这时,定义a发生的变化为da, da=0.001,定义y发生的变化为dy, dy=0.004,读者便能计算得到这一小段变化形成的图中三角形的斜率(slope)=4,此时的斜率便是y=4a在a=3处的导数值f'(3)=slope=4。当然,这里的0.001只是说明a的变化很小而已,实际上da是一个无限趋近于0的值,远比0.001要小。类似的,计算a=5时的导数,也能用上述方法,a=5, y=20, a=5.001, y=20.004,从而dy=0.004, dx=0.001。函数y=f (a)=4a在a=5处的导数为f '(5)=slope=dy/da=4。相似的,其他形状曲线的任意一点的导数,也能用类似的方法计算得到。此外,读者也许会发现,直线的导数在任意一点都相同,为一个确定的值。
上面描述的是在某一点的导数概念,接下来将这个概念推广开来。若函数f (x)在其定义域内包含的每一个点都可导,那么也可以说函数f (x)在这个区间内可导。这样定义函数f '(x)为函数f (x)的导函数,通常也称为导数。函数f (x)的导数f '(x)也可以记作∇xf (x), 或,以上便是函数与变量的导数的基本知识。
2.偏导数
一个多变量的函数的偏导数(Partial Derivative),就是它关于其中一个变量的导数而保持其他变量恒定(相对于全导数,在全导数中所有变量都允许变化)。简单来说,偏导数就是对多元函数求其中一个未知数的导数,比如在含x和y的函数中对x求导,此时是将另一个未知数y看成是常数,相当于未知数只是x求导,如公式1-11、1-12所示:
此时被称为函数关于x的偏导数,同理,函数关于y的偏导数为
拓展到更多元的情况,对一个含有多个未知数的函数f对于其中任意一个变量p求偏导时,只将p视为未知量,其余未知数视为常量(注意只是视为),记作。
特别的,当函数f中本身只含有一个未知数x时,f关于x的导数也就是f关于x的偏导数,即
读者可以参考图1-3所示的例子,J是一个关于a和b的函数,J=f (a, b)=3a+2b:
图1-3 偏导数推导计算示意图
当a不变,b发生变化的时候,假定b在2发生变化,a=1, b=2,此时J=7。而当b增加0.001时,a=1, b=2.001,此时J=7.002。类比于前一小节推导导数时的方法,偏导数也能用相似的方法推导得到,在点(1,2)处,求J关于b的偏导数,由于a不发生变化,所以J对b的偏导数。用类似的方法,读者也能求得在点(1,2)处,J对a的偏导数。
3.向量的导数
之前介绍的函数都是关于一个标量的函数,例如f (x)=x,在这样的函数中,变量本身是一个数。但是在机器学习和深度学习中,有时候还需要对向量求导,下面介绍向量的求导方法。
(1)标量对向量求导
首先介绍维度的概念。对于向量而言,向量的维度是一个向量中分量的个数。对于函数而言,这样由数值型变量构成的函数也称为标量的函数。现有向量X=[x1, x2, x3, …, xp]T,这样函数f (x)关于向量X的导数仍然是p维向量,导数向量中第i个元素的值为(i=1, 2 … p)。也即函数对向量求导数,其结果为函数对向量的各个分量求偏导数。更为严谨的数学定义为,对于一个p维向量x∈Rp,关于标量的函数y=f (x)=f (x1, x2, …, xp)∈R,则y关于x的导数为
(2)向量对向量求导
当函数中是关于标量的函数,这样f本身是一个q维度的向量,现有向量X=[x1, x2, …, xp]T, p与q不相同时,函数f对于向量X求导,所得到的结果是一个p×q的矩阵,其中第i行第j列的元素为(i=1, 2, 3…p, j=1, 2, 3…q)。也即是由标量的函数构成的向量f对于向量X求导,其结果为一个矩阵,矩阵的第n行为函数向量f中每一个函数,对x求偏导。更为严谨的数学定义为,对于一个p维向量x∈Rp,函数y=f=( f1, f2, …, fq),则y关于x的导数为:
4.导数法则
(1)加减法则(Addition Rule)
两个函数的和(或差)的导数,等于两个函数分别对自变量求导的和(或差)。设y=f (x)并且z=g(x),则二者的和的函数对于同一个变量求导的结果,其值将会是两个函数对于变量分别求导后的结果做求和运算(如公式1-17所示)。
加减法则常常被用于简化求导过程。在一些情形下,往往函数本身是很复杂的,直接求导将会有很高的复杂度,这时利用加减法则,将函数分成两个或者多个独立的简单函数,再分别求导求和,原本复杂的问题就变得简单了。
在深度学习和机器学习中,加减法则常常用于计算两个直接相连的神经元之间的相互影响。例如神经网络后一层节点为x,它同时受到前一层中的神经元y和z的影响,影响关系为x=y+z,那么当y和z同时变化时,若要计算x所发生的变化,便可通过公式1-5计算得到。
(2)乘法法则(Product Rule)
接触完了导数的加减法则,读者也许会推测乘法法则是否与之类似:即两个函数乘积的导数等于两个函数分别求导的乘积,答案是否定的。这里以矩阵乘法为例,若x∈Rp, y=f(x)∈Rq, z=g(x)∈Rq,乘积的求导过程将如公式1-18所示。
乘法法则乍看之下比较抽象,这里用一个实际的例子来说明。如果y的转置代表函数中的系数矩阵,z是自变量矩阵,二者同时对于x求偏导数,所得到的结果将会变成两个部分,一个部分是自变量的矩阵,另一个部分是系数的矩阵。机器学习乘法法则也常常用于计算两个直接相连的神经元之间的相互影响,当后一层某一神经元C是由前一层神经元A和B通过乘法关系得到的,则可以利用乘法法则计算A和B变化时对于C的影响。
(3)链式法则(Chain Rule)
链式法则作为在机器学习和深度学习中最为常用的法则,其重要性毋庸置疑,但链式法则本身不好理解,这里我们以一个函数输入输出流为例阐释链式法则。
观察如下一组函数,这组函数的输入值是x=(x1, x2)。第一个函数f1是一个求和过程,第二个函数f2是一个求积的过程:
把这两个函数值作为输入送给第三个函数g,函数g就是一个关于x1, x2的复合函数,其最终的输出值用y表示。由输入x逐步计算得到结果y的过程用计算图表示(如图1-4所示)。
图1-4 复合函数计算图
如果由变量到函数是一个正向传递的过程,那么求导便是一个反向的过程(如图1-5所示)。
如果要求得函数g对x1的偏导数,观察图1-5,可以发现其由g节点到x1节点共有两条路径,每条路径有两条有向边组成。每条路径可以看作其经过的边的值的乘积,而两条路径求和就恰巧得到了函数g对x1的偏导数。当我们把函数g看作关于x1, x2的复合函数时,分别求得g对x1和x2的偏导数可以得到如下的公式,这样的求复合函数导数的公式,便是复合函数求导的链式法则。
图1-5 复合函数求导计算图
特别的,当f1与f2均为向量函数时,此时链式法则将会发生调整,如公式1-21所示:
向量求导的链式法则与标量函数的链式法则很相似,只不过求导过程变成了求Jacobi矩阵,Jacobi矩阵定义如下:
需要注意的是,偏导数链式法则中的乘法所用到的都是1.2.1节中第5部分所提到的元素乘,符号为⊙。
链式法则作为深度学习中最为常用的一条求导法则,常常用于利用逆向传播算法进行神经网络的训练工作,我们将在后续章节详细学习逆向传播算法。
5.常见的向量和矩阵的导数
这里提供一些常见的向量及矩阵的导数知识,读者在推导神经网络中的导数计算时会用到这些知识。向量对于其本身的导数为单位向量,这一点与标量的计算相类似。当一个数或者一个向量对其本身求导,所得到的结果将是1或者单位向量。反映到深度学习的神经网络中神经元的相互影响上,便可以理解为一个神经元如果受到自身变化的影响,那么其自身变化多少,影响的大小就有多少:
向量w和x的乘积,设其为z,那么z对于w求偏导数的结果为x的转置:
拓展到矩阵,矩阵W和矩阵X的乘积设其为矩阵Z,那么Z对于W求偏导数,其结果为X的转置:
上述两条规则常常用于通过神经元的结果,依照系数向量(或矩阵)反推输入向量(或矩阵),即倘若在神经网络中我们知道了神经元的输出结果和系数向量(或矩阵),便能反推得到输入,从而进行验证或其他操作。
矩阵A与向量x的乘积对x求偏导数,其结果为矩阵A的转置AT。这个规则常常用于求解具有Ax关系的神经元之间的相互连接,也即后一个神经元如果收到前一个神经元x的影响是Ax,那么当直接相连的前一个神经元增加(或减少)一个单位时,后一个神经元将相应地增加(或减少)AT个单位:
向量x的转置与矩阵A的乘积对向量x求偏导数,其结果为矩阵A本身。这个规则常常用于求解具有XTA关系的神经元之间的相互连接,也即后一个神经元如果收到前一个神经元x的影响是XTA,那么当直接相连的前一个神经元增加(或减少)一个单位时,后一个神经元将相应地增加(或减少)A个单位:
6.梯度
之前讨论的导数,基本上是直接考量函数变化率,梯度(Gradient)则从另一个角度,考量函数变化最快的方向。在机器学习和深度学习中梯度下降法用以求解损失函数的最小值。梯度的本意是一个向量,该向量表示某一函数在某一点处的方向导数沿着向量方向取得最大值,即函数在该点处沿着该方向(梯度的方向)变化最快,变化率最大(为该梯度的模)。
在机器学习中,考虑二元函数的情形。设函数z=f (x, y)在平面区域D内具有一阶连续偏导数,则对于每一点P(x, y)∈D,都可以定出一个向量,这个向量称为函数z=f (x, y)在点P(x, y)的梯度,记作grad f (x, y)。如图1-6所示,红色折线折线方向便是梯度方向。
倘若图1-6中的曲面表示的是损失函数,那么梯度方向便是损失函数中损失减少最快的方向。使用梯度就找到了探测最小损失效率最高的方向,设定一个恰当的初始值和探测步长,就能在最快的速度下找到需要的最小的损失值。梯度作为探测损失函数中最小损失的一个“指南针”,避免了寻找一个最低的损失时低效率的枚举的情况发生。在机器学习和深度学习中涉及最优解问题时提供了一个较为方便的初始搜索方向,对于机器学习和深度学习具有很重要的意义。
图1-6 梯度下降示意图