残差网络(ResNet) -深度学习(Residual Networks (ResNet) – Deep Learning)

news2024/11/17 7:48:22

在第一个基于cnn的架构(AlexNet)赢得ImageNet 2012比赛之后,每个随后的获胜架构都在深度神经网络中使用更多的层来降低错误率。这适用于较少的层数,但当我们增加层数时,深度学习中会出现一个常见的问题,称为消失/爆炸梯度。这会导致梯度变为0或太大。因此,当我们增加层数时,训练和测试错误率也会增加。
在这里插入图片描述

在上图中,我们可以观察到56层的CNN在训练和测试数据集上的错误率都高于20层的CNN架构。通过对错误率的进一步分析,得出错误率是由梯度消失/爆炸引起的结论。

ResNet于2015年由微软研究院的研究人员提出,引入了一种名为残余网络的新架构。

Residual Networks ResNet– Deep Learning

  • 1、残差网路
  • 2、网络架构
  • 3、代码运行
  • 4、结果与总结

1、残差网路

为了解决梯度消失/爆炸的问题,该架构引入了残差块的概念。在这个网络中,我们使用一种称为跳过连接的技术。跳过连接通过跳过中间的一些层将一个层的激活连接到其他层。这就形成了一个残块。通过将这些剩余的块堆叠在一起形成Resnets。

这个网络背后的方法不是层学习底层映射,而是允许网络拟合残差映射。所以我们不用H(x)初始映射,让网络适合。

F(x) := H(x) - x which gives H(x) := F(x) + x.

在这里插入图片描述
添加这种类型的跳过连接的优点是,如果任何层损害了体系结构的性能,那么将通过正则化跳过它。因此,这可以训练一个非常深的神经网络,而不会出现梯度消失/爆炸引起的问题。本文作者在CIFAR-10数据集的100-1000层上进行了实验。

还有一种类似的方法叫做“高速公路网”,这些网络也采用跳线连接。与LSTM类似,这些跳过连接也使用参数门。这些门决定有多少信息通过跳过连接。然而,这种体系结构并没有提供比ResNet体系结构更好的准确性。

2、网络架构

该网络采用受VGG-19启发的34层平面网络架构,并增加了快捷连接。然后,这些快捷连接将架构转换为剩余网络。
在这里插入图片描述

3、代码运行

使用Tensorflow和Keras API,我们可以从头开始设计ResNet架构(包括残块)。下面是不同的ResNet架构的实现。对于这个实现,我们使用CIFAR-10数据集。该数据集包含10个不同类别(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船和卡车)等的60,000张32×32彩色图像。该数据集可以通过keras进行评估。datasets API函数。

第1步:首先,我们导入keras模块及其api。这些api有助于构建ResNet模型的体系结构。

代码:导入库

# Import Keras modules and its important APIs
import keras
from keras.layers import Dense, Conv2D, BatchNormalization, Activation
from keras.layers import AveragePooling2D, Input, Flatten
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
from keras.callbacks import ReduceLROnPlateau
from keras.preprocessing.image import ImageDataGenerator
from keras.regularizers import l2
from keras import backend as K
from keras.models import Model
from keras.datasets import cifar10
import numpy as np
import os

第2步:现在,我们设置ResNet架构所需的不同超参数。我们还对数据集做了一些预处理,为训练做准备。

代码:设置训练超参数

# Setting Training Hyperparameters
batch_size = 32  # original ResNet paper uses batch_size = 128 for training
epochs = 200
data_augmentation = True
num_classes = 10
  
# Data Preprocessing 
subtract_pixel_mean = True
n = 3
  
# Select ResNet Version
version = 1
  
# Computed depth of 
if version == 1:
    depth = n * 6 + 2
elif version == 2:
    depth = n * 9 + 2
  
# Model name, depth and version
model_type = 'ResNet % dv % d' % (depth, version)
  
# Load the CIFAR-10 data.
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
  
# Input image dimensions.
input_shape = x_train.shape[1:]
  
# Normalize data.
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255
  
# If subtract pixel mean is enabled
if subtract_pixel_mean:
    x_train_mean = np.mean(x_train, axis = 0)
    x_train -= x_train_mean
    x_test -= x_train_mean
  
# Print Training and Test Samples 
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
print('y_train shape:', y_train.shape)
  
# Convert class vectors to binary class matrices.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

第3步:在这一步中,我们根据epoch的个数来设置学习率。随着迭代次数的增加,学习率必须降低以保证更好的学习。

代码:设置不同epoch数的LR

# Setting LR for different number of Epochs
def lr_schedule(epoch):
    lr = 1e-3
    if epoch > 180:
        lr *= 0.5e-3
    elif epoch > 160:
        lr *= 1e-3
    elif epoch > 120:
        lr *= 1e-2
    elif epoch > 80:
        lr *= 1e-1
    print('Learning rate: ', lr)
    return lr

第4步:定义基本的ResNet构建块,可以用来定义ResNet V1和V2架构。

代码:基本的ResNet构建块

# Basic ResNet Building Block
  
  
def resnet_layer(inputs,
                 num_filters=16,
                 kernel_size=3,
                 strides=1,
                 activation='relu',
                 batch_normalization=True,
    conv=Conv2D(num_filters,
                  kernel_size=kernel_size,
                  strides=strides,
                  padding='same',
                  kernel_initializer='he_normal',
                  kernel_regularizer=l2(1e-4))
  
    x=inputs
    if conv_first:
        x = conv(x)
        if batch_normalization:
            x = BatchNormalization()(x)
        if activation is not None:
            x = Activation(activation)(x)
    else:
        if batch_normalization:
            x = BatchNormalization()(x)
        if activation is not None:
            x = Activation(activation)(x)
        x = conv(x)
    return x

第5步:定义基于我们上面定义的ResNet构建块的ResNet V1架构:

代码:ResNet V1架构

def resnet_v1(input_shape, depth, num_classes=10):
  
    if (depth - 2) % 6 != 0:
        raise ValueError('depth should be 6n + 2 (eg 20, 32, 44 in [a])')
    # Start model definition.
    num_filters = 16
    num_res_blocks = int((depth - 2) / 6)
  
    inputs = Input(shape=input_shape)
    x = resnet_layer(inputs=inputs)
    # Instantiate the stack of residual units
    for stack in range(3):
        for res_block in range(num_res_blocks):
            strides = 1
            if stack & gt
            0 and res_block == 0:  # first layer but not first stack
                strides = 2  # downsample
            y = resnet_layer(inputs=x,
                             num_filters=num_filters,
                             strides=strides)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters,
                             activation=None)
            if stack & gt
            0 and res_block == 0:  # first layer but not first stack
                # linear projection residual shortcut connection to match
                # changed dims
                x = resnet_layer(inputs=x,
                                 num_filters=num_filters,
                                 kernel_size=1,
                                 strides=strides,
                                 activation=None,
                                 batch_normalization=False)
            x = keras.layers.add([x, y])
            x = Activation('relu')(x)
        num_filters *= 2
  
    # Add classifier on top.
    # v1 does not use BN after last shortcut connection-ReLU
    x = AveragePooling2D(pool_size=8)(x)
    y = Flatten()(x)
    outputs = Dense(num_classes,
                    activation='softmax',
                    kernel_initializer='he_normal')(y)
  
    # Instantiate model.
    model = Model(inputs=inputs, outputs=outputs)
    return model

第6步:定义基于我们上面定义的ResNet构建块的ResNet V2架构:

代码:ResNet V2架构

# ResNet V2 architecture
def resnet_v2(input_shape, depth, num_classes=10):
    if (depth - 2) % 9 != 0:
        raise ValueError('depth should be 9n + 2 (eg 56 or 110 in [b])')
    # Start model definition.
    num_filters_in = 16
    num_res_blocks = int((depth - 2) / 9)
  
    inputs = Input(shape=input_shape)
    # v2 performs Conv2D with BN-ReLU on input before splitting into 2 paths
    x = resnet_layer(inputs=inputs,
                     num_filters=num_filters_in,
                     conv_first=True)
  
    # Instantiate the stack of residual units
    for stage in range(3):
        for res_block in range(num_res_blocks):
            activation = 'relu'
            batch_normalization = True
            strides = 1
            if stage == 0:
                num_filters_out = num_filters_in * 4
                if res_block == 0:  # first layer and first stage
                    activation = None
                    batch_normalization = False
            else:
                num_filters_out = num_filters_in * 2
                if res_block == 0:  # first layer but not first stage
                    strides = 2    # downsample
  
            # bottleneck residual unit
            y = resnet_layer(inputs=x,
                             num_filters=num_filters_in,
                             kernel_size=1,
                             strides=strides,
                             activation=activation,
                             batch_normalization=batch_normalization,
                             conv_first=False)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters_in,
                             conv_first=False)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters_out,
                             kernel_size=1,
                             conv_first=False)
            if res_block == 0:
                # linear projection residual shortcut connection to match
                # changed dims
                x = resnet_layer(inputs=x,
                                 num_filters=num_filters_out,
                                 kernel_size=1,
                                 strides=strides,
                                 activation=None,
                                 batch_normalization=False)
            x = keras.layers.add([x, y])
  
        num_filters_in = num_filters_out
  
    # Add classifier on top.
    # v2 has BN-ReLU before Pooling
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = AveragePooling2D(pool_size=8)(x)
    y = Flatten()(x)
    outputs = Dense(num_classes,
                    activation='softmax',
                    kernel_initializer='he_normal')(y)
  
    # Instantiate model.
    model = Model(inputs=inputs, outputs=outputs)
    return model

第7步:下面的代码用于训练和测试我们上面定义的ResNet v1和v2架构:

代码:Main函数

# Main function 
if version == 2:
    model = resnet_v2(input_shape = input_shape, depth = depth)
else:
    model = resnet_v1(input_shape = input_shape, depth = depth)
  
model.compile(loss ='categorical_crossentropy',
              optimizer = Adam(learning_rate = lr_schedule(0)),
              metrics =['accuracy'])
model.summary()
print(model_type)
  
# Prepare model saving directory.
save_dir = os.path.join(os.getcwd(), 'saved_models')
model_name = 'cifar10_% s_model.{epoch:03d}.h5' % model_type
if not os.path.isdir(save_dir):
    os.makedirs(save_dir)
filepath = os.path.join(save_dir, model_name)
  
# Prepare callbacks for model saving and for learning rate adjustment.
checkpoint = ModelCheckpoint(filepath = filepath,
                             monitor ='val_acc',
                             verbose = 1,
                             save_best_only = True)
  
lr_scheduler = LearningRateScheduler(lr_schedule)
  
lr_reducer = ReduceLROnPlateau(factor = np.sqrt(0.1),
                               cooldown = 0,
                               patience = 5,
                               min_lr = 0.5e-6)
  
callbacks = [checkpoint, lr_reducer, lr_scheduler]
  
# Run training, with or without data augmentation.
if not data_augmentation:
    print('Not using data augmentation.')
    model.fit(x_train, y_train,
              batch_size = batch_size,
              epochs = epochs,
              validation_data =(x_test, y_test),
              shuffle = True,
              callbacks = callbacks)
else:
    print('Using real-time data augmentation.')
    # This will do preprocessing and realtime data augmentation:
    datagen = ImageDataGenerator(
        # set input mean to 0 over the dataset
        featurewise_center = False,
        # set each sample mean to 0
        samplewise_center = False,
        # divide inputs by std of dataset
        featurewise_std_normalization = False,
        # divide each input by its std
        samplewise_std_normalization = False,
        # apply ZCA whitening
        zca_whitening = False,
        # epsilon for ZCA whitening
        zca_epsilon = 1e-06,
        # randomly rotate images in the range (deg 0 to 180)
        rotation_range = 0,
        # randomly shift images horizontally
        width_shift_range = 0.1,
        # randomly shift images vertically
        height_shift_range = 0.1,
        # set range for random shear
        shear_range = 0.,
        # set range for random zoom
        zoom_range = 0.,
        # set range for random channel shifts
        channel_shift_range = 0.,
        # set mode for filling points outside the input boundaries
        fill_mode ='nearest',
        # value used for fill_mode = "constant"
        cval = 0.,
        # randomly flip images
        horizontal_flip = True,
        # randomly flip images
        vertical_flip = False,
        # set rescaling factor (applied before any other transformation)
        rescale = None,
        # set function that will be applied on each input
        preprocessing_function = None,
        # image data format, either "channels_first" or "channels_last"
        data_format = None,
        # fraction of images reserved for validation (strictly between 0 and 1)
        validation_split = 0.0)
  
    # Compute quantities required for featurewise normalization
    # (std, mean, and principal components if ZCA whitening is applied).
    datagen.fit(x_train)
  
    # Fit the model on the batches generated by datagen.flow().
    model.fit_generator(datagen.flow(x_train, y_train, batch_size = batch_size),
                        validation_data =(x_test, y_test),
                        epochs = epochs, verbose = 1, workers = 4,
                        callbacks = callbacks)
  
# Score trained model.
scores = model.evaluate(x_test, y_test, verbose = 1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

4、结果与总结

在ImageNet数据集上,作者使用了152层的ResNet,其深度是VGG19的8倍,但参数仍然较少。在ImageNet测试集上,这些ResNets的集合产生的错误率仅为3.7%,这一结果赢得了ILSVRC 2015竞赛。在COCO对象检测数据集上,由于它的深度表示,也产生了28%的相对改进。
在这里插入图片描述

  • 上面的结果表明,快捷连接将能够解决增加层数所带来的问题,因为当我们将层数从18层增加到34层时,ImageNet验证集上的错误率也会与普通网络不同而降低。
    在这里插入图片描述
  • 下面是ImageNet测试集的结果。ResNet的前5名错误率为3.57%,是最低的,因此ResNet架构在2015年ImageNet分类挑战中排名第一。
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MachineLearningWu_6_FeatureScaling

x.1 feature scale 接下俩我们将考虑数据的不一致性,例如有的数据的范围很大,可能分布在好几千,但是我们的weight矩阵最好是在[-1, 1]的小数,如果数值太大就会导致我们的weight变化也很大,如下面这个例子就并不好&…

编译型语言和解释型语言的区别

1.操作系统怎么识别编程语言 计算机能识别二进制数,但是无法识别编程语言,比如你把 01000001100通过相关手段输入计算机中计算机就能识别其中的含义并且执行对应的命令,但是你输入 print(hello world)计算机就无法识别其含义,这就…

基于springboot+mybatis-plus+mysql+vue音乐网站管理系统

基于springbootmybatis-plusmysqlvue音乐网站管理系统 一、系统介绍1、系统主要功能:2.涉及技术框架:3.项目说明: 二、功能展示三、其它系统四、获取源码 一、系统介绍 1、系统主要功能: 音乐播放 用户登录注册 用户信息编辑、头…

4. PS切图

4.1常见的图片格式 jpg图像格式: JPEG ( .JPG )对色彩的信息保留较好,高清,颜色较多,我们产品类的图片经常用jpg格式的gif图像格式 : GIF格式最多只能储存256色,所以通常用来显示简单图形及字体,但是可以保存透明背景和动画效果,实际经常用于一些图片小动画效果png图像格式&am…

Tomcat 线程池

目录 概述 tomcat线程池工作原理 关键源码 Connector 配置 Executor 线程配置 tomcat核心组件(题外) 概述 Tomcat 是一个流行的 Java Web 服务器,它使用线程池来处理客户端请求。线程池是一组预先创建的线程,用于执行并发任…

FreeRTOS ~(七)互斥量 ~ (1/3)互斥量解决互斥缺陷

前情提要 FreeRTOS ~(四)同步互斥与通信 ~ (2/3)互斥的缺陷 FreeRTOS ~(五)队列的常规使用 ~ (2/5)队列解决互斥缺陷 FreeRTOS ~(六)信号量 ~ (2/…

Android Camera2 获取RAW数据

这边文章主要记录下在Android系统上,如何通过Camera2 API去拿到RAW数据,也是当个备忘。 平时我们拿实时预览数据,更多的是获取yuv数据。一般涉及到raw域算法在APP层实现的时候,我们才会用到获取raw数据。 APP上集成Raw算法的思路…

【CSDN新星计划】初阶牛C/C++赛道——顺序程序设计(运算符和表达式)

目录 🍉2.运算符和表达式 2.1 C运算符 2.2基本的算术运算符 2.3自增( )自减( - - )运算符 2.4算术表达式和运算符的优先级与结合性 2.运算符和表达式 2.1 C运算符 C语言提供了以下运算符: (1)算术…

印度反垄断机构偏袒亚马逊,谷歌对滥用安卓市场地位罚款提出质疑

根据路透社消息,谷歌指控印度反垄断机构在其安卓系统调查中对亚马逊持偏袒态度,并向印度最高法院提起诉讼,对其关于滥用安卓市场地位的罚款提出质疑。 印度竞争委员会(CCI)最近要求谷歌改变商业模式,称谷歌…

结合具体场景举例说明chatgpt预训练模型中Tokenization的原理

假设我们有一个场景,Alice想向Chatbot询问一部电影的推荐。她发送了一条消息:“你好,能给我推荐一部好看的电影吗?” 在这个场景中,Chatbot使用了ChatGPT预训练模型。首先,Chatbot需要对Alice的消息进行Tok…

【力扣周赛】第 108 场双周赛

文章目录 Q1:6913. 最长交替子序列思路竞赛时代码代码优化 Q2:6469. 重新放置石块思路竞赛时代码 Q3:6923. 将字符串分割为最少的美丽子字符串解法1—— dfs回溯 剪枝 判断解法2——动态规划 Q4:6928. 黑格子的数目代码优化 成绩…

Jenkins持续集成

文章目录 Jenkins介绍Jenkins的特征 Jenkins架构Gitlab安装1. Gitlab代码托管服务器安装2. Gitlab添加组、创建用户、创建项目 jenkins安装安装JenkinsJenkins插件管理Jenkins用户权限管理Jenkins凭证管理安装Git插件和Git工具设置SSH免密登录 Maven安装和配置JenkinsDockerspr…

【数据结构】栈和队列详解

⭐️ 往期相关文章 ✨链接1:数据结构和算法的概念以及时间复杂度空间复杂度详解 ✨链接2:【数据结构】手撕顺序表 ✨链接3:【数据结构】手撕单链表 ✨链接4:【数据结构】双向带头循环链表 ⭐️ 栈和队列 🌠 栈 栈是…

react-native项目手机预览

初始化项目 使用 expo 初始化 react-native 项目,https://reactnative.cn/docs/environment-setup 运行项目 执行 start 命令运行项目 拿起你的iPhone手机,安装 expo APP,https://expo.dev/client 或者到 APP store 搜索下载。下载完成之…

基于TCP协议的聊天系统TCP-ChatSystem

基于TCP协议的点对点聊天系统 网络协议:TCP 聊天形式:点对点 所用技术:socket、多路转接、线程池、互斥锁、条件变量、MFC等。 功能点:注册、登录、添加好友、聊天等。 实现示意图 客户端登陆注册消息流转图: 客…

【MATLAB第54期】基于LSTM长短期记忆网络的多输入多输出滑动窗口回归预测模型

【MATLAB第54期】基于LSTM长短期记忆网络的多输入多输出滑动窗口回归预测模型 往期第13期已实现多输入单输出滑动窗口回归预测 本次在此代码基础上,新增多输出滑动窗口功能。 多输入单输出滑动窗口回归预测 一、实现效果 往期文章提到了对单列时间序列数据进行滑…

spdlog入门教程(1)

spdlog入门教程(1) 文章目录 spdlog入门教程(1)1、前言1.1 为什么要使用日志库1.2 尽量使用通用日志框架而不要自己实现1.3 spdlog概述1.4 地址 2、源码编译配置spdlog3、在Qt中使用spdlog1.1 验证spdlog是否配置成功1.2 将日志输…

全网最牛,Pytest自动化测试-pytest.mark.parametrize参数化实战(详细)

目录:导读 前言 一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 pytest允许在多个…

删除数据库记录错误

删除数据库记录错误:Unexpected update count received (Actual: 2, Expected: 1). All changes will be rolled back. 解决:同时删掉ID为8的记录就行了 分析:这种情况是未设置主键约束,插入了相同的记录导致的。推测应该是框架对…

Clip-Path

前言 借助clip-path,我们可以实现一些复杂的animation动画效果,我们先来简单概述一下它的特性,如MDN所描述的。 The clip-path CSS property creates a clipping region that sets what part of an element should be shown. Parts that are inside the region are shown, whi…