戳一戳!和我一起走进深度学习的世界

导读

之前,我们学习了AlexNet的原理分析,今天我们一起来看一下AlexNet的具体实现。


今天要分享这篇文章带我们一起了解AlexNet的重要组成部分,AlexNet的具体实现,以及不同方式的输出



1 说在前面的话

1 说明

前面我们通过一篇文章,详细分析了AlexNet,今天要带领大家进行实战,实战之前,我们先来一起复习一下AlexNet的结构。


AlexNet的结构图如下:


【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_2d


网上还有很多自己绘制的图,这里,我们还是使用原作者的吧!


原论文中使用了双GPU,我们在这里只是为了让大家能够更好地掌握AlexNet,我们使用pytorch帮助我们实现AlexNet,并且,我们在实际情况中,我们只使用单CPU或GPU来实现。


想了解AlexNet的论文翻译,可以看下面的文章:



【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_卷积_02

​【DL论文翻译】AlexNet:ImageNet Classification with Deep CNN​

想了解AlexNet的原理分析,可以看下面的文章。



【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_全连接_03

​【卷积神经网络】03-1 AlexNet网络结构与原理分析​


想了解相关的其他文章,那就看下面的相关阅读吧!

2 相关阅读

卷积神经网络系列文章兜兜转转,也更新了一些了。大家可以从这里更快速阅读相关的文章。


【深度学习基础系列】

  一篇文章解决卷积运算中的尺寸问题

  盘天盘地盘“直男”,激活函数不简单


【卷积神经网络系列】

▶  01 卷积神经网络简介

▶  02 LeNet-5原理及代码详解

▶  03-1 AlexNet网络结构与原理分析


【相关论文】

▶  AlexNet:ImageNet Classification with Deep CNN

▶  Large Scale Distributed Deep Networks

▶  Cooperative Initialization based DNN Training


【目标检测系列】

▶  YOLO v1 论文笔记 01

▶  YOLO v1 论文笔记 02

▶  YOLO v4 论文翻译

▶  重磅!!!OpenCV4.4.0新鲜出炉!支持YOLO v4,SIFT免费使用

▶  ​​尝鲜!Windows下实现YOLOv4物体检测​

▶  Python+OpenCV4实现YOLO v4物体检测

▶  视频教程:基于OpenCV4.4的YOLO4实战教程


接下来,让我们一起走进今天的内容吧!

2 环境要求

在讲解代码之前呢,我们先说一下我这边的环境值与要求。

1 硬件与相关配置

我其实在三台电脑执行过我的程序,两台是使用GPU的,一台是没有GPU的。


针对GPU版本,要根据GPU来选择对应的CUDA。


如果你不是用GPU,那你可以跳过这一环节,如果你要使用GPU就要从这里好好看了。


我的笔记本是1050Ti显卡,CUDA使用的是10.2,有GPU的台式机的显卡是3070。


秀一下(显卡占了整机的一半价格):


【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_2d_04


2 Pytorch版本

如果你只是使用CPU版本的,pytorch完全可以在Anaconda环境中安装使用。


如果你是要使用GPU版本的,需要的就比较多了。具体的安装与配置可以查看如下教程:



【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_卷积_05

​无惧网络限制!一篇文章带你快速搞定GPU版的Pytorch安装与配置​


3 Python环境

我们使用Python来实现,所以我们需要一个好的Python环境,我的选择是PyCharm + Anaconda + Python3.7。


具体的安装教程如下:



【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_卷积_06

​Python基础 | 02 超详细Python安装教程(Win10+Anaconda+Pycharm)​


3 AlexNet 结构定义

前面我们回顾了ALexNet的结构,从这里,我们一起来实现一下。

1 调用包与简单配置

首先就是需要调用一系列的包:


# coding:utf-8
import time
import torch.nn as nn
import torch
from torchsummary import summary


其中,第一个time在我们今天的内容中没有用处,大家可以暂时注释掉,time包主要是后面做模型训练的时候,查看训练的时长用的。

中间两个是torch的相关包,主要是用来做模型定义和后续的模型训练等。


最后一个包是用来负责输出我们的模型,能够更好的看模型的输出的数据的大小。

2 结构定义

根据我们前面讲的AlexNet的结构,我们可以定义AlexNet的结构。


注意,最重要的是结构,只要我们掌握了结构,能够自己计算结构,实现其实是很简单的


在讲结构定义之前呢,我们先来看一下我们要用到的几个方法:


torch.nn.modules.container.Sequential:用来实现模型的简单连接
torch.nn.modules.conv.Conv2d:用来构建卷积层
torch.nn.modules.activation.ReLU:用来构建ReLU激活层
torch.nn.modules.pooling class MaxPool2d:用来构建最大池化
torch.nn.modules.linear.Linear:用来构建全连接层
torch.nn.modules.dropout:用来构建dropout


后续如果有必须,我专门写一篇文章来介绍上面这些方法,现在,还是让我们把重心放在AlexNet结构上吧!AlexNet的结构,主要分两大部分:


初始化定义:定义网络的结构
前向传播:实现网络的前向传播过程


前向传播主要是调用结构初始化定义的各个部分,所以,最重要的是初始化定义。


1、初始化定义


初始化定义中分三部分:


super(AlexNet, self).__init__()
特征提取层
全连接层


我们首先说一下第一部分,这一部分格式固定:


super(“网络名称”, self).__init__()


简单点说,就是定义网络结构,他会自动调用其上层结构(父结构),方便实现自身的初始化。


接下来是第二部分:特征提取层,包括卷积层、激活层和池化层


注意,因为我们前面说,图像先修改尺寸为227×227×3,所以我们输入图像就直接默认是227×227×3,具体的实战中,如果参与训练的图像是224×224×3,数据预处理会修改图像尺寸大小的。


为了方便大家写,我们先将所有的总结一下:


【特征提取层】
# 第一层卷积 [227, 227, 3] -> [27, 27, 96] K:11/4(0) P:3/2


# 第二层卷积 [27, 27, 96] -> [13, 13, 256] K:5/1(2) P:3/2


# 第三层卷积 [13, 13, 256] -> [13, 13, 384] K:3/1(1)


# 第四层卷积 [13, 13, 384] -> [13, 13, 384] K:3/1(1)


# 第五层卷积 [13, 13, 384] -> [6, 6, 256] K:3/1(1) P:3/2


其中:


[227, 227, 3] -> [27, 27, 96] 
表示尺寸为227×227,深度为3的特征图经过运算得到尺寸为27×27,深度为96的特征图.


K:5/1(2)
表示卷积核大小为(5×5),卷积步长为1,四个边缘有2像素的填充。


P:3/2
表示池化核大小为(3×3),池化步长为2。


根据总结,写特征提取层结构如下:


# 特征提取层
self.conv = nn.Sequential(
# 第一层卷积 [227, 227, 3] -> [27, 27, 96] K:11/4(0) P:3/2
nn.Conv2d(3, 96, 11, 4),
nn.ReLU(),
nn.MaxPool2d(3, 2),

# 第二层卷积 [27, 27, 96] -> [13, 13, 256] K:5/1(2) P:3/2
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),

# 第三层卷积 [13, 13, 256] -> [13, 13, 384] K:3/1(1)
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),

# 第四层卷积 [13, 13, 384] -> [13, 13, 384] K:3/1(1)
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),

# 第五层卷积 [13, 13, 384] -> [6, 6, 256] K:3/1(1) P:3/2
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)


接下来是第三部分,全连接层,全连接层很简单,我们直接写结构:


self.fc = nn.Sequential(
# 第一层全连接层
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(),
nn.Dropout(0.5),

# 第二层全连接层
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),

# 第三层全连接层(输出层)
nn.Linear(4096, 10)
)


对原理有疑惑的,请看原理的这篇文章。





【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_全连接_03

​【卷积神经网络】03-1 AlexNet网络结构与原理分析​


2、前向传播


接下来就是前向传播,前向传播过程就是利用权值计算分类的过程,而反向传播是权值更新的过程


前向传播就是调用上面定义的结构:


def forward(self, x):  # 前向传播
x = self.conv(x)
x = self.fc(x.view(x.shape[0], -1))
return x


最后,让我们一起来看一下整体的结构吧!


class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()

# 特征提取层
self.conv = nn.Sequential(
# 第一层卷积 [227, 227, 3] -> [27, 27, 96] K:11/4(0) P:3/2
nn.Conv2d(3, 96, 11, 4),
nn.ReLU(),
nn.MaxPool2d(3, 2),

# 第二层卷积 [27, 27, 96] -> [13, 13, 256] K:5/1(2) P:3/2
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),

# 第三层卷积 [13, 13, 256] -> [13, 13, 384] K:3/1(1)
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),

# 第四层卷积 [13, 13, 384] -> [13, 13, 384] K:3/1(1)
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),

# 第五层卷积 [13, 13, 384] -> [6, 6, 256] K:3/1(1) P:3/2
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)

self.fc = nn.Sequential(
# 第一层全连接层
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(),
nn.Dropout(0.5),

# 第二层全连接层
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),

# 第三层全连接层(输出层)
nn.Linear(4096, 10)
)

def forward(self, x): # 前向传播
x = self.conv(x)
x = self.fc(x.view(x.shape[0], -1))
return x


3 结构输出

定义好结构以后,我们就可以输出了,输出代码为:


if __name__=="__main__":
model=AlexNet()
print(model)
print(summary(model, (3, 227, 227), device='cpu'))


第一种输出方式,是直接输出所有的层结构,是对你上面定义的结构更加详细的参数介绍。


如果你也按照这种写法写程序,好处就是入门的人比较容易看明白,你也能更加清楚各个参数的含义。坏处就是代码看起来很繁琐


所以一般采取的策略是像我上面那样,简单定义结构,看着清晰,后面输出一下结构,检查是否出错。当然了,这个是我的习惯,只要你自己用着舒服就可以。


输出如下:


AlexNet(
(conv): Sequential(
(0): Conv2d(3, 96, kernel_size=(11, 11), stride=(4, 4))
(1): ReLU()
(2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(3): Conv2d(96, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(4): ReLU()
(5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Conv2d(256, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(7): ReLU()
(8): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): ReLU()
(10): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU()
(12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(fc): Sequential(
(0): Linear(in_features=9216, out_features=4096, bias=True)
(1): ReLU()
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU()
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=10, bias=True)
)
)


第二种输出方式,是将所有的运算参数输出。


第一种的方法只能看所有层结构,如果层的参数定义错误,是检查不出来的,但是对于第二种方式,如果你参数有错误,它没有办法计算到最后一步,就会报错,所以当我们自定义网络结构的时候经常需要使用第二种方式来检查自己的结构是否在运算过程中不会出错


第二种方式执行结果如下:


----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 96, 55, 55] 34,944
ReLU-2 [-1, 96, 55, 55] 0
MaxPool2d-3 [-1, 96, 27, 27] 0
Conv2d-4 [-1, 256, 27, 27] 614,656
ReLU-5 [-1, 256, 27, 27] 0
MaxPool2d-6 [-1, 256, 13, 13] 0
Conv2d-7 [-1, 384, 13, 13] 885,120
ReLU-8 [-1, 384, 13, 13] 0
Conv2d-9 [-1, 384, 13, 13] 1,327,488
ReLU-10 [-1, 384, 13, 13] 0
Conv2d-11 [-1, 256, 13, 13] 884,992
ReLU-12 [-1, 256, 13, 13] 0
MaxPool2d-13 [-1, 256, 6, 6] 0
Linear-14 [-1, 4096] 37,752,832
ReLU-15 [-1, 4096] 0
Dropout-16 [-1, 4096] 0
Linear-17 [-1, 4096] 16,781,312
ReLU-18 [-1, 4096] 0
Dropout-19 [-1, 4096] 0
Linear-20 [-1, 10] 40,970
================================================================
Total params: 58,322,314
Trainable params: 58,322,314
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.59
Forward/backward pass size (MB): 11.04
Params size (MB): 222.48
Estimated Total Size (MB): 234.11
----------------------------------------------------------------
None


4 敲黑板

AlexNet真正让深度学习走到舞台中央,至此以后,深度学习开始了蓬勃发展。


希望大家能够通过今天这篇文章,了解AlexNet的实现过程,也能通过AlexNet自己去搭建简单的网络。


后续,我们会继续讲解AlexNet的具体训练过程,感谢大家的支持!



AI与区块链技术

【卷积神经网络】03-2 小白也能学会的AlexNet网络搭建与输出_卷积_08

长按二维码关注