resNet神经网络的学习

残差神经网络(ResNet)是由微软研究院的何恺明、张祥雨、任少卿、孙剑等人提出的。ResNet 在2015 年的ILSVRC(ImageNet Large Scale Visual Recognition Challenge)中取得了冠军。

这里我附上论文下载地址(谢谢这位好心的博主),感兴趣下来看看

http://openaccess.thecvf.com/content_cvpr_2016/papers/He_Deep_Residual_Learning_CVPR_2016_paper.pdf

         resent就是残差网络(Residual Networks,ResNet),它是一种很经典的CNN。由于概率论和数理统计没好好学(很重要一定要好好听)对于残差的概念比较模糊。先介绍一下三差的知识。

         残差指预测结果与真实值之间的差异而机器学习中噪声是真实标记与数据集中的实际标记间的偏差,二者的概念比较接近,在某种程度上也可以把残差理解成噪声,但是二者还是有本质区别,噪声是模型泛化能力不足,且不可预测。残差则是模型准确但与真实值仍然存在差异,这个可以计算。

   偏差(bias)偏差衡量了模型的预测值与实际值之间的偏离关系。通常在深度学习中,我们每一次训练迭代出来的新模型,都会拿训练数据进行预测,偏差就反应在预测值与实际值匹配度上。

         方差(variance)方差描述的是训练数据在不同迭代阶段的训练模型中,预测值的变化波动情况(或称之为离散情况)。从数学角度看,可以理解为每个预测值与预测均值差的平方和的再求平均数。

残差神经网络的本质是这样的:

f(x)=g(x)+x

f(x)是最终残差网络的输出,g(x)是残差网络中两次卷积的输出,x 是样本数据集。

残差神经网络的应用需求是什么————解梯度消失和梯度爆炸问题

目前优化神经网络的方法都是基于BP,即根据损失函数计算的误差通过梯度反向传播的方式,指导深度网络权值的更新优化。其中将误差从末层往前传递的过程需要链式法则(Chain 而链式法则是一个连乘的形式,所以当层数越深的时候,梯度将以指数形式传播。在根据损失函数计算的误差通过梯度反向传播的方式对深度网络权值进行更新时,得到的梯度值接近0或特别大,也就是梯度消失或爆炸。

梯度消失和梯度爆炸的原因

【梯度消失】经常出现,产生的原因有:

  • 是在深层网络
  • 二是采用了不合适的损失函数

【梯度爆炸】一般出现在深层网络权值初始化值太大的情况下。在深层神经网络或循环神经网络中,误差的梯度可在更新中累积相乘。如果网络层之间的梯度值大于 1.0,那么重复相乘会导致梯度呈指数级增长,梯度变的非常大,然后导致网络权重的大幅更新,并因此使网络变得不稳定。

以最简单的网络结构为例,加入有三个隐藏层,每层的神经元个数都是1,且对应的非线函数为 (其中为某个激活函数)如下图:

 

 

现在假设我们需要更新参数b1,那么我们就要求出损失函数对参数b1的导数,根据链式法则,可以写成下面这样:

而对于激活函数,之前一直使用Sigmoid函数,其函数图像成一个S型,如下所示,它会将正无穷到负无穷的数映射到0~1之间:

 

当我们对Sigmoid函数求导时,得到其结果如下:
 

由此可以得到它Sigmoid函数图像,呈现一个驼峰状(很像高斯函数),从求导结果可以看出,Sigmoid导数的取值范围在0~0.25之间,而我们初始化的网络权值|w|通常都小于1,因此,当层数增多时,小于0的值不断相乘,最后就导致梯度消失的情况出现。同理,梯度爆炸的问题也就很明显了,就是当权值|w|过大时,导致 最后大于1的值不断相乘,就会产生梯度爆炸。

Sigmoid函数求导图像

 

残差神经网络的架构

         首先是思考这么一个问题,假设有一个3层的神经网络和一个5层的神经网络,如果3层可以得到一个输出,那么5层的剩下两成啥也不干(恒等映射)也可以得到这个输出,那么5成的出差不会高于三层,可是实验的结果不是这样。在网络达到一定深度之后,便会出现训练结果变差,这就是网络退化,原因就是按照传统的方法我们没有办法找到一个很好的参数量表示恒等映射。

我们假设输入为X,进过几层堆积之后,得到学习特征为H(X),那么残差就是F(X)=H(X)-X;那么当残差为零时就能实现恒等映射,残差是不为零的,这样,我们在继承了原有特征的基础上又有了这一层变换得到的特征,因为类似电路短路因此叫短路连接。

在我看来就是把残差项补在下一层,防止衰退。以前的网络上一层一层的特征矩阵相乘,而残差矩阵变差了算残差项一层一层去加。因为通过一个短路连接使得梯度能够比较完整的传递到上一层,虽然有残差项,但是梯度比没有短路前更加完整,从而使得梯度的衰减进一步得到了抑制,这样使得从深层反向传播回来的梯度不至于消失,这也为增加更多层实现更深层的神经网络提供了可行性的保障。

 创新点:

短路连接,使得梯度消失得到了一定的改善

图像输入直接使用了步长为2进行下采样

使用全局平均池化代替了全连接层

当特征图大小发生倍数变化时,其个数也会发生相应的倍数变换,比如大小减半则数量会增倍,保证了网络结构的复杂度

 

resNet在设计上参考了VGG19,在设计上它给做成了这样

 

这是一个 34 层 ResNet 模型的架构图 

 

34 层 ResNet 模型架构图(此图来源于《TensorFlow 深度学习实战大全 》)

一个构建层可以包含一个或多个网络层、以及一个或多个构建块(如 ResNet 构建块)。

第一个构建层,由 1 个普通卷积层和最大池化层构建。

第二个构建层,由 3 个残差模块构成。

第三 、第四、第五构建层,都是由降采样残差模块开始,紧接着 3 个、5 个/2 个残差模块

ResNet 各个版本的网络架构如下所示:

 

ResNet的进一步改进

 在2015年的ILSVRC比赛获得第一之后,何恺明对残差网络进行了改进,主要是把ReLu给移动到了conv之前,相应的shortcut不在经过ReLu,相当于输入输出直连。并且论文中对ReLu,BN和卷积层的顺序做了实验,最后确定了改进后的残差网络基本构造模块,如下图8所示,因为对于每个单元,激活函数放在了仿射变换之前,所以论文叫做预激活残差单元(pre-activation residual unit)。作者推荐在短路连接(shortcut)采用恒等映射(identity mapping)。

那么所有的问题都可以归结为算残差,残差怎么算呢?

http://t.csdn.cn/74TVh

这篇博客写的很详细了。

我在在这篇论文里得到了些许灵感,我们做硬件仿真例如CPU的指令架构集改进时是不是可以用resent进行辅助呢,自动怎么做的可以给我留言,

论文如下:ResNet神经网络硬件加速器设计及验证研究 作者 龚英凡 指导老师 刘洋

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ResNet 是一种非常流行的深度卷积神经网络,可以用于图像分类、物体检测等任务。ResNet 的训练可视化可以帮助我们更好地理解模型的优化过程,以及如何进一步改进模型的性能。下面是一些使用 PyTorch 和 TensorBoard 可视化 ResNet 训练的示例代码: ```python import torch import torchvision import torchvision.transforms as transforms from torch.utils.tensorboard import SummaryWriter # 定义数据预处理 transform_train = transforms.Compose([ transforms.RandomCrop(32, padding=4), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载 CIFAR10 数据集 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2) # 加载 ResNet18 模型 net = torchvision.models.resnet18(pretrained=False, num_classes=10) # 定义损失函数和优化器 criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(net.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4) # 创建 TensorBoard SummaryWriter 对象 writer = SummaryWriter() # 训练循环 for epoch in range(200): running_loss = 0.0 for i, data in enumerate(trainloader, 0): # 获取输入数据和标签 inputs, labels = data # 将输入数据和标签转换为 GPU 上的 tensor inputs, labels = inputs.cuda(), labels.cuda() # 清除梯度 optimizer.zero_grad() # 前向传播 outputs = net(inputs) # 计算损失函数 loss = criterion(outputs, labels) # 反向传播 loss.backward() # 更新模型参数 optimizer.step() # 统计损失函数值 running_loss += loss.item() if i % 100 == 99: # 每 100 个 batch 输出一次损失函数值 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) # 将损失函数值写入 TensorBoard writer.add_scalar('training_loss', running_loss / 100, epoch * len(trainloader) + i) running_loss = 0.0 print('Finished Training') # 关闭 TensorBoard SummaryWriter 对象 writer.close() ``` 在上面的代码中,我们首先定义了数据预处理、加载 CIFAR10 数据集和 ResNet18 模型。接着,我们定义了损失函数和优化器,并创建了一个 TensorBoard SummaryWriter 对象。在训练循环中,我们依次读取每个 batch 的数据,将输入数据和标签转换为 GPU 上的 tensor,然后进行前向传播、计算损失函数、反向传播和更新模型参数等操作。在每 100 个 batch 计算一次平均损失函数值并输出到控制台,同时将损失函数值写入 TensorBoard 以便后续可视化分析。当训练结束后,我们关闭 TensorBoard SummaryWriter 对象。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding 潘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值