PyTorch 卷积神经网络全解析:从原理到实践
一、引言
在深度学习蓬勃发展的今天,卷积神经网络(Convolutional Neural Network,CNN)凭借其在图像识别、目标检测、语义分割等计算机视觉任务中的卓越表现,成为了该领域的核心技术。PyTorch 作为一款广泛应用的深度学习框架,为开发者提供了便捷且高效的工具来构建、训练和部署 CNN 模型。本文将深入探讨 PyTorch 框架下卷积神经网络的相关知识,从卷积的基本概念出发,逐步介绍卷积神经网络的原理、构建方法以及模型的保存与调用,记录 PyTorch 在 CV 开发中的应用。
二、卷积的基本概念与术语
2.1 什么是卷积
卷积是一种数学运算,在信号处理、图像处理等领域有着广泛的应用。在深度学习中,卷积操作是卷积神经网络的核心组成部分。简单来说,卷积可以理解为 “输入 + 脉冲 = 输出”,其运算过程包括翻转、移位、相乘和相加 。以一维离散卷积为例,假设有输入序列 [2, 3, 0, 5, 6, 7, 1, 8, 2, 9, 0] 和卷积核 [1, 1, 1],计算过程如下:
通过这样的计算,卷积操作可以提取输入数据中的特征。在图像处理中,卷积核可以看作是一个滤波器,它在图像上滑动,对每个位置的像素进行卷积运算,从而得到处理后的图像。
2.2 基本图像卷积
对于图像卷积,假设有一个简单的输入图像和卷积核。输入图像部分像素值如下:
卷积核为:
计算过程为:
这就是图像卷积的基本计算方式,通过卷积核与图像像素的对应相乘和求和,得到输出图像的像素值。
2.3 卷积操作相关术语
- 卷积核 / 操作数 /filter:卷积核是卷积操作中的关键元素,它决定了卷积操作对输入数据的处理方式。不同的卷积核可以提取不同类型的特征,例如边缘检测、模糊处理等。
- 卷积的锚定位置:默认情况下,卷积的锚定位置在卷积核的中心位置。但在实际应用中,锚定位置可以根据需求进行调整,不同的锚定位置会影响卷积操作的结果。
- 卷积的边缘填充方式:常见的边缘填充方式有 valid 和 same。valid 表示不进行边缘填充,卷积操作只在输入数据的有效区域进行,这样会导致输出数据的尺寸变小;same 表示进行边缘填充,使得输出数据的尺寸与输入数据相同。
2.4 边缘处理
在卷积操作中,边缘处理是一个重要的环节。不同的边缘填充方式会对卷积结果产生不同的影响。常见的边缘填充方式包括:
- BORDER_CONSTANT:用指定的常数填充边缘,如 Python 中
cv.BORDER_CONSTANT
,填充效果为iiiiiii|abcdefgh|iiiiiii
。 - BORDER_REPLICATE:复制边缘像素进行填充,如
cv.BORDER_REPLICATE
,填充效果为aaaaaa|abcdefgh|hhhhhhh
。 - BORDER_REFLECT:以边缘为对称轴进行反射填充,如
cv.BORDER_REFLECT
,填充效果为fedcba|abcdefgh|hgfedcb
。 - BORDER_WRAP:以循环的方式进行填充,如
cv.BORDER_WRAP
,填充效果为cdefgh|abcdefgh|abcdefg
。 - BORDER_REFLECT_101:类似
BORDER_REFLECT
,但在边界像素的处理上略有不同,如cv.BORDER_REFLECT_101
,填充效果为gfedcb|abcdefgh|gfedcba
。 - BORDER_TRANSPARENT:表示边缘不进行填充,保持透明,如
cv.BORDER_TRANSPARENT
,填充效果为uvwxyz|abcdefgh|ijklmno
。
三、卷积神经网络基本原理与参数
3.1 卷积神经网络基本原理
卷积神经网络由多个卷积层、池化层和全连接层组成。其基本原理是通过卷积层中的卷积核在输入数据上滑动,进行卷积操作,提取数据的特征。这些特征经过池化层的降采样处理,减少数据的维度,同时保留重要的特征信息。最后,全连接层对提取的特征进行分类或回归等操作,得到最终的输出结果。
卷积神经网络具有共享权重、像素迁移和空间信息提取等好处。共享权重机制使得网络在训练过程中可以减少参数的数量,降低计算量,同时提高模型的泛化能力。通过卷积操作,网络可以自动学习到图像中的空间特征,如边缘、纹理等,从而对图像进行有效的分类和识别。
3.2 卷积层操作
- 步长(strides):步长决定了卷积核在输入数据上滑动的步幅。当步长为 1 时,卷积核每次移动一个像素;当步长为 2 时,卷积核每次移动两个像素。步长的大小会影响输出数据的尺寸,步长越大,输出数据的尺寸越小。
- 填充(padding):填充用于控制卷积操作后输出数据的尺寸。当填充为 VALID 时,不进行边缘填充,输出数据的尺寸会根据输入数据和卷积核的大小进行相应的计算;当填充为 SAME 时,进行边缘填充,使得输出数据的尺寸与输入数据相同。例如,对于一个 3x3 的卷积核,当填充为 SAME 时,会在输入数据的边缘填充一圈像素,以保证输出数据的尺寸不变。
- 卷积核大小(filter size):卷积核的大小通常为奇数,如 3x3、5x5 等。较大的卷积核可以提取更全局的特征,但计算量也会相应增加;较小的卷积核可以提取更局部的特征,计算量相对较小。在实际应用中,需要根据任务的需求和数据的特点选择合适的卷积核大小,1×1卷积是通道升降的利器。
3.3 卷积层输出大小计算
对于一个 WxW 的特征图(feature map),假设卷积核的大小为 FxF,卷积时填充边缘 P 个像素,卷积步长为 S,则输出的大小计算公式为:
输出大小
当 P = 0 时,公式简化为:
输出大小
这个公式对于设计卷积神经网络的结构非常重要,通过合理设置参数,可以控制网络中各层输出数据的尺寸,从而达到优化模型性能的目的。
3.4 池化层详解
池化层主要有均值池化和最大值池化两种方式。均值池化是计算池化窗口内像素的平均值,作为输出;最大值池化是取池化窗口内像素的最大值,作为输出。例如,对于一个 2x2 的池化窗口,在输入特征图上进行池化操作:
- 均值池化:计算窗口内像素的平均值,得到输出特征图。
- 最大值池化:取窗口内像素的最大值,得到输出特征图。
最大值池化能够保留图像中的显著特征,对于图像的平移、旋转等变换具有一定的不变性,但可能会丢失一些细节信息;均值池化则可以对图像进行平滑处理,减少噪声的影响,但可能会使图像的特征变得模糊。
四、构建 CNN 手写数字识别网络
4.1 CNN 手写数字识别网络结构
要构建的 CNN 手写数字识别网络结构包括卷积层、池化层、全连接层和输出层。具体结构如下:
- 首先通过
Conv2d
层进行卷积操作,例如第一个Conv2d
层的权重为 (8x1x3x3),偏置为 (8),通过卷积操作提取图像的特征。 - 接着使用
MaxPool2d
层进行池化操作,降低特征图的维度。 - 然后经过
ReLU
激活函数,增加网络的非线性。 - 再通过多个
Conv2d
、MaxPool2d
、ReLU
和Linear
层的组合,进一步提取特征并进行分类。 - 最后通过
LogSoftmax
层得到最终的输出结果,用于识别手写数字。
4.2 Pytorch 函数支持
- torch.nn.Module:这是 PyTorch 中构建神经网络模型的基类。通过继承
torch.nn.Module
,可以方便地定义自己的神经网络模型,并实现前向传播等方法。 - torch.nn.Conv2d:用于创建二维卷积层。在构建 CNN 手写数字识别网络时,通过
torch.nn.Conv2d
定义卷积层,设置卷积核的大小、步长、填充等参数,实现对输入数据的卷积操作。 - torch.nn.MaxPool2d:用于创建最大池化层。在网络中,使用
torch.nn.MaxPool2d
对卷积层输出的特征图进行池化操作,降低特征图的维度,减少计算量。
五、模型保存与调用
5.1 模型保存方式
- 保存整个模型:使用
torch.save(model, PATH)
可以将整个模型保存到指定路径。这种方式保存的模型包含了模型的结构和参数,加载时可以直接恢复整个模型。 - 保存模型参数(state_dict):使用
torch.save(model.state_dict(), PATH)
只保存模型的参数。state_dict
是一个 Python 格式的字典数据,只保存各层的参数相关信息,可以通过model
和optimizer
获取。加载时,需要先创建模型实例,然后使用model.load_state_dict(torch.load(PATH))
加载参数,并通过model.eval()
将模型设置为评估模式。 - 保存检查点:除了保存模型参数,还可以保存训练过程中的其他信息,如当前的 epoch、优化器的状态、损失值等。使用以下代码保存检查点:
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
}, PATH)
恢复检查点时,需要先创建模型和优化器的实例,然后加载检查点并恢复相关信息:
model = TheModelClass(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)
checkpoint = torch.load(PATH)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']
model.eval()
model.train() # -or
5.2 模型预测
在模型保存后,可以加载模型进行预测。首先加载保存的模型,然后将输入数据传入模型,得到预测结果。例如,在手写数字识别任务中,加载训练好的 CNN 模型,将待识别的手写数字图像进行预处理后传入模型,模型会输出预测的数字类别。
就比如我之前利用Yolov5用作目标检测可视化,Yolov5 是基于卷积神经网络构建的。从原理上看,卷积神经网络通过卷积层、池化层等组件提取图像特征,Yolov5 也利用卷积操作对输入图像进行特征提取 。在其网络架构中,存在多个卷积层,通过不同大小和参数的卷积核来捕捉图像不同尺度和类型的特征,进而实现目标检测任务,包括目标的定位与分类。效果如图所示:
同时Yoov5也可用作语义分割模型,处理其任务效果也是嘎嘎厉害,实验结果如下:
六、总结
本篇文章介绍了 PyTorch 框架下卷积神经网络的相关知识,从卷积的基本概念、卷积神经网络的原理与参数,到构建 CNN 手写数字识别网络,以及模型的保存与调用。旨在对 PyTorch 在 CV 开发中的应用有一个较为深入的理解。在实际应用中,需要根据具体的任务需求和数据特点,合理设计卷积神经网络的结构,选择合适的参数,并运用模型保存与调用技术,实现高效的图像识别等计算机视觉任务。随着深度学习技术的不断发展,卷积神经网络在各个领域的应用将会越来越广泛,最后感谢大家的观看(_ _)。゜。