《动手学深度学习》第十八天---深度卷积神经网络(AlexNet)

(一)模型结构

Deep Learning里面大名鼎鼎的AlexNet基本的结构如下:
AlexNet包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
AlexNet中层的设计(网图):
在这里插入图片描述

(二)核心创新点和效果

查阅一些资料,了解了一下为什么AlexNet能够刷新Image Classification的几率。
首先是AlexNet 把sigmoid激活函数改成了简单的ReLU函数
①sigmoid函数求幂运算比较复杂,而ReLU函数运算很简单
在这里插入图片描述
在这里插入图片描述
②ReLU激活函数在不同的参数初始化方法下使模型更容易训练
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
如上图所示,当sigmoid激活函数输出极接近0或1时,这些区域的梯度几乎为0,从而造成反向传播无法继续更新部分模型参数;而ReLU激活函数在正区间的梯度恒为1。因此,若模型参数初始化不当,sigmoid函数可能在正区间得到几乎为0的梯度,从而令模型无法得到有效训练。

③ReLU比tanh的收敛速度更快

AlexNet采用**局部反应标准化(local response normalization)**实现相同位置的神经元之间的相互抑制。

其次AlexNet通过丢弃法来控制全连接层的模型复杂度。对于某一层神经元,通过定义的概率来随机删除一些神经元,同时保持输入层和输出层的神经元个数不变,然后按照神经网络的学习方法进行参数更新。同样缓解了过拟合。

AlexNet引入了数据增强(Data Augmentation),从而进一步扩大数据集来缓解过拟合。

  1. 方法1:生成平移图像和水平翻转图像。做法就是从256x256的图像中提取随机的224x224大小的块(以及它们的水平翻转),然后基于这些提取的块训练网络。softmax层对这十个块做出的预测取均值。
  2. 方法2:改变训练图像的RGB通道的强度。特别的,本文对整个ImageNet训练集的RGB像素值进行了PCA。对每一幅训练图像,本文加上多倍的主成分,倍数的值为相应的特征值乘以一个均值为0标准差为0.1的高斯函数产生的随机变量。

AlexNet采用重叠池化层(OverlappingPooling)。池化层步长为2,池化区域为3×3,这种重叠池化层不容易过拟合。

(三)简化的AlexNet代码实现:

(1)定义层

import d2lzh as d2l
from mxnet import gluon, init, nd
from mxnet.gluon import data as gdata, nn
import os   #  os模块主要处理操作系统相关的功能
import sys   #  sys模块主要处理系统相关的功能

net = nn.Sequential()
# 使用较大的11 x 11窗口来捕获物体。同时使用步幅4来较大幅度减小输出高和宽。这里使用的输出通
# 道数比LeNet中的也要大很多
net.add(nn.Conv2D(96, kernel_size=11, strides=4, activation='relu'),
        nn.MaxPool2D(pool_size=3, strides=2),
        # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
        nn.Conv2D(256, kernel_size=5, padding=2, activation='relu'),
        nn.MaxPool2D(pool_size=3, strides=2),
        # 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
        # 前两个卷积层后不使用池化层来减小输入的高和宽
        nn.Conv2D(384, kernel_size=3, padding=1, activation='relu'),
        nn.Conv2D(384, kernel_size=3, padding=1, activation='relu'),
        nn.Conv2D(256, kernel_size=3, padding=1, activation='relu'),
        nn.MaxPool2D(pool_size=3, strides=2),
        # 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合
        nn.Dense(4096, activation="relu"), nn.Dropout(0.5),
        nn.Dense(4096, activation="relu"), nn.Dropout(0.5),
        # 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
        nn.Dense(10))

(2)观察每一层的输出情况:

X = nd.random.uniform(shape=(1, 1, 227, 227))
net.initialize()
for layer in net:
    X = layer(X)
    print(layer.name, 'output shape:\t', X.shape)

在这里插入图片描述
结果和上面的层的设计结果类似。
我们仍然使用Fashion-MNIST数据集来演示AlexNet。

(3)定义下载数据集的函数

先来看一下预备知识:

class mxnet.gluon.data.vision.transforms.Resize(size, keep_ratio=False, interpolation=1)
将图像或一批图像按给定的大小调整大小。应该在mxnet.gluon.data.vision.transforms.to sensor之前应用。

class mxnet.gluon.data.vision.transforms.ToTensor()
将图像数组或一批图像数组转换为张量数组。
将[0,255]范围内的形状(h×w×c)的图像数组转换为[0,1]范围内的float32张量形状(c×h×w)数组。
如果是批处理输入,将[0,255]范围内的批处理图像形状数组(n×h×w×c)转换为float32张量形状数组(n×c×h×w)。

在这里插入图片描述

class mxnet.gluon.data.vision.transforms.Compose(transforms)
依次组成多个变换。

在这里插入图片描述 在实践中,数据读取经常是训练的性能瓶颈,特别当模型较简单或者计算硬件性能较高时。Gluon的DataLoader中一个很方便的功能是允许使用多进程来加速数据读取(暂不支持Windows操作系统)。这里我们通过参数num_workers来设置4个进程读取数据。

现在来看一下我们定义的load_data_fashion_mnist()函数:

# 本函数已保存在d2lzh包中方便以后使用
def load_data_fashion_mnist(batch_size, resize=None, root=os.path.join(
        '~', '.mxnet', 'datasets', 'fashion-mnist')):
 #利用os.path.join(path,name):连接目录与文件名或目录,结果为path/name
    root = os.path.expanduser(root)  # 把path中包含的“~”和“~user”转换成用户目录
    transformer = []
    if resize:
        transformer += [gdata.vision.transforms.Resize(resize)]
        #  利用Resize函数改变形状
    transformer += [gdata.vision.transforms.ToTensor()]
    #  利用ToTensor函数变成张量
    transformer = gdata.vision.transforms.Compose(transformer)
    #  利用Compose函数把步骤结合起来
    mnist_train = gdata.vision.FashionMNIST(root=root, train=True)
    #从root下载数据集,通过train参数决定是训练还是测试数据集
    mnist_test = gdata.vision.FashionMNIST(root=root, train=False)
    num_workers = 0 if sys.platform.startswith('win32') else 4
    #  sys.paltform各个平台的返回值,windows返回的值为win32
    #  0表示不用额外的进程来加速读取数据
    train_iter = gdata.DataLoader(
        mnist_train.transform_first(transformer), batch_size, shuffle=True,
        num_workers=num_workers)
    test_iter = gdata.DataLoader(
        mnist_test.transform_first(transformer), batch_size, shuffle=False,
        num_workers=num_workers)
    return train_iter, test_iter

(四)训练数据

    batch_size = 128
    # 如出现“out of memory”的报错信息,可减小batch_size或resize
    train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=227)
    lr, num_epochs, ctx = 0.01, 5, d2l.try_gpu()
    net.initialize(force_reinit=True, ctx=ctx, init=init.Xavier())
    trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr})
    d2l.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs)

AlexNet跟LeNet结构类似,但使用了更多的卷积层和更大的参数空间来拟合大规模数据集ImageNet。它是浅层神经网络和深度神经网络的分界线。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值