动手学深度学习(PyTorch实现)(八)--AlexNet模型

1. AlexNet模型介绍

由于受到计算机性能的影响,虽然LeNet在图像分类中取得了较好的成绩,但是并没有引起很多的关注。 直到2012年,Alex等人提出的AlexNet网络在ImageNet大赛上以远超第二名的成绩夺冠,卷积神经网络乃至深度学习重新引起了广泛的关注。AlexNet首次证明了学习到的特征可以超越⼿⼯设计的特征,从而⼀举打破计算机视觉研究的前状

1.1 AlexNet的特点

AlexNet是在LeNet的基础上加深了网络的结构,学习更丰富更高维的图像特征。AlexNet的特点:

  • 更深的网络结构
  • 使用层叠的卷积层,即卷积层+卷积层+池化层来提取图像的特征
  • 使用Dropout抑制过拟合
  • 使用数据增强Data Augmentation抑制过拟合
  • 使用Relu替换之前的sigmoid的作为激活函数
  • 多GPU训练
1.2 AlexNet的结构

AlexNet的结构为:
在这里插入图片描述
上图是论文中的原图,比较复杂,不容易看清楚,下图是更清晰的结构图:
Image Name
网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。

  • 卷积层C1
    • 该层的处理流程是: 卷积–>ReLU–>池化–>归一化。
    • 卷积,输入是227×227,使用96个11×11×3的卷积核,得到的FeatureMap为55×55×96。
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中。
    • 池化,使用3×3步长为2的池化单元(重叠池化,步长小于池化单元的宽度),输出为27×27×96((55−3)/2+1=27)
    • 局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为27×27×96,输出分为两组,每组的大小为27×27×48
  • 卷积层C2
    • 该层的处理流程是:卷积–>ReLU–>池化–>归一化
    • 卷积,输入是2组27×27×48。使用2组,每组128个尺寸为5×5×48的卷积核,并作了边缘填充padding=2,卷积的步长为1. 则输出的FeatureMap为2组,每组的大小为27×27 times128. ((27+2∗2−5)/1+1=27)
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
    • 池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为(27−3)/2+1=13,输出为13×13×256
    • 局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为13×13×256,输出分为2组,每组的大小为13×13×128
  • 卷积层C3
    • 该层的处理流程是: 卷积–>ReLU
    • 卷积,输入是13×13×256,使用2组共384尺寸为3×3×256的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
  • 卷积层C4
    • 该层的处理流程是: 卷积–>ReLU
    • 该层和C3类似。
    • 卷积,输入是13×13×384,分为两组,每组为13×13×192.使用2组,每组192个尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384,分为两组,每组为13×13×192
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
  • 卷积层C5
    • 该层处理流程为:卷积–>ReLU–>池化
    • 卷积,输入为13×13×384,分为两组,每组为13×13×192。使用2组,每组为128尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13×256
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
    • 池化,池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为 (13−3)/2+1=6,即池化后的输出为6×6×256
  • 全连接层FC6
    • 该层的流程为:(卷积)全连接 -->ReLU -->Dropout
    • 卷积->全连接: 输入为6×6×256,该层有4096个卷积核,每个卷积核的大小为6×6×256。由于卷积核的尺寸刚好与待处理特征图(输入)的尺寸相同,即卷积核中的每个系数只与特征图(输入)尺寸的一个像素值相乘,一一对应,因此,该层被称为全连接层。由于卷积核与特征图的尺寸相同,卷积运算后只有一个值,因此,卷积后的像素层尺寸为4096×1×1,即有4096个神经元。
    • ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
    • Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
  • 全连接层FC7
    • 流程为:全连接–>ReLU–>Dropout
    • 全连接,输入为4096的向量
    • ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
    • Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
  • 输出层
    • 第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出1000个float型的值,这就是预测
1.3 AlexNet参数数量

卷积层的参数 = 卷积核的数量 * 卷积核 + 偏置

  • C1: 96个11×11×3的卷积核,96×11×11×3+96=34848
  • C2: 2组,每组128个5×5×48的卷积核,(128×5×5×48+128)×2=307456
  • C3: 384个3×3×256的卷积核,3×3×256×384+384=885120
  • C4: 2组,每组192个3×3×192的卷积核,(3×3×192×192+192)×2=663936
  • C5: 2组,每组128个3×3×192的卷积核,(3×3×192×128+128)×2=442624
  • FC6: 4096个6×6×256的卷积核,6×6×256×4096+4096=37752832
  • FC7: 4096∗4096+4096=16781312
  • output: 4096∗1000=4096000
    卷积层 C2,C4,C5中的卷积核只和位于同一GPU的上一层的FeatureMap相连。从上面可以看出,参数大多数集中在全连接层,在卷积层由于权值共享,权值参数较少。

2. AlexNet的PyTorch实现

2.1 导入相应的包
import time
import torch
from torch import nn, optim
import torchvision
import numpy as np
import sys
sys.path.append("/home/kesci/input/") 
import d2lzh1981 as d2l
import os
import torch.nn.functional as F
2.2 构建AlexNet网络
# 如果有GPU,开启GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()
        self.conv = nn.Sequential(
        	 # in_channels, out_channels, kernel_size, stride, padding
            nn.Conv2d(1, 96, 11, 4),
            nn.ReLU(),
            # kernel_size, stride
            nn.MaxPool2d(3, 2), 
            # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
            nn.Conv2d(96, 256, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(3, 2),
            # 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
            # 前两个卷积层后不使用池化层来减小输入的高和宽
            nn.Conv2d(256, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 256, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(3, 2)
        )
         # 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合
        self.fc = nn.Sequential(
            nn.Linear(256*5*5, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            #由于使用CPU镜像,精简网络,若为GPU镜像可添加该层
            #nn.Linear(4096, 4096),
            #nn.ReLU(),
            #nn.Dropout(0.5),

            # 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
            nn.Linear(4096, 10),
        )

    def forward(self, img):

        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output
# 新建AlexNet网络
net = AlexNet()
2.3 加载数据集
# 加载Fashion MNIST数据集
def load_data_fashion_mnist(batch_size, resize=None, root='/home/kesci/input/FashionMNIST2065'):
    """Download the fashion mnist dataset and then load into memory."""
    trans = []
    if resize:
        trans.append(torchvision.transforms.Resize(size=resize))
    trans.append(torchvision.transforms.ToTensor())
    
    transform = torchvision.transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)
    mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)

    train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=2)
    test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=2)

    return train_iter, test_iter

batch_size = 16
# 如出现“out of memory”的报错信息,可减小batch_size或resize
train_iter, test_iter = load_data_fashion_mnist(batch_size,224)
2.4 训练网络
lr, num_epochs = 0.001, 3
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
# .train_ch5()函数在LeNet模型中已经定义,不在重复定义
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)
发布了163 篇原创文章 · 获赞 188 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42580947/article/details/104397939
今日推荐