2015年,何恺明等人提出了残差网络(ResNet),并在ImageNet图像识别挑战赛夺魁,深刻影响了后来的深度神经网络的设计。

残差块

残差块,残差网络中的重要组成部分。

WHY?

先前就可以看出,加深网络深度,在一定程度上可以提升模型性能。因此,有人对此进行实验研究,发现加深网络深度确实可以提高模型效果,但随着网络的加深,导致了网络退化问题逐渐严重;甚至层数太深的,比部分浅层网络效果更差。

退化问题,何恺明对此进行假设:是不是深层网络没有在进行学习,仅仅对浅层网络的特征进行复制?那么这些网络层做的就是恒等映射(Identity mapping)。于是何博提出了残差学习。

当输入x时,其学习到的特征标记为H(x),而我们希望其学习到的特征不完全等同于H(x),而是F(x),F(x) = H(X)-x;这样一来,网络学习到的特征便成为了F(x)+x。
为啥是加x?假设网络并未学到任何特征,那么向下一层传递的时候,可以将该层的输入当做下一层的输出,一定程度上避免了网络退化的问题,让下一层网络有特征可学。
“+x”操作,就是熟知的短路连接(shortcut connection)。

shortcut connection,有两种。第一种输入与输出相同,则在跳跃连接时,直接将输入相加;第二种输入与输出不同,则在跳跃连接时,需通过1x1卷积进行调整(1x1卷积作用之前有进行说明哦),再进行相加操作。

ResNet网络架构

ResNet网络主要是参考VGG19;共由4个残差块进行组成。

变化:

  1. 融入残差结构
  2. 使用步长为2的卷积做下采样(同时令feature map数量翻一倍)
  3. 采用global average pool层替换fc层

代码中需要注意的是,不谈跳跃连接,ResNet18、ResNet32的残差块是由两个3x3卷积组成,ResNet50、ResNet101、ResNet152则由 1x1卷积 + 3x3卷积 + 1x1卷积组成

以下展示ResNet50的网络架构:

ResNet((conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(layer1): Sequential((0): Bottleneck((conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential((0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): Bottleneck((conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(2): Bottleneck((conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential()))(layer2): Sequential((0): Bottleneck((conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential((0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): Bottleneck((conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(2): Bottleneck((conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(3): Bottleneck((conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential()))(layer3): Sequential((0): Bottleneck((conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential((0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): Bottleneck((conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(2): Bottleneck((conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(3): Bottleneck((conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(4): Bottleneck((conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(5): Bottleneck((conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential()))(layer4): Sequential((0): Bottleneck((conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential((0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): Bottleneck((conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential())(2): Bottleneck((conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(shortcut): Sequential()))(linear): Linear(in_features=2048, out_features=10, bias=True)
)

CNN-ResNet相关推荐

  1. 使用CNN/ResNet实现自动调制识别(RML2018.01a)

    本文基于RML2018.01a大型数据集,给出CNN及其变体ResNet的信号识别的实现方式(附代码) 相关内容: 深度学习框架 Tensorflow+Keras 模型 相关代码 CNN/ResNet ...

  2. NeurIPS 2021 | 视觉Transformer和CNN看到的特征是相同的吗?谷歌大脑新作

    本文转载自:DeepHub IMBA 作者:Akihiro FUJII 近年来,Vision Transformer (ViT) 势头强劲.本文将解释论文<Do Vision Transform ...

  3. 当CNN遇见Transformer!华为诺亚提出CMT:新视觉Backbone

    点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 转载自:AIWalker 标题&作者团队 CMT: Convolutional Neural Net ...

  4. 苹果公司提出Mobile-ViT | 更小更轻精度更高,MobileNets或成为历史

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨ChaucerG 来源丨集智书童 MobileviT是一个用于移动设备的轻量级通用可视化Tran ...

  5. densenet tensorflow 中文汉字手写识别

    densenet 中文汉字手写识别,代码如下: import tensorflow as tf import os import random import math import tensorflo ...

  6. 搜索推荐炼丹笔记:融合GNN、图谱、多模态的推荐

    作者:十方,公众号:炼丹笔记 说到推荐系统,就不得不面对数据稀疏和冷启动问题,怎么解决呢?美团这篇论文<Multi-Modal Knowledge Graphs for Recommender ...

  7. 深度学习-服务端训练+android客户端物体识别实战(caffe入门教程+mobilenet+ncnn+android)

    文章目录 背景 物体识别简介 自动驾驶 淘宝京东使用物体识别技术 公司业务需求 深度学习简介 深度学习的位置 深度学习概念 深度学习优势 深度学习基础知识 感知机 激活函数 多层感知机 卷积神经网络 ...

  8. 【ICLR2019】Poster 论文汇总

    ICLR2019 Poster 文章汇总, 共478 papers Convolutional Neural Networks on Non-uniform Geometrical Signals U ...

  9. 英伟达RTX 3080值不值得抢?在TensorFlow上训练了卷积网络

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:机器之心 AI博士笔记系列推荐 周志华<机器学习> ...

  10. pb 保存变量文件名_【Tensorflow 2.0 正式版教程】模型的保存、加载与迁移

    模型的保存和加载可以直接通过Model类的save_weights和load_weights实现.默认的保存格式为tensorflow的checkpoint格式,也可以手动设置保存为h5文件. mo ...

最新文章

  1. 如何最大限度提高.NET的性能
  2. 程序员的疯狂:打工与创业的残酷区别
  3. 买卖股票的最佳时机III
  4. Codeforces Round #358 (Div. 2) A. Alyona and Numbers 水题
  5. 线性结构 —— 前缀和
  6. Webhook入门教程:Webhook vs API 它们之间有什么区别?
  7. matlab 圆锥投影,基于MATLAB的等差分纬线多圆锥投影变换
  8. 【图像去噪】基于matlab GUI HSI彩色图像去噪【含Matlab源码 1786期】
  9. 利用模板导出文件(一)之XLSTransformer导出excel文件
  10. 创业挑战杯获奖作品范例_2017年挑战杯大学生创业大赛优秀作品
  11. 安装北京极通EWebs作为企业虚拟化平台突然出现应用程序无法访问的现象
  12. 当不知轴承型号时如何寻找轴承故障频率_电机轴承的故障诊断与失效分析
  13. java语言获取应用服务器的时间_java如何获得服务器时间
  14. AspNetPager 与分页存储过程详解
  15. 史上最全 Vue 前端代码风格指南
  16. UltraVNC 使用,内网局域网远程控制
  17. 程序员们一个一个的都挺神的,堪称 35 岁毕业之后再就业的标兵,不服不行
  18. 计算机入门模拟试卷c卷,《计算机入门》模拟卷C答案-华东师范大学.doc
  19. 25.(cesium之家)cesium军事标绘-攻击箭头采集(燕尾)
  20. STM32F10xxx20xxx21xxxL1xxxx Cortex-M3程序设计手册 阅读笔记二(5):Cortex-M3处理器能量管理

热门文章

  1. 嵌入式开发日记(6)——对串口数据读取的优化以及处理程序的改写
  2. 电脑快捷键横屏变竖屏_电脑屏幕横屏与竖屏之间怎么来回切换?
  3. 第八章:Java8新增特性,Lambda表达式
  4. 什么叫做云计算?云计算基础学习路线
  5. 智能开关如何实现双控
  6. 天猫欲攻手机市场 中华酷联倒戈 京东或将失势
  7. 【零基础玩转BLDC系列】基于霍尔传感器的无刷直流电机控制原理
  8. CTC算法论文阅读笔记:Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurren
  9. 《游戏系统设计六》一步一步实现王者荣耀等级系统
  10. tif怎么转化为jpg_tif怎么批量转换成jpg