让我们从最简单的形式开始,导数(Derivative),大家都知道,最直白的说法就是变化率,也就是衡量一个变量在另一变量的影响下变化快慢的量。
一:标量求导
对于单个变量的求导,也就是标量求导。下面的式子是导数的定义式,这里的
x
x
x是标量,则
Δ
x
\Delta x
Δx也是标量,式子很好理解,分子部分为因变量
f
f
f的变化量,分母为自变量
x
x
x的变化量,当自变量的变化量
Δ
x
\Delta x
Δx无限接近于0时则认为该式子得到的值为
f
f
f在
x
0
x_0
x0处对
x
x
x的导数,也就是在
x
0
x_0
x0处x的值的变化对y值的变化的影响力大小。
f
′
(
x
0
)
=
lim
Δ
x
→
0
f
(
x
0
+
Δ
x
)
−
f
(
x
0
)
Δ
x
f'(x_0)=\lim_{\Delta x\to0} \frac{f(x_0+\Delta x)-f(x_0)}{\Delta x}
f′(x0)=Δx→0limΔxf(x0+Δx)−f(x0)
二:标量对向量求导
有时候情况没那么简单,函数的输入不再是一个变量,而是多个变量,而函数值输出仍然是一个标量,比如下面这个函数:
f
(
x
1
,
x
2
,
x
3
)
=
x
1
+
2
x
2
+
3
x
3
f(x_1, x_2, x_3)=x_1+2x_2+3x_3
f(x1,x2,x3)=x1+2x2+3x3
函数的输入值是三个变量,这里可将输入看作是一个三维的向量
[
x
1
,
x
2
,
x
3
]
[x_1, x_2, x_3]
[x1,x2,x3],这时再来求导数,不同于标量求导,这时候的函数值
f
f
f和三个变量都有关,那该怎么求?
在我的另一篇博客(介绍矩阵乘法)时提到,矩阵的乘法并不只是简单的左行右列的计算规则,它表示的内涵是矩阵列向量的线性组合,在那个示例中,鼓励你把矩阵的列向量看作一个整体,把矩阵乘法看作是向量级的运算,但是在这里,我们要反其道行之。
输入的是向量,其实换句话说也就是一次输入了多个变量,上面的输入被我表示为了
[
x
1
,
x
2
,
x
3
]
[x_1, x_2, x_3]
[x1,x2,x3],这看起来的确很像向量,但是从本质上讲它们和
[
x
,
y
,
z
]
[x, y ,z]
[x,y,z]是没有区别的,都是三个变量的组合,如果我把函数写为
f
(
x
,
y
,
z
)
=
x
+
2
y
+
3
z
f(x, y ,z) = x+2y+3z
f(x,y,z)=x+2y+3z
这时候再来求
f
f
f对x,y,z的导数就显而易见了,这不过就是个多元函数,对单个变量的导数就是对该变量求偏导,到这里我们就明白了,标量对向量求导,本质上就是一个多元函数对各个自变量求偏导,只不过输入和输出结果被组织成了固定的形式罢了。这样对于上面的例子得到的导数就可以写为向量形式[1,2,3],这个也叫
f
f
f对X的梯度。
到目前为止我们所看到的都是自变量是什么样的shape求到的导数就是相同的shape,是不是所有的求导都满足这个规律呢?继续看吧。
三:矩阵对矩阵求导
如果看懂了二,后面也就不用多所作解释了,假设输入A矩阵为MxN维,输出C的矩阵为MxD,计算
C
=
f
(
A
)
C=f(A)
C=f(A)(这里的
f
f
f运算可以看作是对A左乘一个NxD维的矩阵),那么同样,对于输入A,把矩阵中每一个元素看作是一个变量,然后求C对它的偏导,问题来了,这次C不是标量了,C也是矩阵,道理是相同的,C的每一个元素也可看作独立的因变量,这样对于每一个
C
i
j
C_{ij}
Cij,求它对A的梯度,结果的shape为MxN,这是C中一个元素的求导结果,但是C中有MxD个元素,每一个都应该有导数,所以,最终结果的shape为MxDxMxN,表示成矩阵形式为:
[
∂
C
11
∂
A
∂
C
12
∂
A
⋯
∂
C
1
d
∂
A
∂
C
21
∂
A
∂
C
22
∂
A
.
.
.
∂
C
2
d
∂
A
⋮
⋮
⋱
⋮
∂
C
m
1
∂
A
∂
C
m
2
∂
A
.
.
.
∂
C
m
d
∂
A
]
\left[ \begin{matrix} \frac{\partial{C_{11}}}{\partial{A}} & \frac{\partial{C_{12}}}{\partial{A}} & \cdots & \frac{\partial{C_{1d}}}{\partial{A}} \\ \\ \frac{\partial{C_{21}}}{\partial{A}} & \frac{\partial{C_{22}}}{\partial{A}} & ...& \frac{\partial{C_{2d}}}{\partial{A}}\\ \vdots & \vdots & \ddots & \vdots \\ \frac{\partial{C_{m1}}}{\partial{A}} & \frac{\partial{C_{m2}}}{\partial{A}} & ...& \frac{\partial{C_{md}}}{\partial{A}}\\ \end{matrix} \right]
⎣⎢⎢⎢⎢⎢⎡∂A∂C11∂A∂C21⋮∂A∂Cm1∂A∂C12∂A∂C22⋮∂A∂Cm2⋯...⋱...∂A∂C1d∂A∂C2d⋮∂A∂Cmd⎦⎥⎥⎥⎥⎥⎤
这里只是展示了二维的形式,对于矩阵中的每一个元素,都是一个MxN的矩阵(也就是标量
C
i
j
C_{ij}
Cij对矩阵A求导的结果),上面这个矩阵又被称为雅可比矩阵。
到这里也就回答了上面的问题,是不是所有导数的shape都和自变量的shape相同,答案是否定的,这取决于因变量是否是标量。
为什么我提了这个关于shape的问题,实现过神经网络的同学可能有所体会,对于神经网络中的参数,使用梯度下降法对参数进行更新时,每次求到的梯度的shape都和参数的shape是一样的,这样给人的感觉就是导数的shape总是和自变量的shape是一样的,不然怎么进行参数更新?但是这里之所以shape一样,原因在于loss是一个标量,即使是多分类问题,输出的y是向量,当它直接对参数W进行求导时导数的shape肯定和W的shape是不一样的,但是由于神经网络的目标是最小化loss,所以参数更新的依据也是loss对W的导数,所以使用链式法则计算loss对W的导数时会计算loss对y的导数点乘y对W的导数,这样求导的矩阵的shape肯定就是和W一样的了。