pytorch复现resnet
1.Resnet网络介绍(个人理解)
对于传统的CNN,层数在25层之前,准确率会随着层数增加提高。但是一旦层数过深,网络过于庞大,准确率反而会下降。而Resnet较好的解决了这一问题。其原因在于:
Resnet具有一定的记忆性,在第一次进入某个卷积块(多个卷积层)时,Tensor0
(输入)通过卷积块进行前向传播得到Tensor1
,之后,如果Tensor0
与Tensor1
维数不一致,Tensor0
通过downsample
(下采样,包含一个卷积层和一个BatchNorm层)转成和Tensor1
维度一致的Tensor2
。然后将Tensor1
和Tensor2
或Tensor0
(Tensor0,Tensor2取决于有没有downsample)相加,最后将上一步的结果通过relu激励函数,便得到一个卷积块最终的输出。这样的方法使得计算Tensor1
等同于计算残差,而Tensor2
就等同于原输入,这样的话即使Tensor1
无法对识别做出贡献,Tensor2
也不会让其影响之后的网络,可以有效避免梯度消失等问题,这种残差网络会使得网络之间的依赖性不会特别强,不会因为前面网络的问题影响整个网络的准确性。
ps:以上仅为个人理解,如有错误,欢迎批评
2.网络结构与复现代码
上图为下述代码中Block的一种特殊情况
上图为完整的网络结构,但是还有一些细节上面没有,比如bn,relu,以及什么时候size减半,下面我写的代码有介绍
import torch.nn as nn
import torch.nn.functional as F
class Block(nn.Module):
def __init__(self,in_planes,out_planes,stride=1,downsample=None):
super(Block,self).__init__()
# conv1为网络中1*1的卷积核所在的那一层,以图片为例,为1*1,64
self.conv1 = nn.Conv2d(in_planes,out_planes,kernel_size=1,stride=1,bias=False)
self.bn1 = nn.BatchNorm2d(out_planes)
# conv2为网络中3*3的卷积核所在的那一层,这一层的stride要根据构造函数中的stride变化,
# 原因在于conv_2x卷积块的尺寸减半是maxpool的结果,所以之后的卷积不能再减小尺寸了,
# 而conv3_x及以后的卷积块尺寸减半是stride=2的结果,同时要注意padding=1才能达到上述的尺寸变换
self.conv2 = nn.Conv2d(out_planes,out_planes,kernel_size=3,stride=stride,padding=1,bias=False)
self.bn2 = nn.BatchNorm2d(out_planes)
self.conv3 = nn.Conv2d(out_planes