一.ResNet概述

resnet在2015名声大噪,微软公司提出了一种新的网络结构---残差网络(resnet)。残差模块结构图如下图1,图中曲线连接方式(X identity)称为近道连接,这种连接方式直接跳过了权重层;经过权重层的连接方式(F(X))与近道连接(X identity)构成了残差模块

                                                    图1

残差网络是由一系列残差块组成的(1式)。一个残差块可以用表示为:

残差块分成两部分直接映射部分和残差部分。h(x1)  是直接映射,反应在图1中是左边的曲线;

F(X1,w1) 是残差部分,一般由两个或者三个卷积操作构成,即1式中右侧包含卷积的部分。

残差网络结构允许网络尽可能加深,较为常见的是:ResNet50和ResNet101。具体结构如下

从表中可以看出,所有ResNet网络主要被分为5个部分。

残差块可以大致分成2种,一种有bottleneck结构,即下图右中的1*1,3*3,1*1 的卷积层,用于先降维再升维,主要出于降低计算复杂度的现实考虑,称之为“bottleneck block”,另一种没有bottleneck结构,如下图左所示,称之为“basic block”。即下图左中的basic block由2个3×3和3×3卷积层构成。

近道连接(shortcut)也分为两种(如下图是以两个3*3的卷积核的残差块进行划分恒等块和卷积块的),一种是近道连接中有卷积模块,另一种是近道连接无卷积模块,残差块根据近道连接是否有卷积模块可以分为卷积块(convolutional block)和恒等快(identity block)。为什么在近道连接中加入卷积块?原因在于如果近道连接所连接的两组数据的通道(channel)个数不同,则可以在近道连接中加入1*1卷积模块对通道个数进行调整。

在本篇文章中主要分享ResNet50,在ResNet50中,为了减少参数计算量,会使用1*1的卷积核对输入数据进行降维,再进行卷积运算,当输出时同样使用1*1的卷积核使数据维度恢复到输入时的维度。

ResNet50残差模块结构图如下:输入数据256维,在第一层1*1的卷积层中降维到64维,再经过3*3的卷积后,最后由1*1的卷积层将其恢复到256维

二.ResNet50实现MNIST分类

基于keras框架

代码如下:

from keras.models import Model
from keras.layers import Input,Dense,Dropout,Flatten,MaxPooling2D,Conv2D,AveragePooling2D,Activation,BatchNormalization,\ZeroPadding2D,Add
from keras.initializers import glorot_uniform
from keras.datasets import mnist
from keras.utils import np_utils
from matplotlib import pyplot as plt
import numpy as np#数据集预处理
(X_train,Y_train),(X_test,Y_test)=mnist.load_data()
X_test1=X_test
Y_test1=Y_test
#处理特征数据
X_train=X_train.reshape(-1,28,28,1).astype("float32")/255.0
X_test=X_test.reshape(-1,28,28,1).astype("float32")/255.0
# 处理标签
Y_train=np_utils.to_categorical(Y_train,10)
Y_test=np_utils.to_categorical(Y_test,10)
print(X_train.shape)
print(Y_train.shape)
#搭建恒等快
#X代表输入数据,f代表该恒等快的第二个卷积的大小,因为第一个和第三个卷积核大小都是1*1,stage代表第几个卷积核,block代表卷积核的名字
def identity_block(X,f,filters,stage,block):#命名cov_name="res"+str(stage)+block+"branch"bn_name="bn"+str(stage)+block+"branch"F1,F2,F3=filters #该恒等快的各个卷积核的大小X_TEMP=X  #保存输入数据,为近道连接做准备#定义第一层卷积核X=Conv2D(filters=F1,kernel_size=(1,1),strides=1,padding="valid",name=cov_name+"2a",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2a")(X)X=Activation("relu")(X)#定义第二层卷积核X=Conv2D(filters=F2,kernel_size=(f,f),strides=1,padding="same",activation="relu",name=cov_name+"2b",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2b")(X)#定义第三层卷积核X=Conv2D(filters=F3,kernel_size=(1,1),strides=1,padding="valid",activation="relu",name=cov_name+"2c",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2c")(X) #归一化#将近道连接与经过权重的输出加起来X=Add()([X,X_TEMP])#经过激活函数输出值X=Activation("relu")(X)return X#搭建卷积块
def cov_block(X,f,filters,stage,block,s=2):#卷积块命名cov_name="res"+str(stage)+block+"branch"bn_name="bn"+str(stage)+block+"branch"X_TEMP=XF1,F2,F3=filters#搭建固定的卷积模块#搭建第一层的卷积核,步长为sX=Conv2D(filters=F1,kernel_size=(1,1),strides=s,activation="relu",name=cov_name+"2a",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2a")(X)#搭建第二层卷积核X=Conv2D(filters=F2,kernel_size=(f,f),strides=1,padding="same",activation="relu",name=cov_name+"2b",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2b")(X)#搭建第三层卷积核X=Conv2D(filters=F3,kernel_size=(1,1),strides=1,name=cov_name+"2c",kernel_initializer=glorot_uniform(seed=0))(X)X=BatchNormalization(axis=3,name=bn_name+"2c")(X)#搭建近道连接的卷积核,加入卷积层和归一化层X_TEMP=Conv2D(filters=F3,kernel_size=(1,1),strides=(s,s),name=cov_name+"1",kernel_initializer=glorot_uniform(seed=0))(X_TEMP)X_TEMP=BatchNormalization(axis=3,name=bn_name+"1")(X_TEMP)  #归一化层#将近道连接与经过卷积的输出加在一起X=Add()([X,X_TEMP])#激活层X=Activation("relu")(X)return X
#利用恒等快和卷积块搭建resnet50网络结构
def resnet():X_input=Input(shape=(28,28,1)) #输入X=ZeroPadding2D((3,3))(X_input) #填充0#搭建stage1:卷积层(卷积层,归一化层,激活层,池化层)X=Conv2D(filters=64,kernel_size=(7,7),strides=2,activation="relu",name="cov1")(X)X=BatchNormalization(axis=3,name="bn_cov1")(X)X=MaxPooling2D(pool_size=(3,3),strides=2)(X)#搭建stage2:一个卷积块和两个恒等快,卷积块中卷积核大小均为3*3,卷积核个数分别为64,64,256,恒等快的卷积核大小均为3*3,卷积核大小为3*3#卷积核个数分别为64,64,256X=cov_block(X,f=3,filters=[64,64,256],stage=2,block="a",s=1)X=identity_block(X,f=3,filters=[64,64,256],stage=2,block="b")X=identity_block(X,f=3,filters=[64,64,256],stage=2,block="c")#搭建stage3:一个卷积块和3个恒等快,卷积块的卷积核的大小为3*3,卷积核的个数128,128,512;恒等块的卷积核大小为3*3,卷积核的个数为#128,128,512X=cov_block(X,f=3,filters=[128,128,512],stage=3,block="a",s=2)X=identity_block(X,f=3,filters=[128,128,512],stage=3,block="b")X=identity_block(X,f=3,filters=[128,128,512],stage=3,block="c")X=identity_block(X,f=3,filters=[128,128,512],stage=3,block="d")#搭建stage4:一个卷积块和5个恒等块,卷积块中卷积核的大小为3*3,卷积核个数为256,256,1024,恒等快卷积核的大小为3*3,卷积核个数分别为256#256,1024X=cov_block(X,f=3,filters=[256,256,1024],stage=4,block="a",s=2)X=identity_block(X,f=3,filters=[256,256,1024],stage=4,block="b")X=identity_block(X,f=3,filters=[256,256,1024],stage=4,block="c")X=identity_block(X,f=3,filters=[256,256,1024],stage=4,block="d")X=identity_block(X,f=3,filters=[256,256,1024],stage=4,block="e")X=identity_block(X,f=3,filters=[256,256,1024],stage=4,block="f")#搭建stage5:一个卷积块与两个恒等快,卷积块中卷积核大小为3*3,卷积核个数为512,512,2048,恒等快中卷积核的大小为3*3,卷积核的个数分别为512#512,2048X=cov_block(X,f=3,filters=[512,512,2048],stage=5,block="a",s=2)X=identity_block(X,f=3,filters=[512,512,2048],stage=5,block="b")X=identity_block(X,f=3,filters=[512,512,2048],stage=5,block="c")#搭建平均池化层X=AveragePooling2D(pool_size=(2,2),name="avg_pool",strides=1,padding="same")(X)#搭建平坦层X=Flatten()(X)#输出层X=Dense(units=10,activation="softmax",name="fc")(X)#调用model函数,定义所搭建的网络模型model=Model(inputs=X_input,outputs=X,name="resnet50")return model
model=resnet()
#模型编译
model.compile(loss="categorical_crossentropy",optimizer="adam",metrics=["accuracy"]
)
model.summary()
#模型训练
n_epoch=4
batch_size=128
def run_resnet():training=model.fit(X_train,Y_train,epochs=n_epoch,batch_size=batch_size,validation_split=0.25,verbose=1)test=model.evaluate(X_train,Y_train,verbose=1)return training,test
training,test=run_resnet()
print("误差:",test[0])
print("准确率:",test[1])def show_history(training_history,train,validation):plt.plot(training.history[train],linstyle="-",color="b")plt.plot(training.history[validation],linstyle="--",color="r")plt.title("Training history")plt.xlabel("epoch")plt.ylabel("accuracy")plt.legend(["train","validation"],loc="lower right")plt.show()
show_history(training,"accuracy","val-accuracy")def show_history1(training_history,train,validation):plt.plot(training.history[train],linstyle="-",color="b")plt.plot(training.history[validation],linstyle="--",color="r")plt.title("Training history")plt.xlabel("epoch")plt.ylabel("loss")plt.legend(["train","validation"],loc="upper right")plt.show()
show_history1(training,"loss","val-loss")prediction=model.predict(X_test)
def image_show(image):fig=plt.gcf()fig.set_size_inches(2,2)fig.imshow(image,cmap="binary")plt.show()
def result(i):image_show(X_test1[i])print("真实值:",Y_test1[i])print("预测值:",np.argmax(prediction[i]))
result(1)
result(0)

经典卷积网络进阶--ResNet详解相关推荐

  1. 经典卷积网络进阶--GoolgleNet详解

    一.GoolgleNet概述 GoogLeNet是google推出的基于Inception模块的深度神经网络模型,在2014年的ImageNet竞赛中夺得了冠军.其性能比vgg网络更好.通常来说提高网 ...

  2. 经典卷积神经网络--AlexNet的详解

    一.AlexNet的概述 AlexNet由Geoffrey和他的学生Alex提出,并在2012年的ILSVRC竞赛中获得了第一名.Alexnet共有8层结构,前5层为卷积层,后三层为全连接层. Ale ...

  3. 经典卷积神经网络--LeNet-5的详解

    一.LeNet概述 LeNet由Yann Lecun 创建,并将该网络用于邮局的邮政的邮政编码识别,有着良好的学习和识别能力.LeNet又称LeNet-5,具有一个输入层,两个卷积层,两个池化层,3个 ...

  4. 经典卷积网络:AlexNet、ZFNet、VGG、GoogleNet、ResNet

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.AlexNet 1.理论介绍 2.代码实现 model部分 二.ZFNet 三.VGG 四.GoogleNet 五 ...

  5. 41_经典卷积网络、LeNet、AlexNet、VGG、GoogleNet、ResNet、NIN、DenseNet、EfficientNet、MobileNetV1/2/3、SENet等

    1.38.经典卷积网络 1.38.1.LeNet 1.38.1.1.介绍 1.38.1.2.网络结构 1.38.1.3.代码实现 1.38.2.AlexNet 1.38.2.1.介绍 1.38.2.2 ...

  6. 【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理(1)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  7. Incremental-Network-Quantization增量网络量化论文详解

    Incremental-Network-Quantization增量网络量化论文详解 笔者将从以下几个方面分析该论文的原理及其实现,由于笔者能力有限,如有错误望诸公指正. 论文作者代码:https:/ ...

  8. 轻量级网络之mobilenet_v1详解

    轻量级网络之mobilenet_v1详解 前言:学习网络结构有一段时间了,记录下mobilenet_v1的结构 论文地址:https://arxiv.org/pdf/1704.04861.pdf 一. ...

  9. AI 以 5:0 比分击败美顶级飞行员;经典对抗攻击 Deepfool 原理详解

    开发者社区技术周刊又和大家见面了,快来看看这周有哪些值得我们开发者关注的重要新闻吧. 2019 年全球公共云服务市场总额达 2334 亿美元 新里程碑!IBM 宣布最高量子体积 64 马斯克将通过实时 ...

最新文章

  1. httpd默认配置文件详解
  2. 通过 .gitlab-ci.yml配置任务-官方配置文件翻译
  3. github snap android,GitHub - albuer/heapsnap: HeapSnap 是一个定位内存泄露的工具,适用于Android平台。...
  4. USACO SEC.1.2 No.4 Palindromic Squares
  5. 【MD5】加密/解密大小写问题
  6. 好货日报邀请码54321软件的操作逻辑
  7. MFC中绘制动态曲线
  8. “康园圈--互联网+校园平台“项目之成果展示及项目总结
  9. vue键盘抬起_vue实现编辑器键盘抬起时内容跟随光标距顶位置向上滚动效果
  10. 【实践】多业务建模在美团搜索排序中的实践
  11. 蓝桥杯BASIC-28 基础练习 Huffuman树
  12. WebLogic部署项目成功后,访问Error 404
  13. jquery ajax提交form表单,jquery+ajax提交form表单方法总结
  14. 使用EasyCHM破解版制作CHM帮助文档
  15. 通过系统日志采集大数据
  16. 计算机功能转动怎么设定,怎么旋转电脑屏幕
  17. NLP入门(十)使用LSTM进行文本情感分析
  18. 并发控制五(封锁的粒度)
  19. 1、如何给视频和照片进行调色
  20. static、const、volatile等关键字作用

热门文章

  1. boost::geometry::bg::model::multi_linestring用法的测试程序
  2. boost::fusion::map用法的测试程序
  3. boost::endian模块实现benchmark的测试程序
  4. Boost:parallel grep测试程序
  5. VTK:可视化之TextureMapImageData
  6. VTK:Qt之RenderWindowNoUiFile
  7. VTK:PolyData之InterpolateTerrain
  8. VTK:图片之ImageGradientMagnitude
  9. VTK:图表之TreeBFSIterator
  10. OpenCV在相机或图像中检测QR码的实例(附完整代码)