目录
一、概念
卷积网络也叫卷积神经网络,是一种专门用来处理网络结构的神经网络。它是一种前馈神经网络,它的人工神经元可以相应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。
二、卷积在深度学习中的作用:
卷积神经网络(CNN)的核心层就是卷积层,它的优势在于:
- 自动提取特征:通过不同的卷积核,模型可以学习到边缘、角点、纹理等低级特征,再到复杂物体(如人脸、汽车)的高级特征。
- 参数共享:同一卷积核在整个图像上重复使用,极大减少参数数量(相比全连接层)。
- 平移不变性:无论物体出现在图像哪个位置,卷积核都能检测到它。
三、卷积运算
卷积计算图:
1.计算步骤(以上图为例):
假如上图是一张像素3*4的图片,那么卷积核就是图片旁边的Kernel 2*2的矩阵,滑动窗口就是图片中标黑的2*2的方框,用滑动窗户框住的矩阵和卷积核进行点乘求和(不是矩阵相乘),滑动窗口按照自己定义的步长Stride每移动一次计算一次,直到滑动完整个图片,卷积结束。
2.举个例子:
原图:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
卷积核:
[0, 1, 0]
[1, 0, 1]
[0, 1, 0]
点乘结果为:
(1×0)+(2×1)+(3×0) + (4×1)+(5×0)+(6×1) + (7×0)+(8×1)+(9×0) = 2+4+6+8 = 20
3.填充(padding)
如果原图尺寸不能被卷积核整除,可以通过添加边缘像素(通常是0)补全,避免信息丢失。也就是在你输入图像的外围加上一圈圈的0,padding等于1就围一层,等于2就围两层。
四、1x1卷积
卷积核尺寸为 1x1 时的卷积,也即卷积核变成只有一个数字,1x1 卷积的作用在于能有效地减少维度,降低计算的复杂度.如下图所示:
通道数:图片的维度,除了h和w以外的一个维度,比如彩色图片就是3个通道数
和上面的卷积运算不一样的是这里新加了一个维度(通道数),那么我们给卷积核也加上整个维度就可以了,每个维度的图片像素数据和卷积核分别像上面的卷积运算一样运算后,在将每个维度卷积后的数值加起来就是上图那样啦!
1. 什么是1×1卷积?
- 本质:卷积核大小为
1×1
的卷积操作。 - 数学形式:输入图片数据和卷积核的每个元素逐点相乘后求和。
- 核心特点:不改变输入的 空间尺寸(宽度和高度不变),但会影响 通道数(深度)。
2. 1×1卷积的作用
① 通道混合(Channel Mixing)
假设输入特征图有 C_in
个通道,1×1卷积核可以生成 C_out
个新通道,每个新通道是原通道的线性组合:
输出通道 = 原通道 × 卷积核权重 + 偏置
作用:自动学习哪些通道对当前任务更重要,并将信息融合到新通道中。
② 降维/升维
通过调整卷积核数量 C_out
,可以直接压缩或扩展特征图的通道数:
- 降维:
C_out < C_in
(减少计算量,保留关键信息)。 - 升维:
C_out > C_in
(增加非线性表达能力)。
③ 添加非线性
虽然1×1卷积本身是线性操作,但通常会搭配激活函数(如ReLU),从而引入非线性。
3. 为什么需要1×1卷积?
- 参数效率高:相比大尺寸卷积,1×1卷积参数量仅为
C_in × C_out
,计算成本低。 - 灵活性:在保持空间尺寸不变的情况下,灵活调整通道数。
- 适配深度网络:在深层网络中(如ResNet、Inception),1×1卷积常用于残差连接或跨层信息交互。
4.代码示例(pytorch)
import torch
import torch.nn as nn
# 输入:batch_size=1, channels=3, H=W=5
input = torch.randn(1, 3, 5, 5)
# 定义1x1卷积层:输入3通道 → 输出64通道
conv1x1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=1)
# 前向传播
output = conv1x1(input)
print(output.shape) # 输出:torch.Size([1, 64, 5, 5])
5.详细计算
对于 1×1卷积层,权重矩阵的形状是 (C_out, C_in, 1, 1)
,即:
- 第一个维度
C_out
:输出通道数(64)。 - 第二个维度
C_in
:输入通道数(3)。 - 后两个维度
(1,1)
:卷积核的大小(1×1)。
举个例子,若 C_in=3
、C_out=64
,则权重矩阵 W
的形状为 (64, 3, 1, 1)
,类似这样:
W = [
[w1_1, w1_2, w1_3], # 输出第1个通道的权重
[w2_1, w2_2, w2_3], # 输出第2个通道的权重
...
[w64_1, w64_2, w64_3] # 输出第64个通道的权重
]
W中有64个数据与输入的3通道数的数据点乘计算后就变成64维的啦
五、分组卷积
卷积核被分成不同的组,每组负责对相应的输入层进行卷积计算,最后再进行合并。如下图,卷积核被分成前后两个组,前半部分的卷积组负责处理前半部分的输入层,后半部分的卷积组负责处理后半部分的输入层,最后将结果合并组合。
1. 什么是分组卷积?
- 核心思想:将输入通道分成多个组,每组独立进行卷积操作。
- 数学形式:输入通道数为
C_in
,输出通道数为C_out
,组数G
,每组包含C_in/G
个通道。 - 关键特点:
- 每个组的卷积核尺寸为
(k×k)
,但仅作用于该组的输入通道。 - 输出通道数是各组卷积结果的拼接。
- 每个组的卷积核尺寸为
2. 分组卷积的具体步骤
假设输入为 (N, C_in, H, W)
,卷积核为 (k×k)
,组数 G
,输出通道数为 C_out
(需满足 C_out % G == 0
)。
步骤1:分割输入通道
将输入的 C_in
个通道均分到 G
个组中,每组包含 C_in/G
个通道。
例如:C_in=12
,G=3
→ 每组 4
个通道。
步骤2:每组独立卷积
对每个组的输入进行普通卷积操作:
- 卷积核形状为
(k×k)
,输出通道数为C_out/G
。 - 每组生成
(C_out/G, H, W)
的特征图。
步骤3:合并各组结果
将 G
组的输出特征图沿通道维度拼接,最终输出形状为 (N, C_out, H, W)
。
import torch
import torch.nn as nn
# 输入:batch=1, channels=12, H=W=5
input = torch.randn(1, 12, 5, 5)
# 定义分组卷积层:
# - 组数 G=3
# - 每组输入通道数 C_in/G = 4
# - 每组输出通道数 C_out/G = 16 (总输出 C_out=3×16=48)
conv_grouped = nn.Conv2d(
in_channels=12,
out_channels=48,
kernel_size=3,
groups=3,
padding=1 # 补零使尺寸不变
)
# 前向传播
output = conv_grouped(input)
print(output.shape) # 输出:torch.Size([1, 48, 5, 5])
六、反卷积
卷积是对输入图像提取出特征(可能尺寸会变小),而所谓的 “反卷积” 便是进行相反的操作。但这里说是 “反卷积” 并不严谨,因为并不会完全还原到跟输入图像一样,一般是还原后的尺寸与输入图像一致,主要用于向上采样。
(注解:从数学计算上,“反卷积” 相当于是将卷积核转换为稀疏矩阵后, 通过将卷积核进行翻转(旋转180度)和填充,之后再进行卷积来实现,因此,有时也被称为转置卷积。)
1. 反卷积是什么?
- 核心思想:将低维特征图(如
H×W
)映射到高维空间(如2H×2W
),常用于 图像重建、上采样。 - 别称:转置卷积(Transpose Convolution)、逆卷积(Inverse Convolution)。
- 数学本质:卷积操作的逆过程(但需注意傅里叶变换下的严格逆与实际工程实现的差异)
2. 反卷积 vs 卷积
操作 | 输入尺寸 | 输出尺寸 | 权重处理 | 核心用途 |
---|---|---|---|---|
卷积 | (H, W) | (H', W') | 正向传播 | 特征提取(下采样) |
反卷积 | (H, W) | (H×stride, W×stride) | 权重矩阵转置 + 上采样 | 特征恢复(上采样) |
3. 反卷积的具体步骤
假设输入为 (H, W)
,反卷积核为 k×k
,步长为 s
,填充为 p
,则输出尺寸为:
Output Size=(H−1)×s+k−p
通常设置 p = k - s
以保证输出尺寸可控。
4.代码示例
import torch
import torch.nn as nn
# 输入:batch=1, channels=3, H=W=2
input = torch.randn(1, 3, 2, 2)
# 定义反卷积层:
# - kernel_size=3, stride=2, padding=1
# - 输出尺寸: (2-1)*2 +3 -1 = 2 * 2 +2 =6?
# 实际输出尺寸计算: (2-1)*2 +3 -1 = 2+2=4 → 4x4
conv_transpose = nn.ConvTranspose2d(
in_channels=3,
out_channels=64,
kernel_size=3,
stride=2,
padding=1
)
# 前向传播
output = conv_transpose(input)
print(output.shape) # 输出:torch.Size([1, 64, 4, 4])