CV学习笔记-ResNet
ResNet
文章目录
- ResNet
- 1. ResNet概述
- 1.1 常见卷积神经网络
- 1.2 ResNet提出背景
- 2. ResNet网络结构
- 2.1 Residual net
- 2.2 残差神经单元
- 2.3 Shortcut
- 2.4 ResNet50网络结构
- 3. 代码实现
- 3.1 Identity Block
- 3.2 Conv Block
- 3.3 ResNet网络定义
- 3.4 整体代码测试
1. ResNet概述
1.1 常见卷积神经网络

卷积神经网络的发展历史如上所示,在AlexNet进入大众的视野之后,卷积神经网络的作用与实用性得到了广泛的认可,由此,对于卷积神经网络的优化进入了快速发展的阶段,经典的里程碑式的优化思想大致归为四大类:
- 网络加深
表现为在卷积神经网络的网络结构方面,在网络结构上增加卷积激活层,使得网络结构越变越深,深层次的网络在训练学习的过程中所考虑的因素就会更多,理论上会更加准确,但是网络的深度要与实际问题相关,在实践中折衷选取,过深过浅都不利于问题的解决。
- 增强卷积模块功能
表现为在一个卷积块中对特征提取的方式做出改变(也即变更传统卷积层的结构以获取更多的滤波作用),一般处于对feature map的尺度以及优化计算量的考量。
- 从分类的目标到检测的目标
同样利用CNN,但是设计网络的目标从分类的任务变更为了检测任务,检测任务不仅需要对图片中的区域进行特征提取、对结果进行分类,还要通过相关性的信息将目标框框出。
- 增加新的功能单元
丰富网络处理某一层输入或者输出的功能,此处的功能单元指传统卷积(Conv)、激活以及全连接、分类器之外的新增功能模块,例如LSTM增加的遗忘门,能够考虑历史数据,增加神经网络的功能。
1.2 ResNet提出背景
在ResNet提出之前,卷积神经网络的优化方式往往是通过加深网络的深度,堆叠基本单元,卷积层与池化层越堆积越多,科研工作者们在加深网络深度从而提高网络效果的情况愈演愈烈,学术界普遍认为,卷积层与池化层越多,提取到的图像特征信息越全面,对于分类的拟合度越高,但是随着网络的加深,问题也逐渐暴露出来了:
-
梯度弥散以及梯度爆炸
若每一层的误差梯度小于1,对于深度较深的网络反向转播时会使梯度趋近于0,反而会使得训练的过程难以有效继续。
若每一层的误差梯度大于1,对于深度较深的网络反向传播时会使梯度越来越大,直到“爆炸”(数值极大)
-
结果退化问题
当网络结构深到一定程度之后,对于分类问题的预测差距反而不符合期望,变得越来越差
本文介绍的ResNet卷积神经网络摒弃了一味堆叠卷积层和池化层的方法,并巧妙解决了梯度弥散和梯度爆炸的问题以及结果退化的问题。
2. ResNet网络结构
2.1 Residual net
Residual net(残差网络)

通过上图通俗解释,残差网络即是将前若干层的某一层数据输出直接跳过多层处理模块,直接引入到后面数据层的输入部分。
64维的数据输入到网络之后,一方面经过了卷积层的处理,另一方面跳过了卷积层从而直接与处理过的数据“会和”,这样,经过卷积层处理的数据相当于提取了特征,但是提取特征必然会造成信息的丢失,而未经处理的部分却保留了原始信息,这样做既能够考虑到特征提取不够的问题,又能考虑保留feature map的原始信息。
Residual有两种类型
- 左图残差结构称为BasicBlock
- 右图残差结构称为Bottleneck

2.2 残差神经单元
假定某段神经网络的输入是x,期望输出是H(x),如果我们直接将输入x传到输出作
为初始结果,那么我们需要学习的目标就是F(x) = H(x) - x,这就是一个残差神经单元,相当于将学习目标改变了,不再是学习一个完整的输出H(x),只是输出和输入的差别 H(x) - x ,即残差。
2.3 Shortcut
普通的直连的卷积神经网络和ResNet的最大区别在于,ResNet有很多旁路的支线将输入直接连到后面的层,使得后面的层可以直接学习残差,这种结构也被称为shortcut或skip connections。

传统的卷积层或全连接层在信息传递时,或多或少会存在信息丢失、损耗等问题。ResNet在某种程度上解决了这个问题,通过直接将输入信息绕道传到输出,保护信息的完整性,整个网络只需要学习输入、输出差别的那一部分,简化了学习目标和难度。
2.4 ResNet50网络结构
ResNet50有两个基本的块,分别名为Conv Block和Identity Block,其中Conv Block输入和输出的维度是不一样的,因为其直接输出一面也采用了一个卷积和一个归一化的BN层,所以不能连续串联,它的作用是改变网络的维度;Identity Block输入维度和输出维度相同,可以串联,用于加深网络的。
由于输出预处理和BN层的引入,解决了梯度弥散和梯度爆炸的问题。
BN层为Batch Normalization层,此部分的作用在笔者《CV学习笔记-Inception》中已经详细介绍,此处不再赘述。
由于神经网络的某些层跳过了下一层神经元的连接,隔层相连,这样弱化了每层之间的强联系,Residual结构缓解了退化的问题。
Conv Block结构

Identity Block结构

ResNet的网络结构:
ResNet的网络结构大部分由上面介绍的Conv Block和Identity Block组合构成,在网络的最后接上了平均池化与全连接层,最终输出分类。

3. 代码实现
3.1 Identity Block
Identity Block的定义实现,完全根据上图中Identity Block的结构定义构造,结构中最经典的就是Conv+BN+Relu的组合拳。
def identity_block(input_tensor, kernel_size, filters, stage, block):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)x = layers.add([x, input_tensor])x = Activation('relu')(x)return x
3.2 Conv Block
Conv Block的定义实现,完全根据上图中Conv Block的结构定义构造,结构中最经典的就是Conv+BN+Relu的组合拳。注意,Conv Block在shortcut的部分多了Conv+BN的操作,此处与Identity Block不同,故shortcut = Conv2D()、shortcut = BatchNormalization(),在shortcut处理之后,x = layers.add([x, shortcut]),对shortcut部分和左边的卷积处理部分进行了整合(加法)。
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), strides=strides,name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size, padding='same',name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)shortcut = Conv2D(filters3, (1, 1), strides=strides,name=conv_name_base + '1')(input_tensor)shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut)x = layers.add([x, shortcut])x = Activation('relu')(x)return x
3.3 ResNet网络定义
def ResNet50(input_shape=[224,224,3],classes=1000):img_input = Input(shape=input_shape)x = ZeroPadding2D((3, 3))(img_input)x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)x = BatchNormalization(name='bn_conv1')(x)x = Activation('relu')(x)x = MaxPooling2D((3, 3), strides=(2, 2))(x)x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')x = AveragePooling2D((7, 7), name='avg_pool')(x)x = Flatten()(x)x = Dense(classes, activation='softmax', name='fc1000')(x)model = Model(img_input, x, name='resnet50')model.load_weights("resnet50_weights_tf_dim_ordering_tf_kernels.h5")return model
3.4 整体代码测试
本主程序使用ResNet50加载模型对美洲象的图片进行了预测输出:

#-------------------------------------------------------------#
# ResNet50的网络部分
#-------------------------------------------------------------#
from __future__ import print_functionimport numpy as np
from keras import layersfrom keras.layers import Input
from keras.layers import Dense,Conv2D,MaxPooling2D,ZeroPadding2D,AveragePooling2D
from keras.layers import Activation,BatchNormalization,Flatten
from keras.models import Model# from keras.preprocessing import image
from keras.utils import image_utils as image
import keras.backend as K
from keras.utils.data_utils import get_file
from keras.applications.imagenet_utils import decode_predictions
from keras.applications.imagenet_utils import preprocess_inputdef identity_block(input_tensor, kernel_size, filters, stage, block):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)x = layers.add([x, input_tensor])x = Activation('relu')(x)return xdef conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), strides=strides,name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size, padding='same',name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)shortcut = Conv2D(filters3, (1, 1), strides=strides,name=conv_name_base + '1')(input_tensor)shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut)x = layers.add([x, shortcut])x = Activation('relu')(x)return xdef ResNet50(input_shape=[224,224,3],classes=1000):img_input = Input(shape=input_shape)x = ZeroPadding2D((3, 3))(img_input)x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)x = BatchNormalization(name='bn_conv1')(x)x = Activation('relu')(x)x = MaxPooling2D((3, 3), strides=(2, 2))(x)x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')x = AveragePooling2D((7, 7), name='avg_pool')(x)x = Flatten()(x)x = Dense(classes, activation='softmax', name='fc1000')(x)model = Model(img_input, x, name='resnet50')model.load_weights("resnet50_weights_tf_dim_ordering_tf_kernels.h5")return modelif __name__ == '__main__':model = ResNet50()model.summary()img_path = 'elephant.jpg'# img_path = 'bike.jpg'img = image.load_img(img_path, target_size=(224, 224))x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)print('Input image shape:', x.shape)preds = model.predict(x)print('Predicted:', decode_predictions(preds))
测试结果:

相关文章:
CV学习笔记-ResNet
ResNet 文章目录ResNet1. ResNet概述1.1 常见卷积神经网络1.2 ResNet提出背景2. ResNet网络结构2.1 Residual net2.2 残差神经单元2.3 Shortcut2.4 ResNet50网络结构3. 代码实现3.1 Identity Block3.2 Conv Block3.3 ResNet网络定义3.4 整体代码测试1. ResNet概述 1.1 常见卷积…...
百亿数据,毫秒级返回查询优化
近年来公司业务迅猛发展,数据量爆炸式增长,随之而来的的是海量数据查询等带来的挑战,我们需要数据量在十亿,甚至百亿级别的规模时依然能以秒级甚至毫秒级的速度返回,这样的话显然离不开搜索引擎的帮助,在搜…...
cpp之STL
STL原理 STL ⼀共提供六⼤组件,包括容器,算法,迭代器,仿函数,适配器和空间配置器,彼此可以组合套⽤。容器通过配置器取得数据存储空间,算法通过迭代器存取容器内容,仿函数可以协助算…...
基于Spring Boot开发的资产管理系统
文章目录 项目介绍主要功能截图:登录首页信息软件管理服务器管理网络设备固定资产明细硬件管理部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目…...
Markdown总结
文字的着重标记与段落的层次划分 Tab键可以缩进列表; shift Tab:取消缩进列表 加粗(****)、斜体(**)高亮:xxx$$:特殊标记删除:~~xxx~~多级标题:######无序列…...
字节跳动软件测试岗4轮面经(已拿34K+ offer)...
没有绝对的天才,只有持续不断的付出。对于我们每一个平凡人来说,改变命运只能依靠努力幸运,但如果你不够幸运,那就只能拉高努力的占比。 2021年10月,我有幸成为了字节跳动的一名测试工程师,从外包辞职了历…...
docker - 搭建redis集群和Etcd
概述 由于业务需要,需要把之前的分布式架构调整成微服务,把老项目迁移到k8s的服务中,再开始编码之前,需要再本地环境里做相应的准备工作,使用docker搭建redis集群,Etcd主要是注册本地的rpc服务。 Liunx O…...
Java程序开发中如何使用lntelliJ IDEA?
完成了IDEA的安装与启动,下面使用IDEA创建一个Java程序,实现在控制台上打印HelloWorld!的功能,具体步骤如下。 1.创建Java项目 进入New Project界面后,单击New Project选项按钮创建新项目,弹出New Project对话框&…...
【Linux】理解进程地址空间
🍎作者:阿润菜菜 📖专栏:Linux系统编程 我们在学习C语言的时候,都学过内存区域的划分如栈、堆、代码区、数据区这些。但我们其实并不真正理解内存 — 我们之前一直说的内存是物理上的内存吗? 前言 我们…...
Unity脚本 --- 常用API(类)--- GameObject类 和
第一部分 --- GameObject类 1.在Hierarchy 层级面板中添加游戏物体其实就相当于在场景中添加游戏物体 2.每一个场景都有一个自己的Hierarchy层级面板,用来管理场景中的所有游戏物体 3.是的,我们可以创建多个场景 1.首先上面这两个变量都是布尔变量&am…...
HTML标签——表格标签
HTML标签——表格标签 目录HTML标签——表格标签一、表格标题和表头单元格标签场景:注意点:案例实操小结二、表格的结构标签场景:注意点:案例实操:三、合并单元格思路场景:代码实现一、表格标题和表头单元格…...
Telerik JustMock 2023 R1 Crack
Telerik JustMock 2023 R1 Crack 制作单元测试的最快、最灵活和模拟选项。 Telerik JustLock也很简单,可以使用一个模拟工具来帮助您更快地生成更好的单元测试。JustLock使您更容易创建对象并建立对依赖关系的期望,例如,互联网服务需求、数据…...
筑基八层 —— 问题思考分析并解决
目录 零:移步 一.修炼必备 二.问题思考(先思考) 三.问题解答 零:移步 CSDN由于我的排版不怎么好看,我的有道云笔记相当的美观,请移步有道云笔记 一.修炼必备 1.入门必备:VS2019社区版&#x…...
【面试题】当面试官问 Vue2与Vue3的区别,你该怎么回答?
大厂面试题分享 面试题库后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库被问到 《vue2 与 vue3 的区别》应该怎么回答Vue 内部根据功能可以被分为三个大的模块:响应性 reactivite、运行时 runtime、编辑器…...
使用Python对excel中的数据进行处理
一、读取excel中的数据首先引入pandas库,没有的话使用控制台安装 —— pip install pandas 。import pandas as pd #引入pandas库,别名为pd#read_excel用于读取excel中的数据,这里只列举常用的两个参数(文件所在路径ÿ…...
TCP协议原理三
文章目录七、延时应答八、捎带应答九、面向字节流粘包问题十、TCP异常情况总结七、延时应答 如果说滑动窗口的关键是让窗口大一些,传输速度就快一些。那么延时应答就是在接收方能够处理的前提下,尽可能把ack返回的窗口大小尽可能大一些。 如果在接受数据…...
mac在命令行里获取root权限
1、为什么要获取root权限? 答:一些命令在正常状态下没有权限会报错,只有获取了root权限才能正常操作。 比如我们想修改一些系统的文件: vim /etc/shells 1 修改后保存,发现没权限,报错了。如下图…...
文献阅读 Improving Seismic Data Resolution with Deep Generative Networks
题目 Improving Seismic Data Resolution with Deep Generative Networks 使用深度生成网络提高地震数据分辨率 摘要 叠前数据的使用,通常可以来解决噪声迹线、覆盖间隙或不规则/不适当的迹线间距等问题。但叠前数据并不总是可用的。作为替代方案,叠后…...
mysql数据库之子查询练习
1、查询员工的姓名、年龄、职位、部门信息(隐式内连接)。 #emp、dept #连接条件:emp.dept_iddept.id select e.name,e.age,e.job,d.name from emp e,dept d where e.dept_idd.id; 2、查询年龄小于30岁的员工姓名、年龄、职位、部…...
西电计算机通信与网络(计网)简答题计算题核心考点汇总(期末真题+核心考点)
文章目录前言一、简答计算题真题概览二、网桥,交换机和路由器三、ARQ协议四、曼彻斯特编码和差分曼彻斯特编码五、CRC六、ARP协议七、LAN相关协议计算前言 主要针对西安电子科技大学《计算机通信与网络》的核心考点进行汇总,包含总共26章的核心简答。 【…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
