本文档旨在帮助您了解和获取矢量、矩阵和高阶张量(具有三维或更多维的阵列)的导数。
1 简化,简化,简化
对数组进行求导的大部分困惑源于试图同时做太多事情。这些事情包括同时获取多个部分的导数、在存在求和符号的情况下获取导数、以及应用链式法则。至少在缺乏经验的情况下,试图同时完成所有这些事情将会使我们犯错的可能性大大增加。
1.1 将符号扩展为每个部分的显式和与方程式
为了简化给定的计算,为输出的单个标量元素(除了标量变量之外)写出显式公式通常很有用。一旦根据其他标量值能够得到输出的单个标量元素的一个显式公式,那么使用微积分就可以解决问题,这比尝试同时进行矩阵数学,求和以及导数计算更容易。
Example. 假设我们有一个长度为CCC的列向量y⃗\vec{y}y,它通过形成C×DC\times DC×D矩阵WWW与长度为DDD的列向量x⃗\vec{x}x的乘积来计算:
(1)y⃗=Wx⃗。
\vec{y}=W\vec{x} \tag{1}。
y=Wx。(1) 假设我们需要研究y⃗\vec{y}y关于x⃗\vec{x}x的导数。该导数的完整表征需要y⃗\vec{y}y的每个分量相对于x⃗\vec{x}x的每个分量的(偏)导数,在这种情况下,其将包含C×DC×DC×D个值,因为在y⃗\vec{y}y中有CCC个分量,在x⃗\vec{x}x中有DDD个分量。
让我们从计算其中一个开始,比如y⃗\vec{y}y的第3个分量,相对于x⃗\vec{x}x的第7个分量。也就是说,我们想要计算
∂y⃗3∂x⃗7,
\frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}},
∂x7∂y3,这只是一个标量关于另一个标量的导数。
要做的第一件事就是写下计算y⃗3\vec{y}_{3}y3的公式,这样我们就可以得出它的导数。 根据矩阵向量乘法的定义,通过取WWW的第3行和向量x⃗\vec{x}x之间的点积来计算值y⃗3\vec{y}_{3}y3:
(2)y⃗3=∑j=1DW3,jx⃗j。
\vec{y}_{3}=\sum_{j=1}^{D}{W_{3,j} \vec{x}_{j}} \tag{2}。
y3=j=1∑DW3,jxj。(2)此时,我们已经将原始矩阵方程(1)(1)(1)简化为标量方程。这使得计算所需的导数变得更容易。
1.2 去掉求和符号
虽然直接从公式(2)(2)(2)计算导数当然是可能的,但人们在区分包含求和符号(∑\sum∑)或乘积符号(∏\prod∏)的表达式时经常会出错。开始计算时,写出一个没有任何求和符号的计算有时候是有用的,这能确保你做的一切正确。使用“1”作为第一个下标,我们有:
y⃗3=W3,1x⃗1+W3,2x⃗2+...+W3,7x⃗7+...+W3,Dx⃗D。
\vec{y}_{3}=W_{3,1} \vec{x}_{1}+W_{3,2} \vec{x}_{2}+...+W_{3,7} \vec{x}_{7}+...+W_{3,D} \vec{x}_{D}。
y3=W3,1x1+W3,2x2+...+W3,7x7+...+W3,DxD。当然,我已经明确地包含了涉及x⃗7\vec{x}_{7}x7的术语,因为这就是我们在这方面的不同之处。 在这一点上,我们可以看到y⃗3\vec{y}_{3}y3的表达式仅依赖于x⃗7\vec{x}_{7}x7到单个项W3,7x⃗7W_{3,7} \vec{x}_{7}W3,7x7。 由于求和中的其他项都不包括x⃗7\vec{x}_{7}x7,因此它们相对于x⃗7\vec{x}_{7}x7的导数都是0.因此,我们有
(3)∂y⃗3∂x⃗7=∂∂x⃗7[W3,1x⃗1+W3,2x⃗2+...+W3,7x⃗7+...+W3,Dx⃗D]=0+0+...+∂∂x⃗7[W3,7x⃗7]+...+0=∂∂x⃗7[W3,7x⃗7]=W3,7。
\begin{aligned}
\frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}}&=\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,1} \vec{x}_{1}+W_{3,2} \vec{x}_{2}+...+W_{3,7} \vec{x}_{7}+...+W_{3,D} \vec{x}_{D}]} \tag{3}\\
&=0+0+...+\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,7} \vec{x}_{7}]}+...+0\\
&=\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,7} \vec{x}_{7}]}\\
&=W_{3,7}。
\end{aligned}
∂x7∂y3=∂x7∂[W3,1x1+W3,2x2+...+W3,7x7+...+W3,DxD]=0+0+...+∂x7∂[W3,7x7]+...+0=∂x7∂[W3,7x7]=W3,7。(3) 通过关注y⃗\vec{y}y的一个分量和x⃗\vec{x}x的一个分量,我们使计算变得尽可能简单。 在将来,当您感到困惑时,可以尝试将问题减少到这个最基本的设置,以查看您出错的地方。
1.2.1 完成导数:Jacobian矩阵
回想一下,我们的最初目标是计算y⃗\vec{y}y的每个分量相对于x⃗\vec{x}x的每个分量的导数,并且我们注意到其数量将是C×DC\times DC×D。 它们可以以下列形式写成矩阵:
[∂y⃗1∂x⃗1∂y⃗1∂x⃗2∂y⃗1∂x⃗3⋯∂y⃗1∂x⃗D∂y⃗2∂x⃗1∂y⃗2∂x⃗2∂y⃗2∂x⃗3⋯∂y⃗2∂x⃗D⋮⋮⋮⋱⋮∂y⃗C∂x⃗1∂y⃗C∂x⃗2∂y⃗C∂x⃗3⋯∂y⃗C∂x⃗D]
\begin{bmatrix}
\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{D}} \\
\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{D}} \\
\vdots &\vdots &\vdots &\ddots &\vdots \\
\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{D}} \\
\end{bmatrix}
⎣⎢⎢⎢⎢⎡∂x1∂y1∂x1∂y2⋮∂x1∂yC∂x2∂y1∂x2∂y2⋮∂x2∂yC∂x3∂y1∂x3∂y2⋮∂x3∂yC⋯⋯⋱⋯∂xD∂y1∂xD∂y2⋮∂xD∂yC⎦⎥⎥⎥⎥⎤在这种特殊情况下,这称为雅可比矩阵,但这个术语对我们的目的来说并不太重要。
请注意,对于等式
y⃗=Wx⃗,
\vec{y}=W\vec{x},
y=Wx,关于x⃗7\vec{x}_{7}x7的y⃗3\vec{y}_{3}y3的部分简单地由W3,7W_{3,7}W3,7给出。如果你对其他组件进行相同的处理,你会发现,对于所有iii和jjj,
∂y⃗i∂x⃗j=Wi,j。
\frac{\partial \vec{y}_{i}}{\partial \vec{x}_{j}}=W_{i,j}。
∂xj∂yi=Wi,j。这意味着偏导数矩阵是
[∂y⃗1∂x⃗1∂y⃗1∂x⃗2∂y⃗1∂x⃗3⋯∂y⃗1∂x⃗D∂y⃗2∂x⃗1∂y⃗2∂x⃗2∂y⃗2∂x⃗3⋯∂y⃗2∂x⃗D⋮⋮⋮⋱⋮∂y⃗C∂x⃗1∂y⃗C∂x⃗2∂y⃗C∂x⃗3⋯∂y⃗C∂x⃗D]=[W1,1W1,2W1,3⋯W1,DW2,1W2,2W2,3⋯W2,D⋮⋮⋮⋱⋮WC,1WC,2WC,3⋯WC,D]
\begin{bmatrix}
\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{D}} \\
\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{D}} \\
\vdots &\vdots &\vdots &\ddots &\vdots \\
\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{D}} \\
\end{bmatrix}=
\begin{bmatrix}
W_{1,1} & W_{1,2} & W_{1,3} &\cdots & W_{1,D} \\
W_{2,1} & W_{2,2} & W_{2,3} &\cdots & W_{2,D} \\
\vdots & \vdots & \vdots &\ddots &\vdots \\
W_{C,1} & W_{C,2} & W_{C,3} &\cdots & W_{C,D} \\
\end{bmatrix}
⎣⎢⎢⎢⎢⎡∂x1∂y1∂x1∂y2⋮∂x1∂yC∂x2∂y1∂x2∂y2⋮∂x2∂yC∂x3∂y1∂x3∂y2⋮∂x3∂yC⋯⋯⋱⋯∂xD∂y1∂xD∂y2⋮∂xD∂yC⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎡W1,1W2,1⋮WC,1W1,2W2,2⋮WC,2W1,3W2,3⋮WC,3⋯⋯⋱⋯W1,DW2,D⋮WC,D⎦⎥⎥⎥⎤这显然就是WWW本身。
因此,基于以上所做工作我们可以得出结论,对于
y⃗=Wx⃗,
\vec{y}=W\vec{x},
y=Wx,我们有
dy⃗dx⃗=W。
\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=W。
dxdy=W。
2 行向量而不是列向量
在处理不同的神经网络包时,我们应当密切注意权重矩阵、数据矩阵等的排列。 例如,如果数据矩阵XXX包含许多不同的矢量,每个矢量代表一个输入,则每个数据矢量是否构成数据矩阵XXX的行或列?
在第一部分的示例中,我们使用了矢量x⃗\vec{x}x,它是一个列向量。 但是,当x⃗\vec{x}x是行向量时,您还应该能够使用相同的基本思想。
2.1 Example 2
令y⃗\vec{y}y是长度为CCC的行向量,其通过取另一长度为DDD的行向量x⃗\vec{x}x和DDD行CCC列的矩阵W的乘积来计算。
y⃗=x⃗W。
\vec{y}=\vec{x}W。
y=xW。重要的是,尽管y⃗\vec{y}y和x⃗\vec{x}x分量数量并未改变,但WWW的形状却变成WWW之前形状的转置。特别是,因为我们现在左乘x⃗\vec{x}x,而之前x⃗\vec{x}x在右边,所以WWW必须转换为矩阵代数才能使用。
在这种情况下,由
y⃗3=∑j=1Dx⃗jWj,3
\vec{y}_{3}=\sum_{j=1}^{D}{ \vec{x}_{j} W_{j,3}}
y3=j=1∑DxjWj,3可以得到
∂y⃗3∂x⃗7=W7,3。
\frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}}=W_{7,3}。
∂x7∂y3=W7,3。请注意,W的下标与第一个示例中的下标相反。 然而,当写出完整的雅可比矩阵时,我们仍然可以看到,
(4)dy⃗dx⃗=W。
\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=W \tag{4}。
dxdy=W。(4)
3 处理更高的维度
让我们考虑另一个密切相关的问题,即计算
dy⃗dW。
\frac{\mathrm{d} \vec{y}}{\mathrm{d} W}。
dWdy。在这种情况下,y⃗\vec{y}y沿一个坐标变化,而WWW沿两个坐标变化。 因此,所有的导数自然而然包含在三维阵列中。我们避免使用术语“三维矩阵”,因为不清楚矩阵乘法和其他矩阵运算是如何在三维阵列上定义的。
处理三维数组时,尝试找到显示它们的方法可能会更麻烦。 相反,我们应该简单地将结果定义为可用于计算所需三维数组的任何元素的结果的公式。
让我们再次计算y⃗\vec{y}y的一个分量之间的标量导数,比如y⃗3\vec{y}_{3}y3和WWW的一个分量,比如W7,8W_{7,8}W7,8。 让我们从相同的基本设置开始,在这些设置中我们用其他标量分量来记录y⃗3\vec{y}_{3}y3的等式。 现在我们想要一个用标量值表示y⃗3\vec{y}_{3}y3的方程,并显示W7,8W_{7,8}W7,8在其计算中的作用。
然而,我们看到的是W7,8W_{7,8}W7,8在y⃗3\vec{y}_{3}y3的计算中没有任何作用,因为
(5)y⃗3=x⃗1W1,3+x⃗2W2,3+...+x⃗DWD,3。
\vec{y}_{3}= \vec{x}_{1}W_{1,3}+\vec{x}_{2}W_{2,3} +...+\vec{x}_{D}W_{D,3} \tag{5} 。
y3=x1W1,3+x2W2,3+...+xDWD,3。(5)也就是说,
∂y⃗3∂W7,8=0。
\frac{\partial \vec{y}_{3}}{\partial W_{7,8}}=0。
∂W7,8∂y3=0。然而,y⃗3\vec{y}_{3}y3关于WWW的第3列的元素的导数肯定是非零的。 例如,y⃗3\vec{y}_{3}y3相对于W_{2,3}的导数由下式给出
(6)∂y⃗3∂W2,3=x⃗2,
\frac{\partial \vec{y}_{3}}{\partial W_{2,3}}=\vec{x}_{2}\tag{6},
∂W2,3∂y3=x2,(6)通过检查公式(5)(5)(5)可以很容易地看出。
通常,当y⃗\vec{y}y分量的下标等于WWW的第二下标时,导数将为非零,否则将为零。 即:
∂y⃗j∂Wi,j=x⃗i,
\frac{\partial \vec{y}_{j}}{\partial W_{i,j}}=\vec{x}_{i},
∂Wi,j∂yj=xi,但是该三维数组的其他元素将为0.令FFF表示代表y⃗\vec{y}y相对于WWW的导数的三维数组,其中
Fi,j,k=∂y⃗i∂Wj,k,
F_{i,j,k}=\frac{\partial \vec{y}_{i}}{\partial W_{j,k}},
Fi,j,k=∂Wj,k∂yi,则
Fi,j,i=x⃗j,
F_{i,j,i}=\vec{x}_{j},
Fi,j,i=xj,但是FFF的所有其他元素都是零。
最后,如果我们将一个新的二维数组GGG定义为
Gi,j=Fi,j,i,
G_{i,j}=F_{i,j,i},
Gi,j=Fi,j,i,我们可以看到,我们需要的关于FFF的所有信息都可以存储在GGG中,并且FFF的非平凡部分实际上是二维的,而不是三维的。
以紧凑的方式表示导数阵列的重要部分对于神经网络的有效实现是至关重要的。
4 多个数据点
重复一些前面的例子是一个很好的练习,但是我们可以使用x⃗\vec{x}x的多个例子,堆叠在一起形成矩阵XXX.假设每个x⃗\vec{x}x都是长度为DDD的行向量,而XXX是二维的、具有NNN行DDD列的数组。WWW,如在我们的上一个示例中,将是具有DDD行和CCC列的矩阵。YYY,由下式给出
Y=XW,
Y=XW,
Y=XW,也将是一个矩阵,有NNN行和CCC列。 因此,YYY的每一行将给出与输入XXX的相应行相关联的行向量。
坚持之前为输出的给定部分写下表达式的操作,我们有
Yi,j=∑k=1DXi,kWk,j。
Y_{i,j}=\sum_{k=1}^{D}{X_{i,k}W_{k,j}}。
Yi,j=k=1∑DXi,kWk,j。我们可以从这个等式中直接看出导数
∂Ya,b∂Xc,d,
\frac{\partial Y_{a,b}}{\partial X_{c,d}},
∂Xc,d∂Ya,b,除非a=ca = ca=c,否则它们都为零。 也就是说,由于YYY的每个分量仅使用相应的XXX行来计算,因此YYY和XXX的不同行之间的分量的导数都是零。
此外,我们可以知道
(7)∂Yi,j∂Xi,k=Wk,j,
\frac{\partial Y_{i,j}}{\partial X_{i,k}}=W_{k,j}\tag{7},
∂Xi,k∂Yi,j=Wk,j,(7)并不完全取决于我们正在比较的YYY和XXX的行。
事实上,矩阵WWW保持所有这些部分——我们只需要根据等式(7)(7)(7)索引,来获得我们想要的特定偏导数。
如果我们让Yi,:Y_{i,:}Yi,:成为YYY的第i行,让Xi,:X_{i,:}Xi,:成为XXX的第i行,那么我们得到
∂Yi,:∂Xi,:=W,
\frac{\partial Y_{i,:}}{\partial X_{i,:}}=W,
∂Xi,:∂Yi,:=W,这是我们先前从公式(4)(4)(4)得到的结果的简单推广。
5 链式法则与向量和矩阵相结合
现在我们已经完成了几个基本的例子,让我们将这些想法与链式法则的例子结合起来。 同样,假设y⃗\vec{y}y和x⃗\vec{x}x是列向量,让我们从这个等式开始
y⃗=VWx⃗,
\vec{y}=VW\vec{x},
y=VWx,并尝试计算y⃗\vec{y}y相对于x⃗\vec{x}x的导数。 我们可以简单地观察到两个矩阵VVV和WWW的乘积是另一个矩阵,令之为UUU,因此
dy⃗dx⃗=VW=U。
\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=VW=U。
dxdy=VW=U。但是,我们想通过使用链式法则来定义中间结果,这样我们就可以看到链式法则如何应用于非标量导数的情况下的过程。
定义中间结果为
m⃗=Wx⃗。
\vec{m}=W\vec{x}。
m=Wx。则我们有
y⃗=Vm⃗。
\vec{y}=V\vec{m}。
y=Vm。运用链式法则,可以进一步得到
dy⃗dx⃗=dy⃗dm⃗dm⃗dx⃗。
\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{m}}\frac{\mathrm{d} \vec{m}}{\mathrm{d} \vec{x}}。
dxdy=dmdydxdm。 为了确保我们确切地知道这能给我们带来什么,让我们采用分析单个元素的老方法,从y⃗\vec{y}y的单个元素和x⃗\vec{x}x的单个元素开始:
dy⃗idx⃗j=dy⃗idm⃗dm⃗dx⃗j。
\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}}\frac{\mathrm{d} \vec{m}}{\mathrm{d} \vec{x}_{j}}。
dxjdyi=dmdyidxjdm。 但是我们究竟应该如何解释右边的乘积呢? 链式法则的含义是将y⃗i\vec{y}_{i}yi相对于每个标量中间变量的变化乘以每个标量中间变量相对于x⃗j\vec{x}_{j}xj的变化。 特别是,如果m⃗\vec{m}m有MMM个元素,那么我们可以改写
dy⃗idx⃗j=∑k=1Mdy⃗idm⃗kdm⃗kdx⃗j。
\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\sum_{k=1}^{M}{\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}_{k}}\frac{\mathrm{d} \vec{m}_{k}}{\mathrm{d} \vec{x}_{j}}}。
dxjdyi=k=1∑Mdmkdyidxjdmk。 回想一下我们之前关于矢量导数的结果:
dy⃗idm⃗k
\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}_{k}}
dmkdyi就是Vi,kV_{i,k}Vi,k,且
dm⃗kdx⃗j
\frac{\mathrm{d} \vec{m}_{k}}{\mathrm{d} \vec{x}_{j}}
dxjdmk就是Wk,jW_{k,j}Wk,j。所以我们可以得出
dy⃗idx⃗j=∑k=1MVi,kWk,j,
\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\sum_{k=1}^{M}{V_{i,k}W_{k,j}},
dxjdyi=k=1∑MVi,kWk,j,也即是VWVWVW的表达式,或者说是我们对问题的原始答案。
总而言之,我们可以在矢量和矩阵的导数求解中按照以下步骤使用链式法则:
•清楚地说明中间结果和用于表示它们的变量,
•按照链式法则将最终所求导数写成各项乘积的表达式,
•对链式法则表达式中的中间结果进行适当的运算。