ResNet架构解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 残差块
参考论文:Deep Residual Learning for Image Recognition

这篇文章我以前也翻译过,但当时感觉就大概了解了一下,由于后面好多东西都需要用到残差,就再回来看看。

1、残差块

image-20220805172609745

  上图中的weight layer是3*3的卷积层;

  F(x)表示经过连个卷积层计算后得到的结果;

  identity表示“恒等映射”,也成为“shortcut connection”,说白了就是把x的值不做任何处理直接传过去。

  最后计算F(x)+x,这里的F(x)跟x是种类相同的信号,所以其对应位置进行相加。

这里残差F(x)与输入x的维度一致才能实现相加,如果不一致,可以使用shortcur connection执行一个线性投影以匹配shape

2、残差网络优势

  • 易于优化、收敛
  • 解决网络推化问题
  • 网络的层数可以很深,准确率大大提升

3、带残差与不带残差的结构对比

image-20220805173648560

4、残差分支的下采样

当残差分支出出现下采样时,对于short connection有两种方案:

  • A方案:对多出来的通道使用padding补零填充
  • B方案:用1*1卷积升维
不管采取哪种方案,shortcut分支第一个卷积层步长都为2

5、ResNet各层参数配置

image-20220805174133771

注意,这里18-layer和34-layer的搭建方式一致,50-layer、101-layer、152-layer的搭建方式一致。

image-20220805174347498

上图左边为ResNet18和ResNet34的残差快,右边为ResNet50/101/152对应的残差快。

5.1 ResNet18/34

图片来源:6.1 ResNet网络结构,BN以及迁移学习详解

image-20220805174544232

实线表示输入和输出的shape相同,虚线表示输入和输出的shape不一致,需要使用1*1卷积保持维度相等才能执行Add操作。

5.2 ResNet50/101/152

image-20220805174749186

其实也不是非要使用1*1卷积进行维度变换,原论文作者给出了三种解决方案:

  • A 所有shortcut物额外参数,升维时用padding补零
  • 平常的shrotcut用identity mapping ,升维时用1*1卷积
  • 所有的shortcut都使用1*1卷积。

    image-20220805175132788

6、模型复现

6.1 ResNet18

image-20220515212714040

实线表示维度相同,虚线表示维度不同,需要使用1*1卷积调整维度。

结合下表看

image-20220805175515210

  对于ResNet18和ResNet34,我们发现除过conv2_x都是实现连接之外,conv3_x、copnv4_x、conv5_x的第一个卷积都是虚线连接,即输入和输出的shape不一致,需要使用1*1卷积保持维度一致之后才能相加。

  ResNet18代码复现:

import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model
from plot_model import plot_model

image_size=224
num_classes=1000

# 定义残差单元
# 定义残差单元
# residual_path决定是否需要1*1卷积操作,保证x能和F(x)维度相同
def block(x, filters, strides=1,residual_path=False):
    # projection shortcut
    if residual_path:
        shortcut = Conv2D(filters, kernel_size=1, strides=strides, padding='same',use_bias=False)(x)
        # epsilon为BN公式中防止分母为零的值
        shortcut = BatchNormalization(epsilon=1.001e-5)(shortcut)
    else:
        # identity_shortcut
        shortcut = x
    # 2个卷积层
    x = Conv2D(filters=filters, kernel_size=3, strides=strides, padding='same',use_bias=False)(x)
    x = BatchNormalization(epsilon=1.001e-5)(x)
    x = Activation('relu')(x)


    x = Conv2D(filters=filters, kernel_size=3, strides=1, padding='same',use_bias=False)(x)
    x = BatchNormalization(epsilon=1.001e-5)(x)

    x = Add()([x, shortcut])
    x = Activation('relu')(x)
    return x
# 堆叠残差单元
# 从第二个block开始,每次的第一个输入和输出维度不相同,需要1*1卷积(虚线连接)
def stack(x, filters, blocks):
    x = block(x, filters, strides=2,residual_path=True)
    for i in range(blocks - 1):
        x = block(x, filters,residual_path=False)
    return x
# 第一个block块的输入和输出维度相同(实线连接)
def stack_conv2_x(x,filters,blocks):
    for i in range(blocks):
        x=block(x,filters,residual_path=False)
    return x
# 定义ResNet18
inputs = Input(shape=(image_size, image_size, 3))
# 填充3圈0,填充后图像从224×224变成230×230
x = ZeroPadding2D((3, 3))(inputs)
x = Conv2D(filters=64, kernel_size=7, strides=2, padding='valid')(x)
x = BatchNormalization(epsilon=1.001e-5)(x)
x = Activation('relu')(x)
# 填充1圈0
x = ZeroPadding2D((1, 1))(x)
x = MaxPool2D(pool_size=3, strides=2, padding='valid')(x)
# 堆叠残差结构
# blocks表示堆叠数量, 每个blocks中有三个卷积层
# filters是每个卷积块第一层的filters,第二层与第一层相等
# 第三层的filters为第一层的四倍
x = stack_conv2_x(x, filters=64, blocks=2)
x = stack(x, filters=128, blocks=2)
x = stack(x, filters=256, blocks=2)
x = stack(x, filters=512, blocks=2)
# 根据特征图大小进行平均池化,池化后得到2维数据
x = GlobalAvgPool2D()(x)
x = Dense(num_classes, activation='softmax')(x)
# 定义模型
model = Model(inputs=inputs, outputs=x)
model.summary()
plot_model(model,to_file='img/ResNet18.png',show_shapes=True)
还有一种更优雅的搭建方式,看这里:经典卷积网络--ResNet残差网络

网络结构如下:

image-20220805175939218

6.2 ResNet50

image-20220805180038572

image-20220805180112606

  上图右边为ResNet50的部分结构图,通过上边的参数和上图的结构可以发现,每个conv块中的第一个块都是使用虚线连接(即输入和输出维度不相同,需要使用1*1卷积进行维度变换)。

  我们以conv3_x为例,输入为[56,56,256],输出的shape为[28,28,512]。可以还想,此时输入和输出的唯独已经不一致了。图像的高宽和通道数都不一致,所以使用512个1*1大小的卷积核,步长为2来保持shape一致可以执行相加操作。如下图所示。

image-20220805180544191

ResNet50代码复现如下:

import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model
from plot_model import plot_model

image_size=224
num_classes=1000


# 定义残差单元
def block(x, filters, strides=1, conv_shortcut=True):
    # projection shortcut
    if conv_shortcut:
        shortcut = Conv2D(filters * 4, kernel_size=1, strides=strides, padding='valid')(x)
        # epsilon为BN公式中防止分母为零的值
        shortcut = BatchNormalization(epsilon=1.001e-5)(shortcut)
    else:
        # identity_shortcut
        shortcut = x
    # 3个卷积层
    x = Conv2D(filters=filters, kernel_size=1, strides=strides, padding='valid')(x)
    x = BatchNormalization(epsilon=1.001e-5)(x)
    x = Activation('relu')(x)

    x = Conv2D(filters=filters, kernel_size=3, strides=1, padding='same')(x)
    x = BatchNormalization(epsilon=1.001e-5)(x)
    x = Activation('relu')(x)

    x = Conv2D(filters=filters * 4, kernel_size=1, strides=1, padding='valid')(x)
    x = BatchNormalization(epsilon=1.001e-5)(x)

    x = Add()([x, shortcut])
    x = Activation('relu')(x)
    return x


# 堆叠残差单元
def stack(x, filters, blocks, strides):
    # 观察ResNet50结构可知,只有每个block中的第一块的第一层输入和输出的维度不一样
    # 需要使用1*1卷积保持维度一致再Add,其他的输入和输出的shape是一致的,可以直接Add
    x = block(x, filters, strides=strides)
    for i in range(blocks - 1):
        x = block(x, filters, conv_shortcut=False)
    return x


# 定义ResNet50
inputs = Input(shape=(image_size, image_size, 3))
# 填充3圈0,填充后图像从224×224变成230×230
x = ZeroPadding2D((3, 3))(inputs)
x = Conv2D(filters=64, kernel_size=7, strides=2, padding='valid')(x)
x = BatchNormalization(epsilon=1.001e-5)(x)
x = Activation('relu')(x)
# 填充1圈0
x = ZeroPadding2D((1, 1))(x)
x = MaxPool2D(pool_size=3, strides=2, padding='valid')(x)
# 堆叠残差结构
# blocks表示堆叠数量, 每个blocks中有三个卷积层
# filters是每个卷积块第一层的filters,第二层与第一层相等
# 第三层的filters为第一层的四倍
x = stack(x, filters=64, blocks=3, strides=1)
x = stack(x, filters=128, blocks=4, strides=2)
x = stack(x, filters=256, blocks=6, strides=2)
x = stack(x, filters=512, blocks=3, strides=2)
# 根据特征图大小进行平均池化,池化后得到2维数据
x = GlobalAvgPool2D()(x)
x = Dense(num_classes, activation='softmax')(x)
# 定义模型
model = Model(inputs=inputs, outputs=x)
model.summary()
plot_model(model,to_file='img/ResNet50Test.png',show_shapes=True)

image-20220805180626151

注意观察每个conv块的第一个块的输入和输出维度。

ResNet18与ResNet34的搭建方式是一样的,ResNet50与ResNet101、ResNet152搭建方式是一样的。只不过每层的block个数不一致,这里不再赘述。

Reference

经典卷积网络--ResNet残差网络

Deep Residual Learning for Image Recognition

6.1 ResNet网络结构,BN以及迁移学习详解

【精读AI论文】ResNet深度残差网络

(10) Resnet18、34 残差网络复现,附python完整代码

resnet18 50网络结构以及pytorch实现代码

神经网络学习小记录20——ResNet50模型的复现详解

目录
相关文章
|
2天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
21 6
|
2天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
11 1
|
2天前
|
Kubernetes Cloud Native 云计算
云原生技术深度解析:重塑企业IT架构的未来####
本文深入探讨了云原生技术的核心理念、关键技术组件及其对企业IT架构转型的深远影响。通过剖析Kubernetes、微服务、容器化等核心技术,本文揭示了云原生如何提升应用的灵活性、可扩展性和可维护性,助力企业在数字化转型中保持领先地位。 ####
|
3天前
|
运维 Kubernetes Cloud Native
Kubernetes云原生架构深度解析与实践指南####
本文深入探讨了Kubernetes作为领先的云原生应用编排平台,其设计理念、核心组件及高级特性。通过剖析Kubernetes的工作原理,结合具体案例分析,为读者呈现如何在实际项目中高效部署、管理和扩展容器化应用的策略与技巧。文章还涵盖了服务发现、负载均衡、配置管理、自动化伸缩等关键议题,旨在帮助开发者和运维人员掌握利用Kubernetes构建健壮、可伸缩的云原生生态系统的能力。 ####
|
7天前
|
机器学习/深度学习 人工智能 自然语言处理
医疗行业的语音识别技术解析:AI多模态能力平台的应用与架构
AI多模态能力平台通过语音识别技术,实现实时转录医患对话,自动生成结构化数据,提高医疗效率。平台具备强大的环境降噪、语音分离及自然语言处理能力,支持与医院系统无缝集成,广泛应用于门诊记录、多学科会诊和急诊场景,显著提升工作效率和数据准确性。
|
11天前
|
消息中间件 编解码 开发者
深入解析 Flutter兼容鸿蒙next全体生态的横竖屏适配与多屏协作兼容架构
本文深入探讨了 Flutter 在屏幕适配、横竖屏切换及多屏协作方面的兼容架构。介绍了 Flutter 的响应式布局、逻辑像素、方向感知、LayoutBuilder 等工具,以及如何通过 StreamBuilder 和 Provider 实现多屏数据同步。结合实际应用场景,如移动办公和教育应用,展示了 Flutter 的强大功能和灵活性。
82 6
|
11天前
|
存储 SQL 缓存
AnalyticDB 实时数仓架构解析
AnalyticDB 是阿里云自研的 OLAP 数据库,广泛应用于行为分析、数据报表、金融风控等应用场景,可支持 100 trillion 行记录、10PB 量级的数据规模,亚秒级完成交互式分析查询。本文是对 《 AnalyticDB: Real-time OLAP Database System at Alibaba Cloud 》的学习总结。
32 1
|
6月前
|
机器学习/深度学习 PyTorch 测试技术
|
1月前
|
机器学习/深度学习 编解码 自然语言处理
ResNet(残差网络)
【10月更文挑战第1天】
|
机器学习/深度学习 算法 计算机视觉
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)
3574 1
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)

推荐镜像

更多
下一篇
无影云桌面