如何在Tensorflow实现ResNet网络
实现ResNet使用的也是先搭建网络,然后评价迭代耗时的方法,在这里我们把 代码分成了ResNet_struct.py和ResNet_run.py,其中ResNet_struct.py用来搭建网络,ResNet_run.py用来评测网络,今天主要介绍ResNet_struct.py,我们先从搭建网络开始,导入一些需要用到的库:
接下来创建一个Block类,这个类用来配置残差学习模型的大小。初始化一个Block类需要传入3个参数:name、residual_unit和args。其中name就是这个残差学习模块的名称。residual_unit指的就是创建这个残差学习模块用到的函数,args指的就是残差学习模块的大小信息。
接下来定义一个conv2d_same()函数,创建卷积层:
接下来通过函数 residual_unit()定义残差学习单元的创建过程。我们来看一下 residual_unit()函数的参数, inputs 是输入,它是模拟的图像数据集经由 ResNet 最开始的卷积层和池化层处理得到。residual_unit()被创建 ResNet结构的主函数 resnet_v2()所调用,在 resnet_v2()函数中则先是创建了 ResNet最开始的卷积层和池化层。depth、degpth_residual和stride3个参数可以对应到Blocks类中的args,实际上args是一个由元组组成的列表,每一个元组中包含3个值,分别是一个残差学习单元中第三个卷积层的输出通道数、前两个卷积层的输出通道数以及中间卷积层的步长。接下来就是残差单元的实现,每一个残差单元中都用到了BatchNomalization,。(这是一种正则化操作,针对每一批数据,在网络的每一层输入之前增加归一化处理(均值为0,标准差为1),这样做的目的是为了增强模型的泛化能力。)
函数 residual_unit()的重点是创建残差 (代码中的 residual ),也就是3 层卷积。第一个卷积的核大小为 1 x 1,步长为1、输出通道数由 depth_residual 参数确定;第二个卷积的核大小为 3 x 3 、步长由 sride 参数确定、输出通道数由 depth_residual 参数确定;第二个卷积的核大小为1x1、步长为1、输出通道数由 depth 参数确定。在经过3步卷积后得到残差 residual 的结果,将这个结果与identity相加,得到最后结果ouput。ouput通过slim.utils.coBeet_named_outputs()函数添加进 collection 就可以作为结果返回。以下是函数源码:
接下来是学习ResNet的各个残差学习模块在resnet_v2_152()函数中的配置,整个网络的4个残差学习模块的残差学习单元输了分别是3,8,36,4,总层数为((3+8+36+3)x3+2)=152此外需要注意的是,残差学习模块之前的卷积,池化已经将尺寸缩小了4倍。除此之外前3个残差学习模块又都包含步长为2的层。以下是resnet_v2_152()的源码:
在resnet_v2_152()函数的返回值中,调用了生成 ResNet V2 的主函数resnet_v2()。使用 resnet_v2()函数就可以生成对应的完整的 ResNet。关于 resnet_v2()函数的参数,inputs 就是模拟的图片数据集,由resnet_v2_ l 52()函数传递到 resnet_v2()函数blocks 就是在 resnet_v2_152()函数内定义好的 Block 类的列表:num classes 是最后输出的类数,在外部我们会赋值为 1000,也是经由 resnet_v2_1 52()函数传递到 resnet_v2()函数,以下就是resnet_v2()函数的源码:
以上就是ResNet_struct.py的全部内容,在实现ResNet_struct.py的过程中我们用到了很多陌生的函数,这些东西都需要我们慢慢去学习消化。
关注小鲸融创,一起深度学习金融科技!