VGG网络

1.简介

VGG是在2014年由牛顿大学著名研究组VGG(Visual Geometry Group)提出,斩获该年ImageNet竞赛中Localization Task(定位任务)第一名和Classfication Task(分类任务第二名)。

2. 网络结构

在这里插入图片描述
一般情况下,都会采用D、E这两种规模的网络,也就是VGG16和VGG19。

  • VGG16:13个卷积层和3个全连接层
  • VGG19:16个卷积层和3个全连接层

以VGG16为例

  • 卷积层参数:卷积核大小(3*3),步长(Stride)为1,填充(padding)为1。
  • 池化层参数:最大池化maxpooling参数均为(2*2)
    在这里插入图片描述
    在全连接层(蓝色)之前所有部分,即卷积和池化的操作,可以理解为提取特征,而在全连接层及之后,实现分类
    网络接收大小为(224x224)的图像,channels为3的RGB图,每一次卷积均不改变图片的长宽(224-3+2)/1+1=224
    Out_size=(In_size-Kernel_size+2Padding)/Sride+1
    而每次最大池化会使得图片长宽减半。而最后全连接层部分,因为目标任务imagenet是1000分类,所以最后值是1000,再加上softmax激活函数,求最大的概率分布。

3.优缺点

  1. 优点
    与传统网络结构不同的是,VGGnet采用两个小的3x3的卷积核代替一个5x5的卷积核,采用三个3x3的卷积核代替一个7x7的卷积核。
    之所以可以这样做的原因是因为其具有相同的感受野。
    在这里插入图片描述
    5x5卷积可以看作先做一个3x3卷积,然后再用全连接层链接这个3x3的卷积输出。
    感受野计算公式:
    F(i)=(F(i+1)-1) * Stride +Ksize
    F(i):第i层感受野
    Feature map=1
    F=(1-1)*1+3=3
    F=(3-1)*2+3=5
    F=(5-1)*2+3=7
    而通过小尺寸的卷积核去替代大尺寸的卷积核的目的是减少参数
    假定输入channel和输出channel都为C
    则7x7大小的参数为:7x7xCxC=49C²
    而三个3x3大小的参数为:3x3xCxC+3x3xCxC+3x3xCxC=27C²
  2. 缺点
    耗费资源,使用了更多的参数,全连接层就有3层,第一个全连接层还是1x1x4096,且训练时间过长,存储容量大。

4. 网络复现

采用pytorch实现网络复现

class Vgg16(nn.Module):
    def __init__(self, num_classes):
        super(Vgg16, self).__init__()

        self.conv_unit = nn.Sequential(
            # BLOCK1
            nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            # BLOCK2
            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            # BLOCK3
            nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            # BLOCK 4
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            # BLOCK5
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
        )

        self.fn_unit = nn.Sequential(
            nn.Linear(7*7*512, 4096),
            nn.ReLU(),
            nn.Dropout(p=0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(p=0.5),
            nn.Linear(4096, num_classes),
        )
    def forward(self,x):
        x = self.conv_unit(x)
        x = x.view(x.size(0), -1)
        x = self.fn_unit(x)
        return x

网络是逐层写的,尽管其中有很多层都是一样的,略显有点冗长,不过基本功能还是能实现。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值