共计 1999 个字符,预计需要花费 5 分钟才能阅读完成。
卷积神经网络入门实战
为什么选择 CNN?
卷积神经网络(CNN)在计算机视觉领域几乎无处不在。从人脸识别到自动驾驶,CNN 通过其独特的结构能够有效捕捉图像的局部特征。但对于刚入门的新手来说,实现一个完整的 CNN 往往会遇到几个典型问题:

- 不知道如何设置卷积核大小(kernel_size)和步长(stride)
- 对 padding 方式(如 ’same’ 或 ’valid’)的选择感到困惑
- 不理解特征图尺寸如何随着网络深度变化
- 难以平衡模型复杂度和计算资源消耗
下面我们就从最基础的卷积层开始,一步步构建完整的 CNN 实现。
6.5.1 卷积层实现
卷积层是 CNN 的核心组件,PyTorch 中通过 nn.Conv2d 实现。我们先看一个最简单的单通道卷积示例:
import torch
import torch.nn as nn
# 输入:1 张 1 通道的 5x5 图像
input = torch.randn(1, 1, 5, 5) # (batch_size, in_channels, height, width)
# 定义卷积层:1 输入通道,1 输出通道,3x3 卷积核
conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
output = conv(input)
print(output.shape) # torch.Size([1, 1, 3, 3])
关键参数说明:
kernel_size=3:使用 3 ×3 的卷积核stride=1:每次移动 1 个像素padding=0:不使用边缘填充
输出尺寸计算公式:
$$
\text{output_size} = \left\lfloor\frac{\text{input_size} – \text{kernel_size} + 2\times\text{padding}}{\text{stride}}\right\rfloor + 1
$$
常见错误:
- 忘记输入数据需要 4 维张量(batch, channel, height, width)
- padding 设置不合理导致输出尺寸为负数
- 没有初始化卷积核权重(PyTorch 会自动初始化)
6.5.2 池化层实现
池化层用于降低特征图的空间维度,最常见的两种池化方式是最大池化和平均池化:
# 最大池化示例
max_pool = nn.MaxPool2d(kernel_size=2, stride=2)
output_max = max_pool(output)
print(output_max.shape) # torch.Size([1, 1, 1, 1])
# 平均池化示例
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)
output_avg = avg_pool(output)
print(output_avg.shape) # torch.Size([1, 1, 1, 1])
池化层特点:
- 不包含可训练参数
- 通常 stride 等于 kernel_size 以避免重叠
- 最大池化能保留显著特征,平均池化更平滑
6.5.3 全连接层实现
全连接层通常放在 CNN 的最后几层,需要先将多维特征展平:
# 展平操作
flatten = nn.Flatten()
flat_output = flatten(output_avg)
print(flat_output.shape) # torch.Size([1, 1])
# 全连接层
fc = nn.Linear(in_features=1, out_features=10)
final_output = fc(flat_output)
print(final_output.shape) # torch.Size([1, 10])
全连接层的注意事项:
- 输入特征数量必须与
in_features匹配 - 大型全连接层会显著增加参数量
- 现代 CNN 架构中全连接层的使用在减少
性能优化技巧
计算量估算
卷积层的浮点运算次数(FLOPs)可以估算为:
$$
\text{FLOPs} = \text{output_h} \times \text{output_w} \times \text{kernel_h} \times \text{kernel_w} \times \text{in_ch} \times \text{out_ch}
$$
显存占用分析
显存占用主要来自:
- 模型参数
- 前向传播的中间结果
- 反向传播的梯度
cuDNN 加速
PyTorch 默认使用 cuDNN 加速卷积运算,确保:
- 使用固定大小的输入(非动态)
- 输入尺寸是 8 的倍数(对某些架构更优)
- 使用 float16 精度(如果硬件支持)
生产环境 Checklist
- 输入归一化 :将像素值缩放到[0,1] 或[-1,1]范围
- BatchNorm 位置:通常在卷积层后、激活函数前
- 学习率设置:大卷积核需要更小的学习率
- 数据增强:旋转、翻转等提高泛化能力
- 早停机制:防止过拟合
通过以上步骤,你应该能够实现一个完整的 CNN 网络。记住,深度学习是实验性科学,多尝试不同配置才能找到最优解。
