Part 2 图像卷积
约 1073 字大约 4 分钟
2025-08-01
1 互相关运算
严格来说,卷积是个错误的叫法,它所表达的运算其实是互相关运算。根据我们之前的描述,在卷积层中,输入张量和核张量通过互相关运算产生输出张量。
我们先忽略输入通道的情况,在这个 3×3 的二维图像张量中,卷积核的大小为 2×2。在二维互相关运算中,卷积窗口从输入张量的左上角开始,从左至右、从上至下滑动。 当卷积窗口滑动到新一个位置时,包含在该窗口中的部分张量与卷积核张量进行按元素相乘,得到的张量再求和得到一个单一的标量值,由此我们得出了这一位置的输出张量值。
例如输出张量左上角的 19 来源于:
19=0×0+1×1+3×2+4×3
2 简单的目标边缘检测
我们设计一个简单的卷积应用,通过找到像素变化的位置,来检测图像中不同颜色的边缘。
例如对于一幅 6×8 的黑白图像X,我们构造一个高度为 1、宽度为 2 的卷积核K。当进行互相关运算时,如果水平两元素相同,则输出为 0,否则不为 0。
X = tensor([[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 0., 0., 0., 1., 1.]])
K = tensor([[1., -1.]])
然后我们定义一个互相关操作函数:
def corr2d(X, K):
h, w = K.shape
Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
return Y
将输入X和卷积核K输入函数中,即可得到操作结果:
tensor([[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.],
[ 0., 1., 0., 0., 0., -1., 0.]])
3 学习卷积核
在实际应用中我们不可能手动设计卷积核,因此我们需要通过训练得到能适用于复杂图像的卷积核。
正如我们训练线性神经网络时一样,我们先构造一个卷积层,然后将卷积核初始化为随机张量,接着迭代、计算梯度、更新卷积核。
PyTorch 提供了二维卷积层,我们可以直接使用:
# 构造一个二维卷积层,它具有 1 个输出通道和 1×2 的卷积核
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)
# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2
for i in range(10):
Y_hat = conv2d(X)
l = (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
# 迭代卷积核
conv2d.weight.data[:] -= lr * conv2d.weight.grad
if (i + 1) % 2 == 0:
print(f'epoch {i+1}, loss {l.sum():.3f}')
print(f'卷积核:{conv2d.weight.data.reshape((1, 2))}')
得到的卷积核为:
tensor([[ 1.0307, -0.9488]])
4 特征映射和感受野
卷积层有时称为特征映射,因为它可以被视为一个输入映射到下一层的空间维度的转换器。
在卷积神经网络中,对于某一层的任意元素x,其感受野是指在前向传播期间可能影响计算的所有元素(来自所有先前层)。
请注意,感受野可能大于输入的实际大小。以我们上边体积的 2×2 卷积核为例,阴影输出元素值 19 的感受野是输入阴影部分的四个元素。假设之前输出为 Y,其大小为 2×2,现在我们在其后附加一个卷积层,该卷积层以 Y 为输入,输出单个元素 z。在这种情况下,Y 上的 z 的感受野包括 Y 的所有四个元素,而输入的感受野包括最初所有九个输入元素。
因此,当一个特征图中的任意元素需要检测更广区域的输入特征时,我们可以构建一个更深的网络。