卷积神经网络(CNN)的反向传播细节

本文系统阐述卷积神经网络(CNN)反向传播的数学原理与工程实现,聚焦卷积层梯度计算三大公式:对bias求和、对权重的互相关累加、对输入的full convolution(转置卷积)。明确互相关约定下dX需经dilation、rot180翻转、padding裁剪等操作,并统一于VJP(向量-雅可比积)视角。涵盖池化、ReLU、FC及softmax+CE等算子的反向规则,通过3×3手算实例与666参数微型CNN端到端数值验证,揭示常见错误根源与计算/内存开销规律。

0 · 导读:为什么 CNN 的反向传播值得单独一篇

《神经网络》篇的结论可以压成一句话:反向传播 = 链式法则沿计算图逆拓扑序走一遍,每个密集层只出两种形态——误差回传 δ(l)=(W(l+1))⊤δ(l+1)⊙φ′(z(l))\delta^{(l)} = (W^{(l+1)})^\top\delta^{(l+1)}\odot\varphi'(z^{(l)})δ(l)=(W(l+1))⊤δ(l+1)⊙φ′(z(l)),权重梯度 ∂L/∂W=(a(l−1))⊤δ\partial\mathcal{L}/\partial W = (a^{(l-1)})^\top\delta∂L/∂W=(a(l−1))⊤δ。卷积层并没有推翻这个框架,它只是把「密集矩阵乘」换成了带权重共享的稀疏线性算子。由此产生三个 MLP 时代不存在的新问题:

  1. 权重梯度要累加,不是平均。一个 3×33\times33×3 核被 Ho×WoH_o\times W_oHo​×Wo​ 个空间位置共享,每个位置都对同一份 WWW 产生一份梯度——∂L/∂W\partial\mathcal{L}/\partial W∂L/∂W 是对全部位置的求和。写丢一个 ∑\sum∑ 是最常见的静默错误;
  2. 输入梯度是 full convolution(转置卷积)。感受野重叠意味着同一个输入像素被多个输出位置共享,回传时同样要累加;而「前向算子的转置」在卷积这里的标准形式是 full conv——「翻转」第一次出现在反向传播里,这是全文的核心;
  3. stride / padding / dilation 各自变形。stride sss 在反向里变成对上游梯度 δ\deltaδ 的 dilation(插零);padding ppp 变成 full conv 之后的 裁剪;不能整除时的余数 rrr 变成 PyTorch 的 output_padding——三个超参在反向里各有归宿,记混任何一个都会得到「形状对、数值错」的梯度。

全文路线图:§1 把前向约定钉死(互相关 vs 真卷积、线性算子视角、im2col 视角)→ §2 给出统御全篇的「VJP / 转置」观点 → §3 卷积层三条公式的完整推导 + 3×3 手算全数字 → §4 其余算子(池化/激活/FC/softmax)→ §5 端到端微型 CNN(666 个参数全部过数值梯度检验)→ §6 常见错误清单 → §7 计算量与内存 → §8 框架映射与高性能内核。


1 · 前向传播速查:先把约定钉死

1.1 互相关 vs 真卷积:一切混乱的根源

一维情形,两个「卷积」的定义:

互相关: Y[i]=∑u=0k−1X[i⋅s+u−p]⋅W[u]真卷积: Y[i]=∑u=0k−1X[i⋅s+u−p]⋅W[k−1−u] \text{互相关:}\ Y[i] = \sum_{u=0}^{k-1} X[i\cdot s + u - p]\cdot W[u] \qquad \text{真卷积:}\ Y[i] = \sum_{u=0}^{k-1} X[i\cdot s + u - p]\cdot W[k-1-u] 互相关: Y[i]=u=0∑k−1​X[i⋅s+u−p]⋅W[u]真卷积: Y[i]=u=0∑k−1​X[i⋅s+u−p]⋅W[k−1−u]

差别只有一个:核要不要翻转 180°180°180°。PyTorch nn.Conv2d、TensorFlow、cuDNN 用的都是互相关(翻转对可学习的核是冗余操作,学出来的权重自然适配);而 Goodfellow《Deep Learning》教材、经典信号处理文献用的是真卷积。同一个公式在两套约定下长得不一样,是网上 CNN 反向传播推导互相矛盾的唯一根源。

本文约定表(后文所有公式都基于互相关约定):

约定 前向 ∂L/∂W\partial\mathcal{L}/\partial W∂L/∂W ∂L/∂X\partial\mathcal{L}/\partial X∂L/∂X
互相关(PyTorch,本文) Y=X⋆WY = X \star WY=X⋆W XXX 与 GGG 的互相关 GGG 与 WWW 的 full convolution(有翻转)
真卷积(Goodfellow 教材) Y=X∗WY = X * WY=X∗W XXX 与 GGG 的 full convolution GGG 与 WWW 的互相关(无翻转)

两条约定数学上完全等价(把对方的核 rot180 即可互换),§3.3 末尾给出了这一点的机械证明。读任何推导前先问一句:他的卷积翻转吗?

1.2 前向公式与输出尺寸

batch 形式(NNN 样本、CCC 输入通道、FFF 输出通道、核 kH×kWk_H\times k_WkH​×kW​、stride sss、padding ppp):

Y[n,f,i,j]=b[f]+∑c=1C∑u=0kH−1∑v=0kW−1X[n,c,  i⋅s+u−p,  j⋅s+v−p]⋅W[f,c,u,v] Y[n,f,i,j] = b[f] + \sum_{c=1}^{C}\sum_{u=0}^{k_H-1}\sum_{v=0}^{k_W-1} X\big[n,c,\; i\cdot s + u - p,\; j\cdot s + v - p\big]\cdot W[f,c,u,v] Y[n,f,i,j]=b[f]+c=1∑C​u=0∑kH​−1​v=0∑kW​−1​X[n,c,i⋅s+u−p,j⋅s+v−p]⋅W[f,c,u,v]

输出尺寸(向下取整;不可整除时余数 r=(H+2p−kH) mod sr=(H+2p-k_H)\bmod sr=(H+2p−kH​)mods,记住它,§3.3 和 §6 都要用):

Ho=⌊H+2p−kHs⌋+1 H_o = \left\lfloor \frac{H + 2p - k_H}{s}\right\rfloor + 1 Ho​=⌊sH+2p−kH​​⌋+1

记上游梯度 G=∂L/∂YG = \partial\mathcal{L}/\partial YG=∂L/∂Y(形状与 YYY 相同)。反向传播要产出三样东西:dXdXdX(形状同 XXX,回传给前层)、dWdWdW(形状同 WWW)、dbdbdb(形状同 bbb)。

1.3 线性算子视角:conv 就是稀疏矩阵乘

把一维例子写成就知道了。X=(x0,…,x4)X=(x_0,\dots,x_4)X=(x0​,…,x4​) 长 5,W=(w0,w1,w2)W=(w_0,w_1,w_2)W=(w0​,w1​,w2​) 长 3,p=1p=1p=1,s=1s=1s=1,输出长 5。前向 Y=MxY = MxY=Mx,其中

M=(0w1w200w0w1w2000w0w1w2000w0w1w2000w0w1) M = \begin{pmatrix} 0 & w_1 & w_2 & 0 & 0\\ w_0 & w_1 & w_2 & 0 & 0\\ 0 & w_0 & w_1 & w_2 & 0\\ 0 & 0 & w_0 & w_1 & w_2\\ 0 & 0 & 0 & w_0 & w_1 \end{pmatrix} M= ​0w0​000​w1​w1​w0​00​w2​w2​w1​w0​0​00w2​w1​w0​​000w2​w1​​ ​

——一条带状 Toeplitz 矩阵(每条对角线上的元素相同)。三个立刻到手的事实:

  1. conv = 稀疏矩阵乘:非零元只有 5×3=155\times3=155×3=15 个,密度 15/25=60%15/25=60\%15/25=60%;核再大些(k=7k=7k=7、H=64H=64H=64)密度降到 ≈11%\approx 11\%≈11%。所谓「局部连接 + 权重共享」在矩阵语言里就是「同一组 www 在对角线上反复出现」;
  2. BP = 矩阵转置:dX=M⊤GdX = M^\top GdX=M⊤G——这就是「转置卷积」这个名字的来历。M⊤M^\topM⊤ 对应的核正是 WWW 的 180°180°180° 翻转(§3.3 会把这个对应关系算实);
  3. 若 XXX 是循环补零(circular padding),MMM 变成循环矩阵,可被 FFT 对角化——这是 FFT 卷积的全部理论(§8)。

用 numpy 验证过:MxMxMx 与直接卷积逐元素一致(最大相对误差 2.1×10−152.1\times10^{-15}2.1×10−15),M⊤GM^\top GM⊤G 与直接索引累加完全相等(误差 0)。

1.4 im2col 视角:把 conv 变成一次 GEMM

把每个感受野窗口拉成一列,Xcol[n]∈RCkHkW×HoWoX_{\text{col}}[n]\in\mathbb{R}^{Ck_Hk_W \times H_oW_o}Xcol​[n]∈RCkH​kW​×Ho​Wo​,核摊平 Wmat∈RF×CkHkWW_{\text{mat}}\in\mathbb{R}^{F\times Ck_Hk_W}Wmat​∈RF×CkH​kW​,前向就是一次矩阵乘:

Y[n]=Wmat Xcol[n]+b Y[n] = W_{\text{mat}}\,X_{\text{col}}[n] + b Y[n]=Wmat​Xcol​[n]+b

这就是 im2col(Chellapilla, Puri & Simard, 2006):卷积 → GEMM,直接吃 cuBLAS 的高度优化。代价是显存:重叠窗口被复制 kHkWk_Hk_WkH​kW​ 倍,XcolX_{\text{col}}Xcol​ 比 XXX 大 CkHkW/CCk_Hk_W/CCkH​kW​/C 倍(3×33\times33×3、C=64C=64C=64 时是 9 倍)。现代框架用 implicit GEMM(在 GEMM 内部按索引取数,不落地拷贝)绕开这个开销,但数学恒等不变——§3.5 的反向传播公式在 im2col 视图下是三行矩阵运算,这是手写实现最不容易错的形态。


2 · 反向传播总纲:每个算子只需交出 VJP

统御全篇的观点:前向是算子 fff,反向就是它的转置(伴随算子)fˉ\bar ffˉ​——给定上游梯度 GGG,产出对各输入的梯度。自动微分里这叫 VJP(vector-Jacobian product),loss.backward() 干的就是给计算图每个节点挂上 VJP。

算子 前向 VJP(输入 G=∂L/∂YG=\partial\mathcal{L}/\partial YG=∂L/∂Y)
conv Y=X⋆W+bY = X\star W + bY=X⋆W+b 三条:dX=⋆‾(G;W)dX = \overline{\star}(G;W)dX=⋆(G;W),dW=X⋆GdW = X\star GdW=X⋆G,db=∑Gdb=\sum Gdb=∑G(§3)
max pool 窗口取 max dXdXdX 只路由到 argmax 位置(§4.1)
avg pool 窗口取均值 dXdXdX 窗口内均分 G/(kHkW)G/(k_Hk_W)G/(kH​kW​)(§4.2)
ReLU max⁡(0,z)\max(0,z)max(0,z) dZ=G⊙1[Z>0]dZ = G\odot\mathbb{1}[Z>0]dZ=G⊙1[Z>0](§4.3)
FC Z=AW+bZ = A W + bZ=AW+b dA=GW⊤dA = GW^\topdA=GW⊤,dW=A⊤GdW = A^\top GdW=A⊤G,db=∑Gdb=\sum Gdb=∑G(§4.5)
softmax+CE p=softmax(z)p=\mathrm{softmax}(z)p=softmax(z) dZ=(P−Y)/ndZ = (P-Y)/ndZ
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

reset2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值