CNN实现简易教程
一、CNN基础回顾与设计原则
在开始实践之前,我们先快速回顾CNN的核心组件和设计原则,这将帮助你理解后续的代码和设计决策。
1. CNN的核心组件
- 卷积层(Convolutional Layer):通过卷积核提取局部特征(如边缘、纹理)。主要参数包括:
- 输入通道数(
in_channels
):输入数据的通道数,例如RGB图像为3。 - 输出通道数(
out_channels
):卷积核的数量,决定了输出的特征图数量。 - 卷积核大小(
kernel_size
):如3x3或5x5。 - 步幅(
stride
):卷积核移动的步长,影响输出尺寸。 - 填充(
padding
):在输入边界填充0,控制输出尺寸。
- 输入通道数(
- 激活函数(Activation Function):如ReLU,增加非线性。
- 池化层(Pooling Layer):如最大池化(MaxPooling),下采样以减少空间尺寸,保留重要特征。
- 全连接层(Fully Connected Layer):将卷积层的特征展平后,用于分类或回归。
- 正则化(Normalization/Dropout):如BatchNorm(批归一化)或Dropout,防止过拟合。
2. CNN设计的核心问题
设计CNN时,需要回答以下问题:
- 输入输出尺寸如何计算? 卷积和池化会改变特征图的尺寸。
- 通道数如何选择? 通道数影响模型容量和计算量。
- 层数如何确定? 层数与任务复杂度和数据集规模相关。
- 如何根据数据集设计网络? 数据集的图像尺寸、类别数等直接影响网络结构。
3. 尺寸计算公式
卷积层的输出尺寸是设计网络时必须掌握的。假设输入特征图尺寸为 [ H i n , W i n ] [H_{in}, W_{in}] [Hin,Win],卷积核大小为 k × k k \times k k×k,步幅为 $s $,填充为 $p $,输出尺寸 [ H o u t , W o u t ] [H_{out}, W_{out}] [Hout,Wout] 计算公式为:
H o u t = ⌊ H i n + 2 p − k s ⌋ + 1 H_{out} = \left\lfloor \frac{H_{in} + 2p - k}{s} \right\rfloor + 1 Hout=⌊sHin+2p−k⌋+1, W o u t = ⌊ W i n + 2 p − k s ⌋ + 1 W_{out} = \left\lfloor \frac{W_{in} + 2p - k}{s} \right\rfloor + 1 Wout=⌊sWin+2p−k⌋+1
池化层的计算类似,但通常没有填充( p = 0 p=0 p=0)。
4. 通道数设计原则
- 早期层:较少的通道数(如16或32),提取低级特征(如边缘)。
- 中间层:通道数逐渐增加(如64、128),捕获更复杂的特征。
- 后期层:通道数可能减少,结合全连接层进行分类。
- 通道数通常是2的倍数(如16、32、64),便于硬件优化。
5. 网络深度与宽度
- 深度(层数):更深的网络可以捕获更复杂的特征,但需要更多数据和计算资源。
- 宽度(通道数):更宽的网络可以捕获更多特征,但计算成本更高。
- 对于小型数据集,建议从简单的网络开始(如2-3个卷积层),逐步增加复杂度。
二、设计一个简单的CNN:以MNIST数据集为例
为了让你更好地理解CNN的设计和实现,我们以MNIST手写数字数据集(10类,28x28灰度图像)为例,设计一个简单的CNN,并详细讲解每个步骤。MNIST是一个经典的入门数据集,适合学习CNN的基本原理。
1. 数据集分析
- 图像尺寸:28x28,单通道(灰度图,
in_channels=1
)。 - 类别数:10类(数字0-9)。
- 数据规模:训练集60,000张,测试集10,000张,适合中等规模的网络。
- 任务:图像分类,输出10个类别的概率。
基于这些信息,我们可以设计一个简单的CNN,包含: - 2-3个卷积层,逐步提取特征。
- 池化层,减少空间尺寸。
- 全连接层,输出10个类别的概率。
2. 网络结构设计
我们设计以下CNN结构:
- 卷积层1:输入1通道,输出16通道,3x3卷积核,步幅1,填充1,激活函数ReLU。
- 最大池化层1:2x2池化,步幅2,降低空间尺寸。
- 卷积层2:输入16通道,输出32通道,3x3卷积核,步幅1,填充1,激活函数ReLU。
- 最大池化层2:2x2池化,步幅2。
- 全连接层:将特征展平后,映射到10个类别,输出logits。
3. 尺寸和通道数计算
假设输入图像为 [ 1 , 28 ,