Pytorch CIFAR10图像分类 VGG篇
Posted Real&Love
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch CIFAR10图像分类 VGG篇相关的知识,希望对你有一定的参考价值。
Pytorch CIFAR10图像分类 VGG篇
文章目录
这里贴一下汇总篇: 汇总篇
4.定义网络(VGG)
VGG模型是Oxford的Visual Geometry Group的组提出的,这个网络是在ILSVRC 2014上进行相关的工作,在ILSVRC 2014中超过Alex Net网络,拿到了当时分类项目的top 2 和 定位项目的top 1,VGGNet的拓展性很强,迁移到其他图片数据上的泛化性非常好。从此VGG进入了我们的视野,主要证明了增加网络的深度能够在一定程度上影响了网络最终的性能。
VGG net可以说是从Alex-net发展而来的网络,VGGNet论文中全部使用了3x3的卷积核和2x2的池化核,通过不断加深网络结构来提升性能,现在主要的都是VGG16和VGG19,顾名思义,就是有16层和19层。
在论文《Very Deep Convolutional Networks for Large-Scale Image Recognition》详细的给出了VGG的详细介绍,D和E分别就是我们的VGG16和VGG19。先以VGG16为例子,VGG有16层,我把它分为六块.
VGG-16 一些性质:
VGG 是一个很经典的卷积神经网络结构,是由 AlexNet 改进的,相比于 AlexNet,主要的改变有两个地方:
- 使用 3 x 3 卷积核代替 AlexNet 中的大卷积核
- 使用 2 x 2 池化核代替 AlexNet 的 3 x 3 池化核
- VGGNet 有很多类型,论文中提出了 4 种不同层次的网络结构(从 11 层到 19 层)
- VGG 有很多优点,最本质的特点就是用小的卷积核(3x3)代替大的卷积核,2个 3x3 卷积堆叠等于1个 5x5 卷积,3 个 3x3 堆叠等于1个 7x7 卷积,感受野大小不变。
- 可以想象一下,在步长 s 为 1,填充 padding 为 0 时,2 个 3x3 卷积后的图像 size 为 (((N-3)/1+1)-3)/1+1 = ((N-3+1)-3+1) = N-4 = (N-5)/1+1。且做卷积后,得到的特征,都是从原图像上相同的像素点提取的(原图像每 5x5 的空域像素点对应一个新的特征),因此感受野大小不变。故 2 个 3x3 的卷积核与 5x5 的卷积核等价。
首先我们还是得判断是否可以利用GPU,因为GPU的速度可能会比我们用CPU的速度快20-50倍左右,特别是对卷积神经网络来说,更是提升特别明显。
device = 'cuda' if torch.cuda.is_available() else 'cpu'
我们依据论文给出的VGG模型进行定义,分别定义了VGG11,VGG13,VGG16和VGG19
cfg = {
'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
class VGG(nn.Module):
def __init__(self, vgg_name):
super(VGG, self).__init__()
self.features = self._make_layers(cfg[vgg_name])
self.classifier = nn.Sequential(
nn.Linear(512,512),
nn.ReLU(True),
nn.Dropout(0.2),
nn.Linear(512,512),
nn.ReLU(True),
nn.Dropout(0.2),
nn.Linear(512,10),
)
# self.classifier = nn.Linear(512,10)
self._initialize_weight()
def forward(self, x):
out = self.features(x)
# 在进入
out = out.view(out.size(0), -1)
out = self.classifier(out)
return out
# make layers
def _make_layers(self, cfg):
layers = []
in_channels = 3 # RGB 初始通道为3
for x in cfg:
if x == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2)] # kernel_size 为 2 x 2,然后步长为2
else:
layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), # 都是(3.3)的卷积核
nn.BatchNorm2d(x),
nn.ReLU(inplace=True)] # RelU
in_channels = x # 重定义通道
# layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
return nn.Sequential(*layers)
# 初始化参数
def _initialize_weight(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
# xavier is used in VGG's paper
nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
m.weight.data.normal_(0, 0.01)
m.bias.data.zero_()
net = VGG('VGG16').to(device)
summary(net,(3,32,32))
---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Conv2d-1 [-1, 64, 32, 32] 1,792 BatchNorm2d-2 [-1, 64, 32, 32] 128 ReLU-3 [-1, 64, 32, 32] 0 Conv2d-4 [-1, 64, 32, 32] 36,928 BatchNorm2d-5 [-1, 64, 32, 32] 128 ReLU-6 [-1, 64, 32, 32] 0 MaxPool2d-7 [-1, 64, 16, 16] 0 Conv2d-8 [-1, 128, 16, 16] 73,856 BatchNorm2d-9 [-1, 128, 16, 16] 256 ReLU-10 [-1, 128, 16, 16] 0 Conv2d-11 [-1, 128, 16, 16] 147,584 BatchNorm2d-12 [-1, 128, 16, 16] 256 ReLU-13 [-1, 128, 16, 16] 0 MaxPool2d-14 [-1, 128, 8, 8] 0 Conv2d-15 [-1, 256, 8, 8] 295,168 BatchNorm2d-16 [-1, 256, 8, 8] 512 ReLU-17 [-1, 256, 8, 8] 0 Conv2d-18 [-1, 256, 8, 8] 590,080 BatchNorm2d-19 [-1, 256, 8, 8] 512 ReLU-20 [-1, 256, 8, 8] 0 Conv2d-21 [-1, 256, 8, 8] 590,080 BatchNorm2d-22 [-1, 256, 8, 8] 512 ReLU-23 [-1, 256, 8, 8] 0 MaxPool2d-24 [-1, 256, 4, 4] 0 Conv2d-25 [-1, 512, 4, 4] 1,180,160 BatchNorm2d-26 [-1, 512, 4, 4] 1,024 ReLU-27 [-1, 512, 4, 4] 0 Conv2d-28 [-1, 512, 4, 4] 2,359,808 BatchNorm2d-29 [-1, 512, 4, 4] 1,024 ReLU-30 [-1, 512, 4, 4] 0 Conv2d-31 [-1, 512, 4, 4] 2,359,808 BatchNorm2d-32 [-1, 512, 4, 4] 1,024 ReLU-33 [-1, 512, 4, 4] 0 MaxPool2d-34 [-1, 512, 2, 2] 0 Conv2d-35 [-1, 512, 2, 2] 2,359,808 BatchNorm2d-36 [-1, 512, 2, 2] 1,024 ReLU-37 [-1, 512, 2, 2] 0 Conv2d-38 [-1, 512, 2, 2] 2,359,808 BatchNorm2d-39 [-1, 512, 2, 2] 1,024 ReLU-40 [-1, 512, 2, 2] 0 Conv2d-41 [-1, 512, 2, 2] 2,359,808 BatchNorm2d-42 [-1, 512, 2, 2] 1,024 ReLU-43 [-1, 512, 2, 2] 0 MaxPool2d-44 [-1, 512, 1, 1] 0 Linear-45 [-1, 512] 262,656 ReLU-46 [-1, 512] 0 Dropout-47 [-1, 512] 0 Linear-48 [-1, 512] 262,656 ReLU-49 [-1, 512] 0 Dropout-50 [-1, 512] 0 Linear-51 [-1, 10] 5,130 ================================================================ Total params: 15,253,578 Trainable params: 15,253,578 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.01 Forward/backward pass size (MB): 6.59 Params size (MB): 58.19 Estimated Total Size (MB): 64.79 ----------------------------------------------------------------
首先从我们summary可以看到,我们定义的模型的参数大概是15 millions,实际上,这是我们遇到的最大参数的模型了,说明之中有很多计算过程,也会更加繁琐,我们输入的是(batch,3,32,32)的张量,并且这里也能看到每一层后我们的图像输出大小的变化,最后输出10个参数,再通过softmax函数就可以得到我们每个类别的概率了。
我们也可以打印出我们的模型观察一下
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1Keras CIFAR-10图像分类 VGG 篇
VGG 系列的探索与pytorch实现 (CIFAR10 分类问题) - Acc: 92.58 % (一文可通VGG + pytorch)