技术博客

对称矩阵求导的坑:独立变量只有一半时梯度怎么修正

第 10 / 147 篇 · 2026-06-07 · ai · 矩阵求导对称矩阵梯度推导

矩阵微分里最隐蔽的一类错误来自对称矩阵。目标函数 $f(X)$ 里 $X$ 是对称阵(协方差、核矩阵、格拉姆矩阵),直接套微分法推出的"梯度"代入方向导数一验——差一半或差一倍。问题不在微分法本身,而在于对称矩阵的自由度只有 $n(n+1)/2$ 个,把 $X$ 当一般矩阵处理等于假装非对角元素能独立变化,它们实际上成对联动。这篇把这个修正讲严格,顺带澄清一个相关但独立的常见困惑:$d(x^\top Ax)$ 里的因子 2 到底从哪来。

先分清两件常被混为一谈的事

文献里"对称矩阵求导"的困惑其实是两个不同的问题搅在一起,先拆开。

问题一:常量 $A$ 对称时公式退化。 $f=x^\top Ax$ 的一般梯度是 $(A+A^\top)x$(速查表里推过),$A$ 对称时退化为 $2Ax$。这里对称的是常量,微分变量 $x$ 没有任何约束。因子 2 的来源是纯代数:展开 $x^\top Ax=\sum_{ij}a_{ij}x_ix_j$,对 $x_k$ 求导时 $a_{kj}x_kx_j$ 与 $a_{ik}x_ia_k$ 两类项各自贡献一份,对称时两份相等。这与下面的问题二无关。

问题二:微分变量 $X$ 本身对称。 这才是真正的坑。$X\in\mathrm{Sym}(n)$,$f:\mathrm{Sym}(n)\to\mathbb{R}$,问梯度是什么。

问题出在哪:方向导数检验

梯度的定义从不依赖"矩阵"身份,只依赖内积空间结构:$G$ 是 $f$ 在 $X$ 处的梯度,当且仅当对一切允许的方向 $V$(对称矩阵空间里 $V$ 也必须对称),

$$ df_X(V)=\langle G,V\rangle_F=\mathrm{tr}(G^\top V). $$

微分法推出 $df=\mathrm{tr}(M^\top dX)$ 后,若 $X$ 无约束,$M$ 就是梯度。但 $X$ 对称时 $dX$ 只能取对称方向,而 trace 内积有个被忽视的性质:任意矩阵 $M$ 与对称矩阵 $V$ 的内积只"看见" $M$ 的对称部分:

$$ \mathrm{tr}(M^\top V)=\mathrm{tr}\Big(\frac{M+M^\top}{2}V\Big),\qquad V\text{ 对称}. $$

(因为 $\mathrm{tr}(M^\top V)=\sum_{ij}m_{ij}v_{ij}$,而 $v_{ij}=v_{ji}$,配对后 $\sum_{i完全相同的方向导数——梯度在对称子空间里不唯一,差一个反对称分量。要得到落在对称空间里的规范梯度,必须取对称部分:

$$ \boxed{\;\nabla_X f=\frac{M+M^\top}{2},\qquad M=\text{微分法按一般矩阵读出的结果}\;} $$

标准例子:f(X)=tr(XA),X 对称

$A$ 为常量(不必对称),$X$ 对称。按一般矩阵微分:$df=\mathrm{tr}(A\,dX)$,朴素读出 $M=A^\top$。代入对称化修正:

$$ \nabla_X f=\frac{A^\top+A}{2}. $$

数值验证一下差别。取 $X_0$ 对称、方向 $E$ 对称,沿 $X_0+tE$ 的方向导数应为 $\mathrm{tr}(A E)$。用朴素梯度 $A^\top$ 算 $\langle A^\top,E\rangle=\mathrm{tr}(AE)$,用修正梯度算 $\langle\frac{A+A^\top}{2},E\rangle=\frac{1}{2}\big(\mathrm{tr}(A^\top E)+\mathrm{tr}(AE)\big)=\frac{1}{2}\big(\mathrm{tr}(EA^\top)+\mathrm{tr}(AE)\big)=\mathrm{tr}(AE)$(循环轮换)。两者数值相同——这正说明差别不在方向导数而在梯度的身份:修正版本本身是对称阵,落在切空间内;朴素版本含反对称分量,而它在对称方向的投影恰好一样。

什么时候这个差别会咬人?把梯度当矩阵用的时候:梯度下降更新 $X\leftarrow X-\eta M$ 若 $M$ 不对称,一步就走出对称流形,下一步连 $\mathrm{tr}(AdX)$ 这种推导的前提都没了。修正版保证更新序列始终留在对称阵空间里。做优化时这不是美学问题,是正确性问题。

完整战例:对称二次型 f(X)=tr(XᵀAX),X 对称

$A$ 对称常量、$X$ 为对称变量(比如核方法里的格拉姆矩阵参数化)。微分法按一般矩阵给出 $M=AX+A^\top X=2AX$(用了 $A$ 对称)。再对 $X$ 的对称性做修正:

$$ \nabla_X f=\frac{2AX+(2AX)^\top}{2}=AX+XA. $$

$AX+XA$ 而不是 $2AX$——两者一般不相等($AX$ 与 $XA$ 各自都不是对称阵,和才是)。如果用错了的 $2AX$ 去做梯度步,$X$ 的对称性立即被破坏。大纲标题里"为什么 $d(X^\top AX)$ 对对称 $A$ 是 $2AX\,dX$"指的是微分表达式本身没错($df=\mathrm{tr}(2AX\,dX)$ 对一切方向成立),错的是把 $2AX$ 直接当成对称变量下的梯度——中间还差一次对称化。

对称矩阵的非对角元成对联动:v_ij 与 v_ji 是同一个自由度,trace 内积只看见对称部分 v₁₂ v₂₁ v₁₂ = v₂₁ 同一自由度 对称方向 V:镜像元素颜色成对 tr(MᵀV) = tr( (M+Mᵀ)/2 · V ),V 对称 M 的反对称部分 (M−Mᵀ)/2 与一切对称 V 正交 ⇒ 对称变量梯度 = 对称化:∇ = (M+Mᵀ)/2 梯度保持在对称流形内,迭代不破坏结构 tr(XᵀAX) 案例:A 对称给 M=2AX,X 对称再修正为 ∇=AX+XA

用代码把坑复现一次

光讲道理不如让错误真的发生。用 float64 写一个对称变量的目标,对比朴素梯度与修正梯度在对称方向上的方向导数,再看它们在反对称方向上的分歧:

import numpy as np
rng = np.random.default_rng(0)
n = 4
A = rng.standard_normal((n, n)); A = A + A.T          # 对称常量
X = rng.standard_normal((n, n)); X = X + X.T          # 对称变量
f = lambda X: np.trace(X.T @ A @ X)

M = 2 * A @ X                     # 微分法按一般矩阵读出的结果
G = (M + M.T) / 2                 # 对称化修正:AX + XA

for _ in range(5):
    E = rng.standard_normal((n, n)); E = E + E.T      # 对称方向
    eps = 1e-6
    dir_num = (f(X + eps * E) - f(X - eps * E)) / (2 * eps)
    assert abs(dir_num - np.trace(M.T @ E)) < 1e-8    # 两个梯度在对称方向上都对
    assert abs(dir_num - np.trace(G.T @ E)) < 1e-8

E_skew = rng.standard_normal((n, n)); E_skew -= E_skew.T   # 反对称方向
print(np.trace(M.T @ E_skew))     # 非零:朴素梯度"看见"了不存在的方向
print(np.trace(G.T @ E_skew))     # 恒为零:修正梯度只活在对称空间里

对称方向上两者数值完全一致(这解释了为什么这个坑难被发现——沿合法方向检验根本测不出来),反对称方向上朴素梯度有非零响应而修正梯度恒零。如果拿 $M$ 直接做梯度下降,$X-\eta M$ 的反对称分量每一步都在积累,对称性静默崩坏;拿 $G$ 更新则 $X-\eta G$ 恒对称。

一个修正"自动失效"的重要案例

并非所有对称变量问题都要多付一次对称化。看 $\log\det$:$X$ 对称正定,$f=\log\det X$。微分法(下一篇的 Jacobi 公式)给出 $df=\mathrm{tr}(X^{-1}dX)$,朴素读出 $M=X^{-\top}$。但 $X$ 对称意味着 $X^{-1}$ 也对称,$X^{-\top}=X^{-1}$,于是

$$ \frac{M+M^\top}{2}=\frac{X^{-1}+X^{-1}}{2}=X^{-1}, $$

修正项自动归零——$M$ 已经落在对称空间里。这是个有用的判别经验:朴素梯度若碰巧已对称,对称化不起作用;坑只咬那些朴素结果本身不对称的表达式(比如上面的 $2AX$)。高斯 MLE 里 $\nabla_\Sigma\log\det\Sigma=\Sigma^{-1}$ 之所以从来没人提对称化问题,就是因为它属于前者。

工程上的标准解法:把约束参数化掉

实战中更常见的是绕开而不是修正:要优化对称正定矩阵 $\Sigma$,直接参数化 Cholesky 因子 $\Sigma=LL^\top$($L$ 下三角、对角元取正),对无约束的 $L$ 求导。设 $\partial f/\partial\Sigma=G_\Sigma$(已对称化),链式法则给 $L$ 的梯度一个紧凑形式。由 $d\Sigma=dL\cdot L^\top+L\,dL^\top$,

$$ df=\mathrm{tr}(G_\Sigma\,d\Sigma)=2\,\mathrm{tr}(G_\Sigma L\,dL^\top)=2\,\mathrm{tr}(L^\top G_\Sigma\,dL), $$

所以 $\partial f/\partial L=2G_\Sigma L$,再把严格上三角部分置零(因为 $L$ 的对角线以上不是自由变量)。VAE 的全协方差后验、高斯过程的超参学习都是这个套路:重参数化把带约束问题变回普通微分法问题,对称正定约束由 $LL^\top$ 的结构兜底,比每次手动对称化稳妥得多。

深度学习里的实际触点

对称矩阵在大模型主线里不算高频,但几个关键场景绕不开。协方差/精度矩阵参数化已在上一节说过;注意力里的相对位置偏置矩阵、图神经网络里强制对称的邻接矩阵,同样受本节约束。还有理论侧:分析 $\mathrm{tr}(X^\top AX)$ 型目标(谱方法、瑞利商推广)的临界点时,梯度必须取 $AX+XA$,临界点条件 $AX+XA=0$ 与朴素版 $AX=0$ 的解集完全不同,用错公式连理论结论都是错的。

顺带把问题一也收个尾:为什么标量二次型 $x^\top Ax$ 里"对称化"不需要操心?因为任何方阵 $A$ 都可以拆成对称加反对称,而反对称部分在二次型里恒为零($x^\top A_{\text{skew}}x=0$,标量等于自己的转置再取负)。所以 $x^\top Ax$ 本来就只依赖 $A$ 的对称部分——写成 $2Ax$ 的前提是 $A$ 对称,而 $A$ 不对称时正确答案是 $(A+A^\top)x$,这个公式无条件成立。背"无条件版"、在对称时心算退化,永不翻车。

小结

对称矩阵求导的陷阱一句话说清:微分法按一般矩阵读出的 $M$ 含反对称分量,而对称方向上的内积看不见它;规范梯度是对称化版本 $(M+M^\top)/2$,它既给出正确的方向导数,又保证梯度迭代留在对称流形内。两个相关结论分开记:常量 $A$ 对称时 $x^\top Ax$ 梯度退化 $2Ax$(纯代数退化);变量 $X$ 对称时任何梯度都要过一道 $(M+M^\top)/2$(几何约束修正)。工程上更省心的路线是 Cholesky 这类重参数化,把约束参数化掉,回到无约束世界用普通微分法。下一篇是第一章数学基础的收尾:行列式与逆矩阵的导数——Jacobi 公式,以及它为什么撑起整个归一化流家族。