Bootstrap

深度学习:实现和训练VGG网络

目录

1. 引言        

2. 环境设置和数据加载

3. 定义VGG块

4. 定义VGG网络

5. 打印网络层的输出形状

6. 训练VGG-11

7. VGG-19网络

8. 学习率和动量设置

9. 文献中的相关补充

10. VGG-11和VGG-19的对比

11. 总结


1. 引言        

在本学习笔记中,我们将讨论如何实现和训练VGG网络,并进行VGG-11VGG-19两种结构的比较。我们将使用Fashion-MNIST数据集进行实验,并介绍相关代码和文献中的参数设置。VGG网络的设计灵感来源于其在ImageNet挑战赛中取得的优异成绩,本文参考了《Very Deep Convolutional Networks for Large-Scale Image Recognition》这篇文献中的内容。

2. 环境设置和数据加载

首先,我们设置工作目录并定义数据加载函数,用来避免Permission Error的常见问题。

import torch
from torch import nn
from d2l import torch as d2l
import os
import torchvision

data_dir = '自行修改'
os.makedirs(data_dir, exist_ok=True)

def load_data_fashion_mnist(batch_size, resize=None, root=data_dir):
    trans = [torchvision.transforms.ToTensor()]
    if resize:
        trans.insert(0, torchvision.transforms.Resize(resize))
    trans = torchvision.transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(
        root=root, train=True, transform=trans, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(
        root=root, train=False, transform=trans, download=True)
    return (torch.utils.data.DataLoader(mnist_train, batch_size, shuffle=True,
                                        num_workers=d2l.get_dataloader_workers()),
            torch.utils.data.DataLoader(mnist_test, batch_size, shuffle=False,
                                        num_workers=d2l.get_dataloader_workers()))

我们定义了load_data_fashion_mnist函数,用于加载并预处理Fashion-MNIST数据集。该函数返回训练和测试数据加载器。

3. 定义VGG块

VGG块由多个卷积层和一个最大池化层组成。以下函数定义了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)

4. 定义VGG网络

我们定义了两个版本的VGG网络,分别为VGG-11和VGG-19。下面是VGG11的定义:

# VGG-11
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
def vgg(conv_arch):
    conv_blks = []
    in_channels = 1
    for (num_convs, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *conv_blks, 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))

5. 打印网络层的输出形状

为了检查网络的正确性,我们构建一个输入样本并逐层打印输出形状:

net = vgg(conv_arch)

# 构建一个高度和宽度为224的单通道数据样本
X = torch.randn(size=(1, 1, 224, 224))
for blk in net:
    X = blk(X)
    print(blk.__class__.__name__, 'output shape:\t', X.shape)

6. 训练VGG-11

ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)

lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

运行结果:

loss 0.176, train acc 0.935, test acc 0.920

1191.0 examples/sec on cuda:0

7. VGG-19网络

根据文献《Very Deep Convolutional Networks for Large-Scale Image Recognition》的描述,VGG-19的架构如下:

# VGG-19
conv_arch = ((2, 64), (2, 128), (4, 256), (4, 512), (4, 512))
def vgg(conv_arch):
    conv_blks = []
    in_channels = 1
    for (num_convs, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *conv_blks, 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)

# 构建一个高度和宽度为224的单通道数据样本
X = torch.randn(size=(1, 1, 224, 224))
for blk in net:
    X = blk(X)
    print(blk.__class__.__name__, 'output shape:\t', X.shape)

# 训练模型
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)

lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

运行结果:

loss 0.216, train acc 0.921, test acc 0.914
580.6 examples/sec on cuda:0

8. 学习率和动量设置

根据文献描述,初始学习率设置为0.01,当验证集准确率不再提升时逐步减小,动量设置为0.9:

trainer = torch.optim.SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)

9. 文献中的相关补充

文献《Very Deep Convolutional Networks for Large-Scale Image Recognition》中提到,VGG网络通过增加网络的深度来提升模型的性能。文献中对VGG11和VGG19的描述如下:

  • VGG-11:包含8个卷积层和3个全连接层,总计11个可训练层。
  • VGG-19:包含16个卷积层和3个全连接层,总计19个可训练层。

文献中还提到,VGG网络的卷积层使用了小的3x3卷积核,这使得网络能够捕捉更多的细节信息。同时,网络中使用的最大池化层可以有效地减少特征图的尺寸,从而降低计算复杂度。

10. VGG-11和VGG-19的对比

  • 网络深度:VGG-19比VGG-11多了8个卷积层,使得VGG19的网络更深,能够提取更丰富的特征。
  • 参数量和计算复杂度:由于VGG-19的卷积层更多,参数量和计算复杂度也显著增加。训练VGG-19需要更多的计算资源和更长的训练时间。
  • 性能:通常情况下,VGG-19在大规模图像分类任务中的性能优于VGG-11,因为更深的网络能够提取更高级的特征。然而,过深的网络也可能带来过拟合的问题,需要通过正则化等手段加以缓解。

11. 总结

通过这次学习,我们了解了如何实现VGG11和VGG19网络,并设置合适的训练参数。文献中关于学习率、动量等参数的建议对模型的训练效果有重要影响。在实际应用中,我们可以根据具体需求调整这些参数,以达到最佳效果。同时,我们也认识到在选择网络深度时需要在性能和计算复杂度之间进行权衡。

;