【十九周】文献阅读:图像识别的深度残差学习

目录

  • 摘要
  • Abstract
  • 图像识别的深度残差学习
  • 研究背景
  • 研究动机
  • 解决办法
    • Residual Learning
    • Shortcut Connections
    • 网络结构
  • 实验结果
  • 代码实践
  • 论文原文
  • 总结

摘要

在之前对神经网络的基础学习中,师兄推荐了我去了解一下 ResNet。因此本周对 ResNet 的开山之作—Deep Residual Learning for Image Recognition 进行了详细的阅读并进行了简单的代码实践。

Abstract

In the previous foundational learning of neural networks, my senior recommended that I look into ResNet. Therefore, this week I have read in detail the pioneering work of ResNet — Deep Residual Learning for Image Recognition — and conducted some simple code practices.


图像识别的深度残差学习

Title: Deep Residual Learning for Image Recognition
Author: He, KM (He, Kaiming); Zhang, XY (Zhang, Xiangyu); Ren, SQ (Ren, Shaoqing); Sun, J (Sun, Jian)
Source: 2016 IEEE CONFERENCE ON COMPUTER VISION AND PATTERN RECOGNITION (CVPR)
DOI: 10.1109/CVPR.2016.90


研究背景

深度卷积神经网络在图像识别方面取得了巨大的突破。CNN中不同深度的层可以捕捉到不同的特征,通过堆叠大量的层可以提高网络的性能。作者也认为网络深度至关重要,他提到了最近的很多成果都用到了非常深的网络结构。

Recent evidence [40, 43] reveals that network depth is of crucial importance, and the leading results [40, 43, 12, 16] on the challenging ImageNet dataset [35] all exploit “very deep” [40] models, with a depth of sixteen [40] to thirty [16]. Many other nontrivial visual recognition tasks [7, 11, 6, 32, 27] have also greatly benefited from very deep models.

研究动机

随着网络层数的加深,一个问题也显现出来了:神经网络越深性能一定越好吗?

答案显然不是,一昧地增加网络深度可能会导致梯度消失或者梯度爆炸,使得整个神经网络难以收敛。

然而,这并不是阻碍我们疯狂堆叠网络深度的唯一问题,作者也给出了目前解决这个问题的办法。

This problem, however, has been largely addressed by normalized initialization [23, 8, 36, 12] and intermediate normalization layers [16], which enable networks with tens of layers to start converging for stochastic gradient descent (SGD) with backpropagation [22].

解决梯度消失和梯度爆炸可以通过初始归一化中间归一化来解决,也就是说我们可以在初始化的时候做好一点,比如权重参数初始化的时候不要太大也不要太小,或者在中间加入归一化层。

即使解决了收敛问题,一个更大的问题暴露出来——网络退化

请添加图片描述

作者给出了这个图,通过该图我们可以看到,56层的网络无论是训练误差还是测试误差都比20层还高。从图中我们可知这并不是由于过拟合引起的。

正是这个吊诡的现象引起了作者的关注,作者也正是在对这个现象进行研究的过程中解决了网络退化的问题,从而发了这篇 paper。

接下来作者提出了一个解决方案:假设有一浅一深两个神经网络,深层网络前面的层直接复制浅层网络,而新加入的层为恒等映射,也就是说深层网络和浅层网络最后的输出是相同的。按照这个假设,那深层网络的精度就算不会变得更优也至少不会变差。
在这里插入图片描述

但是在实践中来看,让神经网络拟合一个恒等映射——也就是说让神经网络什么都不做,这是非常有挑战性的。

But experiments show that our current solvers on hand are unable to find solutions that are comparably good or better than the constructed solution (or unable to do so in feasible time).

有时候什么都不做就是最优解。

解决办法

Residual Learning

在这里插入图片描述
作者提出了这样一个结构,称之为残差块。首先将上一层的输出通过一个权重层然后激活,然后再通过一个权重层不激活,最后将结果于上一层的输出相加再进行一次激活。假设我们真实需要学习的函数是 H ( x ) H(x) H(x),由于最后输出的是 F ( X ) + x F(X)+x F(X)+x 的值,实际上在残差块的内部学习到的就是 H ( x ) − x H(x)-x H(x)x 的值,即预测值和真实值的残差。

在这种情况下,如果上一层输出的值已经是最佳了,那么机器就会将残差块拟合成一个恒等映射,也就是上文提到的“什么都不做”。对神经网络来说,将权重层中的训练权重拟合为0比直接去拟合一个恒等映射要简单,因此如果上一层输出的值已经是最佳,那么残差块中的各个权重就会趋向于0。

Shortcut Connections

采用了上图的残差块结构之后,我们可以把它的函数表达式写成这样:
y = F ( x , W i ) + x y=F(x,{W_i})+x y=F(x,Wi)+x
其中,x和y分别为这个块中输入和输出向量, F ( x , W i ) F(x,{W_i}) F(x,Wi)表示残差块中学习的函数。

在上图的结构中,函数F可以写成下式:
F = W 2 σ ( W 1 x ) F=W_2σ(W_1x) F=W2σ(W1x)
其中,σ代表激活函数 ReLU。

接下来作者提到,采用了跳连接之后神经网络既不会引入额外的参数也不会提高计算复杂度,这是采用跳连接的一个显著优点。

The shortcut connections in Eqn.(1) introduce neither ex- tra
parameter nor computation complexity.

由于跳连接采用了直接将x于F(x)相加的方法,所以我们必须保证x的维度和F(x)一致,函数表达式如下所示:
y = F ( x , W i ) + W s x y=F(x,{W_i})+W_sx y=F(x,Wi)+Wsx
其中, W s W_s Ws表示一个将 x 进行维度变换的投影矩阵。

作者在他的另一篇论文——Identity Mapping in Deep Residual Networks 给出了不同的恒等映射方法,在本文中他指出了恒等映射是有效且经济地解决网络退化问题的方法。

But we will show by experiments that the identity mapping is
sufficient for addressing the degradation problem and is economical

对于残差块的结构其实我们一直还有一个疑问——为什么残差块中要经过两层的权重层呢?作者在本段的最后一部分说明了这个问题。他解释道,残差块如果只有一层就会类似一个普通线性层,残差结构就不会再表现出来优势了。

网络结构

在这里插入图片描述
网络结构如上图所示,其中左边的是VGG-19的网络结构,中间的是不带残差的34层普通神经网络,右边是带残差的34层神经网络。

我们可以通过观察看到,残差网络中有许多跳连接使用虚线表示,这代表着输入输出维度不一致,因此我们在进行处理的时候需要对残差块的输入进行升维操作。

作者在此处给出了两个方案:

  • (A)用0去对残差块的输入x进行padding(填充)
  • (B)用1×1的卷积核对 x 进行升维

实验结果

在这里插入图片描述
图中细线代表训练误差,粗线代表测试误差。从左图可以看出34层的普通神经网络无论是训练误差还是测试误差都比18层的要高,可知网络退化问题并不是由于过拟合引起的。再观察右图加了残差之后的结果可以看到,34层的网络无论是训练误差还是测试误差都比18层的要低,由此可知作者解决了网络退化的问题。

作者在这个部分继续探讨了为什么会发生网络退化的现象,并且认为这个问题也不是由于梯度消失引起的。

在这里插入图片描述
作者在实现这个普通神经网络的时候采用了批量归一化技术(BN),这使得反向传播的梯度有着一个比较健康的范数,也就是说梯度不会极端地向0靠近。通过上图各个网络有着相似的错误率也可以验证梯度是可以正常的进行传播的。

随后作者推测,深层神经网络难以训练的原因有可能是因为其收敛速度以指数级的速度减小。

We conjecture that the deep plain nets may have exponentially low
convergence rates, which impact the reducing of the training error.

针对于这个问题,作者还在题注里说明,即使增加迭代次数也依然不能解决网络退化问题。

We have experimented with more training iterations (3×) and still ob-served the degradation problem, suggesting that this problem cannot be feasibly addressed by simply using more iterations.

在这里插入图片描述
通过上面的图表和之前的 Figure 4,作者观察到了三个重要的结论:

第一,34层的残差网络比18层的要好;
第二,残差学习可用来搭建比较深的网络;
第三,带残差的网络收敛速度更快。

在这里插入图片描述
在这段的后半部分,作者还给出一个新的残差模块结构。上图左边为普通的残差模块,右边称之为 bottleneck 残差模块。其中 1×1 的卷积就是为了将输入张量进行降维,这个原理和上一周学习 Inception 时的 1×1 卷积的作用是一样的。先降维再升维可以减少大量的计算量。

在这里插入图片描述
上图可以看到各种网络的误差变化,其中中间的突变是由于学习率改变而导致的。

We start with a learning rate of 0.1, divide it by 10 at 32k and 48k
iterations, and terminate training at 64k iterations, which is
determined on a 45k/5k train/val split.

从上图中我们也可以看到残差神经网络解决了网络退化问题,即使是1202层的超深度网络也能正常的进行训练。但是当深度达到一定的大小之后又会产生过拟合。因此神经网络的深度依然不是越大越好。

代码实践

在这里插入图片描述由上图可以看到,深层网络的误差比浅层网络还高有可能是因为发生了梯度消失现象。随着网络深度的加深,越来越多的梯度相乘可能会导致梯度无限趋近于0从而使得参数无法进行有效的更新。

在这里插入图片描述

而对于经过残差块的数据来说,令:
H ( x ) = F ( x ) + x H(x)=F(x)+x H(x)=F(x)+x
假设不考虑激活函数,对 x x x 求偏导有:
∂ H ∂ x = ∂ F ∂ x + 1 \frac{\partial H}{\partial x}=\frac{\partial F}{\partial x}+1 xH=xF+1

由上式可知,即使 ∂ F ∂ x \frac{\partial F}{\partial x} xF趋向于0,整体的梯度都会在1的附近,从而使得梯度可以有效地传递。

注意,由于经过残差块之后的输出要加上最开始的输入,也就是说最后输出的结果是F(x)+x,所以在残差块的内部学习到的是H(x)-x。

并且由于最后要与x做加法,所以残差块内部的输出张量维度必须要和输入张量(x)维度是一致的。

下面以图中这个简单的残差网络为例子来进行手动实现:
在这里插入图片描述

残差块的实现:

class ResidualBlock(nn.Module):
    def __init__(self, in_channels):
        super(ResidualBlock, self).__init__()
        self.channels = in_channels
        # 3x3的卷积核会使得图片宽高减2,padding为1正好加回去使得图片尺寸不变
        self.conv1 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)

    def forward(self, x):
        y = F.relu(self.conv1(x))
        y = self.conv2(y)
        return F.relu(y + x)

网络设计:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=5)
        self.maxpool = nn.MaxPool2d(2)

        self.rblock1 = ResidualBlock(16)
        self.rblock2 = ResidualBlock(32)

        self.fc1 = nn.Linear(32 * 4 * 4, 10)

    def forward(self, x):
        in_size = x.size(0) # 获取batch_size
        x = self.maxpool(F.relu(self.conv1(x)))
        x = self.rblock1(x)
        x = self.maxpool(F.relu(self.conv2(x)))
        x = self.rblock2(x)
        x = x.view(in_size, -1) # 除batch_size之外的维度展平
        x = self.fc1(x)
        return x

训练结果:

我们可以把训练结果和上一期使用 inception 模块的训练结果做对比。

下图为采用了 inception 模块的卷积神经网络的训练结果:

在这里插入图片描述

而下图为采用了 residual 模块的训练结果:

在这里插入图片描述
对比后可以发现采用残差模块的 CNN 网络的精度显著提高,最高的时候甚至能达到99%。

论文原文

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

ResNet 主要解决了训练非常深的神经网络时出现的梯度消失或梯度爆炸问题,通过引入“残差块”或“跳连接”(skip connections)来解决这个问题。在传统的深度神经网络中,随着网络层数的增加,模型可能会遭遇网络退化问题,即随着网络深度的增加,模型的准确率反而会下降。而ResNet通过在层之间添加直接的连接,允许信息跨越多层传递,从而使得深层网络的训练变得更加容易。这种结构也有助于梯度在整个网络中的流动,从而改善了深层网络的训练效果。每个残差块通常包含两个或多个卷积层,并且输入可以直接跳过这些层到达输出。如果输入X通过几个卷积层后得到F(X),那么最终的输出可以表示为F(X) + X。这样做的好处是,在反向传播过程中,梯度可以通过这两个路径进行传递,即可以通过残差路径直接传回给前面的层,减少了梯度消失的风险。由于其出色的性能和简便的设计,ResNet已经成为许多计算机视觉任务的标准模型之一,包括但不限于图像分类、目标检测和语义分割等

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB/Simulink学习|在Simulink中调用C语言-01使用C Function 实现比例运算

前面的博客中,提到如果想将Simulink仿真推进至硬件实验,需要将积木式的仿真搭建,变换成C语言实现,那么如何在Simulink中验证C代码的正确性呢?我将一边学习,一边更新,一边比较不同方法实现C语言&…

基于BP神经网络的手写体数字图像识别

基于BP神经网络的手写体数字图像识别 摘要 在信息化飞速发展的时代,光学字符识别是一个重要的信息录入与信息转化的手段,其中手写体数字的识别有着广泛地应用,如:邮政编码、统计报表、银行票据等等,因其广泛地应用范围…

分享一个免费的网页转EXE的工具

HTML2EXE是一款在Windows系统下将Web项目或网站打包成EXE执行程序的免费工具。这款工具能够将单页面应用、传统HTMLJavaScriptCSS生成的网站、Web客户端,以及通过现代前端框架(如Vue)生成的应用转换成独立的EXE程序运行。它支持将任何网站打包…

ubuntu安装与配置Nginx(2)

1. 配置 Nginx Nginx 的配置文件通常位于 /etc/nginx/nginx.conf,而虚拟主机的配置文件通常在 /etc/nginx/sites-available/ 和 /etc/nginx/sites-enabled/ 目录中。 在/etc/nginx/conf.d目录下新建xx.conf文件,配置文件, nginx -t 检查语法…

C++_day2

目录 1. 引用 reference(重点) 1.1 基础使用 1.2 特性 1.3 引用参数 2. C窄化(了解) 3. 输入(熟悉) 4. string 字符串类(掌握) 4.1 基础使用 4.2 取出元素 4.3 字符串与数字转换 5. …

JAVA WEB — HTML CSS 入门学习

本文为JAVAWEB 关于HTML 的基础学习 一 概述 HTML 超文本标记语言 超文本 超越文本的限制 比普通文本更强大 除了文字信息 还可以存储图片 音频 视频等标记语言 由标签构成的语言HTML标签都是预定义的 HTML直接在浏览器中运行 在浏览器解析 CSS 是一种用来表现HTML或XML等文…

第十五章 Vue工程化开发及Vue CLI脚手架

目录 一、引言 二、Vue CLI 基本介绍 三、安装Vue CLI 3.1. 安装npm和yarn 3.2. 安装Vue CLI 3.3. 查看 Vue 版本 四、创建启动工程 4.1. 创建项目架子 4.2. 启动工程 五、脚手架目录文件介绍 六、核心文件讲解 6.1. index.html 6.2. main.js 6.3. App.vue 一、…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第4天,注册登录功能设计

24.11.03 1.修改项目目录 从今天开始将正式进行功能的设计,首先需要对原来的项目结构进行修改,主要是添加新的文件夹用于存放新的文件。下面进行展示和讲解: 我用红圈圈出了新添加的文件夹,介绍下它们都是干啥的: da…

动态库实现lua网络请求GET, POST, 下载文件

DLL需要使用的网络封装 WinHttp异步实现GET, POST, 多线程下载文件_webclient post下载文件-CSDN博客文章浏览阅读726次。基于WinHttp封装, 实现异步多线程文件下载, GET请求, POST请求_webclient post下载文件https://blog.csdn.net/Flame_Cyclone/article/details/142644088…

unet中的attn_processor的修改(用于设计新的注意力模块)

参考资料 文章目录 unet中的一些变量的数据情况attn_processorunet.configunet_sd 自己定义自己的attn Processor ,对原始的attn Processor进行修改 IP-adapter中设置attn的方法 参考的代码: 腾讯ailabipadapter 的官方训练代码 unet中的一些变量的数据…

深度学习基础—序列采样

引言 深度学习基础—循环神经网络(RNN)https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link …

Qt中的Model与View5: QStyledItemDelegate

目录 QStyledItemDelegate API 重载公共函数 保护函数 重载保护函数 当在 Qt 项目视图中显示模型数据时,例如 QTableView,每个项目由代理绘制。此外,当项目被编辑时,提供一个编辑器小部件,该小部件在编辑时显示在项…

AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?

内容概要 在这个科技飞速发展的时代,超写实虚拟人物仿佛从科幻小说中走进了我们的日常生活。它们以生动的形象和细腻的动作,不仅在影视、广告和游戏中吸引了无数目光,更让我们对AI技术的未来充满了期待和疑惑。这些数字化身在逼真的外貌下&a…

海浪中的记忆:海滨学院班级回忆录开发

3系统分析 3.1可行性分析 通过对本海滨学院班级回忆录实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本海滨学院班级回忆录采用SSM框架,JAVA作为开…

文本串的应用(1)

一、文本串的加密解密操作 一个文本串可用事先给定的字母映射表进行加密。 例如,假设字母映射表为: a b c d e f g h i j k l m n o p q r s t u v w x y z n g z q t c o b m u h e l k p d a w x f y i v r s j 则字符串“encrypt”被加密为“tkz…

MCU裸机任务调度架构

第1章 方式一(平均主义) int main(int argc, char **argv){/* RTC 初始化 */bsp_RTC_Init(&rtc);/* 串口初始化 */uartInit(115200);/* LED初始化 */ledInit();while(1){// 任务1(获取传感器数据)// 任务2// 任务3} } 1.1 平均主义的缺陷 获取传感器数据可以600ms去读取一…

【力扣专题栏】面试题 01.02. 判定是否互为字符重排,如何利用数组模拟哈希表解决两字符串互排问题?

题解目录 1、题目描述解释2、算法原理解析3、代码编写(1)、两个数组分别模拟哈希表解决(2)、利用一个数组模拟哈希表解决问题 1、题目描述解释 2、算法原理解析 3、代码编写 (1)、两个数组分别模拟哈希表解决 class Solution { public:bool CheckPermutation(string s1, stri…

【OJ题解】C++实现反转字符串中的每个单词

💵个人主页: 起名字真南 💵个人专栏:【数据结构初阶】 【C语言】 【C】 【OJ题解】 题目要求:给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 题目链接: 反转字符串中的所…

全新更新!Fastreport.NET 2025.1版本发布,提升报告开发体验

在.NET 2025.1版本中,我们带来了巨大的期待功能,进一步简化了报告模板的开发过程。新功能包括通过添加链接报告页面、异步报告准备、HTML段落旋转、代码文本编辑器中的文本搜索、WebReport图像导出等,大幅提升用户体验。 FastReport .NET 是…

【数据结构与算法】第8课—数据结构之二叉树(堆)

文章目录 1. 树1. 什么是树?1.2 树的相关概念1.3 树的表示法 2. 二叉树2.1 特殊的二叉树2.2 二叉树的性质2.3 二叉树的存储结构 3. 实现顺序结构二叉树3.1 堆的概念3.2 堆的实现3.2.1 堆的数据结构3.2.2 堆的初始化3.2.3 堆插入数据3.2.4 删除堆顶数据3.2.5 堆的判空…