矩阵偏分


在学习深度学习的过程中,很多次遇到了矩阵求导的问题,发现网上很多教程写的不是很好理解,记录自己的浅薄认知.

(矩阵求导有分子转置(和分子行数一样)和分母转置(和分母行数一样)两种,两种结果互为转置。本篇介绍的不太一样,因为很多教程也是混杂的(太难蚌了)。

符号

标量:\(x\)

向量:\(\mathbf{x}\) ()

矩阵:\(X\)

逐点乘积:\(\odot\)()

矩阵的迹:\(tr(X)\)

加入有两个矩阵\(A_{m\times n},B_{m\times n}\),其中一个转置乘以另一个得到矩阵\(C\),该矩阵的迹为两个矩阵对应位置的元素相乘并相加 ,可以理解为向量的点积在矩阵上的推广,即:

\[ \begin{align*} \text{tr}\left( AB^T \right) &= a_{11}b_{11} + a_{12}b_{12} + \cdots + a_{1n}b_{1n} \\ &+ a_{21}b_{21} + a_{22}b_{22} + \cdots + a_{2n}b_{2n} \\ &+ \cdots \\ &+ a_{m1}b_{m1} + a_{m2}b_{m2} + \cdots + a_{mn}b_{mn} \\ \end{align*} \]

矩阵微分规律

梯度矩阵里的微分:

假设\(A\)矩阵维度列表为\([a_1,a_2,...,a_n]\)

假设\(B\)矩阵维度列表为\([b_1,b_2,...,b_{m}]\)

\(A\)矩阵对\(B\)矩阵求偏导的结果\(C\),维度上相当于\(A\)矩阵维度列表和\(B\)矩阵维度列表连接起来

\(C\)矩阵维度列表为\([a_1,a_2,...,a_n,b_1,b_2,...,b_{m}]\)

根据维度信息也能很方便的推导各个元素的含义,即为\(A\)矩阵的每个元素对\(B\)矩阵的每个元素求一个偏导。

当然,高维的矩阵微分应用场景有限,我们很少需要求一个矩阵关于另一个矩阵的偏导。因此这个规律可能因为博主实践较少有误。

在深度学习的场景中,一般是标量对矩阵求导,因此主要介绍标量对矩阵微分的情况。

一般对于向量,默认为列向量,\(\mathbf{x}=[x_1,x_2,...,x_n]^{T}\),我们有标量函数\(f(\mathbf{x})\),那么对应的梯度为

\[ \frac{\partial f}{\partial \mathbf{x}}=[\frac{\partial f}{\partial x_1},\frac{\partial f}{\partial x_2},..\frac{\partial f}{\partial x_n}]^\top \]

根据这个公式我们可以发现,这个梯度向量的每个元素都是函数对该元素的偏导。

因此,我们有,

\[ \partial f = (\frac{\partial f}{\partial \mathbf{x}})^\top \partial \mathbf{x} \]

对于标量对向量到梯度来说,在左边乘以其梯度的转置就可以对应得到目标的微分。

对于矩阵来说,逐点乘积\(\odot\)然后对应位置求和应该是更广泛的规律。但向量是特殊的,逐点乘积求和和转置相乘的结果是一样的。

对于函数值为标量,变量为二维矩阵的情况,函数值的微分是梯度矩阵和变量矩阵的转置乘积的迹。

\[ df(X)=tr((\frac{df(X)}{dX})^\top \cdot X) \]

雅可比矩阵

雅可比矩阵指的是向量对于向量的微分,假如我们有:

\[ F:R^{N}\to R^{M} ,\mathbf{y}=F(\mathbf{x}) \]

那么雅克比矩阵为,

\[ J_{F:\mathrm{x\to y}}= \left[ \begin {array}{c c c} \frac{\partial y_1}{\partial x_1}&&\frac{\partial y_1}{\partial x_N}\\ &&\\ \frac{\partial y_M}{\partial x_1}&&\frac{\partial y_M}{\partial x_N}\\ \end{array} \right] \]

其中第\(i\)行是\(y_i\)关于\(\mathbf{x}\)的微分的转置。

我们有一阶泰勒展开式:

\[ F({\bf{x}}+d{\bf{x}})=F({\bf{x}})+J_{F:x \to y}d{\bf{x}}+o(\|d{\bf{x}}\,\|). \]

Hessian

在向量微积分中,Hessian 矩阵用于表示标量关于向量的二阶偏导数。

假如我们有

\[ f(\mathbf{x}) : \mathbb{R}^N \to \mathbb{R} \]

那么我们有,

\[ H_{x \to f} = \frac{d^2 f}{dx \, dx^\top} = \left[ \frac{\partial f}{\partial x_i \partial x_j} \right] \]

通过定义也可以看出,Hessian 矩阵可以写成一阶导数构成的向量关于自变量的雅可比矩阵。

\(f\)关于变量的一阶梯度为,

\[ \mathbf{a}(\mathbf{x}) = \left[ \frac{\partial f}{\partial x_i} \right] \]

那么hessian矩阵还可以写为,

\[ H_{x \to f} = \frac{d\mathbf{a}}{d\mathbf{x}} = \left[ \frac{d a_i}{d x_j} \right] = \left[ \frac{\partial f}{\partial x_i \partial x_j} \right] \]

对应的,我们也能得到二阶泰勒展开式,

\[ f(\mathbf{x} + d\mathbf{x}) = f(\mathbf{x}) + \mathbf{a}^\top d\mathbf{x} + \frac{1}{2} d\mathbf{x}^\top H_{x \to f} \, d\mathbf{x} + o(\|d\mathbf{x}\|^2) \]

这里的二次项的推导方式为:

\[ \begin{align*} &\frac{1}{2}(\partial \mathbf{a})^\top\partial \mathbf{x} \\ =&\frac{1}{2}((\frac{\partial \mathbf{a}}{\partial \mathbf{x}})^\top \partial \mathbf{x})^\top\partial \mathbf{x} \\ =&\frac{1}{2} d\mathbf{x}^\top \frac{\partial \mathbf{a}}{\partial \mathbf{x}} \ d\mathbf{x} \\ =&\frac{1}{2} d\mathbf{x}^\top H_{x \to f} d\mathbf{x} \\ \end{align*} \]

根据这个例子我们也能很容易总结规律并且推广到更多公式。(从定义出发推导式子,向量乘以自己的梯度转置获得目标的微分)

链式表达式

假设我们有,

\[ \begin{align*} y &= f(g(h(x))) \\ q &= h(x) \\ k &= g(q) \\ y &= f(k) \end{align*} \]

我们希望得到

\[ \begin{align*} &\partial y \\ =& (\frac{\partial y}{\partial k})^\top \partial k \\ =& (\frac{\partial y}{\partial k})^\top (\frac{\partial k}{\partial q})^\top \partial q \\ =& (\frac{\partial y}{\partial k})^\top (\frac{\partial k}{\partial q})^\top (\frac{\partial q}{\partial x})^\top \partial x \\ =& (\frac{\partial q}{\partial x} \frac{\partial k}{\partial q} \frac{\partial y}{\partial k})^\top \partial x \\ \end{align*} \]

所以我们有

\[ \frac{\partial y}{\partial x} = \frac{\partial q}{\partial x} \frac{\partial k}{\partial q} \frac{\partial y}{\partial k} \]

这个推导前置条件只有:向量左乘其梯度的转置就可以对应得到目标的微分。

别的布局的推导方式也类似。

在数学公式的推导中,链式法则的记忆要点为:能乘维数对就对(可能维度信息其实就包含了部分信息)。

行向量偏导形式

有一种操作把矩阵变成按列堆栈向量化\(vec\),然后进行处理,就可以利用部分在低维中的规律进行计算:

\[ vec(X)=[x_{11},x_{21},..,x_{12},x_{22},...,x_{1n},x_{2n},...,x_{nm}]^T \]

更多介绍阅读矩阵论、弗罗贝尼乌斯内积、克罗内克积等相关资料。

因为博主也不会,只是计算机系的,在深度学习里不会用到所有的数学知识。

合适做法

合适的做法还是对于矩阵的每个元素单独看梯度和贡献,然后根据指标的变化来总结公式。

比如,计算\(x_{ij}\)是如何影响\(y_{ik}\)的,然后总结梯度公式。

示例1:

\[ Y=X*A,而X \in R^{n \times p}, A \in R^{p \times m},Y \in R^{n \times m},l为标量 \\ 已知\frac{\partial l}{\partial Y},求\frac{\partial l}{\partial X} \\ 计算x_{ik}的贡献,有 \frac{\partial l}{\partial x_{ik}}=\sum_{j}a_{kj}\frac{\partial l}{\partial y_{ij}} \\ 根据维度信息(i在左侧,k在右侧)总结,得到\frac{\partial l}{\partial X}=\frac{\partial l}{\partial Y}A^T \]

tip:由于一维向量很多时候会被写为列向量,所以有的教程理解不是很方便,但如果接触过pytorch框架,会方便理解很多.

参考资料


文章作者: bg51717
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 bg51717 !
由于评论系统依托于Github的Discuss存在,因此默认评论者会收到所有通知。可以在邮件里点击"unsubscribe"停止接受,后续也可以点击下列仓库进行通知管理: bg51717/Hexo-Blogs-comments
Since the comment system relies on GitHub's Discussions feature, by default, commentators will receive all notifications. You can click "unsubscribe" in the email to stop receiving them, and you can also manage your notifications by clicking on the following repositories: bg51717/Hexo-Blogs-comments
  目录