CNN卷积神经网络之基础(一)
·
CNN卷积神经网络之基础(一)
文章目录
卷积神经网络(CNN)入门:从原理到代码
卷积神经网络(Convolutional Neural Network, CNN)是深度学习中最常用的模型之一,尤其在图像识别、目标检测等任务中表现优异。本文将带你从基础概念出发,理解 CNN 的核心机制,并通过 PyTorch 代码实现一个可运行的卷积操作案例。
一、为什么需要 CNN?
传统的全连接神经网络(Fully Connected Network)在处理图像时会遇到两个问题:
- 参数量巨大:一张 224×224 的图像,若使用全连接层,参数量将爆炸。
- 无法提取局部特征:图像中的物体具有平移、缩放、旋转不变性,全连接层难以捕捉这些特征。
CNN 通过以下三个特性解决了上述问题:
| 特性 | 描述 |
|---|---|
| 局部连接 | 每个神经元只连接输入图像的局部区域,减少参数量 |
| 权重共享 | 同一个卷积核在图像上滑动,使用相同权重,进一步减少参数并提取平移不变特征 |
| 池化 | 通过下采样保留主要特征,增强模型对位置变化的鲁棒性 |
二、核心组件详解
1. 卷积操作(Convolution)
卷积的本质是:用一个可学习的滤波器(卷积核)在图像上滑动,进行加权求和,生成特征图(Feature Map)。

代码示例:使用 PyTorch 实现二维卷积
import torch
import torch.nn as nn
# 输入图像(单通道 3x3)
input_matrix = torch.tensor([
[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]
], dtype=torch.float32)
# 卷积核(2x2)
kernel = torch.tensor([
[0., 1.],
[2., 3.]
], dtype=torch.float32)
# 转换为4维张量 (batch_size, channels, height, width)
input_tensor = input_matrix.view(1, 1, 3, 3)
# 创建卷积层
conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=2, bias=False)
conv.weight.data = kernel.view(1, 1, 2, 2)
# 执行卷积
output = conv(input_tensor).squeeze().detach()
print("卷积结果:\n", output)
输出结果:
卷积结果:
tensor([[ 11., 16.],
[ 26., 31.]])
2. 步长(Stride)与填充(Padding)
- 步长(stride):控制卷积核每次移动的像素数,影响输出特征图大小。
举例说明:
假设有一个大小为5×5的输入图像(为了简化问题,不考虑颜色通道等复杂情况),而卷积核的大小是3×3。
如果步长设置为1,那么卷积核就从左上角开始,每次向右移动1个单位,当到达图像边缘后,向下移动1个单位,继续向右扫描。这样在横向和纵向都会有很多重叠的计算区域,最终得到的输出特征图尺寸较大,会得到一个3×3的矩阵,可以捕捉到更密集的空间细节。
若步长设置为2,则卷积核在每次移动时会跳过1个单位(因为步长是2),这样输出特征图的尺寸就会减小,会得到一个2×2的矩阵,计算量也会相应减少。较大的步长容易导致特征图中信息的稀疏,但可以有效降低模型的复杂度。
- 填充(padding):在图像边缘补零,保持输出尺寸与输入一致。
举例说明:
假设我们有一张 5×5 的图像(简化为黑白图像,忽略颜色通道)。当我们使用一个 3×3 的卷积核进行卷积操作,并且步长为 1 时,如果没有 padding,输出的特征图尺寸就会变成 3×3。这是因为卷积核只能完全覆盖在原始图像的范围内进行计算。
加齐边缘的作用:如果在原始图像的四周添加一层零填充(padding 的大小设为 1),那么整个图像的尺寸就变成了 7×7(5+2×1)。此时,3×3 的卷积核仍然使用步长 1 进行计算,输出的特征图尺寸就会回到 5×5。这样就能确保输出的特征图在尺寸上与输入图像保持一致,从而便于后续的处理和分析。


示例:计算输出特征图大小
import torch.nn as nn
# 输入:5x5 图像
input = torch.randn(1, 1, 5, 5)
# 卷积层:3x3 卷积核,步长1,填充0
conv = nn.Conv2d(1, 1, kernel_size=3, stride=1, padding=0)
output = conv(input)
print("输出特征图尺寸:", output.shape)
输出:
输出特征图尺寸: torch.Size([1, 1, 3, 3])
若设置 padding=1,则输出尺寸将恢复为 5×5。
3. 池化(Pooling)
池化层用于下采样,常用的是 最大池化(Max Pooling),保留区域内最大值。
import torch.nn as nn
# 输入:4x4 特征图
input = torch.tensor([[[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]]], dtype=torch.float32)
# 最大池化:2x2 池化核
pool = nn.MaxPool2d(kernel_size=2, stride=2)
output = pool(input)
print("池化后结果:\n", output.squeeze())
输出:
池化后结果:
tensor([[ 6., 8.],
[14., 16.]])
三、完整案例:构建一个简单的 CNN 模块
下面是一个完整的 CNN 模块,包含卷积、ReLU 激活和最大池化:
import torch.nn as nn
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv = nn.Conv2d(1, 8, kernel_size=3, padding=1)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(2)
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
x = self.pool(x)
return x
# 测试
model = SimpleCNN()
input = torch.randn(1, 1, 28, 28)
output = model(input)
print("输出形状:", output.shape)
输出:
输出形状: torch.Size([1, 8, 14, 14])
四、总结
| 模块 | 作用 |
|---|---|
| 卷积 | 提取局部特征,减少参数量 |
| 激活函数 | 引入非线性,提升表达能力 |
| 池化 | 降维、增强鲁棒性 |
| 全连接层 | 最终分类或回归输出(可选) |
更多推荐
所有评论(0)