说起ResNet必然要提起He大佬,这真是神一样的存在,这不,不久前又有新的突破RegNet,真是厉害啊。

ResNet开篇之作在此,后面又出了各种变形啥的,ResNeXt,inception-ResNet等等吧,He大佬推荐的tf版本代码在此。keras ResNet50的在此。

总体:

这个网络结构主要是解决加深网络而不能减小loss的问题,如图下:

网络越深越好吗?不是,加一层acc或者其他指标就好了??并不是,既然网络加深了,又难以训练,效果又不好,谁还用深的网络?He大佬的残差学习结构网络大体上比其他模型深,152层,8倍VGG,但复杂性不高,且以ImageNet 测试集3.57%error got first ILSVRC 2015分类任务,同时取得ImageNet 检测,定位,COCO数据集检测,分割的第一。

在keras构建模型中,大多数都是序列化堆叠一些层,但这样有效果吗?

网络结构:

一般定义底层映射H(x),然后堆叠非线性层拟合F(x):=H(x)-x,最初的映射则为F(x)+x,于是我们认为优化后者即F(x)+x,比无参考的前者H(x)更容易【这是直接翻译的,具体啥意思我还没转过来弯】下面就是这个的building block,即有名的identity mapping【恒等映射】

直接将x加过来既没有增加参数,也没有增加复杂度。仍旧可以采用SGD优化器就行反向传播。

对于每层堆叠都采用残差学习模块,正如上图所言,有两层,F=W2*theta(W1*x),theta是激活函数relu,为简化计,忽略偏置。

F+x就是直接相连,每个元素对应相加,然后再用relu激活。如果F和x的维度不同,可采用线性映射Ws,Ws也可为方阵,如下:

y=F+Ws*x,作者证实,这种简单的恒等映射对于处理图1问题是足够的,而且是经济的【划算】。残差结构也不是一成不变的,也可以是其他形式,比如下面:2层或3层都是可以的,或者更多层,但是只有一层【即y=W1*x+x】没有发现优势。

在卷积层和全连接层都是可用的。

下面看看keras版本的代码:其实我之前就看过了这个版本的代码了

1.恒等映射部分

def _shortcut(input, residual):"""Adds a shortcut between input and residual block and merges them with "sum""""# Expand channels of shortcut to match residual.# Stride appropriately to match residual (width, height)# Should be int if network architecture is correctly configured.input_shape = K.int_shape(input)residual_shape = K.int_shape(residual)stride_width = int(round(input_shape[ROW_AXIS] / residual_shape[ROW_AXIS]))stride_height = int(round(input_shape[COL_AXIS] / residual_shape[COL_AXIS]))equal_channels = input_shape[CHANNEL_AXIS] == residual_shape[CHANNEL_AXIS]shortcut = input# 1 X 1 conv if shape is different. Else identity.if stride_width > 1 or stride_height > 1 or not equal_channels:shortcut = Conv2D(filters=residual_shape[CHANNEL_AXIS],kernel_size=(1, 1),strides=(stride_width, stride_height),padding="valid",kernel_initializer="he_normal",kernel_regularizer=l2(0.0001))(input)return add([shortcut, residual])

如果不同width或height及channel,那么采用卷积使得结果相同,如果相同就是简单的相加(add)

下面验证一下不同时的情况:这里有个潜在的约束,就是residual是经过卷积后的,HW肯定比x要小(相同的情况则是上句的直接相加)至于是不是整数倍,这个不一定,因为上面的代码其实是固定了核的大小,如果不固定的话会更加灵活,那就要考虑余数与核大小的关系了。视input1为x,input2为residual。

>>> input1
<tf.Tensor 'input_4:0' shape=(?, 16, 32, 3) dtype=float32>
>>> input2
<tf.Tensor 'input_6:0' shape=(?, 5, 16, 3) dtype=float32>>>> _shortcut(input1,input2)
Traceback (most recent call last):File "<pyshell#54>", line 1, in <module>_shortcut(input1,input2)File "D:\python36\new\keras-resnet\resnet.py", line 92, in _shortcutreturn add([shortcut, residual])File "D:\python36\lib\site-packages\keras\layers\merge.py", line 555, in addreturn Add(**kwargs)(inputs)File "D:\python36\lib\site-packages\keras\engine\base_layer.py", line 425, in __call__self.build(unpack_singleton(input_shapes))File "D:\python36\lib\site-packages\keras\layers\merge.py", line 91, in buildshape)File "D:\python36\lib\site-packages\keras\layers\merge.py", line 61, in _compute_elemwise_op_output_shapestr(shape1) + ' ' + str(shape2))
ValueError: Operands could not be broadcast together with shapes (6, 16, 3) (5, 16, 3)

考虑卷积核大小可以改变,那么可以直接采用下面的卷积

>>> Conv2D(filters=3,kernel_size=(2,2),strides=(3,2))(input1)
<tf.Tensor 'conv2d_60/BiasAdd:0' shape=(?, 5, 16, 3) dtype=float32>>>> input1_=Conv2D(filters=3,kernel_size=(2,2),strides=(3,2))(input1)
>>> _shortcut(input1_,input2)
<tf.Tensor 'add_23/add:0' shape=(?, 5, 16, 3) dtype=float32>

2.关于残差模块,下面是bottleneck,也就是采用了3层卷积

def bottleneck(filters, init_strides=(1, 1), is_first_block_of_first_layer=False):"""Bottleneck architecture for > 34 layer resnet.Follows improved proposed scheme in http://arxiv.org/pdf/1603.05027v2.pdfReturns:A final conv layer of filters * 4"""def f(input):if is_first_block_of_first_layer:# don't repeat bn->relu since we just did bn->relu->maxpoolconv_1_1 = Conv2D(filters=filters, kernel_size=(1, 1),strides=init_strides,padding="same",kernel_initializer="he_normal",kernel_regularizer=l2(1e-4))(input)else:conv_1_1 = _bn_relu_conv(filters=filters, kernel_size=(1, 1),strides=init_strides)(input)conv_3_3 = _bn_relu_conv(filters=filters, kernel_size=(3, 3))(conv_1_1)residual = _bn_relu_conv(filters=filters * 4, kernel_size=(1, 1))(conv_3_3)return _shortcut(input, residual)return f

上面所指的第一层是

因为代码作者采用的是循环的操作,这个第一层就是开始循环的第一层。

he大佬的2层卷积即basic_block中,当维度不同时可以采用补零或者上面所提的投影【代码作者采用的是卷积,如下方框】

步长为2.至于为何为2,不是1,两个大佬都没说。

he大佬在卷积后激活前采用BN层,根据某个实践,没有用dropout,并没有解释或者对照试验。

下面的34层恰好就是repetition中的3463

resnet34=ResnetBuilder.build((299,299,3),20,basic_block, [3, 4, 6, 3])

3关于代码中细节

可能不同的tf版本运行结果报错,请直接修改数据格式,将判断是不是tf后台那里改了就好。

另外,随意增加循环层或者说resnet层数其实并不能提高acc或其他指标,可见我的具体实践。

最后的avg其实就gap

另外有相关问题可以加入QQ群讨论,不设微信群

QQ群:868373192

语音图像视频推荐深度-学习群

关于ResNet50的解读相关推荐

  1. Pytorch_DDC(深度网络自适应,以resnet50为例)代码解读

    最近跑了一下王晋东博士迁移学习简明手册上的深度网络自适应DDC(Deep Domain Confusion)的代码实现,在这里做一下笔记. 来源:Githup开源链接 总结代码的大体框架如下: 1.数 ...

  2. 【论文解读】无需额外数据、Tricks、架构调整,CMU开源首个将ResNet50精度提升至80%+新方法...

    作者|Happy 编辑丨极市平台 极市导读 该文是CMU的Zhiqiang Shen提出的一种提升标准ResNet50精度的方法,它应该是首个将ResNet50的Top1精度刷到80%+的(无需额外数 ...

  3. resnet50代码_十余行代码完成迁移学习,百度PaddleHub实战解读

    机器之心专栏 来源:百度 PaddlePaddle 迁移学习 (Transfer Learning) 是属于深度学习的一个子研究领域,该研究领域的目标在于利用数据.任务.或模型之间的相似性,将在旧领域 ...

  4. 论文解读:ResNet50

    resnet网络结构分析:https://zhuanlan.zhihu.com/p/79378841 resnet论文解读:https://frank909.blog.csdn.net/article ...

  5. resnet50原始网络,从头debug一次,源码解读

    FBI warning :pycharm直接复写代码 ctrl+d 本文目的不在于让你学会各种大小数据的变化,而在于体会resnet执行的流程,大白话解说,读不懂的见谅! 废话少说,直接上最重要的两个 ...

  6. 自监督学习(Self-Supervised Learning)多篇论文解读(上)

    自监督学习(Self-Supervised Learning)多篇论文解读(上) 前言 Supervised deep learning由于需要大量标注信息,同时之前大量的研究已经解决了许多问题.所以 ...

  7. CVPR2020论文解读:CNN合成的图片鉴别

    CVPR2020论文解读:CNN合成的图片鉴别 <CNN-generated images are surprisingly easy to spot- for now> 论文链接:htt ...

  8. CVPR2020 论文解读:少点目标检测

    CVPR2020 论文解读:具有注意RPN和多关系检测器的少点目标检测 Few-Shot Object Detection with Attention-RPN and Multi-Relation ...

  9. RepVGG:极简架构,SOTA性能,论文解读

    ** RepVGG:极简架构,SOTA性能,论文解读 ** 更新:RepVGG的更深版本达到了83.55%正确率!PyTorch代码和模型已经在GitHub上放出.DingXiaoH/RepVGG 2 ...

最新文章

  1. 网友抱怨:「苹果除了每年收我的钱,似乎什么都不想做」
  2. Excel常用英文字母快捷键:
  3. 【Mac】【环境变量】
  4. vba 您正和其他用户尝试修改同一条数据_专辑二 | Moodle学习之Moodle添加用户
  5. 剑指offer(21)从上往下打印二叉树
  6. LeetCode 98. 验证二叉搜索树 思考分析
  7. ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段...
  8. QPSQL driver not loaded
  9. CPU:别再拿我当搬砖工!
  10. Nginx04---编译安装
  11. Weak Pair (dfs+树状数组)
  12. 舒尔特表-遮罩层-计时排序点击 js
  13. python卸载清理注册表_使用Python操作注册表
  14. .Microsoft Visual Studio 2010 Service Pack 1
  15. Python(高级FTP作业)
  16. Python调用kafka构建完整实例分析与应用!
  17. 微带线 带状线 过孔的时延对比
  18. 如何制作自己的网站?
  19. 使用Python编写打字训练小程序升级版
  20. matlab 母小波,小波变换的定义.ppt

热门文章

  1. 嵌入式linux实验截图,嵌入式linux实验二.pdf
  2. 网络协议分析(第二版)期末复习资料一
  3. git如何在某个分支下创建分支
  4. 实验4-1-5 统计素数并求和 (20 分)
  5. TensorFlow实现CGAN
  6. mysql查询distinct_mysql中select distinct的用法
  7. python开发微信订阅号如何申请_基于Python的微信公众平台二次开发(Python常用框架、订阅号开发、公众号开发)...
  8. 领军服务外包 大连软件业加速对接资本市场
  9. 新型网络接入控制技术
  10. Python:开发语言简介