导读

ResNet在ILSVRC 2015竞赛中大放异彩,其核心模块residual block使得卷积网络模型深度提高一个数量级,到达上百、上千层。在今天cv领域我们也经常用到它或它的变种,paper《Deep Residual Learning for Image Recognition

论文中第一张图点出了论文要解决的问题:

左边是训练误差,右边是测试误差,可见将20层网络简单地加深到56层后,并没有带来精度的提升,反而会导致模型的退化。(这里不是过拟合,因为其训练误差也增大了)

那么为什么加深网络会带来退化问题呢?理论上来说,即使新增的网络层什么都没学到,保持恒等输出(所有的weight都设为1),那网络的精度也应该等于原有未加深时的水平,如果新增的网络层学习到了有用特征,那么加深过后的模型精度必然会大于未加深的原网络。

实际上,让新增的网络层在训练过程中每一层都通过了线性修正单元relu处理,而这样的处理方式必然带来特征的信息损失,让其保持什么都不学习的恒等状态,恰恰很困难,因此,简单的堆叠layer必然会带来退化问题。

ResNet解决思想:既然让新增的层保持恒等映射很困难,那就额外增添一条路(identity)来保持恒等,如下图所示,

解释一下这个图,这里假设原有网络结构的映射为H(X),输出为X,,这里又添加了两个layer,在网络中的映射称为F(x)。既然新增layer保持不了恒等性,那我们可以通过跳跃连接来直接跳过它们来保持恒等;这里的融合操作只是单纯的相加,新结构的输出为F(x) + x ,原来结构的输出为x,这一目了然,即使最坏的情况,新加的层不会使网络更优,也不会出现退化的情况,相反新加的层如果提取到了更有用的特征,则模型效果会变好,真正实现了网络的精度加深后 >= 加深前,我们只需要优化F(x),使其趋于0即可,而使得F(x)接近0是相对比较容易的(无论是从权重初始化的角度还是通过激活函数) 虽然新增的F(x)不容易保持恒等,但让其尽量靠近0,还是相对容易做到的,这种训练方式称为残差学习,这种结构块也称为Residual Block残差块。正是残差结构的出现,使得残差网络能很好的加深网络层数,同时解决退化问题。

网络结构

论文列出了VGG、未加残差连接与加残差连接的网络结构示意图(我这里截一部分网络结构图)

在上图中实线代表普通的残差连接,虚线表示需要变换张量形状的残差连接,对于通道数不一致的情况,作者给出两种方法:一是往多出来的通道数里填0;二是使用1x1的卷积,对于大小的减半,都使用步幅为2的操作来实现减半。

这是不同层数的ResNet架构,可以看到是由一些残差块堆叠而成,与AlexNet、VGG这些不同,使用了Average pool代替了全连接层,同时也没有使用droput操作,之后再连接一层1000个神经元的全连接层,最后再接上一个Softmax。。

下图中左侧图是18-layer、34-layer残差块的连接结构,右侧则是50、101、152的残差结构,为了减少运算复杂度,输入进来先降维,再升维,这样由于其输入输出维度不同,需要1x1卷积进行维度转换:

实验分析

实现细节

与AlexNet一致的数据处理有:像素归一化(减去每像素平均)、标准颜色增强、裁剪成 224x224;其他操作:随机缩放图像短边至 [256, 480] 中的均匀随机值、随机翻转

在测试中,采用标准的10-crop测试(对图像裁剪10次,把输入分别输入网络,取结果的平均值)为了得到最好的结果,采用VGG中的全卷积模式,在多个尺度平均分数。(图像尺寸最短边被重整为{224,256,384,480,640})。感觉是为了打比赛弄的操作,现在一般不用

激活函数前加入BN操作,参数初始化使用 He Initialization,使用SGD优化算法,mini-batch为256。学习率初始为0.1,当错误率下降遇到瓶颈时(曲线不再下降时)便降低10倍,我们使用权重衰减0.0001以及momentum设为0.9。不使用dropout(没有使用全连接)。

作者做了一些消融实验和对比实验,

不同深度的ResNet对比:

可以看见,随着网络层数的增加,精度提升,表明残差块结构对深层神经网络的退化现象有效。

我们看一个消融实验:

这个实验作者想比较当输入输出维度不一样时,哪种结构的残差连接效果更好,A: 使用0填充来增添维度 B:当有维度变换时,使用1x1的卷积,没有则用恒等连接 C: 全部使用1x1的卷积;作者认为,B相对A更好,是因为通道数变化时0填充的部分没有残差学习,C相对B更好,是因为参数更多了,但精度没有很多改变,因此使用的B。

论文总结

  1. 解决了随着网络结构的加深,模型出现退化的情况,利用残差结构让网络能够更深、收敛速度更快、优化更容易,同时参数相对之前的模型更少、复杂度更低;
  2. 网络结构在卷积层后没有连接几个全连接层,没有使用dropout,而是一个全局池化
  3. 激活层前使用BN

代码实现

手动搭建了ResNet18、ResNet34、ResNet50、ResNet101、ResNet152,并在和之前AlexNet、VGG同样的数据集上训练与测试,代码在github

论文日记三:ResNet的更多相关文章

  1. oracle入坑日记<三>用户详解(角色理解)

    1   用户是什么 1.1.权限管理是Oracle的精华,不同用户登录到同一数据库中,可能看到不同数量的表,拥有不同的权限.Oracle 的权限分为系统权限和数据对象权限,共一百多种.如果把Oracl ...

  2. [论文理解]关于ResNet的进一步理解

    [论文理解]关于ResNet的理解 这两天回忆起resnet,感觉残差结构还是不怎么理解(可能当时理解了,时间长了忘了吧),重新梳理一下两点,关于resnet结构的思考. 要解决什么问题 论文的一大贡 ...

  3. 【社交系统ThinkSNS+研发日记三】基于 Laravel Route 的 ThinkSNS+ Component

    [社交系统ThinkSNS+研发日记系列] 一.<ThinkSNS+ 基于 Laravel master 分支,从 1 到 0,再到 0.1> 二.<基于 Laravel 开发 Th ...

  4. 【LaTeX排版】LaTeX论文排版<三>

    A picture is worth a thousand words(一图胜千言).图在论文中的重要性不言而喻,本文主要讲解图的制作与插入. 1.图像的插入     图像可以分为两大类:位图和向量图 ...

  5. Python学习日记(三十八) Mysql数据库篇 六

    Mysql视图 假设执行100条SQL语句时,里面都存在一条相同的语句,那我们可以把这条语句单独拿出来变成一个'临时表',也就是视图可以用来查询. 创建视图: CREATE VIEW passtvie ...

  6. Python学习日记(三十六) Mysql数据库篇 四

    MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...

  7. Python学习日记(三十四) Mysql数据库篇 二

    外键(Foreign Key) 如果今天有一张表上面有很多职务的信息 我们可以通过使用外键的方式去将两张表产生关联 这样的好处能够节省空间,比方说你今天的职务名称很长,在一张表中就要重复的去写这个职务 ...

  8. Python学习日记(三十三) Mysql数据库篇 一

    背景 Mysql是一个关系型数据库,由瑞典Mysql AB开发,目前属于Oracle旗下的产品.Mysql是目前最流行的关系型数据库管理系统之一,在WEB方面,Mysql是最好的RDBMS(Relat ...

  9. Linux管理日记(三)

    23. 时间同步 同步时间可以使用 root 执行如下命令完成: rdate -s time.nist.gov 如果需要自动同步,可以采用crontab自动调度,每小时执行一次:  编辑 cronta ...

  10. Linux(Ubuntu)使用日记(三)------git安装使用

    1. 安装 首先,确认你的系统是否已安装git,可以通过git指令进行查看,如果没有,在命令行模式下输入sudo apt-get install git命令进行安装. 2.  配置 git confi ...

随机推荐

  1. ajax面试题总结

    转载请注明出处: 1.ajax异步和同步的区别 Ajax是一种基于JavaScript语言和XMLHttpRequest对象的异步数据传输技术,通过它可以使不用刷新整个页面的情况下,对页面进行部分更新 ...

  2. Flask 上下文是什么 ?

    哈喽大家好,我是咸鱼.今天我们来聊聊什么是 Flask 上下文   咸鱼在刚接触到这个概念的时候脑子里蹦出的第一个词是 CPU 上下文 今天咸鱼希望通过这篇文章,让大家能够对 Flask 上下文设计的 ...

  3. MapStruct实体映射转换

    1.MapStruct简介 MapStruct是一个代码生成器,它基于约定优于配置的方法,极大地简化了Java bean类型之间映射的实现.生成的映射代码使用简单的方法调用,快速.类型安全且易于理解. ...

  4. 笔记:C++学习之旅---面向对象程序的设计1

    笔记:C++学习之旅---面向对象程序的设计1 面向对象的主要特征 1.抽象 2.封装 3.继承 4.多态 抽象:将程序的每一部分都看作一个抽象的对象,即程序有一组抽象的对象组成的更复杂点,这些对象根 ...

  5. 【必知必会的MySQL知识】②使用MySQL

    目录 前言 启动MySQL服务 连接MySQL MySQL数据库基本命令 小结 前言 根据上一篇文章[必知必会的MySQL知识]①初探MySQL的内容,想必您对MySQL数据库有了一个整体的了解了,并 ...

  6. 【Dotnet 工具箱】DotNetCorePlugins- 动态加载和卸载 .NET 程序插件

    你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用! 1. DotNetCorePlugins- 动态加载和卸载 .NET 程序插件 DotNetCore ...

  7. 2022-04-17:给定一个数组arr,其中的值有可能正、负、0, 给定一个正数k。 返回累加和>=k的所有子数组中,最短的子数组长度。 来自字节跳动。力扣862。

    2022-04-17:给定一个数组arr,其中的值有可能正.负.0, 给定一个正数k. 返回累加和>=k的所有子数组中,最短的子数组长度. 来自字节跳动.力扣862. 答案2022-04-17: ...

  8. 2021-08-18:扰乱字符串。使用下面描述的算法可以扰乱字符串 s 得到字符串 t :1.如果字符串的长度为 1 ,算法停止。2.如果字符串的长度 > 1 ,执行下述步骤:在一个随机下标处将字符串

    2021-08-18:扰乱字符串.使用下面描述的算法可以扰乱字符串 s 得到字符串 t :1.如果字符串的长度为 1 ,算法停止.2.如果字符串的长度 > 1 ,执行下述步骤:在一个随机下标处将 ...

  9. 2021-10-12:验证回文串。给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。说明:本题中,我们将空字符串定义为有效的回文串 。输入: “A man, a plan

    2021-10-12:验证回文串.给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写.说明:本题中,我们将空字符串定义为有效的回文串 .输入: "A man, a ...

  10. 【Java】水果超市管理系统

    前言 说是个系统,看着像实训的产物,但实际上这是Java课程最后一个关于jdbc的大实验,yes,挺大的. 过程 看着视频里的一堆一堆的文件,逻辑混乱的讲解,我决定 我自己写这个系统 说干就干: 分析 ...