写点什么

pytorch 实现空洞卷积 + 残差网络实验(torch 实现

作者:Studying_swz
  • 2022-11-16
    天津
  • 本文字数:3732 字

    阅读完需:约 12 分钟

pytorch实现空洞卷积+残差网络实验(torch实现

一:pytorch 实现空洞卷积实验(torch 实现)要求:从至少一个数据集上进行实验,同理,这里我选取了车辆分类数据集(后面的实验都是用的车辆分类数据集),主要在之前利用 torch.nn 实现二维卷积的基础上,为解决感受野比较的问题,将普通的卷积修改为空洞卷积,并且卷几率符合 HDC 条件(这里我选取了 1,2,5),并且堆叠了 2 层 HDC,即一共六层卷积层。实验过程:注:所谓的空洞卷积,与https://blog.csdn.net/qq_37534947/article/details/109726153的 torch.nn 实现的二维卷积除了模型的定义部分不一样之外,其他的如:数据集、画图、计时、优化器等都是一样的,当然参数设置可能会有些不同,主要在实验结果区分,所以我这里主要针对模型定义做相关介绍。1.1 空洞卷积模型定义


1.  #pytorch封装卷积层  2.  class ConvModule(nn.Module):  3.      def __init__(self):  4.          super(ConvModule,self).__init__()  5.          #定义六层卷积层  6.          #两层HDC(1,2,5,1,2,5)  7.          self.conv = nn.Sequential(  8.              #第一层 (3-1)*1+1=3 (64-3)/1 + 1 =62   9.              nn.Conv2d(in_channels = 3,out_channels = 32,kernel_size = 3 , stride = 1,padding=0,dilation=1),  10.              nn.BatchNorm2d(32),  11.              # inplace-选择是否进行覆盖运算  12.              nn.ReLU(inplace=True),  13.              #第二层 (3-1)*2+1=5 (62-5)/1 + 1 =58   14.              nn.Conv2d(in_channels = 32,out_channels = 32,kernel_size = 3 , stride = 1,padding=0,dilation=2),  15.              nn.BatchNorm2d(32),  16.              # inplace-选择是否进行覆盖运算  17.              nn.ReLU(inplace=True),  18.              #第三层 (3-1)*5+1=11  (58-11)/1 +1=48  19.              nn.Conv2d(in_channels = 32,out_channels = 64,kernel_size = 3 , stride = 1,padding=0,dilation=5),  20.              nn.BatchNorm2d(64),  21.              # inplace-选择是否进行覆盖运算  22.              nn.ReLU(inplace=True),  23.               #第四层(3-1)*1+1=3 (48-3)/1 + 1 =46   24.              nn.Conv2d(in_channels = 64,out_channels = 64,kernel_size = 3 , stride = 1,padding=0,dilation=1),  25.              nn.BatchNorm2d(64),  26.              # inplace-选择是否进行覆盖运算  27.              nn.ReLU(inplace=True),  28.              #第五层 (3-1)*2+1=5 (46-5)/1 + 1 =42   29.              nn.Conv2d(in_channels = 64,out_channels = 64,kernel_size = 3 , stride = 1,padding=0,dilation=2),  30.              nn.BatchNorm2d(64),  31.              # inplace-选择是否进行覆盖运算  32.              nn.ReLU(inplace=True),  33.              #第六层 (3-1)*5+1=11  (42-11)/1 +1=32  34.              nn.Conv2d(in_channels = 64,out_channels = 128,kernel_size = 3 , stride = 1,padding=0,dilation=5),  35.              nn.BatchNorm2d(128),  36.              # inplace-选择是否进行覆盖运算  37.              nn.ReLU(inplace=True)  38.                39.          )  40.          #输出层,将通道数变为分类数量  41.          self.fc = nn.Linear(128,num_classes)  42.            43.      def forward(self,x):  44.          #图片经过三层卷积,输出维度变为(batch_size,C_out,H,W)  45.          out = self.conv(x)  46.          #使用平均池化层将图片的大小变为1x1,第二个参数为最后输出的长和宽(这里默认相等了)   47.          out = F.avg_pool2d(out,32)  48.          #将张量out从shape batchx128x1x1 变为 batch x128  49.          out = out.squeeze()  50.          #输入到全连接层将输出的维度变为3  51.          out = self.fc(out)  52.          return out 
复制代码


注:可以从上面可以看出一共有 6 个空洞卷积层,其空洞率分别是 1、2、5、1、2、5;1、2、5 不包含大于 1 的公约数,所以其是包含 2 个的 HDC,然后其每一层的输入和输出的算法见注释。


二:pytorch 实现残差实验(torch 实现)要求:从至少一个数据集上进行实验,这里我选取了车辆分类数据集,在给定结构的残差网络中,进行模型的搭建以及训练。实验结构:



实验过程:这里实验过程和 4 上面大部分一样,主要是模型设计不同,所以这里主要介绍一下给定的残差网络的模型实现代码。2.1 残差网络块的实现


1.  #残差网络块  2.  #每个残差块都是两层  3.  #默认3*3卷积下padding为1,则大小不会变化,如变化则是步长引起的。  4.  class ResidualBlock(nn.Module):  5.      def __init__(self, nin, nout, size, stride=1, shortcut=True):  6.          super(ResidualBlock, self).__init__()  7.          #两层卷积层  8.          #不同步长只有第一层卷积层不同  9.          self.block1 = nn.Sequential(nn.Conv2d(nin, nout, size, stride, padding=1),  10.                                      nn.BatchNorm2d(nout),  11.                                      nn.ReLU(inplace=True),  12.                                      nn.Conv2d(nout, nout, size, 1, padding=1),  13.                                      nn.BatchNorm2d(nout))  14.          self.shortcut = shortcut  15.          #解决通道数变化以及步长不为1引起的图片大小的变化  16.          self.block2 = nn.Sequential(nn.Conv2d(nin, nout, size, stride, 1),  17.                                      nn.BatchNorm2d(nout))  18.          self.relu = nn.ReLU(inplace=True)  19.    20.      def forward(self, input):  21.          x = input  22.          out = self.block1(x)  23.          '''''若输入输出维度相等直接相加,不相等改变输入的维度--包括大小和通道'''  24.          if self.shortcut:  25.              out = x + out  26.          else:  27.              out = out + self.block2(x)  28.          out = self.relu(out)  29.          return out  
复制代码


注:这部分主要借鉴的是 ppt 和网上残差的实现,主要定义了每个残差块内的卷积操作,给定的残差结构内都是两个卷积,,所以这里的 self.block1 就是其实现,然后因为在残差块的开始会有通道的改变,以及步长的改变,从而导致图片的长和宽变化,所以定义了 self.shortcut 定义是否会导致变化,然后利用 self.block2 定义的卷积进行改变输入的大小使得通道可以相加 2.2 模型定义


1.  #定义给定的残差结构  2.  class resnet(nn.Module):  3.      def __init__(self):  4.          super(resnet, self).__init__()  5.          self.block = nn.Sequential(nn.Conv2d(3, 64, 3, stride=1, padding=1),  6.                                     nn.BatchNorm2d(64),  7.                                     nn.ReLU())  8.          #t表示2个相同的残差块,每个残差块两个卷积  9.          self.d1 = self.make_layer(64, 64, 3, stride=1, t=2)  10.          self.d2 = self.make_layer(64, 128, 3, stride=2, t=2)  11.          self.d3 = self.make_layer(128, 256, 3, stride=2, t=2)  12.          self.d4 = self.make_layer(256, 512, 3, stride=2, t=2)  13.    14.          self.avgp = nn.AvgPool2d(8)  15.          self.exit = nn.Linear(512, 3)  16.    17.      def make_layer(self, in1, out1, ksize, stride, t):  18.          layers = []  19.          for i in range(0, t):  20.              if i == 0 and in1 != out1:  21.                  layers.append(ResidualBlock(in1, out1, ksize, stride, None))  22.              else:  23.                  layers.append(ResidualBlock(out1, out1, ksize, 1, True))  24.          return nn.Sequential(*layers)  25.    26.      def forward(self, input):  27.          x = self.block(input)  # 输出维度 64 * 64 * 64    C * H * W  28.          x = self.d1(x)  # 输出维度 64 * 54 * 54  29.          x = self.d2(x)  # i=0 步长为2,输出维度128 * 32 * 32  30.          x = self.d3(x)  # i=0 步长为2,输出维度256 * 16 * 16   31.          x = self.d4(x)  # i=0 步长为2,输出维度512 * 8 * 8  32.          x = self.avgp(x)  # 512 * 1 * 1  33.          #将张量out从shape batchx512x1x1 变为 batch x512  34.          x = x.squeeze()  35.          output = self.exit(x)  36.          return output  
复制代码


注:这部分就是主要的模型结构的实现,定义了 make_layer 函数可以进行相同连续残差块的计算,然后调用之前定义好的残差块。


完整代码及数据集下载,见:https://download.csdn.net/download/qq_37534947/13117846

发布于: 刚刚阅读数: 4
用户头像

Studying_swz

关注

还未添加个人签名 2020-12-23 加入

还未添加个人简介

评论

发布
暂无评论
pytorch实现空洞卷积+残差网络实验(torch实现_深度学习_Studying_swz_InfoQ写作社区