VGG网络论文简读及复现网络构建(Pytorch)

前言

本文中对论文的构建网络部分通读,训练部分暂时忽略,代码构建同样只做网络构建,不进行训练测试和预测(或许会另写一篇)。

理论

vgg相关论文-传送门

论述

卷积网络配置有A-E6种,权重层不断增加。
v2
表二是不同配置的参数的数量。
v3
v4
v5

网络结构

论文中的网络结构解析

2.1 ARCHITECTURE

输入224*224的RGB图片。
唯一的预处理是输入的图片的每个像素点减去训练集的平均RGB值。
使用3*3的过滤器。
在其中一个配置,甚至使用了1*1的过滤器。
卷积步幅是1个像素。
为了保持空间分辨率,3*3的过滤器使用1像素填充。
卷积层使用了5个池化(maxpool)。
maxpool使用了2*2尺寸,步幅为2。
所有的隐藏层都使用了ReLu函数。
没有使用规范化,因为没有提高精确度,反而消耗计算时间和内存。

名词解释

o u t p u t _ s i z e = ⌈ i n t p u t _ s i z e s t r i d e ⌉ output\_size=\lceil\frac{intput\_size}{stride}\rceil output_size=strideintput_size
conv3-64:卷积核=3*3*n,n=输入通道数,有64个卷积核进行卷积
maxpool:最大池化层,尺寸=2*2,stride=2
“Max-pooling is performed over a 2 × 2 pixel window, with stride 2.”
FC-4096:全连接层-4096个神经元
soft-max:就是softmax函数

结构

这次选择了配置D,忽略ReLu

164个333的卷积核,padding=1,stride=1
64个3364的卷积核,padding=1,stride=1
maxpool,size=2*2,stride=2
2128个3364的卷积核,padding=1,stride=1
128个33128的卷积核,padding=1,stride=1
maxpool,size=2*2,stride=2
3256个33128的卷积核,padding=1,stride=1
256个33256的卷积核,padding=1,stride=1
maxpool,size=2*2,stride=2
4512个33256的卷积核,padding=1,stride=1
512个33512的卷积核,padding=1,stride=1
maxpool,size=2*2,stride=2
5512个33512的卷积核,padding=1,stride=1
512个33512的卷积核,padding=1,stride=1
maxpool,size=2*2,stride=2
6全连接成4096个神经元
7全连接成4096个神经元
8全连接成1000个神经元
9softmax

以上序号会对应相应的代码

实践

代码部分

import torch
import torch.nn as nn
import torchvision      
from tensorboardX import SummaryWriter

class vgg16(nn.Module):
    def __init__(self):
        super(vgg16, self).__init__()
        # 1
        self.layer1 = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        
        # 2
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        
        # 3
        self.layer3 = nn.Sequential(
            nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        
        # 4
        self.layer4 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        
        # 5
        self.layer5 = nn.Sequential(
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
    
        self.conv=nn.Sequential(
                self.layer1,
                self.layer2,
                self.layer3,
                self.layer4,
                self.layer5
            )
        
        self.fc=nn.Sequential(
            # 6
            nn.Linear(512*7*7,4096),
            nn.ReLU(inplace=True),
            nn.Dropout2d(p=0.5,),
            # 7
            nn.Linear(4096,4096),
            nn.ReLU(inplace=True),
            nn.Dropout2d(p=0.5,),
            # 8
            nn.Linear(4096,1000),
            nn.ReLU(inplace=True)
        )
        
    def forward(self,x):
        x=self.conv(x)
        x = torch.flatten(x, 1)
        x = x.view(1, 512*7*7)
        x=self.fc(x)
        return x
    
vgg = vgg16()
data = torch.rand(1,3,224,224)

torch.onnx.export(vgg, data, 'D:/tmp/vgg_model2.onnx', export_params=True, opset_version=8)

with SummaryWriter(logdir="network_visualization2") as w:
    w.add_graph(vgg, data)

基于Pytorch的神经网络可视化
后面的代码改成了,可视化模型

网络模型图

注意

使用TensorBoard论述

整体模型

v6
可以看到输入输出分别是3224224和11000,图片问题是32242,其实是3224*224
v7
大概分为卷积层、全连接层和softmax

附上一张大图
v8

卷积层

VGG模型的卷积层分为五个block,每个输入输出的大小不变。
v9
看一下BLOCK1
v10
可以看到每个卷积中都有一个ReLu激活函数
v11
可以看出输入输出确实没有变,只是通道边长,符合VGG的网络要求。
后面几个同理。

全连接层

卷积层转全连接有一个舒展成一维向量
v12
整合向量
v13
全连接层
v14
重点看一下fc-4096
v15
输入输出保持4096个神经元,符合VGG要求
下面以此类推。

softmax

softmax函数,又称归一化指数函数。
将输出数据归一化到0-1之间,并可以进行预测

总结

论文的网络相对于比较清晰,较好复现。
可以根据此文,复现VGG11、VGG13和VGG19.
能力问题,文章有所疏漏,欢迎指出!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值