还是用MLP的思想将图像展开成一个很长的向量,将互相关运算出的像素值当做这一层的一个输出值,那么就会发现和3这个输出值相连的并不是所有的输入值,而只是和我这个卷积核对应大小的一部分,这样就可以做到减小参数;
当卷积核移动后同样的操作,这一次的输出也只是跟下一个框框里的输入有关,而且这一次的权重和上一次的权重是一样的,因为他们用的同一个卷积核,所以这样就又做了一次参数的减少;
AlexNet是由Alex Krizhevsky提出的首个应用于图像分类的深层卷积神经网络,该网络在2012年ILSVRC (ImageNet Large Scale Visual Recognition Competition)图像分类竞赛中以16.4%的测试错误率赢得第一名。AlexNet使用GPU代替CPU进行运算,使得在可接受的时间范围内模型结构能够更加复杂,它的出现证明了深层卷积神经网络在复杂模型下的有效性,使CNN在计算机视觉中流行开来,直接或间接地引发了深度学习的热潮。Reference: ImageNet Classifification with Deep Convolutional Neural Networks
AlexNet一共包含8层,前5层由卷积层组成,而剩下的3层为全连接层。网络结构分为上下两层,分别对应两个GPU的操作过程。最后一层全连接层的输出作为 s o f t m a x softmax softmax的输入,得到1000个图像分类标签对应的概率值。除去GPU并行结构的设计,AlexNet网络结构与LeNet十分相似。
后来就有人想AlexNet之所以比LeNet效果好有一部分原因是因为网络变深了,但是现在AlexNet里面的部分卷积核尺寸太大了,这样妨碍了网络变深,那么如何改进呢?首先要引入感受野的概念
感受野(Receptive Field),指的是神经网络中神经元“看到的”输入区域,在卷积神经网络中,feature map上某个元素的计算受输入图像上某个区域的影响,这个区域即该元素的感受野。那么如果在我感受野相同的条件下,我让中间层数更多,那么能提取到的特征就越丰富,效果就会更好。
从图中可以看出对于一个 5 × 5 5\times5 5×5 的图片,用两个 3 × 3 3\times3 3×3 的卷积核和用一个 5 × 5 5\times5 5×5 的卷积核最后得到的元素感受野是一样的,但是前者将神经网络加深了一层,并且参数量也少了, 11 × 11 11\times11 11×11 的卷积核亦是如此,所以由这种思想便引入了后面的VGG块以及VGG网络。
VGGNet是由牛津大学视觉几何小组(Visual Geometry Group, VGG)提出的一种深层卷积网络结构,网络名称VGGNet取自该小组名缩写。VGGNet是首批把图像分类的错误率降低到10%以内模型,同时该网络所采用的 3 × 3 3\times3 3×3卷积核的思想是后来许多模型的基础,该模型发表在2015年国际学习表征会议(International Conference On Learning Representations, ICLR)后至今被引用的次数已经超过1万4千余次。
在原论文中的VGGNet包含了6个版本的演进,分别对应VGG11、VGG11-LRN、VGG13、VGG16-1、VGG16-3和VGG19,不同的后缀数值表示不同的网络层数(VGG11-LRN表示在第一层中采用了LRN的VGG11,VGG16-1表示后三组卷积块中最后一层卷积采用卷积核尺寸为 1 × 1 1\times1 1×1 ,相应的VGG16-3表示卷积核尺寸为 3 × 3 3\times3 3×3 )。今天主要介绍的VGG16为VGG16-3。
上图中的VGG16体现了VGGNet的核心思路,使用 3 × 3 3\times3 3×3 的卷积组合代替大尺寸的卷积(2个 3 × 3 3\times3 3×3 卷积即可与 5 × 5 5\times5 5×5 卷积拥有相同的感受视野)。
VGG块的组成规律是:连续使用数个相同的填充为1、窗口形状为 3 × 3 3\times3 3×3 的卷积层后接上一个步幅为2、窗口形状为 2 × 2 2\times2 2×2 的最大池化层。卷积层保持输入的高和宽不变,而池化层则对其减半。
网络参数设置如下表所示。
网络层 | 输入尺寸 | 核尺寸 | 输出尺寸 | 参数个数 |
---|---|---|---|---|
卷积层 C 11 C_{11} C11 | 224 × 224 × 3 224\times224\times3 224×224×3 | 3 × 3 × 64 / 1 3\times3\times64/1 3×3×64/1 | 224 × 224 × 64 224\times224\times64 224×224×64 | ( 3 × 3 × 3 + 1 ) × 64 (3\times3\times3+1)\times64 (3×3×3+1)×64 |
卷积层 C 12 C_{12} C12 | 224 × 224 × 64 224\times224\times64 224×224×64 | 3 × 3 × 64 / 1 3\times3\times64/1 3×3×64/1 | 224 × 224 × 64 224\times224\times64 224×224×64 | ( 3 × 3 × 64 + 1 ) × 64 (3\times3\times64+1)\times64 (3×3×64+1)×64 |
最大池化层 S m a x 1 S_{max1} Smax1 | 224 × 224 × 64 224\times224\times64 224×224×64 | 2 × 2 / 2 2\times2/2 2×2/2 | 112 × 112 × 64 112\times112\times64 112×112×64 | 0 0 0 |
卷积层 C 21 C_{21} C21 | 112 × 112 × 64 112\times112\times64 112×112×64 | 3 × 3 × 128 / 1 3\times3\times128/1 3×3×128/1 | 112 × 112 × 128 112\times112\times128 112×112×128 | ( 3 × 3 × 64 + 1 ) × 128 (3\times3\times64+1)\times128 (3×3×64+1)×128 |
卷积层 C 22 C_{22} C22 | 112 × 112 × 128 112\times112\times128 112×112×128 | 3 × 3 × 128 / 1 3\times3\times128/1 3×3×128/1 | 112 × 112 × 128 112\times112\times128 112×112×128 | ( 3 × 3 × 128 + 1 ) × 128 (3\times3\times128+1)\times128 (3×3×128+1)×128 |
最大池化层 S m a x 2 S_{max2} Smax2 | 112 × 112 × 128 112\times112\times128 112×112×128 | 2 × 2 / 2 2\times2/2 2×2/2 | 56 × 56 × 128 56\times56\times128 56×56×128 | 0 0 0 |
卷积层 C 31 C_{31} C31 | 56 × 56 × 128 56\times56\times128 56×56×128 | 3 × 3 × 256 / 1 3\times3\times256/1 3×3×256/1 | 56 × 56 × 256 56\times56\times256 56×56×256 | ( 3 × 3 × 128 + 1 ) × 256 (3\times3\times128+1)\times256 (3×3×128+1)×256 |
卷积层 C 32 C_{32} C32 | 56 × 56 × 256 56\times56\times256 56×56×256 | 3 × 3 × 256 / 1 3\times3\times256/1 3×3×256/1 | 56 × 56 × 256 56\times56\times256 56×56×256 | ( 3 × 3 × 256 + 1 ) × 256 (3\times3\times256+1)\times256 (3×3×256+1)×256 |
卷积层 C 33 C_{33} C33 | 56 × 56 × 256 56\times56\times256 56×56×256 | 3 × 3 × 256 / 1 3\times3\times256/1 3×3×256/1 | 56 × 56 × 256 56\times56\times256 56×56×256 | ( 3 × 3 × 256 + 1 ) × 256 (3\times3\times256+1)\times256 (3×3×256+1)×256 |
最大池化层 S m a x 3 S_{max3} Smax3 | 56 × 56 × 256 56\times56\times256 56×56×256 | 2 × 2 / 2 2\times2/2 2×2/2 | 28 × 28 × 256 28\times28\times256 28×28×256 | 0 0 0 |
卷积层 C 41 C_{41} C41 | 28 × 28 × 256 28\times28\times256 28×28×256 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 28 × 28 × 512 28\times28\times512 28×28×512 | ( 3 × 3 × 256 + 1 ) × 512 (3\times3\times256+1)\times512 (3×3×256+1)×512 |
卷积层 C 42 C_{42} C42 | 28 × 28 × 512 28\times28\times512 28×28×512 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 28 × 28 × 512 28\times28\times512 28×28×512 | ( 3 × 3 × 512 + 1 ) × 512 (3\times3\times512+1)\times512 (3×3×512+1)×512 |
卷积层 C 43 C_{43} C43 | 28 × 28 × 512 28\times28\times512 28×28×512 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 28 × 28 × 512 28\times28\times512 28×28×512 | ( 3 × 3 × 512 + 1 ) × 512 (3\times3\times512+1)\times512 (3×3×512+1)×512 |
最大池化层 S m a x 4 S_{max4} Smax4 | 28 × 28 × 512 28\times28\times512 28×28×512 | 2 × 2 / 2 2\times2/2 2×2/2 | 14 × 14 × 512 14\times14\times512 14×14×512 | 0 0 0 |
卷积层 C 51 C_{51} C51 | 14 × 14 × 512 14\times14\times512 14×14×512 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 14 × 14 × 512 14\times14\times512 14×14×512 | ( 3 × 3 × 512 + 1 ) × 512 (3\times3\times512+1)\times512 (3×3×512+1)×512 |
卷积层 C 52 C_{52} C52 | 14 × 14 × 512 14\times14\times512 14×14×512 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 14 × 14 × 512 14\times14\times512 14×14×512 | ( 3 × 3 × 512 + 1 ) × 512 (3\times3\times512+1)\times512 (3×3×512+1)×512 |
卷积层 C 53 C_{53} C53 | 14 × 14 × 512 14\times14\times512 14×14×512 | 3 × 3 × 512 / 1 3\times3\times512/1 3×3×512/1 | 14 × 14 × 512 14\times14\times512 14×14×512 | ( 3 × 3 × 512 + 1 ) × 512 (3\times3\times512+1)\times512 (3×3×512+1)×512 |
最大池化层 S m a x 5 S_{max5} Smax5 | 14 × 14 × 512 14\times14\times512 14×14×512 | 2 × 2 / 2 2\times2/2 2×2/2 | 7 × 7 × 512 7\times7\times512 7×7×512 | 0 0 0 |
全连接层 F C 1 FC_{1} FC1 | 7 × 7 × 512 7\times7\times512 7×7×512 | ( 7 × 7 × 512 ) × 4096 (7\times7\times512)\times4096 (7×7×512)×4096 | 1 × 4096 1\times4096 1×4096 | ( 7 × 7 × 512 + 1 ) × 4096 (7\times7\times512+1)\times4096 (7×7×512+1)×4096 |
全连接层 F C 2 FC_{2} FC2 | 1 × 4096 1\times4096 1×4096 | 4096 × 4096 4096\times4096 4096×4096 | 1 × 4096 1\times4096 1×4096 | ( 4096 + 1 ) × 4096 (4096+1)\times4096 (4096+1)×4096 |
全连接层 F C 3 FC_{3} FC3 | 1 × 4096 1\times4096 1×4096 | 4096 × 1000 4096\times1000 4096×1000 | 1 × 1000 1\times1000 1×1000 | ( 4096 + 1 ) × 1000 (4096+1)\times1000 (4096+1)×1000 |
import torch
import torch.nn as nn
# 将一个卷积层、BN层和非线性层封装在一起
def conv_layer(channel_in, channel_out, kernel_size, padding_size):
layer = nn.Sequential(
nn.Conv2d(channel_in,channel_out,kernel_size=kernel_size,padding=padding_size),
nn.BatchNorm2d(channel_out),
nn.ReLU()
)
return layer
# 将上述封装的卷积层按照指定的参数组装在一起,最后再加一个最大池化层
def vgg_conv_block(channel_in_list, channel_out_list, kernel_size_list, padding_size_list, pooling_kernel_size, pooling_stride):
layers = [conv_layer(channel_in_list[i], channel_out_list[i], kernel_size_list[i], padding_size_list[i]) for i in range(len(channel_in_list))]
layers += [nn.MaxPool2d(kernel_size = pooling_kernel_size,stride = pooling_stride)]
return nn.Sequential(*layers)
# 将一个线性层、BN层和非线性层封装在一起
def vgg_fc_layer(size_in, size_out):
layer = nn.Sequential(
nn.Linear(size_in, size_out),
nn.BatchNorm1d(size_out),
nn.ReLU()
)
return layer
class VGG16(nn.Module):
def __init__(self):
super(VGG16, self).__init__()
# 指定每一个VGG块的参数
self.layer1 = vgg_conv_block([3,64], [64,64], [3,3], [1,1], 2, 2)
self.layer2 = vgg_conv_block([64,128], [128,128], [3,3], [1,1], 2, 2)
self.layer3 = vgg_conv_block([128,256,256], [256,256,256], [3,3,3], [1,1,1], 2, 2)
self.layer4 = vgg_conv_block([256,512,512], [512,512,512], [3,3,3], [1,1,1], 2, 2)
self.layer5 = vgg_conv_block([512,512,512], [512,512,512], [3,3,3], [1,1,1], 2, 2)
# 过渡全连接层
self.layer6 = vgg_fc_layer(7*7*512, 4096)
self.layer7 = vgg_fc_layer(4096, 4096)
# 最后的全连接层
self.layer8 = nn.Linear(4096, 1000)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = self.layer3(out)
out = self.layer4(out)
out = self.layer5(out)
out = out.view(out.size(0), -1)
out = self.layer6(out)
out = self.layer7(out)
out = self.layer8(out)
return out
def test():
net = VGG16()
x = torch.randn(2,3,224,224)
y = net(x)
print(y.size())
test()
torch.Size([2, 1000])
sum_ = 0
for name, param in net.named_parameters():
mul = 1
for size_ in param.shape:
mul *= size_ # 统计每层参数个数
sum_ += mul # 累加每层参数个数
#print('{} : {}' % (name, param.shape)) # 打印参数名和参数数量
print('参数个数:', sum_)
参数个数: 138382376