共计 1985 个字符,预计需要花费 5 分钟才能阅读完成。
卷积神经网络 (CNN) 是计算机视觉领域的核心架构,其通过局部连接和权值共享显著降低了参数复杂度。反向传播算法作为 CNN 训练的基础,决定了网络能否有效学习到有意义的特征表示。理解卷积层和池化层的梯度计算过程,是掌握 CNN 工作原理的关键环节。

一、数学推导
1. 卷积层误差反向传播
设输入特征图 $X \in \mathbb{R}^{H\times W}$,卷积核 $K \in \mathbb{R}^{k\times k}$,输出特征图 $Y \in \mathbb{R}^{(H-k+1)\times (W-k+1)}$。当步长 stride= 1 时,前向传播计算公式为:
$$Y_{i,j} = \sum_{m=0}^{k-1}\sum_{n=0}^{k-1} X_{i+m,j+n}K_{m,n}$$
根据链式法则,损失 $L$ 对卷积核参数的梯度为:
$$\frac{\partial L}{\partial K_{m,n}} = \sum_{i=0}^{H-k}\sum_{j=0}^{W-k} \frac{\partial L}{\partial Y_{i,j}}X_{i+m,j+n}$$
误差项 $\delta^{l}$ 传递到前一层的公式为:
$$\delta^{l-1}{x,y} = \sum}^{k-1}\sum_{n=0}^{k-1} \delta^{l{x-m,y-n}K$$
需要特别注意边缘位置的处理(当 $x-m<0$ 或 $y-n<0$ 时取 0)。
2. 池化层梯度传递
以 2×2 Max Pooling 为例,记录前向传播时每个区域的最大值位置索引 mask。反向传播时:
$$\frac{\partial L}{\partial X_{i,j}} =
\begin{cases}
\frac{\partial L}{\partial Y_{p,q}} & \text{如果}(i,j)=\text{mask}(p,q) \
0 & \text{其他}
\end{cases}$$
二、Python 实现
import numpy as np
# 正向传播
def conv_forward(X, K):
k_height, k_width = K.shape
out_height = X.shape[0] - k_height + 1
out_width = X.shape[1] - k_width + 1
Y = np.zeros((out_height, out_width))
for i in range(out_height):
for j in range(out_width):
Y[i,j] = np.sum(X[i:i+k_height, j:j+k_width] * K)
return Y
# 反向传播
def conv_backward(dL_dY, X, K):
k_height, k_width = K.shape
dL_dK = np.zeros_like(K)
dL_dX = np.zeros_like(X)
# 计算卷积核梯度
for m in range(k_height):
for n in range(k_width):
dL_dK[m,n] = np.sum(dL_dY * X[m:m+dL_dY.shape[0], n:n+dL_dY.shape[1]])
# 计算输入梯度(带 zero padding)pad_dL_dY = np.pad(dL_dY, ((k_height-1, k_height-1), (k_width-1, k_width-1)))
K_rot180 = np.rot90(K, 2)
for x in range(X.shape[0]):
for y in range(X.shape[1]):
window = pad_dL_dY[x:x+k_height, y:y+k_width]
dL_dX[x,y] = np.sum(window * K_rot180)
return dL_dX, dL_dK
三、避坑指南
-
参数初始化:卷积核建议使用 He 初始化,对于 ReLU 激活函数,标准差设为 $\sqrt{2/(k\times k\times c_{in})}$,其中 $c_{in}$ 是输入通道数
-
学习率设置:基础学习率建议 0.01,配合 Adam 优化器使用时可以降到 0.001
-
Padding 影响:使用 ’SAME’padding 时,反向传播需要保持相同的 padding 方式,否则会导致梯度矩阵尺寸不匹配
-
GPU 优化:
- 使用 im2col 技巧将卷积转为矩阵乘法
- 批量处理时合并多个样本的卷积操作
- 梯度计算时启用 CUDA 加速库(如 cuDNN)
四、思考题
- 当网络深层使用 Sigmoid 激活时,如何通过改进网络结构避免梯度消失?
- 1×1 卷积在反向传播时与传统卷积有何不同?为什么它可以被视为通道维度的全连接层?
- 批归一化层在反向传播时如何影响梯度的分布?它与学习率设置有何关联?
通过本文的推导和实现,读者应该能够建立起 CNN 反向传播的直观理解。建议尝试修改代码实现不同 stride 和 padding 情况下的梯度计算,这是掌握该知识点的最佳实践方式。
