矩阵对矩阵
当输出也是矩阵时,比如 \(\boldsymbol{Y}=\boldsymbol{A}\boldsymbol{X}\boldsymbol{B}\),导数严格来说是线性算子。硬把它写成四维数组当然可以,但场面像把一条鱼塞进文件柜:不是不行,只是很不优雅。
vec 与 Kronecker 积
向量化算子 \(\mathrm{vec}(\cdot)\) 把矩阵按列摞成向量。核心恒等式是:
\[ \mathrm{vec}(\boldsymbol{A}\boldsymbol{X}\boldsymbol{B})=(\boldsymbol{B}^T\otimes \boldsymbol{A})\mathrm{vec}(\boldsymbol{X}). \]因此:
\[ \frac{\partial\,\mathrm{vec}(\boldsymbol{Y})} {\partial\,\mathrm{vec}(\boldsymbol{X})} =\boldsymbol{B}^T\otimes \boldsymbol{A}. \]Kronecker 积像一个巨大的邮政分拣中心:\(\boldsymbol{A}\) 管行方向怎么混合,\(\boldsymbol{B}\) 管列方向怎么混合,最后所有元素都被编号、打包、投递。它不一定适合真的造出来,但非常适合想清楚“这个线性变换到底在干什么”。
伴随算子
实战里我们更常用伴随算子。若前向为:
\[ \boldsymbol{Y}=\boldsymbol{A} \boldsymbol{X} \boldsymbol{B}, \]且上游给来梯度 \(\boldsymbol{G}=\nabla_{\boldsymbol{Y}} L\),那么:
\[ dY=\boldsymbol{A}\,dX\,\boldsymbol{B}, \] \[ dL=\mathrm{tr}(\boldsymbol{G}^T \boldsymbol{A}\,dX\,\boldsymbol{B}) =\mathrm{tr}((\boldsymbol{A}^T \boldsymbol{G} \boldsymbol{B}^T)^T dX), \] \[ \nabla_{\boldsymbol{X}} L=\boldsymbol{A}^T \boldsymbol{G} \boldsymbol{B}^T. \]这就是反向传播的日常:前向时左乘 \(\boldsymbol{A}\)、右乘 \(\boldsymbol{B}\);反向时把梯度通过 \(\boldsymbol{A}^T\)、\(\boldsymbol{B}^T\) 送回去。像寄快递,去程和回程不是同一条路,但地址系统彼此对应。