卷积

Note

全连接层不适合处理图像
图像具有局部性和平移不变形,卷积运算很好地利用了这两点,适合处理图像

局部性和平移不变性

一般来说,真实图片的分辨率不会像Fashion-MNIST那样分辨率那么低。

考虑一个540p的彩色图片,flatten之后的维数是 \(3*960*540 =1555200\)。若和 mlp 节中一样,使用256维的隐藏层,那么这一层的参数量就有 \(1555200 * 256 = 398131200\) 个参数,很难训练,而且就算训练出来了也容易过拟合。

幸运的是,图像具有局部性,比如说假设有一个隐藏层神经元用于判定下图左边那个框中是不是waldo,它只跟这个框里的像素有关,这就表明隐藏层的神经元并不需要连接到所有input。

此外,图像还具有平移不变形,若有两个神经元分别用于判定下图左边框框和右边框框里是不是waldo,神经元功能一样那么它们的参数也应该是一样的。

也就是说,我们可以通过非全连接 + 共享参数来减少参数总量。

jupyter

卷积

jupyter

Kernel就是卷积运算的参数,它从左到右从上到下扫过图像中与它匹配的subset,对应元素相加再相再相乘(\(0*0 + 1*1 + 3*2+4*3=19\))得到output。

Kernel是与subset而非整个图像做运算,这显然是利用了图像的局部性。

与所有subset运算的是同一个kernel,这显然是利用了图像的平移不变性。

假设 input size \(n_{h}\times{n_{w}}\), kernel size \(k_{h}\times{k_{w}}\), 那么 output size 为 \((n_{h} - k_{h} + 1)\times({n_{w} - k_{w} + 1})\)

Pytorch中的卷积运算

import torch

# (batch_size, in_channel, in_h, in_w)
inputs = torch.arange(9).reshape(1, 1, 3, 3)
# (out_channel, in_channel, kernel_h, kernel_w)
kernel = torch.arange(4).reshape(1, 1, 2, 2)
inputs, kernel
(tensor([[[[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]]]]),
 tensor([[[[0, 1],
           [2, 3]]]]))
import torch.nn.functional as F

# 同上图中的output
F.conv2d(inputs, kernel)
tensor([[[[19, 25],
          [37, 43]]]])