卷积(上):如何用卷积为计算机"开天眼"?
一、卷积的定义与基本原理
1. 什么是卷积
卷积是计算机中进行特征提取的功能,是深度学习在图像领域取得成就的基础。它让计算机能够"看到"图像中的特征,相当于为计算机"开了天眼"。[pdf_9]
2. 卷积神经网络的两个重要特点
-
稀疏连接:可以让学习的参数变得很少,大幅降低计算量 -
平移不变性:不关心物体出现在图像中的什么位置,无论物体在图像左上角还是右下角,都能被识别出来[pdf_9]
3. 卷积核(Kernel)
卷积核是卷积层要学习到的参数。卷积计算方式:卷积核与输入特征按位做乘积运算然后再求和,其结果为输出特征图的一个元素。卷积核按从左向右、从上至下的顺序滑动,分别与输入的特征图进行计算。[pdf_9]
二、标准卷积的计算方式
1. 最简单情况
-
输入:4×4 特征图 -
卷积核:2×2 -
步长:1 -
通道数:单通道
2. 标准卷积的通用形式
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 核心规则
-
输出特征图的通道数由卷积核的个数决定——卷积核个数为 n,输出通道数即为 n -
输入特征图有 m 个通道,每个卷积核内也要有 m 个通道 -
卷积核尺寸为 (m, k, k),全部卷积核尺寸为 (n, m, k, k) -
卷积核 1 与全部输入特征进行卷积计算,获得输出特征图第 1 个通道的数据;卷积核 2 获得第 2 个通道,以此类推[pdf_9]
4. 多通道计算方式
多通道计算时,输入特征的每一个通道与卷积核中对应通道的数据进行卷积,生成 m 个特征图后按对应位置求和,合并为输出特征中的一个通道。
5. 标准卷积公式
Outputᵢ = Σₖ₌₀ᵐ kernelₖ ⋆ inputₖ + biasᵢ
其中 i = 1, 2, ..., n
-
Outputᵢ:计算第 i 个输出特征图 -
kernelₖ:一个卷积核里的第 k 个通道的数据 -
inputₖ:输入特征图中的第 k 个通道的数据 -
biasᵢ:偏移项,训练时一般默认加上 -
⋆:卷积计算[pdf_9]
6. 为什么要加 bias
与回归方程同理:
-
不加 bias:方程 y = WX,无论 w 如何变化都必须经过原点 -
加上 bias:方程 y = WX + b,可变化得更加多样,拟合能力更强[pdf_9]
三、卷积的核心参数
1. 步长(stride)
卷积核上下左右滑动的长度称为步长。上述例子中步长为 1。根据问题不同会取不同步长,但通常为 1 或 2。[pdf_9]
2. Padding(补零)
Padding 有两个目的:
-
让输入与输出的特征图保持一样的大小 -
让输入的特征保留更多的信息
当有多层卷积层时,特征图会因卷积计算而逐渐变小;若希望有更多卷积层提取更丰富的信息,可让特征图变小速度慢一些,这时可考虑补零。[pdf_9]
3. PyTorch 中 padding 的三种形式
|
|
|
|
|---|---|---|
| 字符串 | 'valid'
'same'
|
'same'
|
| 整型(int) |
|
|
| 元组(tuple) |
|
|
-
'valid':没有 padding 操作 -
'same':让输出的特征图与输入的特征图获得相同的大小,通过在滑动到边缘时自动补零实现[pdf_9]
4. nn.Conv2d 完整参数
classtorch.nn.Conv2d(
in_channels, # 输入特征图的通道数,int 类型
out_channels, # 输出特征图的通道数,int 类型
kernel_size, # 卷积核的大小,int 或 tuple 类型
stride=1, # 滑动的步长,int 或 tuple 类型,默认 1
padding=0, # 补零方式
dilation=1, # 下节课讲解
groups=1, # 下节课讲解
bias=True, # 是否使用偏移项
padding_mode='zeros',
device=None,
dtype=None
)
关于 tuple 类型参数:kernel_size、stride、padding 都可以是 tuple 类型,当为 tuple 类型时,第一个维度用于 height 的信息,第二个维度用于 width 的信息。[pdf_9]
四、PyTorch 中的卷积实现
1. 卷积操作所在模块
卷积操作定义在 torch.nn 模块中,提供三个类:
-
nn.Conv2d——使用最多的类,用于图像处理 -
nn.Conv1d——用于一维数据(如序列) -
nn.Conv3d——用于三维数据(如视频)
2. 完整代码示例
第一步:创建输入特征图
import torch
import torch.nn as nn
input_feat = torch.tensor([[4, 1, 7, 5],
[4, 4, 2, 5],
[7, 7, 2, 4],
[1, 0, 2, 4]])
print(input_feat.shape) # torch.Size([4, 4])
第二步:创建 2×2 卷积并设置参数
conv2d = nn.Conv2d(1, 1, (2, 2), stride=1, padding='same', bias=False)
# 手动设置卷积核参数以验证计算
kernels = torch.tensor([[[[1, 0], [2, 1]]]], dtype=torch.float32)
conv2d.weight = nn.Parameter(kernels, requires_grad=False)
第三步:执行卷积
output = conv2d(input_feat)
print(output)
# 输出:
# tensor([[[[16., 11., 16., 15.],
# [25., 20., 10., 13.],
# [ 9., 9., 10., 12.],
# [ 1., 0., 2., 4.]]]])
3. 常见报错及解决
报错信息:
RuntimeError: Expected 4-dimensional input for 4-dimensional weight[1, 1, 2, 2]
原因:PyTorch 输入 tensor 的维度信息必须是 (batch_size, 通道数, 高, 宽),本例只给定了高与宽,缺少 batch_size 与通道数。
解决方法:使用 unsqueeze() 调整维度
input_feat = input_feat.unsqueeze(0).unsqueeze(0)
print(input_feat.shape) # torch.Size([1, 1, 4, 4])
unsqueeze() 中的参数指在哪个位置添加维度。[pdf_9]
五、核心要点总结
|
|
|
|---|---|
| 卷积的作用 |
|
| CNN 两大特点 |
|
| 卷积核 |
|
| 输出通道数 |
|
| 每个卷积核通道数 |
|
| 多通道计算 |
|
| 步长(stride) |
|
| Padding |
|
| padding='same' |
|
| bias(偏移项) |
|
| 输入维度要求 |
|
六、每课一练
问题:padding 为 'same' 时,stride 可以为 1 以外的数值吗?
解答:
-
不可以。会出现 ValueError: padding='same' is not supported for strided convolutions。 -
原因分析: -
padding='same' 的目的是让输入特征保留更多信息;而 stride 设置成 2 是为了压缩特征,两者作用刚好相反 -
假定允许在 padding='same' 时 stride 为 2,计算出来的特征图左右两侧部分都会是 0,提取到的这部分特征没有意义 -
当 stride 大于 1 时,相当于通过 stride 进行降采样,输入特征图和输出特征图尺寸不可能相等 -
注意:使用 padding='same' 时,需保证 PyTorch 版本大于等于 1.9,否则会出现 RuntimeError: argument 1 (padding) must be tuple...错误[pdf_9]
七、小结
-
卷积是什么:特征提取的核心操作,让计算机能够"看到"图像中的特征。 -
CNN 两大特点:稀疏连接(参数少)和平移不变性(不受位置影响)。 -
标准卷积计算:卷积核按从左到右、从上到下滑动,与输入特征按位相乘再求和。 -
输出通道数 = 卷积核个数,每个卷积核通道数 = 输入通道数。 -
多通道计算:各通道分别卷积后按对应位置求和,合并为输出特征的一个通道。 -
核心参数:in_channels、out_channels、kernel_size、stride、padding、bias。 -
Padding 三种形式:字符串('valid'/'same')、整型、元组。 -
padding='same' 时 stride 必须为 1,否则会报错。 -
输入维度:必须是 (batch_size, channels, height, width),用 unsqueeze() 调整。 -
核心原则:卷积是整个计算机视觉的基础,包括图像分类、目标检测、图像分割等。

