卷积神经网络中各模块的作用

实验背景

    在学习卷积神经网络的时候,总是被其中的许多模块(层)搞糊涂:到底网上说的这些操作是真的能提高测试的准确率吗?那它又是如何提高的呢?带着这样的疑问,我就开始了实验。
    本实验的目的是通过针对各个模块的对照试验,得到能够提高网络性能的模块以及原理。

实验环境

  • python 3.6
  • pytorch 1.0.0
  • jupyter 1.0.0
  • 实验数据集:CIFAR10

实验内容

  1. torchvision.datasets中的数据集CIFAR10,并设置批数量为100,代码如下:
batch_size = 100
train_dataset = dsets.CIFAR10(root = './data', train = True, transform = transforms.ToTensor(), download = True)
test_dataset = dsets.CIFAR10(root = './data', train = False, transform = transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, batch_size = batch_size, shuffle = True, drop_last = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset, batch_size = batch_size, shuffle = False, drop_last = True)
  1. 设置网络,首先设置一个原始网络。其网络结构如下:
    卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
    最大池化层(size = 2, stride = 2) ->
    卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
    最大池化层(size = 2, stride = 2) ->
    卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
    最大池化层(size = 2, stride = 2) ->
    全连接层(in_feature = 1024, out_feature = 10) ->
    激活函数层(ReLU)

其代码为如下:

class Net1(nn.Module):
    def __init__(self):
        super(Net1, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out
  1. 接下去设置若干个对照组:全连接对照组、卷积对照组、激活函数对照组、批归一层对照组、dropout对照组。每一个组内增加或减少其中的某些模块,观察准确率变化的情况。下面是所有组的网络结构简洁信息:
    在这里插入图片描述

下面给出所有组内每一个神经网络的具体信息:

全连接对照组——网络2结构:在网络1的基础上增加一层全连接层和激活函数层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 1024, out_feature = 100) ->
激活函数层(ReLU) ->
全连接层(in_feature = 100, out_feature = 10) ->
激活函数层(ReLU)
网络2代码:

class Net2(nn.Module):
    def __init__(self):
        super(Net2, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(1024, 100)
        self.fc2 = nn.Linear(100, 10)
        self.relu = nn.ReLU()
        
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc1(out)
        out = self.relu(out)
        out = self.fc2(out)
        out = self.relu(out)
        return out

全连接对照组——网络3结构:在网络2的基础上删除一层激活函数层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 1024, out_feature = 100) ->
全连接层(in_feature = 100, out_feature = 10) ->
激活函数层(ReLU)
网络3代码:

class Net3(nn.Module):
    def __init__(self):
        super(Net3, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(1024, 100)
        self.fc2 = nn.Linear(100, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc1(out)
        out = self.fc2(out)
        out = self.relu(out)
        return out

全连接对照组——网络4结构:在网络1的基础上增加两个全连接层和两个激活函数层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 1024, out_feature = 500) ->
激活函数层(ReLU)
全连接层(in_feature = 500, out_feature = 100) ->
激活函数层(ReLU)
全连接层(in_feature = 100, out_feature = 10) ->
激活函数层(ReLU)
网络4代码:

class Net4(nn.Module):
    def __init__(self):
        super(Net4, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(1024, 500)
        self.fc2 = nn.Linear(500, 100)
        self.fc3 = nn.Linear(100, 10)
        self.relu = nn.ReLU()
        
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc1(out)
        out = self.relu(out)
        out = self.fc2(out)
        out = self.relu(out)
        out = self.fc3(out)
        out = self.relu(out)
        return out

全连接对照组——网络5结构:在网络5的基础上删除两个激活函数层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 1024, out_feature = 500) ->
全连接层(in_feature = 500, out_feature = 100) ->
全连接层(in_feature = 100, out_feature = 10) ->
激活函数层(ReLU)
网络5代码:

class Net5(nn.Module):
    def __init__(self):
        super(Net5, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(1024, 500)
        self.fc2 = nn.Linear(500, 100)
        self.fc3 = nn.Linear(100, 10)
        self.relu = nn.ReLU()
        
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc1(out)
        out = self.fc2(out)
        out = self.fc3(out)
        out = self.relu(out)
        return out

卷积对照组——网络6结构:在网络1的基础上删除一个卷积层和两个最大池化层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 2048, out_feature = 10) ->
激活函数层(ReLU)
网络6代码:

class Net6(nn.Module):
    def __init__(self):
        super(Net6, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(2048, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

卷积对照组——网络7结构:在网络1的基础上删除两个卷积层和两个最大池化层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 4096, out_feature = 10) ->
激活函数层(ReLU)
网络7代码:

class Net7(nn.Module):
    def __init__(self):
        super(Net7, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(4096, 10)
        self.relu = nn.ReLU()
        
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

卷积对照组——网络8结构:在网络1的基础上增加一个卷积层和一个最大池化层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 64, out_channels = 128) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络8代码:

class Net8(nn.Module):
    def __init__(self):
        super(Net8, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.conv4 = nn.Conv2d(64, 128, 3, padding = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(512, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = self.conv4(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

卷积对照组——网络9结构:在网络1的基础上增加两个卷积层和两个最大池化层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 64, out_channels = 128) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 128, out_channels = 256) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 256, out_feature = 10) ->
激活函数层(ReLU)
网络9代码:

class Net9(nn.Module):
    def __init__(self):
        super(Net9, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.conv4 = nn.Conv2d(64, 128, 3, padding = 1, stride = 1)
        self.conv5 = nn.Conv2d(128, 256, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(256, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = self.conv4(out)
        out = self.maxpool(out)
        out = self.conv5(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

激活函数对照组——网络10结构:在网络1的基础上增加三个激活函数层,加在最大池化层之后
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
激活函数层(ReLU) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
激活函数层(ReLU) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
激活函数层(ReLU) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络10代码:

class Net10(nn.Module):
    def __init__(self):
        super(Net10, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.relu(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.relu(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = self.relu(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

激活函数对照组——网络11结构:在网络1的基础上增加三个激活函数层,加在卷积层之后
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络11代码:

class Net11(nn.Module):
    def __init__(self):
        super(Net11, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.relu(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.relu(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.relu(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

激活函数对照组——网络11结构:在网络1的基础上增加三个激活函数层,加在卷积层之后
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
激活函数层(ReLU) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络11代码:

class Net11(nn.Module):
    def __init__(self):
        super(Net11, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.relu(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.relu(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.relu(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

激活函数对照组——网络12结构:在网络1的基础上删除一个激活函数层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10)
网络12代码:

class Net12(nn.Module):
    def __init__(self):
        super(Net12, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return out

批归一对照组——网络13结构:在网络1的基础上增加三个BN层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
批归一化层 ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
批归一化层 ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
批归一化层 ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络13代码:

class Net13(nn.Module):
    def __init__(self):
        super(Net13, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.bn1 = nn.BatchNorm2d(16)
        self.bn2 = nn.BatchNorm2d(32)
        self.bn3 = nn.BatchNorm2d(64)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.bn2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.bn3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

批归一对照组——网络14结构:在网络1的基础上增加一个BN层
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
批归一化层 ->
激活函数层(ReLU)
网络14代码:

class Net14(nn.Module):
    def __init__(self):
        super(Net14, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.bn = nn.BatchNorm1d(10)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.bn(out)
        out = self.relu(out)
        return out

dropout对照组——网络15结构:在网络1的基础上增加一个dropout层(丢弃率=0.5)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
dropout层(p=0.5) ->
激活函数层(ReLU)
网络15代码:

class Net15(nn.Module):
    def __init__(self):
        super(Net15, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(p = 0.5)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.dropout(out)
        out = self.relu(out)
        return out

dropout对照组——网络16结构:在网络1的基础上增加三个dropout层(丢弃率=0.5)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
dropout层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
dropout层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
dropout层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络16代码:

class Net16(nn.Module):
    def __init__(self):
        super(Net16, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(p = 0.5)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

dropout对照组——网络17结构:在网络1的基础上增加一个dropout2d层(丢弃率=0.5, 维度=2)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
dropout2d层(p=0.5) ->
激活函数层(ReLU)
网络17代码:

class Net17(nn.Module):
    def __init__(self):
        super(Net17, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout2d(p = 0.5)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.dropout(out)
        out = self.relu(out)
        return out

dropout对照组——网络18结构:在网络1的基础上增加三个dropout2d层(丢弃率=0.5, 维度=2)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
dropout2d层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
dropout2d层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
dropout2d层(p=0.5) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络18代码:

class Net18(nn.Module):
    def __init__(self):
        super(Net18, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout2d(p = 0.5)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

dropout对照组——网络19结构:在网络1的基础上增加一个dropout层(丢弃率=0.1)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
dropout层(p=0.1) ->
激活函数层(ReLU)
网络19代码:

class Net19(nn.Module):
    def __init__(self):
        super(Net19, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(p = 0.1)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.dropout(out)
        out = self.relu(out)
        return out

dropout对照组——网络20结构:在网络1的基础上增加三个dropout层(丢弃率=0.1)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
dropout层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
dropout层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
dropout层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络20代码:

class Net20(nn.Module):
    def __init__(self):
        super(Net20, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(p = 0.1)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out

dropout对照组——网络21结构:在网络1的基础上增加一个dropout2d层(丢弃率=0.1, 维度=2)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
dropout2d层(p=0.1) ->
激活函数层(ReLU)
网络21代码:

class Net21(nn.Module):
    def __init__(self):
        super(Net21, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout2d(p = 0.1)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.dropout(out)
        out = self.relu(out)
        return out

dropout对照组——网络22结构:在网络1的基础上增加三个dropout2d层(丢弃率=0.1, 维度=2)
卷积层(size=3, padding = 1, stride = 1, in_channels = 3, out_channels = 16) ->
dropout2d层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 16, out_channels = 32) ->
dropout2d层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
卷积层(size = 3, padding = 1, stride = 1, in_channels = 32, out_channels = 64) ->
dropout2d层(p=0.1) ->
最大池化层(size = 2, stride = 2) ->
全连接层(in_feature = 512, out_feature = 10) ->
激活函数层(ReLU)
网络22代码:

class Net22(nn.Module):
    def __init__(self):
        super(Net22, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding = 1, stride = 1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding = 1, stride = 1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding  = 1, stride = 1)
        self.maxpool = nn.MaxPool2d(2, 2)
        self.fc = nn.Linear(1024, 10)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout2d(p = 0.1)
    
    def forward(self, x):
        out = self.conv1(x)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv2(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = self.conv3(out)
        out = self.dropout(out)
        out = self.maxpool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        out = self.relu(out)
        return out
  1. 设置损失函数、正则化器、训练、测试过程。对每一个网络进行三训练,并记录准确率和LOSS值,对于准确率,求平均值
net = Net22().cuda() # 在训练的时候修改该行调用的类
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr = learning_rate)

for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = Variable(images).cuda()
        labels = Variable(labels).cuda()
        optimizer.zero_grad()
        outputs = net(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        if (i + 1) % 100 == 0:
            print("Epoch [%d/%d] image[%d/%d] loss:%.4f"%(epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data))

total = 0
correct = 0
for images, labels in test_loader:
    images = Variable(images).cuda()
    outputs = net(images).cuda()
    _, predicted = torch.max(outputs.data, 1)
    correct += (labels == predicted.cpu()).sum()
    total += labels.size(0)
print("Accurancy of the model on the test images:%d %%"%(100 * correct / total))

实验结果

实验结果如下图。
由1、3、5可得,增加全连接层数对准确率的影响并不大,所以大多数模型只在结尾使用一层全连接层。

由1、12、10、11、2、3、4、5可得,在本实验中(图片大小为32*32),并不需要激活函数,使用激活函数可能会导致模型的非线性程度变高,使模型退化。

由1、6、7、8、9可得,当卷积层数过少时,会导致感受野过小,模型学不到参数;而当卷积层数过多时(如编号9),会导致过拟合(LOSS降低,准确率变低)

由1、13、14可得,三层卷积的网络深度并不深,不会引起梯度爆炸/梯度消失,所以添加归一层后准确率并未提高。

由1、15、19可得,因为网络并无过拟合,所以增加dropout不会提高准确率。由15、19、16、20、17、21、18、22可得,将dropout层的丢失率设置太高会使得模型学习不到参数,并且dropout2d的效果明显高于dropout。所以由22行可得,使用dropout2d的最好方法是,设置较小丢失率并多次使用。

在这里插入图片描述

下一步计划:提高模型准确率

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在MATLAB加入Ghost模块,需要先了解Ghost模块的实现原理。 Ghost模块是一种轻量级的模型压缩技术,它通过将输入特征图拆分成两个不重叠的子集,并在每个子集上应用不同的卷核来减少模型的参数量。Ghost模块的核心是Ghost操作,它将输入特征图拆分成两个子集,并在每个子集上应用不同的卷核,最终将两个子集的输出进行拼接得到Ghost模块的输出。 在MATLAB,可以使用深度学习工具箱的函数来实现Ghost模块。具体步骤如下: 1. 定义Ghost操作。可以使用`depthConcatenationLayer`函数和`convolution2dLayer`函数来实现。 ``` numFilters1 = round(numFilters/2); numFilters2 = numFilters - numFilters1; ghostConv1 = convolution2dLayer(filterSize,numFilters1,'Padding',padding,'Name','ghostConv1'); ghostConv2 = convolution2dLayer(filterSize,numFilters2,'Padding',padding,'Name','ghostConv2'); ghostConcat = depthConcatenationLayer(2,'Name','ghostConcat'); ``` 其,`numFilters`为输出通道数,`filterSize`为卷核大小,`padding`为填充方式。 2. 将Ghost操作组合成Ghost模块。可以使用`addLayers`函数和`connectLayers`函数来实现。 ``` GhostLayer = [ ghostConv1 reluLayer('Name','ghostReLU1') ghostConv2 reluLayer('Name','ghostReLU2') ghostConcat ]; lgraph = addLayers(lgraph,GhostLayer); lgraph = connectLayers(lgraph,inputLayer,'ghostConv1'); lgraph = connectLayers(lgraph,inputLayer,'ghostConv2'); lgraph = connectLayers(lgraph,'ghostConv1','ghostReLU1'); lgraph = connectLayers(lgraph,'ghostConv2','ghostReLU2'); lgraph = connectLayers(lgraph,'ghostReLU1','ghostConcat/in1'); lgraph = connectLayers(lgraph,'ghostReLU2','ghostConcat/in2'); ``` 其,`inputLayer`为Ghost模块的输入层。 3. 将Ghost模块插入到卷神经网络。可以使用`layerGraph`函数和`replaceLayer`函数来实现。 ``` lgraph = layerGraph(net); lgraph = replaceLayer(lgraph,'conv3',GhostLayer); ``` 其,`net`为原始的卷神经网络模型,`conv3`为要替换的层的名称。 通过以上步骤,就可以在MATLAB加入Ghost模块了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值