神经网络-二维卷积 池化 全连接层特征维度计算

对于刚接触神经网络的人,理解了网络层级之后就是要自己搭建网络,设置参数,这个时候就需要计算参数,特征图尺寸,输出维度等,这个其实看一遍流程,动手测试一下就懂了,所以我也在这里记录一下。

不同的框架,函数可能不一样,参数可能不一样,但是原理是不变的

这里我们把矩阵视作(w,h) 

二维卷积

self.conv1 = nn.Conv2d(3, 6, 5)  # 定义conv1函数的是图像卷积函数:输入为图像(3个通道),输出为 6张特征图, 卷积核为5x5正方形

如果把参数写完整就是

nn.Conv2d(in_channels=3,out_channels=6, kernel_size=5)

in_channels 输入通道理解的就是你一个图像有几层,如果是灰度图像那么就一层,如果是RGB彩色什么的就是三通道。当我们对一个二维矩阵做卷积 那么使用卷积核做一次就好,但是如果是三个二维矩阵的话,那么我们的卷积核就得做三次

out_channels 而什么是输出通道,我们使用一个卷积核对输入进行卷积会得到一个卷积后的结果,也是一个矩阵。而我们使用多个卷积核对输入进行卷积,那么会得到多个矩阵。如果我们设定输入通道为

out_channels=6

那么我们会对输入使用多个卷积核进行多次的卷积,得到6个输入矩阵。

kernel_size 卷积核

我们可以设置不同的卷积核的尺寸,那么同情况下输出的卷积结果矩阵也会有不同

 

 

nn.Conv2d(in_channels=3,out_channels=6, kernel_size=5,stride=2,padding=1)

除了上述三个参数,还有的就是步长和填补

padding则是在原输入矩阵的基础上进行扩充的一个过程,(不同框架略有不同 )

这里padding=1则是在输入矩阵四周扩充1单位的元素

那么计算的时候就变成了从新的位置开始进行卷积 

stride表示的步长,因为卷积计算一次之后需要移位,步长不是移动的尺度

可想而知,步长会影响输出的矩阵尺寸

二维卷积维度计算

卷积维度算法

input = input_w  ×  input_h

kernel = kernel_size_w  × kernel_size_h

output_w = ( input_w- kernel_size_w + 2 × padding) / stride + 1

意思就是使用(真实的宽度(填充之后的)-核宽)/步长 再加1   简单理解初始位置 加上可以移动的次数不就是输出的维度了吗

input =  torch.randn(1,1,5,5)
input
tensor([[[[-0.1454,  0.0959,  0.7894, -1.8632,  0.7346],
          [ 1.4939,  0.6125,  0.5970,  1.2868,  0.6414],
          [ 0.1438, -1.9135, -0.2211,  0.9153, -0.8114],
          [ 1.7509,  1.0152,  0.7613, -0.7284, -0.4400],
          [ 0.4867, -0.6124, -0.7566,  0.7052, -0.2713]]]])
m = nn.Conv2d(in_channels=1,out_channels=1, kernel_size=4,stride=1,padding=1)
m(input)

tensor([[[[ 0.0993, -0.1762,  0.2221,  0.3407],
          [-0.4635,  0.3792, -0.1610,  0.1519],
          [-0.3681,  1.0446,  0.5317,  0.1578],
          [-0.3003, -0.0451, -0.2738, -0.2864]]]],
       grad_fn=<ThnnConv2DBackward>)

输入为1通道 5*5的 卷积核为4*4 那么计算一下

(原始5 - 核4+padding2)/ 1 + 1 = 4  那么结果是4*4的 并且由于输出通道为1 所以只有一个输出矩阵

将输出通道更改一下为2,可以看到输出的就是2个矩阵

m = nn.Conv2d(in_channels=1,out_channels=2, kernel_size=4,stride=1,padding=1)
m(input)
tensor([[[[ 0.2068,  0.8328,  0.2907,  0.1911],
          [ 0.0800,  0.9450,  0.1021,  0.7446],
          [-0.5282,  0.0712,  0.0238, -0.2792],
          [ 0.7343,  0.8588, -0.4857, -0.3299]],
         [[ 0.0505, -0.4451,  0.9784,  0.4165],
          [-0.3324, -0.3740,  0.5277, -1.5232],
          [ 1.2352,  0.1066, -0.0122,  0.1837],
          [-0.0487, -1.0785,  0.0505,  0.5279]]]],
       grad_fn=<ThnnConv2DBackward>)

这是方阵的情况 那么使用不是方阵的试一下

input =  torch.randn(1,1,5,8)
m = nn.Conv2d(in_channels=1,out_channels=1, kernel_size=(2,4),stride=2,padding=1)
m(input)
tensor([[[[ 0.1220,  0.3527,  0.0259, -0.6563],
          [ 0.1079,  0.1251, -0.6078,  0.1546],
          [ 0.7988, -0.0212, -0.4859, -0.1893]]]],
       grad_fn=<ThnnConv2DBackward>)

输入为5*8  核函数为2*4 填充1 步长2

out_w= (原始8+填充2-核4)/ 步长2 + 1 = 4  (除法是向下省略的,因为卷积移位中位置不够不会继续计算了)

out_h = (原始5+填充2-核2)/ 步长2 + 1 = 3   输出为3*4

池化

池化对应的操作则是减少我们的特征维度,同样的是移位,不过是不重叠的

  

池化为(n,m)那么输出变为(w/n,h/m)

import torch.nn.functional as F
input
tensor([[[[-0.8740,  0.1030, -0.1662,  1.0354,  0.4021, -1.5810,  1.4051,
           -2.0059],
          [ 0.6855, -0.0885, -0.5764,  0.8782,  2.0018,  0.4929,  0.1271,
            1.1021],
          [ 0.1221,  0.6200, -0.2208, -0.7250,  0.9385, -0.7616,  0.4884,
           -0.1267],
          [ 0.5273,  2.3836, -0.6806,  0.4481,  0.3136, -0.1510,  0.3711,
            0.2278],
          [ 0.1555, -0.2847,  1.2660, -0.1363, -0.5036, -1.7452,  0.1767,
            0.1904]]]])
F.max_pool2d(input,(3,2))
tensor([[[[0.6855, 1.0354, 2.0018, 1.4051]]]])

输入5*8 池化3*2 可见w=5/3=1 而h=8/2=4 所以输出为1*4

可以右池化四次 上下不能了

全连接特征维度计算

input = torch.randn(1,1,7,10)
conv1 = nn.Conv2d(1, 6, 5,padding = 1)
conv2 = nn.Conv2d(6, 16, 3,padding = 1) 

m1 = conv1(input)
m2 = conv2(m)
mp = F.max_pool2d(m,(2, 2))

fc1 = nn.Linear(???,120)

经过两个卷积之后,我们需要全连接 此时的特征维度不允许错误,那么我们来计算一下

输入7*10  卷积核为5*5那么输出为 

(7-5+2)/1 + 1 = 5     (10-5+2)/1+1 = 8   即5*8

第二个卷积层

(5-3+2)/1+1 = 5   (8-3+2)/1+1= 8  不变

池化

5*8 池化 2*2 那么变为 2*4

全连接

所有输出特征图维度为2*4 一共输出16个特征图

2*4*16 = 128

m1 torch.Size([1, 6, 5, 8])  
m2 torch.Size([1, 16, 5, 8])
mp torch.Size([1, 16, 2, 4])

其中的6 16 16 便是通道数 也就是矩阵数目 最后的两个是每个矩阵的尺寸

所以最后的总特征数就是通道数 * 矩阵尺寸的元素数  128

大家注意这个通道数,实际上影响的就是输入输出的特征图的数目,跟输出尺寸是没有关系的,但是在卷积中输入输出一定要对应,输入是多少通道就是多少,不能对应不上。我们这里第一次卷积一个通道生成6个通道,第二层则是6个生成16个通道。

最后得到的则是16张特征图

最前面的1表示的则是样本数,标记一组有多少个样本 该参数在运行过程中是不会变的,也不用我们更改。

猜你喜欢

转载自blog.csdn.net/iamsongyu/article/details/88072757