目录
1. ResNet 介绍
2. ResNet 网络介绍(ResNet34)
3. 搭建ResNet 网络
residual block
ResNet
pre 传播
layer1
layer2
layer3、4
全连接层的forward
ResNet 网络的参数个数
summary
4. 训练网络
5. 预测图片
6. Code
7. 迁移学习
ResNet 的亮点:
- 超深的网络结构,可以突破1000层
- 提出residual 模块
- 使用Batch Normalization 抑制过拟合,丢弃Dropout方法
针对第一点,我们知道加深网络层对于提升网络性能至关重要。然而实际情况中,网络层的加深会导致学习无法进行,性能会更差。因为网络的深度会导致梯度消失或者梯度爆炸的问题
因为层数的加深,反向传播的时候,更新权重w的时候,根据链式法则可能要乘上很多项。
例如传过来的是个0.5,那么网络层数深就会导致 0.5 的n次方,从而导致梯度消失,网络无法学习。同理,梯度爆炸是 > 1的概念。
ResNet 提出了一个residual block 残差块的概念,如图。通过右面的一种shortcut 捷径的方式,这样在反向传播的时候,shortcut 就可以将梯度传递过来,从而解决梯度消失或者爆炸的问题。通过这个快捷路径,从而解决了网络加深的问题。
然后,ResNet 使用了 BN (Batch Normalization)代替了Dropout 方法。
根据之前的预处理方式,我们知道,将数据限定到相似的范围内可以帮助网络更好的训练(之前看吴恩达视频的时候,说是特征缩放到类似的区间,这样损失函数就会是一个类似于碗的样子,这样方便梯度下降。否则,可能会是一个碗被挤压的样子,在steep的一边,梯度就会来回横跳)。例如之前的ToTensor,Normalize 等等。
但是之前都是对数据进行特征缩放,然而我们Normalization后的数据经过网络的时候就已经不是之前归一化之类的数据了,所以BN的思想是在每一层后也正规化一下
经过上面的变换,就可以将每一个 batch 的数据变成mean = 0 ,std = 1的分布
这里要注意以下两点:
- 因为bias 是上下平移,而归一化的时候bias有没有都一样,所以这里的卷积可以不需要bias
- 这里是将每一个batch 所以的图像都做BN变换,具体的设置如下
ResNet 因为加入了shortcut 捷径的方式可以加深更多的网络层。这里常见的resnet有如下的几种,这里只介绍ResNet34
这里50、101、152 每个residual block 第一个都是 1*1 是为了改变特征图的size。观察可以发现,例如conv3_x 、conv4_x、conv5_x 的第一个残差块的第一层右面的shortcut都是虚线
这是因为这里的shortcut需要用1 * 1 的卷积核改变size
并且在conv3_x 、conv4_x、conv5_x 残差块的第一层 3*3 卷积核的stride也发生了变化
因为步长发生了变化,所以这里输出特征图和输入的size以及不是一样了。而右面的shortcut想要和左面的发生叠加,要保证shape一样,所以右面的shortcut上面需要一个1*1 的卷积核来改变size
因为ResNet 网络里面包含很多的residual block
3*3 代表卷积核的size ,64 代表卷积核的个数 = 图像输出的深度
就是网络中上面的结构,所以先将它们封装成一个类
因为residual 结构都是两个3*3 卷积构成的,所以这里先将Conv2d的kernel_size 设置为3
网络结构中没有标stride的都是默认为1,但是这里第一个stride不能直接等于1,因为有的层第一个是2,不是1---------> 所有shortcut是虚线对应的第一个卷积核
然后,经过BN层,ReLU层,残差块的第二个卷积都是3*3 ,且默认stride = 1
这里padding =1 的原因
- 图像输出的size = (in - 3 + 2*1) / 1 + 1 = in 才能保证输出的size是等于输入的
- 如果stride = 2,那么out = (in - 3 + 2*1) / 2 + 1 =in / 2 + 0.5 = in / 2 (向下取整),这样就会将输出的size变成一半,所以conv3_x 、conv4_x、conv5_x 残差块的第一层和上面的size是不一样的。那么右面的捷径就不能由上面直接流过来,因为size不一样没法相加。所以对应的shortcut是虚线,需要特殊的 1*1 卷积核改变size
- 并且,由于BN,所以不需要偏置 b
接下来定义forward:
残差块的传播分为两类,一类是左边主路的传播,这里定义成left。
右边是快捷路径,这里分为两种情况,一种是上游直接传过来,另一种是图像size被改变需要1*1卷积核做运算。如果是第一种,那么为None,residual = x,如果被改变,就为新的shortcut。最后和左边的out相加,经过ReLU输出就可以了
为了方便图像维度的讲解,这里会传入一个batch = 10 的224*224*3 的彩色图像
为了不引起误会,后面描述的依旧是batch而不是10
例如:图像shape:batch*64*56*56 而不是10*64*56*56
pre 传播
首先定义ResNet 前面的传播
因为这里图像的输入是224*224*3 的彩色图像。
首先经过7*7 ,stride = 2 的卷积核,这里padding = 3的原因是为了保证输出size是输入的一半
再经过3*3 最大池化层,就可以将图像的输出维度控制在:batch*64*56*56
这里的stride、padding 都是为了保证图像的size 满足
layer1
这里_make_layer 第一个参数为残差块里面卷积核的size,3、4、6、3为每层包含残差块的个数
首先看第一层
- 用裂变将每一层网络存到layers里面
- 观察网络的结构,conv2_x 的所有卷积核stride 都为1,也就是说conv2_x 里面,图像的shape都是一样的,所有这也是为什么这里shortcut 都是实线,因为它不需要1*1的卷积核改变shape
- 所有第一层(conv2_x)里面的stride = 1,那么就会进入里面的else(这里的if else是为了搭建每个layer 的第一个residual block,因为有stride变化的残差块只在每一个layer的第一个)
- 后面的残差块都是一样的,根据传入的个数(这里是3、4、6、3)搭建残差块就行了
- 经过第一层之后,图像的size是:batch*64*56*56
- 这里的*layers 是将layers每个residual block模块取出来
layer2
如图,第二层(conv3_x)的第一个残差块已经发生了变化,
这里的变化是指:
- stride 由 1变成了2,所以会导致图像的size 变为原来的一半
- 并且图像的深度变成了原来的2倍(因为size减少,少了一部分的特征,所以就拿深度来弥补了)
- 那么这里就会进入if判断,shortcut捷径就不能直接从上游传过来,因为上面的图像是现在的2倍。所以shortcut 需要一个1*1的卷积核,stride =2 就能把上游size减半传到捷径上了。并且这里的第一个residual block 的深度要保证一致,即输入的channel是上面的,输出因为size减少,这里将channel 变成2倍
- 至于后面的残差块都是一样的,保证channel 都是128,size 都是28*28就行了
- batch*128*28*28
layer3、4
layer3和layer4都是和layer2一样的
经过layer3的shape是:batch*256*14*14
经过layer4的shape是:batch*512*7*7
全连接层的forward
全连接层:
forward:
ResNet 网络的参数个数
网络的参数个数可由以下得到:
ResNet 参数个数为:
- ResNet 网络基本上都是3*3 的卷积核组成的
- 3*3 卷积核在stride = 1、padding = 1的情况下,不改变图像的size。所以大部分的shortcut捷径可以直接传递和输出相加
- 而conv3_x、conv4_x、conv5_x 由于卷积核的stride =2,导致输出特征图是输入特征图的一半。那么捷径从上游传过来的size就是2倍了,所以这里需要1*1 stride = 2的卷积核去减半shortcut 的size
- 图像的size减半,相当于提取的特征减少。那么为了更好的提取特征,就将输出特征图的个数变为原来的2倍 = 卷积核的个数
训练网络的代码不做讲解,具体的可以看这篇文章:
pytorch 搭建 LeNet 网络对 CIFAR-10 图片分类
主要对GPU训练的部分做讲解:
首先判断设备:
然后将网络扔到设备上:
然后训练的时候,输入也需要传到GPU
最后就是测试的时候
这里读取的时候需要注意,因为训练的时候实在GPU上,这里我预测的时候实在cpu上,所以读取网络参数的时候,代码要变成下面这样
预测图像
这里有一个注意点:
因为CIFAR10 图像的size 都是32*32 的,而ResNet网络的输入是224*224。那么预处理时候需要将图像放大,这里就会很模糊。所以在预测的时候,有个smart point就是,将预测的图像也转换成32*32,然后再放大成224*224。这样预测的精度就会上升
处理结果:
这里网上随便找了几张图片,都能预测对且有较好的准确率:
ResNet 网络部分:
训练部分:
预测部分:
迁移学习其实就是将别人学习过的权重拿来用,将它们作为初始值训练的过程
因为最后的分类往往是根据自己的设置,建议将官方的权重copy,然后加一个分类层就可以了
例如:将原网络的输出再加一个全连接层
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/79566.html