人可以生如蚁,而美如神!
测试conv2d的操作,理清思路
首先,我们看看conv2d的官方说明,请点击这里!中文官网
下面我主要是想弄清楚conv2d(3,5,(不重要),不重要)这样的操作,也就是多通道的卷积到底是怎么做的,这个函数是如何将3通道的矩阵弄成5通道的矩阵,为了验证我的猜想,我决定实验。
实验代码如下
import torch.nn as nn
import torch
#201907 create by liao
'''
测试卷积操作 conv2d
'''
X = torch.ones((1,3,5,5))#生成一个四维的数,其中第一维可以理解为batchsize,batchsize为1
print(X.shape)
print(X)
conv = nn.Conv2d(3,5,(2,2),1,0,bias=False)#这里设置卷积核为2*2的方块,不要bias,方便后续验证
print(list(conv.parameters()))
print(conv(X))
此程序输出的结果如下,X为3通道的5×5的矩阵,就像一个RGB的小图片!
X的shape:torch.Size([1, 3, 5, 5])
X:tensor([[[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]]])
[Parameter containing:
卷积核:tensor([[[[-0.2459, 0.0202],
[-0.0128, -0.0544]],
[[-0.1597, -0.2395],
[-0.1087, 0.1110]],
[[ 0.1419, 0.1889],
[ 0.1079, 0.1113]]],
[[[ 0.0548, -0.2636],
[-0.2178, -0.0052]],
[[-0.2517, -0.0918],
[-0.1125, -0.1353]],
[[ 0.1517, -0.0493],
[ 0.1624, 0.1028]]],
[[[ 0.0770, -0.2828],
[ 0.1620, 0.2725]],
[[ 0.0179, 0.2088],
[ 0.0909, -0.2115]],
[[ 0.2133, -0.0517],
[ 0.0446, 0.0143]]],
[[[-0.0467, 0.1556],
[-0.2286, 0.1097]],
[[-0.0364, -0.1574],
[ 0.2773, 0.0079]],
[[ 0.2857, -0.0842],
[-0.2203, 0.0901]]],
[[[ 0.0773, -0.0768],
[ 0.0390, -0.0547]],
[[ 0.2591, 0.2572],
[ 0.0899, 0.1484]],
[[ 0.2004, 0.2760],
[ 0.1137, -0.1834]]]], requires_grad=True)]
卷积操作的结果:tensor([[[[-0.1399, -0.1399, -0.1399, -0.1399],
[-0.1399, -0.1399, -0.1399, -0.1399],
[-0.1399, -0.1399, -0.1399, -0.1399],
[-0.1399, -0.1399, -0.1399, -0.1399]],
[[-0.6554, -0.6554, -0.6554, -0.6554],
[-0.6554, -0.6554, -0.6554, -0.6554],
[-0.6554, -0.6554, -0.6554, -0.6554],
[-0.6554, -0.6554, -0.6554, -0.6554]],
[[ 0.5552, 0.5552, 0.5552, 0.5552],
[ 0.5552, 0.5552, 0.5552, 0.5552],
[ 0.5552, 0.5552, 0.5552, 0.5552],
[ 0.5552, 0.5552, 0.5552, 0.5552]],
[[ 0.1527, 0.1527, 0.1527, 0.1527],
[ 0.1527, 0.1527, 0.1527, 0.1527],
[ 0.1527, 0.1527, 0.1527, 0.1527],
[ 0.1527, 0.1527, 0.1527, 0.1527]],
[[ 1.1462, 1.1462, 1.1462, 1.1462],
[ 1.1462, 1.1462, 1.1462, 1.1462],
[ 1.1462, 1.1462, 1.1462, 1.1462],
[ 1.1462, 1.1462, 1.1462, 1.1462]]]],
grad_fn=<MkldnnConvolutionBackward>)
Process finished with exit code 0
看到结果,我想到结论: conv2d( in_channels = X(x>1) , out_channels = N) 有N乘X个filter(N组filters,每组X 个)对输入进行滤波。即每次有一组里X个filter对原X个channels分别进行滤波最后相加输出一个结果,最后输出N个结果即feature map。----这句话是到网上看的!
下面是验证猜想:
由于X这个tensor里面全是1,所以方便我们验证,我直接把第一个组卷积核相加,看结果是不是-0.1399
[[[-0.2459, 0.0202],
[-0.0128, -0.0544]],
[[-0.1597, -0.2395],
[-0.1087, 0.1110]],
[[ 0.1419, 0.1889],
[ 0.1079, 0.1113]]]
-0.2459+0.0202-0.0128-0.0544-0.1597-0.2395-0.1087+0.1110+0.1419+0.1889+0.1079+0.1113 = -0.1398
好了,居然差0.0001,不慌,接下来验证第二组卷积核:
0.0548-0.2636-0.2178-0.0052-0.2517-0.0918-0.1125-0.1353+0.1517-0.0493+0.1624+0.1028 = 0.6555
第三组:
0.0770-0.2828+0.1620+0.2725+0.0179+0.2088+0.0909-0.2115+0.2133-0.0517+0.0446+0.0143 = 0.5553
好了,接下来就不用去验证了,因为已经可以做出判断了。
结合例子来理解
这句话conv = nn.Conv2d(3,5,(2,2),1,0,bias=False)其实是生成了5组权重,每组都是三个2*2的卷积核。每个卷积核在每个通道上运算得到一个值,然后将这三个值相加。这样每一组会得到一个矩阵,所以输出就会有5通道的矩阵。