【深度学习论文阅读】四大分类网络之AlexNet

ImageNet Classification with Deep Convolution Nerual Networks

论文原文:ImageNet Classification with Deep Convolutional Neural Networks

1 引言

解决的问题:

        提高效率(GPU训练),防止过拟合(dropout)

关键点:

        · 大量带标签数据——ImageNet

        · 高性能计算资源——GPU(GPU搭配了高度优化的2D卷积实现,强大到足够促进有趣大量CNN的训练)

        · 合理算法模型——CNN深度卷积网络(与具有层次大小相似的标准前馈神经网络相比,CNNs有更少的连接和参数,因此它们更容易训练,而它们理论上的最佳性能可能仅比标准前馈神经网络稍微差一点)

创新点:

        · 采用ReLu加快大型神经网络训练

        · 采用LRN

        · 采用Overlapping Pooling提升指标

        · 采用随机裁剪翻转及色彩扰动增加数据多样性

        · 采用Dropout减轻过拟合

2 数据集

ImageNet 包含各种分辨率的图像,而我们的系统要求固定的输入维度。

预处理:将图像进行下采样到固定的256×256分辨率。

1)给定一个矩形图像,首先缩放图像短边长度为256;

2)然后从结果图像中裁剪中心的256×256大小的图像块。

除了在训练集上对像素减去平均活跃度外,我们不对图像做任何其它的预处理。因此我们在原始的RGB像素值(中心化的)上训练我们的网络。

3 The Architecture 网络结构

AlexNet的网络结构如图所示。它总共包含八层可学习的层——五层卷积层和三层全连接层。

3.1 ReLU Nonlinearity ReLU非线性激活函数

对模型神经元输出的标准激活函数: f(x)=tanh(x) 或者 f(x)=(1+e^{-x})^{-1} 。

整流线性单元(ReLUs):在训练阶段使用梯度下降算法,在训练期间,这种饱和非线性函数的速度显著慢于非饱和非线性函数 f(x)=max(0,x) 。

ReLU优点:使网络训练更快;防止梯度消失(弥散),使网络具有稀疏性。

结果:用ReLUs训练的卷积神经网络比用tanh训练的网络几倍。在与传统饱和神经元模型做对比时,我们不需要用大型神经网络来做该实验。

3.2 Training on Multiple GPUs 多张GPU训练

优点:

1)当前的GPUs能够有效的跨GPU并行——精确的控制交互的数量从而达到可接收的总计算量

2)能够互相直接读取彼此的内存,还不用增加即时内存——将神经元在每张GPU上放一半

并行机制的限制:GPUs的通信只限于特定的层。例如,第三层可以得到第二层的所有神经元输出。可是第四层就只能得到位于同一GPU的第三层的输出。

3.3 Local Response Normalization 局部响应归一化

ReLUs优势:不需要输入的归一化来避免饱和。如果一些训练样本给予ReLU正向刺激输入,在该神经元就能进行有效学习

LRN能够避免泛化:定义 a_{x,y}^{i} 为核i 在位置 (x,y) 的神经元,然后使用ReLU非线性激活函数,对应的局部响应归一值 b_{x,y}^{i} 的表达式展示如下:

b_{x,y}^{i} = a_{x,y}^{i}/(k+\alpha\sum_{j=max(0,i-n/2)}^{min(N-1,i+n/2)} ( a_{x,y}^{i})^{2})^{\beta }

其中,k\alpha, n, \beta 都为常数,a为特征图中i对应像素具体值,i为通道channel

侧向抑制:lateral inhibition

3.4 Overlapping Pooling 重叠池化

CNN中的池化层只是将同一内核映射层的相邻单元进行了池化。按传统方式,相邻的池化单元是不重叠的。

重叠池化机制分别降低了错误率top-1 0.4个点以及错误率top-5 0.3个点。我们同样发现用重叠池化训练的模型能够有效缓解过拟合。

 

3.5 Overall Architecture 整体架构

        网络总共包含8层及其权重,刚开始五层是卷积层,后三层是全连接层。最后一个全连接层的输出为1000大小的softmax,包含1000种类的分布。我们的网络最大化多项逻辑回归目标,这相当于最大化基于训练样例的预测分布下正确标签的对数概率的平均值。

        第2,4,5卷积层只与同一GPU的前一层输出相关。第三层卷积层与第二层的所有输出相关。全连接层中的神经元与前一层的所有神经元相连。局部响应归一化层在第一、二层卷积层。第五层卷积层包括3.4节中所讨论的最大池化层以及局部响应归一化层。ReLU非线性激活函数用于每一层卷积层和全连接层。
在这里插入图片描述

4 Reducing Overfitting 降低过拟合

4.1 Data Augmentation 数据增强

        用于图像数据集降低过拟合的最简单以及最常用的方式是用标签保留转换(label-preserving transformations)来增强数据集。

        我们使用两种直接的数据增强方式,只需要很少的计算量就可以从原数据集中产生新的转换图像,因此这种增强后的图像不需要保存在磁盘。

第一种方式:针对位置

训练阶段:

1)图片统一缩放至256x256

2)随机位置裁剪出224x224区域 ——(256-224)的平方

3)随机进行水平翻转 ——(256-224)的平方*2

测试阶段:

1)图片统一缩放至256x256

2)裁剪出5个224x224区域(左上角、右上角、左下角、右下角、中心)

3)均进行水平翻转,共得到10张224*224图片

第二种方式:

通过PCA方法修改RGB通道的像素值,实现颜色扰动,效果有限,将top-1错误率降低了1%。

4.2 Dropout

随机失活——weight = 0,无连接无权值,以这种方式"退出"的神经元不参与前向传播,也不参与反向传播。

训练&测试两个阶段的尺度发生变化,测试时,神经元输出值需*p。

效果:每次呈输入时,神经元都会得到不一样的架构,但所有这些架构都是权值共享的。这种技术减少了神经元复杂的协同适应,因为神经元不能依赖于特定其他神经元的存在。因此,这种方式能够使得神经元从不同随机子集合中学到更鲁棒的特征

前两层全连接层中使用dropout。没有dropout的加持,我们的网络面临着严重的过拟合问题。Droput使得需要两倍的迭代周期实现收敛。

5 启发点

(1)深度与宽度可决定网络能力

(2)更强大的GPU及更多数据可进一步提高模型性能

(3)图片缩放细节,对短边先缩放

(4)ReLU不需要对输入进行标准化来防止饱和现象,即说明Siagmoid/tanh激活函数有必要对输入进行标准化

(5)卷积核学习到频率、方向和颜色特征

(6)相似图像具有“相近”的高级特征

(7)图像检索可基于高级特征,效果应该优于基于原始图像

(8)网络结构具有相关性,不可轻易移除某一层

(9)采用视频数据,可能有突破 

代码

1. 网络结构

import torch.nn as nn
import torch
class AlexNet(nn.Module): # 定义类def __init__(self, num_classes=1000, init_weights=False):    super(AlexNet, self).__init__()    # 继承self.features = nn.Sequential(# 特征提取# 卷积层:output_width=(input_width-kernel_size+2*padding)/stride+1# output_height=(input_height-kernel_size+2*padding)/stride+1  # 最大池化层:output_width=(input_width-pool_size)/stride+1# output_height=(input_height-pool_size)/stride+1 nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # 第一层卷积层input[3, 224, 224], output[48, 55, 55], 输入通道数, 输出通道数nn.ReLU(inplace=True),    # 激活函数nn.MaxPool2d(kernel_size=3, stride=2),                  # 第一层最大池化层output[48, 27, 27],输出通道数不变,只改变尺寸nn.Conv2d(48, 128, kernel_size=5, padding=2),           # 第二层卷积层output[128, 27, 27]nn.ReLU(inplace=True),# 激活函数nn.MaxPool2d(kernel_size=3, stride=2),                  # 第二层最大池化层output[48, 27, 27],输出通道数不变,只改变尺寸nn.Conv2d(128, 192, kernel_size=3, padding=1),          # 第三层卷积层output[192, 13, 13]nn.ReLU(inplace=True),# 激活函数nn.Conv2d(192, 192, kernel_size=3, padding=1),          # 第四层卷积层output[192, 13, 13]nn.ReLU(inplace=True),# 激活函数nn.Conv2d(192, 128, kernel_size=3, padding=1),          # 第五层卷积层output[128, 13, 13]nn.ReLU(inplace=True),# 激活函数nn.MaxPool2d(kernel_size=3, stride=2),                  # 第五层最大池化层output[128, 6, 6],输出通道数不变,只改变尺寸)self.classifier = nn.Sequential(# 分类器       nn.Dropout(p=0.5),# Dropout概率nn.Linear(128 * 6 * 6, 2048),# 第六层全连接层128*6*6进行平展nn.ReLU(inplace=True),# 激活函数  nn.Dropout(p=0.5),# Dropout概率nn.Linear(2048, 2048),# 第七层全连接层nn.ReLU(inplace=True),# 激活函数 nn.Linear(2048, num_classes),  # 第八层全连接层(num_classes为类的数量))if init_weights:self._initialize_weights()#初始化权重def forward(self, x):# 实现了网络的前向计算过程:输入图像经过特征提取部分后被平展成一维张量,最后通过分类器部分得到最终的分类结果x = self.features(x)# 特征提取x = torch.flatten(x, start_dim=1)#平展x = self.classifier(x)#分类器return xdef _initialize_weights(self):# 用于初始化模型的权重for m in self.modules():if isinstance(m, nn.Conv2d):# 对卷积层使用kaiming_normal_初始化方法nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')if m.bias is not None:nn.init.constant_(m.bias, 0)# 如果偏置不为None,则使用nn.init.constant_函数将偏置初始化为常数0if isinstance(m, nn.Linear):# 对全连接层使用normal_初始化方法nn.init.normal_(m.weight, 0, 0.01)nn.init.constant_(m.bias, 0)# 用nn.init.constant_函数将偏置初始化为常数0

2. 训练过程

# 若当前有可使用的GPU设备,就是用第一块GPU来进行训练,若没有则使用CPU训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("using {} device.".format(device))# 对数据进行预处理
data_transform = {# 当Key为train时"train": transforms.Compose([transforms.RandomResizedCrop(224),# 将图片随机裁剪成224×224像素大小transforms.RandomHorizontalFlip(),# 将图片在水平方向上随机翻转transforms.ToTensor(),# 转化成tensor类型transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),# 进行标准化处理# Key为val时"val": transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224,224)将图片缩放成224×224的transforms.ToTensor(),# 将图片转化成tensor类型transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}# 进行标准化处理# 读取训练集和测试集并且采用对应的图片处理方式
train_dataset = datasets.ImageFolder(root="flower_data/train",transform=data_transform["train"])
validate_dataset = datasets.ImageFolder(root="flower_data/val",transform=data_transform["val"])# {'daisy':0, 'dandelion':1, 'roses':2, 'sunflower':3, 'tulips':4}
flower_list = train_dataset.class_to_idx
cla_dict = dict((val, key) for key, val in flower_list.items())# write dict into json file
json_str = json.dumps(cla_dict, indent=4)
with open('class_indices.json', 'w') as json_file:json_file.write(json_str)# 训练相关参数设置
batch_size = 32
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size, shuffle=True,num_workers=0)
validate_loader = torch.utils.data.DataLoader(validate_dataset,batch_size=batch_size, shuffle=False,num_workers=0)
net = AlexNet(num_classes=5, init_weights=True)
net.to(device)
# 定义一个损失函数
loss_function = nn.CrossEntropyLoss()
# 定义一个优化器_Adam
optimizer = optim.Adam(net.parameters(), lr=0.0002)def train(dataloader,net,loss_function,optimizer):# 设定训练次数epochs = 10# 设置模型存储路径save_path = './AlexNet.pth'# 用来记录最优的正确率best_acc = 0.0# 一共有多少个batch(训练集数目 / batch_size),用于后面求平均损失train_steps = len(train_loader)# 开始迭代for epoch in range(epochs):# train# 启用Dropout方法net.train()# 记录每一次的损失,所以每次迭代都清0running_loss = 0.0# 生成一个迭代器train_bar = tqdm(train_loader, file=sys.stdout)# 通过enumerate获得迭代器的索引和值for step, data in enumerate(train_bar):# 将值赋给图像和标签images, labels = data# 每次迭代都清空梯度optimizer.zero_grad()# 将图像送入到网络训练(注意添加到设备)outputs = net(images.to(device))# 将输出值和实际值做对比,计算损失(注意labels也要添加到设备)loss = loss_function(outputs, labels.to(device))# 将损失反向传播loss.backward()# 通过优化器更新节点参数optimizer.step()# print statistics# 将每一次的损失累加,用于求平均损失running_loss += loss.item()# 输出进度train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,epochs,loss)# validate# 禁用Dropout方法net.eval()# 用来记录正确预测的个数acc = 0.0# 不需要计算梯度也不进行反向传播with torch.no_grad():# 生成一个迭代器val_bar = tqdm(validate_loader, file=sys.stdout)# 开始验证过程for val_data in val_bar:# 将值赋给图像和标签val_images, val_labels = val_data# 将图像送入到网络训练(注意添加到设备)outputs = net(val_images.to(device))# 在outputs的第1维找最大值;返回的第0维是最大值,第1维是最大值对应的标签;[1]将标签赋给predict_ypredict_y = torch.max(outputs, dim=1)[1]# 将预测值与实际值对比,相同返回1,否则返回0,求和可得正确的个数,通过item()获得其值acc += torch.eq(predict_y, val_labels.to(device)).sum().item()# 求预测正确率val_accurate = acc / val_num# 打印迭代次数,平均损失,预测正确率print('[epoch %d] train_loss: %.3f  val_accuracy: %.3f' %(epoch + 1, running_loss / train_steps, val_accurate))# 找到正确率最高的模型参数,存到目录if val_accurate > best_acc:best_acc = val_accuratetorch.save(net.state_dict(), save_path)

3. 预测过程

# 用GPU训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")# 图片预处理:缩放,转换成tensor,归一化
data_transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 获取图片路径
img_path = "sunflower1.png"
img = Image.open(img_path)# 显示图片
plt.imshow(img)# 对图片进行预处理,载入的图片是[H, W, C],经过预处理后会自动把深度提前[C, H, W]
img = data_transform(img)
# 要求的输入有四个维度,所以给图片加一个维度变为[N, C, H, W]
img = torch.unsqueeze(img, dim=0)# 获取记录类别名称的json文件
json_path = 'class_indices.json'
# 解码成我们需要的字典
with open(json_path, "r") as f:class_indict = json.load(f)# 初始化网络
model = AlexNet(num_classes=5).to(device)# 载入权重
weights_path = "AlexNet.pth"
# 利用torch.load加载权重并利用model.load_state_dict()函数把加载的权重复制到模型的权重中去
model.load_state_dict(torch.load(weights_path))# 禁用Dropout方法
model.eval()# 不需要计算梯度也不进行反向传播
with torch.no_grad():# predict class# 将图片送入网络,利用squeeze注意要将tensor转换到CPU,因为后面的numpy是CPU-onlyoutput = torch.squeeze(model(img.to(device))).cpu()# 利用softmax函数使输出满足概率分布predict = torch.softmax(output, dim=0)# 获取概率最大处所对应的索引值predict_cla = torch.argmax(predict).numpy()# 在记录类别名称的json文件中利用索引获取类别,并且利用索引获得类别对应的概率
print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],predict[predict_cla].numpy())
plt.title(print_res)
# 打印出该图片归于每一类的概率
for i in range(len(predict)):print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],predict[i].numpy()))
# 画图(包括图片展示和归于的最大可能类及其概率)
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java的考研教室在线预约系统/基于springboot的考研教室在线预约系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把考研教室在线预约与现在网络相结合,利用java语言建设考研教室在线预约系统,实现考研教室在线预约的信息化。则对于进一步提高考研教室在线预约发展,丰富考研教室在线预约能起到不少的促进…

语义分割混淆矩阵、 mIoU、mPA计算

一、操作 #vx:桔子code / juzicode.com import cv2 img_gray cv2.imread("nezha.jpg",cv2.IMREAD_GRAYSCALE) for i in range(22):dst cv2.applyColorMap(img_gray,i) cv2.imshow(map,dst) cv2.waitKey(500)cv2.imwrite("map-"str(i)".jpg",…

5G全网通工业三防平板Windows移动电脑

当今科技领域的快速发展为我们的生活带来了许多便利和高效性能。在这个数字化时代,移动设备已成为我们生活的重要组成部分。在这一领域,搭载全新第12代英特尔酷睿Mi5-1235U/i7-1255U处理器的工业三防平板Windows移动电脑无疑是一款引人注目的产品。 这款…

无法找到docker.sock

os环境:麒麟v10(申威) 问题描述: systemctl start docker 然后无法使用docker [rootnode2 ~]# systemctl restart docker [rootnode2 ~]# docker ps Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon r…

vue3使用下载附件功能

效果&#xff1a; 点击即可以下载打开。 代码&#xff1a; <div v-show"item.attachment.length > 0"><h3>下载附件</h3><divv-for"(doc, docIndex) in item.attachment":key"docIndex"><astyle"color: #41…

技术架构的演进-八大架构

目录&#xff1a; 常见概念评价指标单机架构应用数据分离架构应用服务集群架构读写分离 / 主从分离架构引入缓存 —— 冷热分离架构垂直分库业务拆分 —— 微服务容器化引入——容器编排架构总结 1.常见概念&#xff1a; 应用&#xff08;Application&#xff09; / 系统&am…

栈的压入、弹出序列

链接: 栈的压入、弹出序列 class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param pushV int整型vector * param popV int整型vector * return bool布尔型*/bool IsPopOrder(vector<int…

zeppelin的hive使用

zeppelin的hive使用 配置项 default.driver org.apache.hive.jdbc.HiveDriver default.url jdbc:hive2://192.168.xxx.xxx:10000 default.user hiveHive使用&#xff1a;点击create new note Default Interpreter选择hive

生命周期函数和wxs脚本

生命周期函数和wxs脚本 1. 生命周期函数1.1. 应用的生命周期函数1.2. 页面的生命周期函数 2. wxs脚本2.1. wxs与JavaScript的关系2.2. wxs内嵌脚本2.3. wxs外联脚本2.4. tips 1. 生命周期函数 1.1. 应用的生命周期函数 应用的生命周期函数&#xff1a;指小程序从启动 -> 运…

TCP编程流程和粘包

目录 1、TCP编程流程 2、粘包 1、TCP编程流程 socket() 是创建套接字&#xff0c;返回值为监听套接字描述符&#xff0c;有了套接字才能通过网络进行数据的传输。创建套接字的参数要指定服务类型&#xff0c;TCP协议使用的是流式服务&#xff08;SOCK_STREAM&#xff09;。 b…

数据库系统 - 家庭教育平台设计开发

目录 1.绪论 1.1项目背景 1.2家庭教育平台的发展现状与优势 1.2.1国内外发展现状 1.2.2家庭教育平台的优势 2.需求分析 2.1可行性分析 2.1.1经济可行性 2.1.2 技术可行性 2.1.3操作可行性 2.2系统功能 2.2.1 家庭教育资源 2.2.2 家庭教育指导师 2.2.3家庭教育咨询…

BUG解决Button类不能从UnityEngine.UI中引用

Button does not contain a definition for onClick and no accessible extension method onClick accepting a first argument of type Button could be found (are you missing a using directive or an assembly reference?) 一个非常奇葩的问题;突然!!!!! using UnityEn…

redis如何实现持久化

RDB快照 RDB是一种快照存储持久化方式&#xff0c;具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中&#xff0c;默认保存的文件名为dump.rdb&#xff0c;而在Redis服务器启动时&#xff0c;会重新加载dump.rdb文件的数据到内存当中恢复数据。 开启RDB持久化方式 开启…

AWS MSK集群认证和加密传输的属性与配置

通常&#xff0c;身份认证和加密传输是两项不相关的安全配置&#xff0c;在Kafka/MSK上&#xff0c;身份认证和加密传输是有一些耦合关系的&#xff0c;重点是&#xff1a;对于MSK来说&#xff0c;当启用IAM, SASL/SCRAM以及TLS三种认证方式时&#xff0c;TLS加密传输是必须的&…

Ubuntu开机自启动设置

一、创建执行脚本 这里有两个程序所以编写了两个脚本&#xff0c;第一脚本(master.sh)&#xff1a; gnome-terminal -- bash -c "source /home/zyy/anaconda3/bin/activate wood2;cd /home/zyy/pycharmProject/master_program;python main.py > /home/zyy/pycharmProj…

用于语义图像分割的弱监督和半监督学习:弱监督期望最大化方法

这时一篇2015年的论文&#xff0c;但是他却是最早提出在语义分割中使用弱监督和半监督的方法&#xff0c;SAM的火爆证明了弱监督和半监督的学习方法也可以用在分割上。 这篇论文只有图像级标签或边界框标签作为弱/半监督学习的输入。使用期望最大化(EM)方法&#xff0c;用于弱…

JavaScript--修改 HTML 元素

这些是一些用于修改 HTML 元素的常见方法&#xff1a; 1、document.createElement(element)&#xff1a;创建 HTML 元素节点。可以使用这个方法创建一个新的 HTML 元素&#xff0c; 例如 document.createElement(div) 将创建一个 <div> 元素节点。 2、document.createA…

elementUI 非表单格式的校验

在普通表单中对输入框、选择框都有校验案例。 但是在自定义非空中如何进行校验官网并没有说明 关键代码 clearValidate 方法清除校验 this.$refs.formValue.clearValidate(signinimg) 使用案例 <template><div class"stylebg"><Tabs icons"el-…

go mod 设置国内源 windows 环境 win10

启用 go module 功能 go env -w GO111MODULEon 配置 goproxy 变量 go env -w GOPROXYhttps://goproxy.cn,direct 下载包就行了&#xff0c;速度飞快 go mod tidy 检测 goproxy 是否配置好 运行 go env | findstr goproxy 查看 goproxy Go module 从 Go v1.12 版本开始存在&a…

flutter开发实战-底部bottomNavigationBar➕PageView

flutter开发实战-底部bottomNavigationBar tabbar在app中非常常见&#xff0c;底部BottomNavigationBar属性 一、BottomNavigationBar属性 BottomNavigationBar组件的常用属性&#xff1a; type&#xff1a;tabbar样式&#xff0c;默认为白色不显示&#xff1b;fixedColor:t…