神经网络与深度学习——笔记3

一、AlexNet

1.AlexNet网络结构

ALexNet的网络结构如图1-1所示1,由5个卷积层和3个全连接层构成,其中激活函数为Relu:
ALexNet网络结构

图1-1 AlexNet网络结构

  1. 首先对 227 × 227 × 3 227 \times 227 \times 3 227×227×3的原始图像进行卷积,采用96个大小为 11 × 11 × 3 11 \times 11 \times 3 11×11×3的卷积核,步长为4,得到96个大小为55 × \times × 55的特征图。共有 ( 11 × 11 × 3 + 1 ) × 96 \left( {11 \times 11\times3 + 1} \right) \times 96 (11×11×3+1)×96个参数。
  2. 进行最大池化,窗口大小为3 × \times × 3,步长为2,得到96个大小为27 × \times × 27的特征图。
  3. 采用256个大小为 5 × 5 × 96 5 \times 5 \times 96 5×5×96的卷积核对池化后的图片进行卷积,且填充为2,步长为1,得到256个大小为27 × \times × 27的特征图。共有 ( 5 × 5 × 96 + 1 ) × 256 \left( {5 \times 5\times96 + 1} \right) \times 256 (5×5×96+1)×256个参数。
  4. 进行最大池化,窗口大小为3 × \times × 3,步长为2,得到256个大小为13 × \times × 13的特征图。
  5. 接着对池化后的图像进行连续三次的卷积,第一个卷积采用384个大小为 3 × 3 × 256 3 \times 3\times 256 3×3×256的卷积核,第二个卷积采用384个大小为 3 × 3 × 384 3 \times 3\times 384 3×3×384的卷积核,第三个卷积采用256个大小为 3 × 3 × 384 3 \times 3\times 384 3×3×384的卷积核,步长与填充均为1,最终得到256个大小为13 × 13的特征图。共有 ( 3 × 3 × 256 + 1 ) × 384 + ( 3 × 3 × 384 + 1 ) × 384 + ( 3 × 3 × 384 + 1 ) × 256 \left( {3 \times 3\times256 + 1} \right) \times 384+\left( {3 \times 3\times384 + 1} \right) \times 384+\left( {3 \times 3\times384 + 1} \right) \times 256 (3×3×256+1)×384+(3×3×384+1)×384+(3×3×384+1)×256个参数。
  6. 进行最大池化,窗口大小为3 × \times × 3,步长为2,得到256个大小为6 × \times × 6的特征图。
  7. 采用了4096个 6 × 6 × 256 6 \times 6\times 256 6×6×256的卷积核对池化后的图像进行卷积,因此得到特征图大小为 1 × 1 × 4096 1 \times 1 \times 4096 1×1×4096,构成了与前一层的全连接,具有4096个神经元输出(需进行Dropout)。共有 ( 6 × 6 × 256 + 1 ) × 4096 \left( {6 \times 6 \times 256{\rm{ + }}1} \right) \times 4096 (6×6×256+1)×4096 个连接数。
  8. 为具有4096个神经元输出的全连接层。共有 ( 4096 + 1 ) × 4096 (4096 +1)\times4096 (4096+1)×4096个参数。
  9. 为具有1000个神经元输出的全连接层。共有 ( 4096 + 1 ) × 1000 (4096 +1)\times1000 (4096+1)×1000个参数。

2.AlexNet程序实现

网络搭建如下,其中为了避免过拟合在每个全连接层后通过暂退法(Dropout)进行正则化。

import torch
from torch import nn
from d2l import torch as d2l

net = nn.Sequential(
    nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),
    nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),
    nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nn.Flatten(),
    nn.Linear(9216, 4096), nn.ReLU(),
    nn.Dropout(p=0.5),
    nn.Linear(4096, 4096), nn.ReLU(),
    nn.Dropout(p=0.5),
    nn.Linear(4096, 1000))

二、VGG

1.VGG网络结构

VGG网络的主要思想为有规律的反复堆叠3 × \times × 3的卷积和2 × \times × 2的最大池化。其中卷积的填充为1,步长为1,池化的步长为2,激活函数为Relu,每个VGG块的卷积使图像大小缩小一半同时输出通道数翻倍,直到通道数达到512。常用的VGG16网络结构如图2-1所示,采用了13个卷积层和3个全连接层。
VGG

图2-1 VGG网络结构

2.VGG程序实现

程序实现参考李沐《动手学深度学习》第二版7.2节。首先需要定义一个VGG块,传入的参数分别为卷积层的数目,输入输出的通道数,即第一个卷积核的大小为 3 × 3 × i n _ c h a n n e l s × o u t _ c h a n n e l s 3 \times 3 \times in\_channels \times out\_channels 3×3×in_channels×out_channels,第二个卷积核大小为 3 × 3 × o u t _ c h a n n e l s × o u t _ c h a n n e l s 3 \times 3 \times out\_channels \times out\_channels 3×3×out_channels×out_channels ⋯ \cdots n u m _ c o n v s num\_convs num_convs个卷积核大小为 3 × 3 × o u t _ c h a n n e l s × o u t _ c h a n n e l s 3 \times 3 \times out\_channels \times out\_channels 3×3×out_channels×out_channels,每个卷积后的激活函数为Relu,VGG块的最后一层为窗口大小为2 × \times × 2的最大池化层。

import torch
from torch import nn
from d2l import torch as d2l

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)

定义网络的卷积数和输出通道数,共有5个VGG块,每个块中的卷积数分别为2,2,3,3,3,输出通道数分别为64,128,256,512,512。

conv_arch = ((2, 64), (2, 128), (3, 256), (3, 512), (3, 512))

接着可以搭建VGG16网络

def vgg(conv_arch):
   #存放VGG块
    conv_blks = []
    in_channels = 3
    # 卷积层部分
    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, 1000))

net = vgg(conv_arch)

三、ResNet

1.ResNet网络结构

随着网络层数的加深会导致梯度消失,即使靠近数据端的网络参数在误差反传的过程中无法得到有效更新。为了解决这个问题,ResNet的思想是增加一条捷径,如图3-1所示,通过这条捷径可以使在误差反传中靠近数据端的网络参数得到有效更新,因此可以训练较深的神经网络。
Resnet

图3-1 ResNet网络局部结构

有时不可将 X X X F ( X ) F\left( X \right) F(X)直接相加,两者的通道数可能不同也可能图像大小不一致,捷径中需进行1 × \times × 1的卷积使 X X X的通道数与 F ( X ) F\left( X \right) F(X)的通道数保持一致。如图3-2所示,初始特征图大小为 56 × 56 × 64 56 \times 56\times 64 56×56×64,第一个卷积的特征图为 28 × 28 × 128 28 \times 28\times 128 28×28×128,第二个卷积的特征图为 28 × 28 × 128 28 \times 28\times 128 28×28×128与初始特征图大小和通道数均不同,所以“捷径”需要对初始特征图进行卷积,卷积核大小为 1 × 1 × 64 × 128 1 \times 1\times 64 \times 128 1×1×64×128,步长为2,得到卷积后的图像大小为 28 × 28 × 128 28 \times 28\times 128 28×28×128,可以进行相加。
1x1卷积

图3-2 旁路卷积的ResNet网络局部结构

实际的残差块结构如图3-3所示,采用的卷积核大小仍然为3 × \times × 3,填充为1;同时加入了批量归一化层,使得网络中每层输入数据的分布相对稳定,后一层网络不必不断去适应底层网络中输入的变化,从而实现了网络中层与层之间的解耦,允许每一层进行独立学习,有利于提高整个神经网络的学习速度。
残差块

图3-3 实际的残差块结构

2.ResNet程序实现

d2l包中的内置层Residual为残差块实现的层,我们可以直接实例化一个残差块的层, 共有四个参数,前两个参数分别为输入输出通道数input_channels,num_channels,第三个参数表示是否使用1 × \times × 1卷积(默认为False),第四个参数为第一个3 × \times × 3卷积和1 × \times × 1卷积的步长(默认为1),其中两个3 × \times × 3卷积的填充为1,1 × \times × 1卷积无填充。即第一个卷积核大小为 3 × 3 × i n p u t _ c h a n n e l s × n u m _ c h a n n e l s 3 \times 3\times input\_channels\times num\_channels 3×3×input_channels×num_channels,第二个卷积核大小为 3 × 3 × n u m _ c h a n n e l s × n u m _ c h a n n e l s 3 \times 3\times num\_channels\times num\_channels 3×3×num_channels×num_channels,旁路的卷积核大小为 1 × 1 × i n p u t _ c h a n n e l s × n u m _ c h a n n e l s 1 \times 1\times input\_channels\times num\_channels 1×1×input_channels×num_channels,结构类似图3-2中所示。

blk = Residual(64,128, use_1x1conv=True, strides=2)

将多个残差块组合成一个模块,对于非第一个模块需要将模块中的第一个残差块进行旁路卷积使旁路的输出通道数及图像大小与残差块中的3 × \times × 3卷积后的特征图一致(通道数均为num_channels),第二至第num_residuls个残差块不需要进行旁路卷积,输入输出通道数均为num_channels,图像大小也不变(p=1,s=1);对于第一个模块,模块中的残差块均不需要进行旁路卷积,且输入输出通道数均为num_channels,图像大小与残差块的输入一致(p=1,s=1)。

import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l

def resnet_block(input_channels, num_channels, num_residuals,
                 first_block=False):
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(input_channels, num_channels,
                                use_1x1conv=True, strides=2))
        else:
            blk.append(Residual(num_channels, num_channels))
    return blk

实例化多个模块构成ResNet网络

#每个残差模块中含两个残差块
#第一个残差模块输入输出通道数同,且输出的特征图大小与输入特征图大小一致
#其余残差模块会使图像大小减半,输出通道数翻倍
b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))

#b1为多个前置处理层
#在残差模块后接池化层和全连接层
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.BatchNorm2d(64), nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
net = nn.Sequential(b1, b2, b3, b4, b5,
                    nn.AdaptiveAvgPool2d((1,1)),
                    nn.Flatten(), nn.Linear(512, 10))                   

四、算法评价指标

1.基本概念

对于分类问题,例如算法实现的是两类的分类(属于第一类,不属于第一类)
T P TP TP:实际属于第一类且被划分为第一类
F P FP FP:实际不属于第一类但被划分为第一类
F N FN FN:实际属于第一类但被划分为不属于第一类
T N TN TN:实际不属于第一类且被划分为不属于第一类

2.相关指标计算

准确率: P = T P / ( T P + F P ) P=TP/(TP+FP) P=TP/(TP+FP)
召回率: R = T P / ( T P + F N ) R=TP/(TP+FN) R=TP/(TP+FN)
当调整阈值会改变准确率和召回率,准确率与召回率为此消彼长的关系,准确率越高,召回率越低。
平均准确率: A P = ∑ k = 1 N P ( k ) Δ r ( k ) AP = \sum\limits_{k = 1}^N {P(k)\Delta r(k)} AP=k=1NP(k)Δr(k),其中𝑁代表测试集中所有图片的个数,𝑃(𝑘)表示在能识别出𝑘个图片的时准确率的值, 而 Δ𝑟(𝑘)则表示识别图片个数从𝑘 − 1变化到𝑘时(通过调整阈值)召回率的变化情况。
均值平均准确率: m A P = 1 m ∑ i = 1 m ( A P ) i mAP = {1 \over m}\sum\limits_{i = 1}^m {{{(AP)}_i}} mAP=m1i=1m(AP)i,每个类的 A P AP AP均值。


  1. 由于参数过多,实际的AlexNet为双GPU进行训练,因此每层的输出通道数为总通道数一半 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值