VGG简介
我们前面学习了两个神经网络,一个是lenet,另一个是alexnet,其实他们两个的设计并不是那么的科学,因为例如AlexNet的网络结构并没有设计逻辑。似乎就是一个工程上的结果。
那么VGG就是一个框架更加规整的神经网络了。它比AlexNet更深更大,在它的结构里,设计了更多的全连接层、更多的卷积层,并且将一部分的卷积层组合成块。
(1)VGG块
经典卷积神经网络的基本组成部分是下面的这个序列:
- 带填充以保持分辨率的卷积层;
- 非线性激活函数,如ReLU;
- 汇聚层,如最大汇聚层。
而一个VGG块与之类似,由一系列卷积层组成,后面再加上用于空间下采样的最大汇聚层。在最初的VGG论文中,作者使用了带有卷积核、填充为1(保持高度和宽度)的卷积层,和带有汇聚窗口、步幅为2(每个块后的分辨率减半)的最大汇聚层。在下面的代码中,我们定义了一个名为vgg_block
的函数来实现一个VGG块。
(2)VGG架构
它实际上替换了AlexNet中除了全连接层的那一部分,将其替换成了多个VGG块。不同次数的重复块得到不同的架构。VGG-16, VGG-19等
(二)代码实现
import torch
from torch import nn
from torchvision import transforms
import torchvision
from torch.utils import data
from d2l import torch as d2l
import numpy as np
import matplotlib.pyplot as plt
# 设计VGG块,多个卷积过后一个最大池化层
# 卷积过后的输入输出图片大小不变,通道有变化
# 经过最大池化后,宽高缩减一半
def vgg_block(num_convs, in_channels, out_channels):
layers = []
for _ in range(num_convs):
layers.append(nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1))
layers.append(nn.ReLU())
in_channels = out_channels
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
return nn.Sequential(*layers)
# VGG架构,VGG块(卷积层,outtput),经过五层VGG块过后,宽高为(7,7)
# 这个架构可以称为VGG-11,1+1+2*3+1+1+1 = 11
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
def vgg(conv_arch):
conv_blocks = []
in_channels = 1
for (num_convs, out_channels) in conv_arch:
conv_blocks.append(vgg_block(num_convs,in_channels,out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blocks,
nn.Flatten(),
# 全连接层部分
nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 10)
)
net = vgg(conv_arch)
# 观察每个层的输出情况
x = torch.randn(1,1,224,224)
for layer in net:
x = layer(x)
print(layer.__class__.__name__,"output shape:",x.shape)
# 这里我的电脑已经跑不动了,你要是阔以的话那你就跑原来的代码吧
# 这里我们对网络调整一下
small_conv_arch = ((1, 16), (1, 32), (2, 32), (2, 64), (2, 64))
net = vgg(small_conv_arch)
# 现在使用mnist数据集测试一下结果
def load_data_fashion_mnist(batch_size, resize=None):
"""下载或者加载Fashion-MNIST数据集"""
trans = [transforms.ToTensor()]
if resize:
# 需要把图片拉长,正常时不会这么做的
trans.insert(0, transforms.Resize(resize))
trans = transforms.Compose(trans) # 这是一步可以去掉的操作,这个就是把多个图像处理的步骤整合到一起
mnist_train = torchvision.datasets.FashionMNIST(
root="../data/",
train=True,
transform=trans,
download=False # 要是没下载过就选择true
)
mnist_test = torchvision.datasets.FashionMNIST(
root="../data/",
train=False,
transform=trans,
download=False # 要是没下载过就选择true
)
return (data.DataLoader(mnist_train,batch_size=batch_size,shuffle=True,num_workers=0),
data.DataLoader(mnist_test,batch_size=batch_size,shuffle=True,num_workers=0))
batch_size = 64
learning_rate = 0.01
epochs = 10
train_iter,test_iter = load_data_fashion_mnist(batch_size,resize=(224))
d2l.train_ch6(net,train_iter,test_iter,epochs,lr=learning_rate,device=d2l.try_gpu())
train acc 0.913, test acc 0.902
216.1
网友评论