2020.10.10 -2020.10.16

LeNet网络结构

1 LeNet全貌

LeNet-5是一个总共5层的卷积神经网络(一般输入层不计,两个卷积层 + 两个全连接层 + 输出层)。

2 超参数与计算量(FLOPs)

2.1 卷积层

对于卷积层,它的超参数就是对应kernel的值和偏置项。对于c1卷积层,输入为32x32x1,这里的1指的是输入的channel,记为C_in,输出为28x28x6,6是输出的channnel。kernel 为 5x5xC_in xc_out = 5x5x1x6。所以卷积的超参数量为:

    超参数:

                Para = (k_m * k_n * C_in + 1)* C_out = (5 * 5 *1+1)* 6 = 156

FLOPs(Floating Point of operations) 就是执行卷积操作的过程中的浮点数操作,非严格来说,就是乘法操作的次数。如果单看前向传播,对于输出的特征图中的每一个值,都对应了 k_m ∗ k_n ∗ C_i n  次乘法操作,所以总的 FLOPs 如下。其中 m,n是输出的特征图的 size。

FLOPs=k_m​∗k_n​∗C_in∗m∗n∗C_out =5∗5∗1∗28∗28∗6=117600

2.2 池化层

池化就是下采样(子抽样)过程,对图像进行子抽样,可以减少数据处理量同时保留有用信息。这里采用的是最大池化。对于最大池化操作来说,没有超参数。

2.3 全连接层

C5这层卷积层比较特殊,因为S4输出的featuremap的size为 5 ∗ 5, 正好和卷积的kernel size相等,因此卷积结果的size 1 ∗ 1, 所以这里实质上是一个全连接层。因为 kernal size 的 channel 是120, 因此输出为 120 ∗ 1 ∗ 1。

超参数:

               (5∗5∗16+1)∗120=48120

FLOPs:

                120∗1∗1*5∗5∗16=48000

3 总结

LeNet-5 是一个5层卷积神经网络,总共有约6万(60790)个超参数。随着网络越来越深,图像的高度和宽度在缩小,与此同时,图像的 channel 数量一直在增加。

4 LeNet 网络实现mnist

4.1 导入数据库

import argparse:使得我们能够手动输入命令行参数,就是让风格变得和Linux命令行差不多

argparse是python的一个包,用来解析输入的参数。

4.2 判断是否使用GPU

4.3 搭建网络

首先进行网络初始化,输入图像尺寸28*28*1,通过6个5*5的卷积核,步长stride=1进行卷积,并进行padding填充,保证输入输出尺寸相同。然后通过2*2的核,步长为2进行池化,得到14*14*6输出。

进入第二层卷积层,输入通道6(保证输入输出通道数相同),通过16个5*5的卷积核,得到输出为10*10*16,经过池化层。得到5*5*16的输出

然后进入两层全连接层,最后得到输出层。

定义全向传播过程,输入为x。

python mnist.py --outf model

    (意思是将训练的模型保存到model文件夹下,当然,你也可以不加参数,那样的话代码最后一行torch.save()就需要注释掉了)

python mnist.py --net model/net_008.pth

    (意思是加载之前训练好的网络模型,前提是训练使用的网络和测试使用的网络是同一个网络模型,保证权重参数矩阵相等)


设置超参数,定义数据预处理方式

定义损失函数loss function 和优化方式(采用SGD,误差梯度下降算法)

4.4 进入训练网络

首先,先对epoch里面所有的数据进行迭代,将输入和标签送人GPU中进行读取。然后将输入通入网络后,将输出经过交叉熵函数后,进行误差梯度下降,然后进行优化,最后将误差累计。然后没100个进行打印。

每跑完一轮epoch测试一下准确率,然后在测试集里面的数据迭代,然后经过网络输出,将得分最高的那个类取出来,将总共标签叠加,正确的预测叠加,然后求出正确率,最后输出。

5 实验结果

AlexNet 网络结构

它是一个8层的网络结构,5层卷积层和3层卷积层(这里不包括池化层和LRN(局部响应归一化))

注:局部响应归一化(LRN),对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力

conv1:

图像初始的输入是224*224*3(RGB图像),经过预处理之后变成了227*227*3。所以实际上conv1层的输入为227*227*3。

这个图像被11*11*3(3表示RGB三个通道)的卷积核进行卷积计算

(【input_size - kernel_size + 2*padding】/ stride + 1 = output_size)即227-11+0/4+1=55。所以输出特征图大小为55*55*96(用了96个卷积核分成两组,每组48个卷积核)——因为图中用双GPU进行计算,所以将数据分成了两组,所以深度48*2=96。这些像素层经过激活函数ReLU,生成激活像素层,尺寸保持不变

重叠pool池化层:经过池化运算,用3*3的卷积核,步长为2,进行池化。55-3+0/2+1=27。所以经过池化后的规格为27*27*96。

卷积层参数=卷积核大小x卷积核数量+偏置数量(卷积核的数量)=11x11x3x96+96=34848

conv2:

第二层输入数据为第一层输出的27x27x96的像素层,为便于后续处理,每幅像素层的左右两边和上下两边都要填充2个像素;27x27x96的像素数据分成27x27x48的两组像素数据,两组数据分别再两个不同的GPU中进行运算。每组像素数据被5548的卷积核进行卷积运算,共有256个5x5x48卷积核。卷积核沿原始图像的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,卷积核在移动的过程中会生成(27-5+2x2)/1+1=27个像素。即会生成27x27x256个卷积后的像素层。

conv3:

第三层输入数据为第二层输出的2组13x13x128的像素层;为便于后续处理,每幅像素层的左右两边和上下两边都要填充1个像素;2组像素层数据都被送至2个不同的GPU中进行运算。每个GPU中都有192个卷积核,每个卷积核的尺寸是3x3x256。因此,每个GPU中的卷积核都能对2组13x13x128的像素层的所有数据进行卷积运算。

conv4:

第四层输入数据为第三层输出的2组13x13x192的像素层;为便于后续处理,每幅像素层的左右两边和上下两边都要填充1个像素;2组像素层数据都被送至2个不同的GPU中进行运算。每个GPU中都有192个卷积核,每个卷积核的尺寸是3x3x192。因此,每个GPU中的卷积核能对1组13x13x192的像素层的数据进行卷积运算。卷积核对每组数据的每次卷积都生成一个新的像素。卷积核沿像素层数据的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,运算后的卷积核的尺寸为(13-3+12)/1+1=13,2个GPU中共1313*384个卷积后的像素层

conv5:

FC6:

第六层输入数据的尺寸是6x6x256,采用6x6x256=9216尺寸的滤波器对第六层的输入数据进行卷积运算;每个6x6x256尺寸的滤波器对第六层的输入数据进行卷积运算生成一个运算结果,通过一个神经元输出这个运算结果;共有4096个6x6x256尺寸的滤波器对输入数据进行卷积运算,通过4096个神经元输出运算结果;

可以看到卷积神经网络的计算量其实主要集中在全连接层,这些层参数太多了,也最容易发生过拟合。DropOut通过训练时随机使得一部分结点失效,不贡献连接权重而减少过拟合风险。同时强迫这些神经元去学习互补的一些特征。因此最后通过dropout6运算后输出4096个本层的输出结果值。

FC7:

FC8:

AlexNet mnist

1 遇到的问题

实现结果

这里我在最开始找到代码的时候,他的产参数设置是:

最后的结果就是精度很低,只有71%左右。我觉得可能是epoch次数太多,导致过拟合,然后我又调整了epoch为5,精度更低,我发现不能一味的只调整epoch,还要顾及到学习率和batch_size的大小。batch size 太小会使训练速度很慢;太大会加快训练速度,但同时会导致内存占用过高,并有可能降低准确率。选择2的指数倍可能更好(因为计算机内存一般为 2 的指数倍,采用 2 进制编码)。所以32-256可能会更好,尤其是64和128。

但是结果仍然没有太好。我又重新更换了一个。

1 导入工具包


2 搭建网络

3 对图像进行旋转和变换

transforms.RandomHorizontalFlip(),依概率水平翻转

transforms.RandomGrayscale(),依概率转化为灰度图

transforms.ToTensor()转换为tensor格式,这个格式可以直接输入进神经网络了。

4 进入训练

然后,将训练的数据下载文件夹中,然后开始下载数据,划分为训练集和测试集。采用封装好的AlexNet网络,加载到GPU中。用交叉熵函数降低误差,另外用SGD实现随机梯度下降。学习率设为0.001,动量为0.9

这里是对待训练的数据trainloader进行迭代,然后分别将输入和标签分别加载到GPU中。将输入的数据通过我们之前搭好的网络进行训练,之后通过loss=criterion(outputs, labels)计算损失,这里调用了之前的交叉熵函数。optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0。我们使用backward函数之前必须进行梯度清零,不然在pytorch会将上次计算的梯度和本次计算的梯度累加。这样逻辑的好处是,当我们的硬件限制不能使用更大的bachsize时,使用多次计算较小的bachsize的梯度平均值来代替,更方便,坏处当然是每次都要清零梯度。然后optimizer.step()用于更新学习率。

5 进入测试阶段

这是输出结果,经过了20次epoch的训练,用于测试集的测试的精确度达到了97。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353