前言
本文中对论文的构建网络部分通读,训练部分暂时忽略,代码构建同样只做网络构建,不进行训练测试和预测(或许会另写一篇)。
理论
论述
卷积网络配置有A-E6种,权重层不断增加。
表二是不同配置的参数的数量。
网络结构
论文中的网络结构解析
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
1 | 64个333的卷积核,padding=1,stride=1 |
---|---|
64个3364的卷积核,padding=1,stride=1 | |
maxpool,size=2*2,stride=2 | |
2 | 128个3364的卷积核,padding=1,stride=1 |
128个33128的卷积核,padding=1,stride=1 | |
maxpool,size=2*2,stride=2 | |
3 | 256个33128的卷积核,padding=1,stride=1 |
256个33256的卷积核,padding=1,stride=1 | |
maxpool,size=2*2,stride=2 | |
4 | 512个33256的卷积核,padding=1,stride=1 |
512个33512的卷积核,padding=1,stride=1 | |
maxpool,size=2*2,stride=2 | |
5 | 512个33512的卷积核,padding=1,stride=1 |
512个33512的卷积核,padding=1,stride=1 | |
maxpool,size=2*2,stride=2 | |
6 | 全连接成4096个神经元 |
7 | 全连接成4096个神经元 |
8 | 全连接成1000个神经元 |
9 | softmax |
以上序号会对应相应的代码
实践
代码部分
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论述
整体模型
可以看到输入输出分别是3224224和11000,图片问题是32242,其实是3224*224
大概分为卷积层、全连接层和softmax
附上一张大图
卷积层
VGG模型的卷积层分为五个block,每个输入输出的大小不变。
看一下BLOCK1
可以看到每个卷积中都有一个ReLu激活函数
可以看出输入输出确实没有变,只是通道边长,符合VGG的网络要求。
后面几个同理。
全连接层
卷积层转全连接有一个舒展成一维向量
整合向量
全连接层
重点看一下fc-4096
输入输出保持4096个神经元,符合VGG要求
下面以此类推。
softmax
softmax函数,又称归一化指数函数。
将输出数据归一化到0-1之间,并可以进行预测
总结
论文的网络相对于比较清晰,较好复现。
可以根据此文,复现VGG11、VGG13和VGG19.
能力问题,文章有所疏漏,欢迎指出!