解码 ResNet:残差块如何增强深度学习性能【数学推导】

2024-06-18 16:28

本文主要是介绍解码 ResNet:残差块如何增强深度学习性能【数学推导】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ResNet简介

残差网络结构

残差网络(ResNet)是由何凯明等人在2015年提出的,它极大地提高了深度神经网络的训练效果,尤其是非常深的网络。ResNet的核心思想是引入“残差块”(Residual Block),通过跳跃连接(Shortcut Connection)解决深层网络的梯度消失和梯度爆炸问题。

结构示意图

  • 输入层
  • 一系列的卷积层(Conv Layers)
  • 残差块(Residual Blocks)
  • 全连接层(Fully Connected Layer)
  • 输出层

在传统的卷积神经网络中,每一层都会对输入的特征进行某种变换,比如卷积操作,然后直接输出这些变换后的结果到下一层。可以把这种变换看作是对输入进行处理和提取新的特征。
y l = F l ( x l ) \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) yl=Fl(xl)

而ResNet通过增加一条跳跃连接,使得每个残差块输出的是“变换后的特征+原始输入特征”,即:

y = F ( x , { W i } ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x} y=F(x,{Wi})+x

其中, F ( x , { W i } ) \mathcal{F}(\mathbf{x}, \{W_i\}) F(x,{Wi}) 表示通过多层卷积、激活等操作后的特征, x \mathbf{x} x 表示原始输入特征。

什么是跳跃连接?

跳跃连接(Shortcut Connection),又称为“短路连接”或“直连”,是一种直接将输入信号传递到输出信号的技术。具体来说,就是在每个残差块中,除了正常的变换路径外,还增加了一条直接连接输入和输出的路径。

为什么要使用跳跃连接?

在深层网络中,随着层数的增加,梯度可能会逐渐消失或者爆炸,这会导致网络很难训练。而跳跃连接的引入可以缓解这个问题,因为它允许梯度直接传递到前面的层,确保梯度不会消失。

跳跃连接如何缓解梯度消失和梯度爆炸问题

为了理解跳跃连接如何缓解梯度消失和梯度爆炸问题,我们需要从反向传播(Backpropagation)的角度分析梯度传递过程。

在传统的深层网络中,假设某一层的输入是 x l \mathbf{x}_l xl ,输出是 y l \mathbf{y}_l yl 。每层的变换函数记为 F l \mathcal{F}_l Fl,那么:

y l = F l ( x l ) \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) yl=Fl(xl)

而在ResNet中,增加了跳跃连接后,输出变为:

y l = F l ( x l ) + x l \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) + \mathbf{x}_l yl=Fl(xl)+xl

在反向传播中,我们需要计算每层的梯度。对于传统的深层网络,第 l l l 层的梯度计算如下:

∂ L ∂ x l = ∂ L ∂ y l ⋅ ∂ y l ∂ x l = ∂ L ∂ y l ⋅ ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{L}}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \frac{\partial \mathbf{y}_l}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} xlL=ylLxlyl=ylLxlFl(xl)

而在ResNet中,由于增加了跳跃连接,梯度的计算变为:

∂ L ∂ x l = ∂ L ∂ y l ⋅ ( ∂ F l ( x l ) ∂ x l + I ) \frac{\partial \mathcal{L}}{\partial \mathbf{x}_l} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}_l} \cdot \left( \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} + \mathbf{I} \right) xlL=ylL(xlFl(xl)+I)

这里, I \mathbf{I} I 是单位矩阵,表示跳跃连接的梯度。

梯度分析

在ResNet中,由于跳跃连接的存在,梯度不仅传递了变换部分( ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} xlFl(xl) ),还传递了输入部分( I \mathbf{I} I ),这意味着即使在深层网络中,梯度也能有效地通过跳跃连接传递到前面的层,而不会完全依赖于 ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} xlFl(xl)

具体来说,如果 ∂ F l ( x l ) ∂ x l \frac{\partial \mathcal{F}_l(\mathbf{x}_l)}{\partial \mathbf{x}_l} xlFl(xl) 在深层网络中趋近于0(梯度消失)或趋近于无穷大(梯度爆炸),跳跃连接的单位矩阵 I \mathbf{I} I 确保了梯度至少能通过 I \mathbf{I} I 进行传递,缓解了梯度消失或爆炸的问题。

总结

  1. 跳跃连接的引入:在每个残差块中,除了对输入特征进行卷积、归一化和激活等操作外,还增加了一条直接传递输入特征到输出的路径。
  2. 公式中的体现:输出特征不仅包含变换后的特征,还加上了输入特征,即 y = F ( x ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x} y=F(x)+x
  3. 缓解梯度问题:跳跃连接确保了梯度在反向传播过程中,即使变换部分的梯度消失或爆炸,输入特征的梯度(\mathbf{I})也能直接传递,避免梯度完全消失或爆炸。

残差块的组成及功能

残差块是ResNet的基本单元,每个残差块中包含了两个主要部分:

  1. 变换路径:对输入进行卷积、批量归一化和激活操作。
  2. 跳跃连接(Shortcut Connection):直接将输入传递到输出,不进行任何变换,只是将输入特征原样添加到经过变换后的特征上。

详细组成

  1. 卷积层(Convolutional Layer):提取特征。
  2. 批量归一化层(Batch Normalization Layer):加速训练,稳定输入。
  3. ReLU激活函数(ReLU Activation Function):引入非线性,提高网络表达能力。
  4. 跳跃连接(Shortcut Connection):将输入直接加到输出上。

具体的操作流程如下:

  1. 输入特征 x \mathbf{x} x 通过卷积层和批量归一化层,得到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x)
  2. 变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 与输入特征 x \mathbf{x} x 相加,得到输出特征 y \mathbf{y} y

y = F ( x , { W i } ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x} y=F(x,{Wi})+x

这里, x \mathbf{x} x 直接通过跳跃连接加到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x) 上。

  1. 输出特征 y \mathbf{y} y 再经过ReLU激活函数:

y = ReLU ( y ) \mathbf{y} = \text{ReLU}(\mathbf{y}) y=ReLU(y)

这种设计可以确保即使在深层网络中,梯度也能有效传播,避免梯度消失或爆炸。

ResNet的输出计算

在ResNet中,每一层的输出不仅仅取决于当前层的输入,还包括了前面层的输入,这种设计使得网络能够更有效地学习。

详细的数学推导
假设一个简单的ResNet包含L个残差块,每个残差块输出为 y l \mathbf{y}_l yl ,输入为 x l \mathbf{x}_l xl ,则有:

y l = F l ( x l ) + x l \mathbf{y}_l = \mathcal{F}_l(\mathbf{x}_l) + \mathbf{x}_l yl=Fl(xl)+xl

其中 F l ( x l ) \mathcal{F}_l(\mathbf{x}_l) Fl(xl) 表示第l个残差块中的变换函数(例如两层卷积和ReLU激活函数)。

整个网络的输入为 x 0 \mathbf{x}_0 x0 ,输出为 y L \mathbf{y}_L yL,即:

y L = F L ( y L − 1 ) + y L − 1 \mathbf{y}_L = \mathcal{F}_L(\mathbf{y}_{L-1}) + \mathbf{y}_{L-1} yL=FL(yL1)+yL1
y L − 1 = F L − 1 ( y L − 2 ) + y L − 2 \mathbf{y}_{L-1} = \mathcal{F}_{L-1}(\mathbf{y}_{L-2}) + \mathbf{y}_{L-2} yL1=FL1(yL2)+yL2
⋮ \vdots
y 1 = F 1 ( x 0 ) + x 0 \mathbf{y}_1 = \mathcal{F}_1(\mathbf{x}_0) + \mathbf{x}_0 y1=F1(x0)+x0

逐层递推,我们可以得到最终的输出:

y L = x 0 + ∑ l = 1 L F l ( x l ) \mathbf{y}_L = \mathbf{x}_0 + \sum_{l=1}^{L} \mathcal{F}_l(\mathbf{x}_l) yL=x0+l=1LFl(xl)

这种设计可以看作是对输入的逐层增强,每层不仅仅是对输入的简单变换,更是对前面所有层次特征的累积。

总结

  1. 残差网络结构:ResNet引入了残差块,每个残差块中有一条跳跃连接直接将输入加到输出上,这样即使网络很深,信息也能有效传递。
  2. 残差块的组成及功能:每个残差块由卷积、批量归一化、ReLU激活和跳跃连接组成,确保输入信息能够直接加到输出上。
  3. ResNet的输出计算:通过逐层递推,每一层的输出都是对输入和变换后特征的累积,使得网络能够更有效地学习深层特征。

具体实现:残差块的工作原理

  1. 输入特征(原始输入特征):假设输入特征是 x \mathbf{x} x
  2. 变换路径:输入特征 x \mathbf{x} x 经过一系列的卷积操作、批量归一化和激活函数后,得到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x)
  3. 跳跃连接:在变换路径之外,直接将输入特征 x \mathbf{x} x 加到变换后的特征 F ( x ) \mathcal{F}(\mathbf{x}) F(x)上,得到输出特征 y \mathbf{y} y

y = F ( x ) + x \mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x} y=F(x)+x

这里, F ( x ) \mathcal{F}(\mathbf{x}) F(x) 是通过卷积和激活操作后的特征, x \mathbf{x} x 是原始输入特征。这样,每个残差块的输出就是“变换后的特征+原始输入特征”。

这篇关于解码 ResNet:残差块如何增强深度学习性能【数学推导】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072512

相关文章

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Golang中拼接字符串的6种方式性能对比

《Golang中拼接字符串的6种方式性能对比》golang的string类型是不可修改的,对于拼接字符串来说,本质上还是创建一个新的对象将数据放进去,主要有6种拼接方式,下面小编就来为大家详细讲讲吧... 目录拼接方式介绍性能对比测试代码测试结果源码分析golang的string类型是不可修改的,对于拼接字

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常