深度学习中最常见的是各种向量还有矩阵运算,经常会涉及到求导操作。因此准确理解向量矩阵的求导操作就显得非常重要,对我们推导计算过程以及代码书写核对有非常大的帮助。
神经网络中最常见的操作为向量,矩阵乘法,在求导的时候经常需要用到链式法则,链式法则在计算过程中会稍微麻烦,下面我们来详细推导一下,推导过程全程简单明了,稍微有点数学基础的同学都能看明白。
假设x, y, z都为标量(或者说一维向量),链式关系为x -> y -> z。根据高数中的链式法则
∂ z ∂ x = ∂ z ∂ y ⋅ ∂ y ∂ x \frac{\partial z}{\partial x} = \frac{\partial z}{\partial y} \cdot \frac{\partial y}{\partial x} ∂x∂z=∂y∂z⋅∂x∂y
上面的计算过程很简单,不多解释。
假设x,y,z都为向量,链式关系为x -> y -> z。如果我们要求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z,可以直接用链接法则求导
∂ z ∂ x = ∂ z ∂ y ⋅ ∂ y ∂ x \frac{\partial z}{\partial x} = \frac{\partial z}{\partial y} \cdot \frac{\partial y}{\partial x} ∂x∂z=∂y∂z⋅∂x∂y
假设x, y, z的维度分别为m, n, p, ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z的维度为p * m,而 ∂ z ∂ y \frac{\partial z}{\partial y} ∂y∂z的维度为p * n, ∂ y ∂ x \frac{\partial y}{\partial x} ∂x∂y的维度为n * m,p * n与n * m的维度刚好为p * m,与左边相同。
在深度学习中,一般我们的损失函数为一个标量函数,比如MSE或者Cross Entropy,因此最后求导的目标函数为标量。
假设我们最终优化的目标为z是个标量,x,y分为是m,n维向量,依赖关系为x->y->z。现在需要求的是 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z,维度为m * 1。
易知有 ∂ z ∂ y \frac{\partial z}{\partial y} ∂y∂z为n * 1, ∂ y ∂ x \frac{\partial y}{\partial x} ∂x∂y为n * m,则 ( ∂ y ∂ x ) T ⋅ ∂ z ∂ y (\frac{\partial y}{\partial x}) ^ T \cdot \frac{\partial z}{\partial y} (∂x∂y)T⋅∂y∂z的维度为m * 1,与左边能对上。
因此有
∂ z ∂ x = ( ∂ y ∂ x ) T ⋅ ∂ z ∂ y \frac{\partial z}{\partial x} = (\frac{\partial y}{\partial x}) ^ T \cdot \frac{\partial z}{\partial y} ∂x∂z=(∂x∂y)T⋅∂y∂z
扩展到多个向量
y1 -> y2 -> y3 -> …-> yn -> z
∂ z ∂ y 1 = ( ∂ y n ∂ y n − 1 ⋅ ∂ y n − 1 ∂ y n − 2 ⋯ ∂ y 2 ∂ y 1 ) T ⋅ ∂ z ∂ y n \frac{\partial z}{\partial y_1} = (\frac{\partial y_n}{\partial y_{n-1}} \cdot \frac{\partial y_{n-1}}{\partial y_{n-2}} \cdots \frac{\partial y_2}{\partial y_1}) ^ T \cdot \frac{\partial z}{\partial y_n} ∂y1∂z=(∂yn−1∂yn⋅∂yn−2∂yn−1⋯∂y1∂y2)T⋅∂yn∂z
以常见的最小二乘求导为例:
C = ( X θ − y ) T ( X θ − y ) C = (X\theta - y) ^ T (X\theta - y) C=(Xθ−y)T(Xθ−y)
损失函数C是个标量,假设X为m*n的矩阵, θ \theta θ为 n ∗ 1 n*1 n∗1的向量,我们要求C对 θ \theta θ的导数,令 z = X θ − y z = X\theta - y z=Xθ−y, C = z T z C = z^Tz C=zTz,由上面的连式关系
∂ C ∂ θ = ( ∂ z ∂ θ ) T ⋅ ∂ C ∂ z = 2 X T ( X θ − y ) \frac{\partial C}{\partial \theta} = (\frac{\partial z}{\partial \theta})^T \cdot \frac{\partial C}{\partial z} = 2X^T(X \theta - y) ∂θ∂C=(∂θ∂z)T⋅∂z∂C=2XT(Xθ−y)
核对一下维度
∂ C ∂ θ \frac{\partial C}{\partial \theta} ∂θ∂C是n * 1, X T X^T XT是n * m, X θ − y X \theta - y Xθ−y是m * 1, X T ( X θ − y ) X^T (X \theta - y) XT(Xθ−y)是n * 1,能与左边对上。
其中
∂ ( X θ − y ) ∂ θ = X \frac{\partial (X \theta - y)}{\partial \theta} = X ∂θ∂(Xθ−y)=X
∂ ( z T z ) ∂ z = 2 z \frac{\partial (z^Tz)}{\partial z} = 2z ∂z∂(zTz)=2z
X θ − y X \theta - y Xθ−y为m * 1, θ \theta θ为n * 1, X的维度刚好为m * n。
z T z z^Tz zTz是个标量,对 z z z求导结果为 2 z 2z 2z,与 z z z的维度一致。
所以最小二乘最优解的矩阵表达式为
2 X T ( X θ − y ) = 0 2X^T(X \theta - y) = 0 2XT(Xθ−y)=0
θ = ( X T X ) − 1 X T y \theta = (X^TX)^{-1}X^Ty θ=(XTX)−1XTy
神经网络中,最常见的计算方式是 Y = W X + b Y = WX + b Y=WX+b,其中 W W W为权值矩阵。
看个更为常规的描述:
假设 z = f ( Y ) z = f(Y) z=f(Y), Y = A X + B Y = AX + B Y=AX+B,其中A为m * k矩阵,X为k * 1向量,B为m * 1向量,那么Y也为m * 1向量,z为一个标量
如果要求 ∂ z ∂ X \frac{\partial z}{\partial X} ∂X∂z,结果为k * 1的维度。 ∂ z ∂ Y \frac{\partial z}{\partial Y} ∂Y∂z的维度为m * 1, A的维度为m * k
∂ z ∂ X = A T ⋅ ∂ z ∂ Y \frac{\partial z}{\partial X} = A ^ T \cdot \frac{\partial z}{\partial Y} ∂X∂z=AT⋅∂Y∂z
左边的维度为k * 1,右边的维度为k * m 与m * 1相乘,也是k * 1,刚好能对上。
当X为矩阵时,按同样的方式进行推导可以得到一样的结论。
如果要求 ∂ z ∂ A \frac{\partial z}{\partial A} ∂A∂z,结果为m * k矩阵。 ∂ z ∂ Y \frac{\partial z}{\partial Y} ∂Y∂z的维度为m * 1, X的维度为k * 1,
∂ z ∂ A = ∂ z ∂ Y ⋅ X T \frac{\partial z}{\partial A} = \frac{\partial z}{\partial Y} \cdot X^T ∂A∂z=∂Y∂z⋅XT
当X为矩阵时,按同样的方式进行推导可以得到一样的结论。
一句话总结就是:标量对向量或者矩阵进行链式求导的时候,按照维度将结果对其就特别容易推导。