【全网最全】机器学习梯度求解汇总:标量/向量/矩阵求导看这一篇就够了
梯度求解汇总
梯度,我觉得不用过多介绍了吧。当今 AI 时代,大家应该或多或少都听说过反向传播、自动微分。像梯度下降、学习率这些内容,我之前在最大似然函数的文章中也提到过。
简单来说,梯度描述的是函数在某一点附近如何变化。无论是优化问题、机器学习中的反向传播,还是自动微分求解器,本质上都离不开梯度。
阅读路线
- 从一元的导数到多元函数梯度介绍
- 向量梯度
- 雅可比矩阵
- 矩阵梯度
梯度类型概览
| 类型 | 输入 | 输出 | 梯度形状 | 简单例子 | 梯度怎么求 |
|---|---|---|---|---|---|
| 一元函数 | 标量 x | 标量 f | 一个数 | f(x)=x² | 普通微积分,直接求导 |
| 向量梯度 | 向量 x | 标量 f | 和输入向量同形 | f(x,y)=x²+y² | 对每个分量分别求偏导,拼成梯度向量 |
| 雅可比矩阵 | 向量 x | 向量 f | m×n 矩阵 | f(x,y)=(x²+y, xy) | 每个输出分量分别对输入求梯度,再组成矩阵 |
| 矩阵梯度 | 矩阵 X | 标量 f | 和输入矩阵同形 | f 是 X 的 Frobenius 范数平方 | 用迹技巧,把 df 写成 tr(GᵀdX),则 G 就是梯度 |
至于矩阵到矩阵的函数类型,只给一个简单例子:
Y=AXY=AXY=AX
其中 A 是常量矩阵,则:
dY=A dXdY=A\,dXdY=AdX
梯度介绍
我们最熟悉的是一元函数的导数。对于一个函数:
y=f(x)y=f(x)y=f(x)
因为自变量只有一个,所以函数只能沿着 x 轴这一个方向变化。这个时候导数:
f′(x)f'(x)f′(x)
就可以表示函数在这一点附近变化得快不快。
但是多元函数就不一样了。比如:
z=f(x,y)z=f(x,y)z=f(x,y)
它的自变量有两个,点 (x,y) 可以在平面上向很多方向移动。也就是说,函数值 z 的变化不再只对应一个方向,而是和移动方向有关。
这时如果只说“导数”,就不够准确了。因为沿着不同方向走,函数值可能增加得快,也可能增加得慢,甚至可能减少。所以在多元函数中,我们需要一个新的工具来描述函数在某一点附近的变化情况,这个工具就是梯度。
对于二元函数:
z=f(x,y)z=f(x,y)z=f(x,y)
它的梯度定义为:
∇f(x,y)=(∂f∂x,∂f∂y)\nabla f(x,y)=\left(\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}\right)∇f(x,y)=(∂x∂f,∂y∂f)
所以可以这样理解:梯度就是把函数在各个坐标方向上的变化率放在一起,组成的一个向量。
具体例子:
f(x,y)=x2+y2f(x,y)=x^2+y^2f(x,y)=x2+y2
这个函数的图像就是一个碗形曲面,在点 (1,2) 处,梯度为:
∇f(x,y)=(∂f∂x,∂f∂y)=(2x,2y)\nabla f(x,y)=\left(\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}\right)=(2x,2y)∇f(x,y)=(∂x∂f,∂y∂f)=(2x,2y)
所以:
∇f(1,2)=(2,4)\nabla f(1,2)=(2,4)∇f(1,2)=(2,4)
这个向量 (2,4) 告诉你什么?
它告诉你在 (1,2) 这个点,往哪个方向走函数值涨得最大。
向量梯度
在梯度介绍中就已经说了向量梯度了。
这其中最重要的是链式法则。我记得我之前看 Andrej Karpathy 的一个很出名的人工智能课,他写的反向传播求解器,本质上就是链式法则。
以逻辑回归为例,直接看怎么把梯度算出来。
目标是对 w 求梯度,注意观察这里有三层嵌套:
w⟶z=wTx⟶y^=σ(z)⟶Lw \longrightarrow z=w^T x \longrightarrow \hat{y}=\sigma(z) \longrightarrow Lw⟶z=wTx⟶y^=σ(z)⟶L
链式法则就是把每一层分别求导再连乘:
∂L∂w=∂L∂y^⋅∂y^∂z⋅∂z∂w\frac{\partial L}{\partial w}=\frac{\partial L}{\partial \hat{y}}\cdot\frac{\partial \hat{y}}{\partial z}\cdot\frac{\partial z}{\partial w}∂w∂L=∂y^∂L⋅∂z∂y^⋅∂w∂z
三层分别算:
∂L∂y^=y−y^y^(1−y^)\frac{\partial L}{\partial \hat{y}}=\frac{y-\hat{y}}{\hat{y}(1-\hat{y})}∂y^∂L=y^(1−y^)y−y^
∂y^∂z=y^(1−y^)\frac{\partial \hat{y}}{\partial z}=\hat{y}(1-\hat{y})∂z∂y^=y^(1−y^)
∂z∂w=x\frac{\partial z}{\partial w}=x∂w∂z=x
连乘之后,中间项直接约掉:
∂L∂w=y−y^y^(1−y^)⋅y^(1−y^)⋅x\frac{\partial L}{\partial w}=\frac{y-\hat{y}}{\hat{y}(1-\hat{y})}\cdot\hat{y}(1-\hat{y})\cdot x∂w∂L=y^(1−y^)y−y^⋅y^(1−y^)⋅x
所以:
∂L∂w=(y−y^)x\frac{\partial L}{\partial w}=(y-\hat{y})x∂w∂L=(y−y^)x
对所有样本求和,梯度就出来了:
∇wL=∑i=1n(yi−y^i)xi\nabla_w L=\sum_{i=1}^{n}(y_i-\hat{y}_i)x_i∇wL=i=1∑n(yi−y^i)xi
这就是向量梯度最典型的计算过程:拆层、逐层求导、连乘。
雅可比矩阵
前面讨论的大多数情况,输出都是一个标量。不管输入是一个 x,还是一堆变量,最终函数值 f 都是一个数。梯度向量做的事情,就是把这个标量对每个输入方向求偏导,拼成一个向量。
那现在问题来了:如果输出也是一个向量呢?
比如这样一个函数:
f:Rn→Rmf:\mathbb{R}^n\to\mathbb{R}^mf:Rn→Rm
输入是 n 维向量,输出是 m 维向量。这时候“梯度”长什么样?
先从直觉出发
我们先想一个最简单的情况:
f:R2→R2f:\mathbb{R}^2\to\mathbb{R}^2f:R2→R2
也就是:
f(x,y)=(f1(x,y)f2(x,y))f(x,y)=\begin{pmatrix}f_1(x,y)\\f_2(x,y)\end{pmatrix}f(x,y)=(f1(x,y)f2(x,y))
两个输出,每个输出都是一个标量函数。对第一个输出来说,它的梯度是:
∇f1=(∂f1∂x,∂f1∂y)\nabla f_1=\left(\frac{\partial f_1}{\partial x},\frac{\partial f_1}{\partial y}\right)∇f1=(∂x∂f1,∂y∂f1)
对第二个输出来说,它的梯度是:
∇f2=(∂f2∂x,∂f2∂y)\nabla f_2=\left(\frac{\partial f_2}{\partial x},\frac{\partial f_2}{\partial y}\right)∇f2=(∂x∂f2,∂y∂f2)
既然有两个输出,就有两个梯度向量。雅可比矩阵做的事情非常朴素:把这两个梯度向量叠在一起,变成一个矩阵。
J=(∇f1∇f2)=(∂f1∂x∂f1∂y∂f2∂x∂f2∂y)J=\begin{pmatrix}\nabla f_1\\\nabla f_2\end{pmatrix}=\begin{pmatrix}\frac{\partial f_1}{\partial x}&\frac{\partial f_1}{\partial y}\\\frac{\partial f_2}{\partial x}&\frac{\partial f_2}{\partial y}\end{pmatrix}J=(∇f1∇f2)=(∂x∂f1∂x∂f2∂y∂f1∂y∂f2)
这就是雅可比矩阵。第 i 行就是第 i 个输出分量的梯度向量。
定义
对于:
f:Rn→Rmf:\mathbb{R}^n\to\mathbb{R}^mf:Rn→Rm
雅可比矩阵 J 的定义为:
Jij=∂fi∂xjJ_{ij}=\frac{\partial f_i}{\partial x_j}Jij=∂xj∂fi
写成完整矩阵的形式:
J=(∂f1∂x1⋯∂f1∂xn⋮⋱⋮∂fm∂x1⋯∂fm∂xn)J=\begin{pmatrix}\frac{\partial f_1}{\partial x_1}&\cdots&\frac{\partial f_1}{\partial x_n}\\\vdots&\ddots&\vdots\\\frac{\partial f_m}{\partial x_1}&\cdots&\frac{\partial f_m}{\partial x_n}\end{pmatrix}J=∂x1∂f1⋮∂x1∂fm⋯⋱⋯∂xn∂f1⋮∂xn∂fm
记住形状:m 行对应 m 个输出,n 列对应 n 个输入。
例子
设:
f(x,y)=(x2+yxy)f(x,y)=\begin{pmatrix}x^2+y\\xy\end{pmatrix}f(x,y)=(x2+yxy)
两个输出分量分别是:
f1=x2+yf_1=x^2+yf1=x2+y
f2=xyf_2=xyf2=xy
逐个求偏导,填进矩阵:
J=(∂f1∂x∂f1∂y∂f2∂x∂f2∂y)=(2x1yx)J=\begin{pmatrix}\frac{\partial f_1}{\partial x}&\frac{\partial f_1}{\partial y}\\\frac{\partial f_2}{\partial x}&\frac{\partial f_2}{\partial y}\end{pmatrix}=\begin{pmatrix}2x&1\\y&x\end{pmatrix}J=(∂x∂f1∂x∂f2∂y∂f1∂y∂f2)=(2xy1x)
在点 (1,2) 处,雅可比矩阵的值为:
J(1,2)=(2121)J(1,2)=\begin{pmatrix}2&1\\2&1\end{pmatrix}J(1,2)=(2211)
这个矩阵告诉你:在点 (1,2) 附近,如果 x 和 y 发生很小的变化,那么两个输出会大约怎么变。
更具体地说,如果输入有一个很小的变化:
dx=(dxdy)d\mathbf{x}=\begin{pmatrix}dx\\dy\end{pmatrix}dx=(dxdy)
那么输出变化近似为:
df≈Jdxdf\approx Jd\mathbf{x}df≈Jdx
在这个例子中:
df≈(2121)(dxdy)=(2dx+dy2dx+dy)df\approx\begin{pmatrix}2&1\\2&1\end{pmatrix}\begin{pmatrix}dx\\dy\end{pmatrix}=\begin{pmatrix}2dx+dy\\2dx+dy\end{pmatrix}df≈(2211)(dxdy)=(2dx+dy2dx+dy)
也就是说,在点 (1,2) 附近,两个输出的一阶变化趋势是一样的。
矩阵梯度
梯度的形状
这一点先说清楚,避免困惑。
不管输入是标量、向量还是矩阵,梯度的形状通常都和输入保持一致。
- 输入是标量 x,梯度是一个数
- 输入是向量 x,梯度是一个向量
- 输入是矩阵 X,梯度是一个矩阵
如果:
X∈Rm×nX\in\mathbb{R}^{m\times n}X∈Rm×n
那么:
∂f∂X∈Rm×n\frac{\partial f}{\partial X}\in\mathbb{R}^{m\times n}∂X∂f∈Rm×n
其中第 (i,j) 个元素就是:
(∂f∂X)ij=∂f∂Xij\left(\frac{\partial f}{\partial X}\right)_{ij}=\frac{\partial f}{\partial X_{ij}}(∂X∂f)ij=∂Xij∂f
也就是说,矩阵梯度的每一个位置,对应的就是 f 对 X 在那个位置上的元素求偏导。概念上没有任何新东西,只是元素变多了。
概念非常简单,但如果每次都展开成元素,写成求和式,再一个个求偏导,非常容易出错,所以就引入了迹技巧。
迹技巧的核心公式
记住一个关键结论:
df=tr(GTdX)⟹∂f∂X=Gdf=\mathrm{tr}(G^T dX)\quad\Longrightarrow\quad\frac{\partial f}{\partial X}=Gdf=tr(GTdX)⟹∂X∂f=G
需要记住的运算规则
微分的线性性:
d(A+B)=dA+dBd(A+B)=dA+dBd(A+B)=dA+dB
乘积法则:
d(AB)=(dA)B+A(dB)d(AB)=(dA)B+A(dB)d(AB)=(dA)B+A(dB)
迹的交换性:
tr(AB)=tr(BA)\mathrm{tr}(AB)=\mathrm{tr}(BA)tr(AB)=tr(BA)
迹对转置不变:
tr(A)=tr(AT)\mathrm{tr}(A)=\mathrm{tr}(A^T)tr(A)=tr(AT)
这几条规则就够用了,大部分矩阵梯度都能靠这几条推出来。
例子:Frobenius 范数
设:
f=∥X∥F2=tr(XTX)f=\|X\|_F^2=\mathrm{tr}(X^T X)f=∥X∥F2=tr(XTX)
第一步,对 f 求微分:
df=d tr(XTX)=tr(d(XTX))df=d\,\mathrm{tr}(X^T X)=\mathrm{tr}(d(X^T X))df=dtr(XTX)=tr(d(XTX))
用乘积法则展开括号里的部分:
d(XTX)=(dX)TX+XT(dX)d(X^T X)=(dX)^T X+X^T(dX)d(XTX)=(dX)TX+XT(dX)
所以:
df=tr((dX)TX+XTdX)df=\mathrm{tr}((dX)^T X+X^T dX)df=tr((dX)TX+XTdX)
也就是:
df=tr((dX)TX)+tr(XTdX)df=\mathrm{tr}((dX)^T X)+\mathrm{tr}(X^T dX)df=tr((dX)TX)+tr(XTdX)
第二步,利用迹的性质统一形式。
注意:
tr((dX)TX)=tr(XTdX)\mathrm{tr}((dX)^T X)=\mathrm{tr}(X^T dX)tr((dX)TX)=tr(XTdX)
所以两项合并:
df=2tr(XTdX)df=2\mathrm{tr}(X^T dX)df=2tr(XTdX)
第三步,对号入座。
现在 df 已经是下面这种形式:
df=tr(GTdX)df=\mathrm{tr}(G^T dX)df=tr(GTdX)
其中:
GT=2XTG^T=2X^TGT=2XT
所以:
G=2XG=2XG=2X
于是:
∂f∂X=2X\frac{\partial f}{\partial X}=2X∂X∂f=2X
这和我们对标量函数的直觉完全一致:
f(x)=x2⟹f′(x)=2xf(x)=x^2\quad\Longrightarrow\quad f'(x)=2xf(x)=x2⟹f′(x)=2x
只不过这里的输入变成了矩阵。
尾记
最近更新较慢,主要是因为我所在的学校实行的是小学期制,第八周直接迎来了期末周。加上数学专业的专业课确实硬核,实在没法简单糊弄过去,还望大家见谅。
此外,本人目前也只是一名本科生,文章中若有不当或疏漏之处,欢迎大家在评论区多加指正!
更多推荐


所有评论(0)