Skip to content

Lesson-19

卷积

图片识别为什么不用MLP? 输入的 RGB 图片像素大,输入的元素会非常大,这就导致参数非常多,不可能实现。 两个原则: 平移不变性、局部性 重新考察全链接层:

  • 首先,输入输出由原来的一维向量变成了举证
  • 那么,权重由原来的二维矩阵变成了四维矩阵:
\[h_{i,j} = \sum_{k,l}w_{i,j,k,l}x_{i,j}\]
  • 最后,我们对\(w\)进行重新索引\(v_{i,j,a,b}=w_{i,j,i+a,j+b}\),那么,上式变为:
\[h_{i,j} = \sum_{a,b} v_{i,j,a,b}x_{i+a,j+b}\]
原则1:平移不变性
  • \(x\)的平移会导致\(h\)的平移,这里可以将\(\sum_{a,b}v_{i,j,a,b}\)理解为在点\((i,j)\)处点“识别器”,那么自然地,它会随着\((i,j)\)的变化而变化
  • 我们并不希望\(v\)随着\((i,j)\)发生变化,即并不依赖于在哪个位置,就像下面这张图,我们判定这个人的穿着打扮符合什么样的特征并不在乎它在图片上的哪个位置:alt text
  • 所以,我们让\(v_{i,j,a,b}=v_{a,b}\),那么:
\[h_{i,j} = \sum_{a,b} v_{a,b}x_{i+a,j+b}\]
原则2:局限性
  • 我们考察这个式子:\(\(h_{i,j} = \sum_{a,b} v_{a,b}x_{i+a,j+b}\)\)\((a,b)\)反应了以\((i,j)\)为中心向四周扩散的感觉,但是,我们在观察图片的时候,应该只考虑\((i,j)\)周围的一小片区域,而非全局,即原理的参数我们不要管。
  • 解决的方法,我们设定一个阈值\(\Delta\),当\(|a|,|b| > \Delta\)时,\(v_{a,b} = 0\)
\[h_{i,j} = \sum_{a=-\Delta}^{\Delta} \sum_{b=-\Delta}^{\Delta} v_{a,b}x_{i+a,j+b}\]

总结: 我们对全连接层进行一些改变,对参数量进行限制和压缩,就实现了变化成卷积层。

卷积层

二维交叉相关
  • 计算投射的示意:alt text
  • 具体的计算公式:alt text
\[19=0 \times 0 + 1 \times 1 + 2 \times 3 + 4 \times 3\]

我们发现,这里卷积核的大小是超参数,反应了我们希望考察一个点时希望考查到的它周围的范围 * 二维卷积层:(1)输入\(X\)\(n_h\times n_w\);(2)内核\(W\)\(k_h\times k_w\);(3)偏差\(b\);(4)输出\(Y\)\((n_h-k_h+1)\times(n_w-k_w+1)\)其中 \(W,b\) 是学习的参数。 * 具体的例子:alt text 个人的理解是:相同的输入和不同的卷积核相作用,会产生不一样的效果。比如边缘检测,就可以理解为要更大程度的对比每一个window的边缘和中心;锐化则是削弱边缘,增强中心......

我在这里做了一个简单的实验,验证用上述核进行边缘检测的可行性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import torch
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt

def cord2d(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

def corr2d_multi_in(X, K):
    return sum(cord2d(x, k) for x, k in zip(X, K))

def corr2d_multi_out(X, K):
    return torch.stack([corr2d_multi_in(X ,k) for k in K], 0)

image_path = '/Users/hendrick/Desktop/WechatIMG215.jpg'
image = Image.open(image_path)

preprocess = transforms.Compose([
    transforms.ToTensor()
])

image_tensor = preprocess(image)

k_1 = torch.tensor([[-1, -1, -1], [-1, 8, -1], [-1, -1 ,-1]])
k_2 = torch.stack((k_1, k_1, k_1), 0)
K = torch.stack((k_2, k_2, k_2), 0)

result = corr2d_multi_out(image_tensor, K)
image_np = result.permute(1, 2, 0).numpy().clip(0, 1)
plt.imshow(image_np)
plt.axis('off')
plt.show()
结果如下图:alt text

二维交叉相关 VS 卷积

先说结论,就是单纯的反过来,而由于对称性,没有区别。但是我们计算机实现卷积的时候,实际上是实现交叉相关

  • 二维交叉相关:\(y_{i,j} = \sum_{a=1}^{h} \sum_{b=1}^{w}w_{a,b}x_{i,j}+b\)
  • 二维卷积:\(y_{i,j} = \sum_{a=1}^{h} \sum_{b=1}^{w}w_{-a,-b}x_{i,j}+b\)