对于彩色图像有标准的RGB通道来代表红绿和蓝。但是到目前为止,但是到目前为止,我们仅展示了单个输入和单个输出通道的简化例子。 这使得我们可以将输入、卷积核和输出看作二维张量。当我们添加通道时,我们的输入和隐藏的表示都变成了三维张量。例如,每个RGB输入图像具有3 x h x w的形状。我们将这个大小为3的轴称为通道(channel)维度。
多输入通道
当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。假设输入的通道数为$c_i$,那么卷积核的输入通道数也需要为$c_i$。如果卷积核的窗口形状是$k_h \times k_w$,那么$c_i = 1$当时,我们可以把卷积核看作形状为$k_h \times k_w$的二维张量。
然而,当$c_i > 1$时,我们卷积核的每个输入通道将包含形状为$k_h \times k_w $的张量。将这些张量$c_i$连结在一起可以得到形状为$c_i \times k_h \times k_w$的卷积核。由于输入和卷积核都有$c_i$个通道,我们可以对每个通道输入的二维张量和卷积核的二维张量进行互相关运算,再对通道求和(将$c_i$的结果相加)得到二维张量。这是多通道输入和多输入通道卷积核之间进行二维互相关运算的结果。
为了加深理解,我们实现一下多输入通道互相关运算。 简而言之,我们所做的就是对每个通道执行互相关操作,然后将结果相加。
import torch
from d2l import torch as d2l
def corr2d_multi_in(X, K):
# 先遍历“X”和“K”的第0个维度(通道维度),再把它们加在一起
return sum(d2l.corr2d(x, k) for x, k in zip(X, K))
X = torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]])
K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])
corr2d_multi_in(X, K)
多输出通道
用$c_i$和$c_o$分别表示输入和输出通道的数目,并让$k_h$和$k_w$为卷积核的高度和宽度。为了获得多个通道的输出,我们可以为每个输出通道创建一个形状为$c_i \times k_h \times k_w$的卷积核张量,这样卷积核的形状是$c_o \times c_i \times k_h \times k_w$。在互相关运算中,每个输出通道先获取所有输入通道,再以对应该输出通道的卷积核计算出结果。
我们实现一个计算多个通道的输出的互相关函数
def corr2d_multi_in_out(X, K):
# 迭代“K”的第0个维度,每次都对输入“X”执行互相关运算。
# 最后将所有结果都叠加在一起
return torch.stack([corr2d_multi_in(X, k) for k in K], 0)
通过将核张量K与K+1(K中每个元素加)和K+2连接起来,构造了一个具有3个输出通道的卷积核。
K = torch.stack((K, K + 1, K + 2), 0)
K.shape
torch.Size([3, 2, 2, 2])
1 x 1 卷积层
1 x 1 卷积,即$k_h = k_w = 1$,看起来似乎没有多大意义。 毕竟,卷积的本质是有效提取相邻像素间的相关特征,而1 x 1 卷积显然没有此作用。 尽管如此,1 x 1仍然十分流行,经常包含在复杂深层网络的设计中。
我们可以将1 x 1卷积层看作在每个像素位置应用的全连接层,以$c_i$个输入值转换为$c_o$个输出值。 因为这仍然是一个卷积层,所以跨像素的权重是一致的。 同时,1 x 1卷积层需要的权重维度为$c_o \times c_i$,再额外加上一个偏置。
下面,我们使用全连接层实现1 x 1卷积。 请注意,我们需要对输入和输出的数据形状进行调整。
def corr2d_multi_in_out_1x1(X, K):
c_i, h, w = X.shape
c_o = K.shape[0]
X = X.reshape((c_i, h * w))
K = K.reshape((c_o, c_i))
# 全连接层中的矩阵乘法
Y = torch.matmul(K, X)
return Y.reshape((c_o, h, w))
X = torch.normal(0, 1, (3, 3, 3))
K = torch.normal(0, 1, (2, 3, 1, 1))
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
assert float(torch.abs(Y1 - Y2).sum()) < 1e-6
虽然叫“卷积”,但 1×1 卷积不涉及空间感受野(因为核只有 1×1,没有空间滑动信息),它的作用完全发生在通道维度上。
假设输入张量:
X ∈ ℝ^(C_in × H × W)
1×1 卷积核:
K ∈ ℝ^(C_out × C_in × 1 × 1),等价于一个矩阵 W ∈ ℝ^(C_out × C_in)
对每个空间位置 (i, j):
$output[:, i, j] = W @ X[:, i, j] + b $ # 其中 @ 是矩阵乘法
每个像素位置独立地进行一个 C_in → C_out 的线性变换(+偏置)。
| 作用 | 解释 | 优势 |
|---|---|---|
| 1. 通道升维 / 降维(Channel-wise dimensionality control) | 调整通道数(C_in → C_out),不改变空间尺寸(H, W) |
• Inception 模块中用 1×1 卷积压缩通道数(bottleneck),减少后续 3×3/5×5 卷积的计算量 • ResNet 的 bottleneck 块:1×1→降维 → 3×3 → 1×1→升维 |
| 2. 跨通道信息融合(Non-linear channel interaction) | 通过 1×1 conv + ReLU,让不同通道的特征进行线性组合 + 非线性激活 |
原本通道间是独立的;1×1 卷积后,每个新通道是旧通道的加权和 → 实现 channel mixing(类似 MLP 的一层) |
| 3. 引入非线性(配合激活函数) | 单独 1×1 卷积是线性的,但加 ReLU 等激活后,成为轻量级非线性变换 |
替代全连接层(更参数高效),用于特征重映射 |
| 4. 实现“网络中的网络”(NiN) | 用 MLP(即 1×1 conv 堆叠)替代传统卷积后的 FC 层,保持空间结构 | 输入 → Conv → 1×1 Conv → 1×1 Conv → 分类,全程保留 H×W |
| 5. 调整通道数以匹配 shortcut(如 ResNet) | 当残差连接两端通道数不一致时,用 1×1 卷积做通道映射 | x + conv1x1(x) |
| 6. 轻量级“注意力”前置(如 SE Block 的一部分) | 在 SE、CBAM 等注意力模块中,用 1×1 卷积做 channel compression/excitation | 先 global avg pool → 1×1 conv 降维 → ReLU → 1×1 conv 升维 → sigmoid |