精华内容
下载资源
问答
  • 受空洞卷积在图像信息方面保持优秀性能的启发,为进一步提高分类精度,提出一种基于双通道空洞卷积神经网络(DCD-CNN)的高光谱图像分类框架。空洞卷积可扩展滤波器的感受野,有效地避免图像信息丢失,从而提高分类精度。...
  • 在BERT(pre-training of deep bidirectional transformers)预训练语言模型的基础上,提出一种基于残差空洞卷积神经网络和条件随机场的网络安全实体识别模型 BERT-RDCNN-CRF。通过BERT模型训练字符级特征向量表示,...
  • data_x.shape:",test_data_x.shape) print("test_data_y.shape:",test_data_y.shape) # test_data_x.shape: torch.Size([10000, 1, 28, 28]) # test_data_y.shape: torch.Size([10000]) 五、空洞卷积神经网络的搭建 ...

    一、导包

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from sklearn.metrics import accuracy_score,confusion_matrix,classification_report
    import seaborn as sns
    import copy
    import time
    import torch
    import torch.nn as nn
    from torch.optim import Adam
    import torch.utils.data as Data
    from torchvision import transforms
    from torchvision.datasets import FashionMNIST
    

    二、训练集图像数据准备

    ##图像数据准备
    
    #使用FasnionMNIST数据,准备训练数据集
    train_data = FashionMNIST(
        root = "./data/FashionMNIST",
        train = True,
        transform = transforms.ToTensor(),
        download = True
    )
    #定义一个数据加载器
    train_loader = Data.DataLoader(
        dataset = train_data,
        batch_size = 64,
        shuffle = False,
        num_workers = 2,
    )
    #计算train_loader有多少个batch
    print("train_loader的batch数量为:",len(train_loader))
    # train_loader的batch数量为: 938
    

    三、获取一个batch的图像,将其可视化

    #获得一个batch的数据
    for step,(b_x,b_y) in enumerate(train_loader):
        if step > 0 :
            break
    #可视化一个batch的图像
    batch_x = b_x.squeeze().numpy()
    batch_y = b_y.numpy()
    class_label = train_data.classes
    class_label[0] = "T-shirt"
    plt.figure(figsize = (12,5))
    for ii in np.arange(len(batch_y)):
        plt.subplot(4,16,ii+1)
        plt.imshow(batch_x[ii,:,:],cmap = plt.cm.gray)
        plt.title(class_label[batch_y[ii]],size = 9)
        plt.axis("off")
        plt.subplots_adjust(wspace = 0.05)
    
    

    在这里插入图片描述

    四、测试数据集处理

    #对测试集进行处理
    test_data = FashionMNIST(
        root = "./data/FashionMNIST",
        train = False,
        download = False
    )
    ##为数据添加一个通道维度,并且取值范围缩放到0-1之间
    test_data_x = test_data.data.type(torch.FloatTensor)/255.0
    test_data_x = torch.unsqueeze(test_data_x,dim = 1)
    test_data_y = test_data.targets
    print("test_data_x.shape:",test_data_x.shape)
    print("test_data_y.shape:",test_data_y.shape)
    # test_data_x.shape: torch.Size([10000, 1, 28, 28])
    # test_data_y.shape: torch.Size([10000])
    

    五、空洞卷积神经网络的搭建

    ##空洞卷积神经网络的搭建
    class MyConvdilaNet(nn.Module):
        def __init__(self):
            super(MyConvdilaNet,self).__init__()
            ##定义第一个卷积层
            self.conv1 = nn.Sequential(
                ##卷积后: (1*28*28)---(16*28*28)
                nn.Conv2d(1,16,3,1,1,dilation = 2),
                nn.ReLU(),
                nn.AvgPool2d(2,2), ##(16*26*26)--(16*13*13)
            )
            ##定义第二个卷积层
            self.conv2 = nn.Sequential(
                nn.Conv2d(16,32,3,1,0,dilation=2),
                ##卷积操作 (16*13*13)---(32*9*9)
                nn.ReLU(),
                nn.AvgPool2d(2,2),
            )
            self.classifier = nn.Sequential(
                nn.Linear(32*4*4,256),
                nn.ReLU(),
                nn.Linear(256,128),
                nn.ReLU(),
                nn.Linear(128,10)
            )
        ##定义网络的向前传播路径
        def forward(self,x):
            x = self.conv1(x)
            x = self.conv2(x)
            x = x.view(x.size(0),-1) ##展平多维的卷积图层
            output = self.classifier(x)
            return output
    ##输出网络结构
    myconvdilanet = MyConvdilaNet()
    print(myconvdilanet )
    # MyConvdilaNet(
    #   (conv1): Sequential(
    #     (0): Conv2d(1, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), dilation=(2, 2))
    #     (1): ReLU()
    #     (2): AvgPool2d(kernel_size=2, stride=2, padding=0)
    #   )
    #   (conv2): Sequential(
    #     (0): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), dilation=(2, 2))
    #     (1): ReLU()
    #     (2): AvgPool2d(kernel_size=2, stride=2, padding=0)
    #   )
    #   (classifier): Sequential(
    #     (0): Linear(in_features=512, out_features=256, bias=True)
    #     (1): ReLU()
    #     (2): Linear(in_features=256, out_features=128, bias=True)
    #     (3): ReLU()
    #     (4): Linear(in_features=128, out_features=10, bias=True)
    #   )
    # )
    

    六、卷积神经网络预测与训练—定义网络的训练过程函数

    ##定义网络的训练过程函数
    def train_model(model,traindataloader,train_rate,criterion,optimizer,num_epochs=25):
        #model:网络模型
        #trainloader:训练数据集,会切分为训练集和验证集
        #train_rate:训练集batchsize百分比
        #criterion:损失函数
        #optimizer:优化方法
        #num_epochs:训练的轮数
        ##计算训练使用的batch数量
        batch_num = len(traindataloader)
        train_batch_num = round(batch_num * train_rate)
        ##复制模型的参数
        best_model_wts = copy.deepcopy(model.state_dict())
        best_acc = 0.0
        train_loss_all = []
        train_acc_all = []
        val_loss_all = []
        val_acc_all = []
        since = time.time()
        for epoch in range(num_epochs):
            print('Epoch {}/{}'.format(epoch,num_epochs -1))
            print('-'*10)
            ##每个epoch有两个训练阶段
            train_loss = 0.0
            train_corrects= 0
            train_num= 0
            val_loss = 0.0
            val_corrects = 0
            val_num = 0
            for step,(b_x,b_y) in enumerate(traindataloader):
                if step < train_batch_num:
                    model.train() ##设置模型为训练模式
                    output = model(b_x)
                    pre_lab = torch.argmax(output,1)
                    loss = criterion(output,b_y)
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
                    train_loss += loss.item() * b_x.size(0)
                    train_corrects += torch.sum(pre_lab == b_y.data)
                    train_num += b_x.size(0)
                else:
                    model.eval() #3设置模型为评估模式
                    output = model(b_x)
                    pre_lab = torch.argmax(output,1)
                    loss = criterion(output,b_y)
                    val_loss += loss.item()*b_x.size(0)
                    val_corrects += torch.sum(pre_lab == b_y.data)
                    val_num += b_x.size(0)
            
            ##计算一个epoch在训练集和验证集上的损失和精度
            train_loss_all.append(train_loss/train_num)
            train_acc_all.append(train_corrects.double().double().item()/train_num)
            val_loss_all.append(val_loss/val_num)
            val_acc_all.append(val_corrects.double().item()/val_num)
            print('{} Train Loss:{:.4f}  Train Acc: {:.4f}'.format(epoch,train_loss_all[-1],train_acc_all[-1]))
            print('{} Val Loss:{:.4f}  Val Acc:{:.4f}'.format(epoch,val_loss_all[-1],val_acc_all[-1]))
            ##拷贝模型最高精度下的参数
            if val_acc_all[-1] > best_acc:
                best_acc = val_acc_all[-1]
                best_model_wts = copy.deepcopy(model.state_dict())
            time_use = time.time() - since
            print("Train and val complete in {:.0f}m {:.0f}s".format(time_use // 60,time_use % 60))
        ##使用最好模型的参数
        model.load_state_dict(best_model_wts)
        train_process = pd.DataFrame(
            data = {
                "epoch":range(num_epochs),
                "train_loss_all":train_loss_all,
                "val_loss_all":val_loss_all,
                "train_acc_all":train_acc_all,
                "val_acc_all":val_acc_all
            }
        )
        return model,train_process
    
    

    七、对指定的模型和优化器进行训练

    ##空洞卷积神经网络的训练与预测
    ##对模型进行训练
    optimizer = torch.optim.Adam(myconvdilanet.parameters(),lr=0.0003)
    criterion = nn.CrossEntropyLoss() ##损失函数
    myconvdilanet,train_process = train_model(
        myconvdilanet,train_loader,0.8,criterion,optimizer,num_epochs=25
    )
    # Epoch 0/24
    # ----------
    # 0 Train Loss:0.8865  Train Acc: 0.6777
    # 0 Val Loss:0.6442  Val Acc:0.7471
    # Train and val complete in 0m 17s
    # Epoch 1/24
    # ----------
    # 1 Train Loss:0.6174  Train Acc: 0.7630
    # 1 Val Loss:0.5696  Val Acc:0.7806
    # Train and val complete in 0m 33s
    # ...
    # ...
    # Epoch 23/24
    # ----------
    # 23 Train Loss:0.2665  Train Acc: 0.9008
    # 23 Val Loss:0.3092  Val Acc:0.8849
    # Train and val complete in 7m 3s
    # Epoch 24/24
    # ----------
    # 24 Train Loss:0.2620  Train Acc: 0.9027
    # 24 Val Loss:0.3083  Val Acc:0.8852
    # Train and val complete in 7m 20s
    
    
    ##训练过程中的精度和损失函数可视化
    plt.figure(figsize = (12,4))
    plt.subplot(1,2,1)
    plt.plot(train_process.epoch,train_process.train_loss_all,"ro-",label = "Train loss")
    plt.plot(train_process.epoch,train_process.val_loss_all,"bs-",label = "Val loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("Loss")
    plt.subplot(1,2,2)
    plt.plot(train_process.epoch,train_process.train_acc_all,"ro-",label = "Train acc")
    plt.plot(train_process.epoch,train_process.val_acc_all,"bs-",label = "Val acc")
    plt.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    八、测试集预测,并使用混淆矩阵热力图可视化

    ##对测试集进行预测
    myconvdilanet.eval()
    output = myconvdilanet(test_data_x)
    pre_lab = torch.argmax(output,1)
    acc = accuracy_score(test_data_y,pre_lab)
    print("在测试集上的预测精度为:",acc)
    
    ##可视化
    conf_mat = confusion_matrix(test_data_y,pre_lab)
    df_cm = pd.DataFrame(conf_mat,index = class_label,columns = class_label)
    heatmap = sns.heatmap(df_cm,annot = True,fmt = "d",cmap = "YlGnBu")
    heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(),rotation=0,ha = "right")
    heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(),rotation=45,ha = "right")
    plt.ylabel("True label")
    plt.xlabel("Predict label")
    plt.show()
    # 在测试集上的预测精度为: 0.8846
    

    在这里插入图片描述

    展开全文
  • 空洞卷积神经网络低剂量CT图像去噪.pdf
  • 基于空洞卷积神经网络的金刚石图像语义分割.pdf
  • 基于残差空洞卷积神经网络的网络安全实体识别方法.pdf
  • 面向密集人群计数的两列串行空洞卷积神经网络.pdf
  • 基于空洞卷积神经网络的艺术图像风格重建算法.pdf
  • 基于串联空洞卷积神经网络的网球场景语义分割.pdf
  • 基于空洞卷积神经网络的旋转机械故障诊断方法.pdf
  • 分支空洞卷积神经网络的机加工车间场景语义分割.pdf
  • 基于注意力机制的多尺度空洞卷积神经网络模型.pdf
  • 基于改进空洞卷积神经网络的丘陵山区田间道路场景识别.pdf
  • 基于密集连接空洞卷积神经网络的青藏地区云雪图像分类.pdf
  • 融合空洞卷积神经网络与层次注意力机制的中文命名实体识别.pdf
  • 卷积神经网络-空洞卷积

    千次阅读 2020-06-24 13:39:43
    一、空洞卷积的提出 空洞卷积(atrous convolutions)又名扩张卷积(dilated convolutions),向卷积层引入了一个称为 “扩张率(dilation rate)”的新参数,该参数定义了卷积核处理数据时各值的间距。 该结构的目的...

    一、空洞卷积的提出

    空洞卷积(atrous convolutions)又名扩张卷积(dilated convolutions),向卷积层引入了一个称为 “扩张率(dilation rate)”的新参数,该参数定义了卷积核处理数据时各值的间距。
    该结构的目的是在不用pooling(pooling层会导致信息损失)且计算量相当的情况下,提供更大的感受野。 顺便一提,卷积结构的主要问题如下:
    池化层不可学
    内部数据结构丢失;空间层级化信息丢失。
    小物体信息无法重建 (假设有四个pooling layer 则 任何小于 2^4 = 16 pixel 的物体信息将理论上无法重建。)
    而空洞卷积就有内部数据结构的保留和避免使用 down-sampling 这样的特性,优点明显。

    二、空洞卷积原理

    如下如,卷积核没有红点标记位置为0,红点标记位置同正常卷积核。
    在这里插入图片描述
    假设原始特征为feat0,首先使用扩张率为1的空洞卷积生成feat1,feat1上一点相对feat0感受野为33(如图a);
    然后使用扩张率为2的空洞卷积处理feat1生成feat2(如图b),使第一次空洞卷积的卷积核大小等于第二次空洞卷积的一个像素点的感受野,图b即feat1上一个点综合了图a即feat0上3
    3区域的信息,则生成的feat2感受野为77,即整个图b深色区域;
    第三次处理同上,第二次空洞卷积的整个卷积核大小等于第三次空洞卷积的一个像素点的感受野,图c即feat2上每个点综合了feat0上7
    7的信息(感受野),则采用扩张率为3的空洞卷积,生成的feat3每一个点感受野为1515。
    相比较之下,使用stride为1的普通3
    3卷积,三层之后感受野仅仅为(kernel-1)*layer+1=7。

    三、空洞卷积问题

    感受野跳跃
    我们对同一张图连续三次使用扩张率为1的空洞卷积,观察整张图的中心点的感受野(如下图):
    在这里插入图片描述
    很明显,感受野不连续(我们上一小结的例子就没这个问题,所以空洞卷积依赖网络设计)。
    小尺度物体检测
    类似第一个问题,仍然需要调整扩张率的组合来解决这个问题。
    四、网络设计研究
    第一个特性是,叠加卷积的 dilation rate 不能有大于1的公约数。比如 [2, 4, 6] 则不是一个好的三层卷积,依然会出现 gridding effect。
    第二个特性是,我们将 dilation rate 设计成 锯齿状结构,例如 [1, 2, 5, 1, 2, 5] 循环结构。
    第三个特性是,我们需要满足一下这个式子:
    在这里插入图片描述
    一个简单的例子: dilation rate [1, 2, 5] with 3 x 3 kernel (可行的方案):
    在这里插入图片描述
    而这样的锯齿状本身的性质就比较好的来同时满足小物体大物体的分割要求(小 dilation rate 来关心近距离信息,大 dilation rate 来关心远距离信息)。
    单分支设计的研究
    通向标准化设计:Hybrid Dilated Convolution (HDC),可以很好的满足分割需要,如下图所示:
    在这里插入图片描述
    多分支研究解决多尺度分割
    仅仅(在一个卷积分支网络下)使用 dilated convolution 去抓取多尺度物体是一个不正统的方法。比方说,我们用一个 HDC 的方法来获取一个大(近)车辆的信息,然而对于一个小(远)车辆的信息都不再受用。假设我们再去用小 dilated convolution 的方法重新获取小车辆的信息,则这么做非常的冗余。
    基于港中文和商汤组的 PSPNet 里的 Pooling module (其网络同样获得当年的SOTA结果),ASPP 则在网络 decoder 上对于不同尺度上用不同大小的 dilation rate 来抓去多尺度信息,每个尺度则为一个独立的分支,在网络最后把他合并起来再接一个卷积层输出预测 label。这样的设计则有效避免了在 encoder 上冗余的信息的获取,直接关注与物体之间之内的相关性。
    在这里插入图片描述

    展开全文
  • 网络游戏-基于空洞卷积神经网络的人脸深度和表面法向量预测方法.zip
  • 其中,rf为当前层的每个神经元的感受野大小,k为真实的卷积核大小(与dilation系数有关),rf_stride为当前层的感受野步长,其为前馈网络父节点所有stride的连乘。则由rf = rf + rf_stride * (k-1)可计算出当前层的...

    每个卷积层可视为三元组[kernel_size, stride, dilation],
    每个最大池化层可视为二元组[1, stride]。

    以一个类似Deeplabv3+的Resnet50为例。
    总共有4个block,每个block的layer个数为:[3, 4, 6, 3]。
    以最后一个block的参数为例,有[[3, 1, 1], [3, 1, 2], [3, 1, 4]]。
    感受野计算代码如下:

    layers = [[7, 2], [1, 2], [3, 1], [3, 1], [3, 1], [3, 2], [3, 1], [3, 1], [3, 1], [3, 2],[3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1, 1], [3, 1, 2], [3, 1, 4]]
    rf_stride = 1
    rf = 1
    for layer in layers:
        if len(layer) == 2:
            k = layer[0]
            stride = layer[1]
        if len(layer) == 3:
            kernel_size = layer[0]
            stride = layer[1]
            dilation = layer[2]
            k = (dilation-1)*(kernel_size-1)+kernel_size
        rf = rf + rf_stride * (k-1)
        rf_stride *= stride
    	print(rf)
    

    其中,rf为当前层的每个神经元的感受野大小,k为真实的卷积核大小(与dilation系数有关),rf_stride为当前层的感受野步长,其为前馈网络父节点所有stride的连乘。则由rf = rf + rf_stride * (k-1)可计算出当前层的输出的感受野大小。

    展开全文
  • 博客见:https://blog.csdn.net/qq_37534947/article/details/109727232,主要是空洞卷积以及残差网络的代码实现,包含数据集,框架是pytorch
  • 深度学习之空洞卷积

    2018-03-09 13:46:35
    深度学习之空洞卷积原始出处论文,介绍了空洞卷积实现方法以及实现意义。
  • 在填充锯齿状空洞的卷积通路上构建并行三维卷积神经网络,提取多尺度图像块进行训练,捕获大范围空间信息。利用密集连接的恒等映射特性,将浅层特征叠加到网络末端,在MRI多模态图像中分割出水肿区、增强区、核心区和囊...
  • 卷积神经网络是一种具有局部连接、权重共享特性的深层前馈神经网络。局部连接是指通过引入卷积核,使得每次运算学习的特征只和局部输入相关,极大地减少了计算量和连接层数;权值共享是指学习的特征具有局部不变性,...

    Pytorch系列文章:

    算法系列文章

    大数据系列文章

    实验内容

    二维卷积实验

    卷积神经网络是一种具有局部连接、权重共享特性的深层前馈神经网络。局部连接是指通过引入卷积核,使得每次运算学习的特征只和局部输入相关,极大地减少了计算量和连接层数;权值共享是指学习的特征具有局部不变性,使得对此类特征提取更加充分。
    在深度学习中,卷积的定义和分析数学、信号处理中的定义略有不同。一般地,卷积通过互相关(cross-correlation)计算。给定输入 X ∈ R M × N \textbf{X}\in R^{M\times N} XRM×N 和卷积核 W ∈ R U × V \textbf{W}\in R^{U\times V} WRU×V,它们的互相关为
    y i , j = ∑ u = 1 U ∑ v = 1 V w u , v x i + u − 1 , j + v + 1 y_{i,j}= \sum_{u=1}^{U}{ \sum_{v=1}^{V}{w_{u,v}x_{i+u-1,j+v+1}}} yi,j=u=1Uv=1Vwu,vxi+u1,j+v+1
    也记作:
    Y = W ⊗ X \textbf{Y}=\textbf{W}⊗\textbf{X} Y=WX
    在考虑特征抽取问题时,互相关和卷积的运算是等价的。在卷积的基础上,可以引入卷积核的步长(stride)和填充(padding)来控制提取的特征图的尺寸。
    一般地,卷积的输出大小由参数:卷积核数目( F F F)、卷积核大小( K K K)、步长( S S S)、填充( P P P),和输入图片的通道数( D D D)、宽度( W W W)、高度( H H H)共同决定;其中输出的通道数、宽度、高度分别是:
    D o u t = F D_{out}=F Dout=F
    W o u t = W + 2 P − K S + 1 W_{out}=\frac{W+2P-K}{S}+1 Wout=SW+2PK+1
    H o u t = H + 2 P − K S + 1 H_{out}=\frac{H+2P-K}{S}+1 Hout=SH+2PK+1
    对于每个卷积核,共引入 K × K   × D   + 1 K\times K\ \times D\ +1 K×K ×D +1个参数;由于有F个卷积核,所以共有 F × D × K 2 + F F\times D\times K^2+F F×D×K2+F个参数。
    卷积层(Convolution Layer)通常与汇聚层(Pooling Layer)混合使用。汇聚层是一种下采样(down sample)操作,作用是减少参数和特征的数量、加快运算速度和增加模型的鲁棒性。常用的汇聚包括:最大汇聚和平均汇聚。
    二维卷积实验的目的是:(1)手动实现二维卷积;(2)使用torch实现二维卷积;(3)进行实验结果的分析、超参数的对比分析;(4)复现AlexNet模型;(5)与前馈神经网络的效果进行对比。

    空洞卷积实验

    空洞卷积是指通过在卷积核的元素间插入空隙来增加感受野的方法。对于大小为 K × K K\times K K×K的卷积核,在每两个元素中插入 D − 1 D-1 D1个元素,则空洞卷积核的有效大小是:
    K ′ = K + ( K − 1 ) × ( D − 1 ) K'=K+(K-1)×(D-1) K=K+(K1)×(D1)
    其中:D是空洞卷积的膨胀率。例如:原卷积核大小为 3 × 3 3\times3 3×3,则空洞卷积核的单边大小为 3 + ( 3 − 1 ) × ( 2 − 1 ) = 5 3+\left(3-1\right)\times\left(2-1\right)=5 3+(31)×(21)=5。普通卷积可以视为 D = 1 D=1 D=1时的空洞卷积。
    图1.1:空洞卷积引发的网格效应(gridding effect)[3]
    由于空洞卷积引入了空隙,有一部分特征没有参与计算,且捕获具有一定间隔的特征可能是不相关的。Panqu Wang等人在2018年提出混合空洞卷积条件(Hybrid Dilated Convolution, HDC),对网络中每一层的膨胀率变化规律做出规定。满足此条件的网络可以规避特征空隙、同时捕获远程和近距离信息。
    对于卷积核大小均为 K × K K\times K K×K的N层卷积神经网络,其每一层膨胀率组成的序列分别为: [ r 1 , … , r i , … , r n ] \left[r_1,\ldots,r_i,\ldots,r_n\right] [r1,,ri,,rn],需满足:
    ∀ 1 < i < n , M i ≤ K ∀1<i<n,M_i≤K 1<i<n,MiK
    其中:
    M i = m a x [ r i + 1 − 2 r i , 2 r i − r i + 1 , r i ] Mi=max[r_{i+1}-2r_i,2r_i-r_{i+1},r_i] Mi=max[ri+12ri,2riri+1,ri]
    本实验的目的是:(1)利用torch.nn实现空洞卷积,其中:膨胀率序列(dilation)满足HDC条件,在车辆分类数据集上实验并输出结果;(2)比较空洞卷积和普通卷积的结果;(3)选取1-2个超参数进行对比分析。

    残差网络实验

    在深度神经网络中,如果期望非线性单元 f ( x ; θ ) f\left(\textbf{x};\theta\right) f(x;θ)去逼近目标函数 h ( x ) h(\textbf{x}) h(x);可以考虑将目标函数分解为:
    h ( x ) = x + h ( x ) − x h(\textbf{x})=\textbf{x}+h(\textbf{x})-\textbf{x} h(x)=x+h(x)x
    其中, x \textbf{x} x称为恒等函数(identity function), ( h ( x ) − x ) (h(\textbf{x})-\textbf{x}) (h(x)x)称为残差函数(residue function)。
    根据通用近似定理,非线性单元可以在理论上逼近任意函数。因此,原问题可以进行如下转化:期望 f ( x ) f\left(\textbf{x}\right) f(x)逼近残差函数 ( h ( x ) − x ) (h(\textbf{x})-\textbf{x}) (h(x)x),使得 f ( x ) + x f\left(\textbf{x}\right)+\textbf{x} f(x)+x逼近目标函数 h ( x ) h(\textbf{x}) h(x)
    一般地,残差网络可以通过跳层连接(shortcut connection)实现。过往的实验表明:残差网络可以解决深层神经网络的梯度爆炸、梯度消失和网络退化问题。
    本实验的目的是:(1)复现给定的残差网络架构,分析结果;(2)结合空洞卷积,对比分析实验结果。

    实验环境及实验数据集

    数据集采用车辆分类数据集,共1358张车辆图片,三个类别。其中:随机抽取70%作训练集,30%作测试集。
    实验环境为Linux 3.10.0-1062.el7.x86_64;运算器为NVIDIA GeForce RTX 2080;框架为:Pytorch 1.6.0;采用Pycharm内置的SSH连接进行交互。

    实验过程

    二维卷积实验

    手动实现二维卷积

    要实现卷积,需要依次实现:单通道互相关运算、多通道互相关运算、多卷积核互相关运算。需要说明的是,在Open CV读入的图片格式中,通道(channel)是最后一个维度,因此需要对读取的数据进行通道变换。代码段分别如下。

    #单通道互相关运算
    def corr2d(X,K):
        batch_size,H,W = X.shape
        h,w = K.shape[0],K.shape[1]
        Y = torch.zeros(batch_size,H-h+1,W-w+1).to(device)
        for i in range(Y.shape[1]):
            for j in range(Y.shape[2]):
                area = X[:,i:i+h, j:j+w]
                Y[:,i,j] = (area* K).sum()
        return Y
    
    #多通道互相关运算
    def corr2d_multi_in(X, K):
        res = corr2d(X[:,:,:,0],K[:,:,0])
        for i in range(0,X.shape[3]):
           res += corr2d(X[:,:,:,i],K[:,:,i])
        return res
    
    #多卷积核互相关运算
    def corr2d_multi_in_out(X, K):
        return torch.stack([corr2d_multi_in(X,k) for k in K],dim=1)
    

    定义了互相关运算、二维池化运算后,我们可以把卷积封装成卷积层模块。

    #定义池化层
    def pool2d(X, pool_size, mode='max'):
        p_h, p_w = pool_size,pool_size
        Y = torch.zeros((X.shape[0],X.shape[1],X.shape[2] - p_h + 1, X.shape[3] - p_w + 1))
        for i in range(Y.shape[2]):
            for j in range(Y.shape[3]):
                if mode == 'max':
                    Y[:,:,i, j] = X[:,:,i: i + p_h, j: j + p_w].max()
                elif mode == 'avg':
                    Y[:,:,i, j] = X[:,:,i: i + p_h, j: j + p_w].mean()
        return Y
    
    #定义卷积模块
    class MyConv2D(nn.Module):
        def __init__(self,in_channels,out_channels,kernel_size):
            super(MyConv2D,self).__init__()
            if isinstance(kernel_size,int):
                kernel_size = (kernel_size,kernel_size)
            self.weight = nn.Parameter(torch.randn((out_channels,in_channels)+kernel_size))
            self.bias = nn.Parameter(torch.randn(out_channels,1,1))
        def forward(self,x):
            y = corr2d_multi_in_out(x,self.weight) +self.bias
            return y
    
    

    使用torch实现二维卷积

    使用Pytorch可以直接定义模型完成训练。值得注意的是,由于卷积层的参数和输入图片大小会影响全连接层的参数设置,每一次调整网络架构时,全连接层的维度都需要重新计算。
    此次实验中,我们把数据集中的图片压缩为200*100的尺寸,根据公式(3)~(5),我们可以得出全连接层的维度是15532.

    class ConvModule(nn.Module):
        def __init__(self):
            super(ConvModule,self).__init__()
            self.conv = nn.Sequential(
                nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=0),
                nn.BatchNorm2d(32),
                nn.ReLU(inplace=True)
            )
            self.pool = nn.MaxPool2d(2,2)
            self.fc = nn.Linear(155232, num_classes)
        def forward(self,X):
            out = self.conv(X.float())
            out = self.pool(out)
            out = out.view(out.size(0), -1) # flatten each instance
            out = self.fc(out)
            return out
    

    对不同超参数的实验结果对比分析

    此部分,我们试验了不同的卷积层层数(在ConvModule中定义)和卷积核大小。

    复现AlexNet模型

    AlexNet中引入了Dropout、ReLU激活和局部相应归一化技巧,以提升模型的泛化能力。AlexNet中的局部响应归一化(Local Response Normalization, LRN)是一种对于同层的部分神经元的归一化方法。它受到生物学中侧抑制现象的启发,即:活跃神经元对邻近神经元由平衡和约束作用。数学上,可视作在激活函数的基础上,再做一次简单线性回归。此方法现已被池化层取代,很少应用。此处,我们直接采用[1]中的LRN实现.

    AlexNet是第一个现代深度网络模型,由Krizhevsky等人在2012年参与ImageNet竞赛中提出。由于当时GPU的运算性能限制,当时被拆分为两个子网络进行分别训练。它包含5个卷积层、3个汇聚层和3个全连接层。
    在本实验中,我们主要参照[1]中的AlexNet类进行实验。需要注意的是,多层网络、LRN、ReLU激活可能会带来大规模的梯度爆炸问题,造成损失为NaN。因此,我们在每一层卷积的末尾额外添加了一个BatchNorm层进行归一化处理。

    与前馈神经网络的效果进行对比

    我们将卷积网络与实验2中的网络(代码如下)进行对比。

    layers = collections.OrderedDict([
        ('L1',nn.Linear(154587,192)),
        ('A1',nn.Hardswish()),
        ('drop1', nn.Dropout(p=0.1)),
        ('L2', nn.Linear(192, 96)),
        ('A2', nn.LeakyReLU()),
        ('drop2', nn.Dropout(p=0.1)),
        ('FC', nn.Linear(96,3))
    ])
    AnnNet = nn.Sequential(layers)
    
    

    空洞卷积实验

    在torch中,定义空洞卷积较为简便,只需要修改卷积层的dilation参数即可。

    nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=0, dilation=3) #膨胀率为3
    

    残差网络实验

    在这里插入图片描述

    由于复现的残差网络具有一定的子结构相似性,此处,我们进行了模块化处理。首先,我们定义两层卷积的残差网络:

    class Residual(nn.Module):
        def __init__(self, input_channels,num_channels, use_1x1conv=False, strides=1, **kwargs):
            super(Residual,self).__init__()
            self.conv1 = nn.Conv2d(input_channels,num_channels, kernel_size=3, padding=1,stride=strides,dilation=2)
            self.conv2 = nn.Conv2d(num_channels,num_channels, kernel_size=3, padding=1,dilation=5)
            if use_1x1conv:
                self.conv3 = nn.Conv2d(num_channels,num_channels, kernel_size=1,stride=strides)
            else:
                self.conv3 = None
            # AUTHOR:ZIXIN QIN
            self.bn1 = nn.BatchNorm2d(num_channels)
            self.bn2 = nn.BatchNorm2d(num_channels)
    
        def forward(self, X):
            Y = self.bn1(self.conv1(X))
            Y = F.relu(Y)
            Y = self.bn2(self.conv2(Y))
            if self.conv3:
                X = self.conv3(X)
                return F.relu(Y + X)
            return F.relu(Y)
    
    

    之后,我们定义一层上采样、一层卷积的残差网络:

    class UpsampleResidual(nn.Module):
        def __init__(self, in_channel,out_channel, kernel_size=3,strides=1, **kwargs):
            super(UpsampleResidual, self).__init__()
            self.l1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel, kernel_size=kernel_size, stride=strides,padding=1)
            self.l2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel, kernel_size=kernel_size,stride=1,padding=1)
            self.shortcut = nn.Conv2d(in_channels=in_channel,out_channels=out_channel,kernel_size=1,stride=strides)
        def forward(self,X):
            Y = self.l1(X)
            Y = F.relu(Y)
            Y = self.l2(Y)
            shortcut = self.shortcut(X)
            return F.relu(Y+ shortcut)
    
    

    最终,我们将以上两个模块进行多次复合,得到需要复现的网络:

    class ResidualModule(nn.Module):
        def __init__(self):
            super(ResidualModule,self).__init__()
            self.conv1 = nn.Conv2d(3,64,3)
            self.conv2 = Residual(64,64,True)
            self.conv3 = UpsampleResidual(64,128,3)
            self.conv4 = Residual(128,128, True)
            self.conv5 = UpsampleResidual(128,256,3)
            self.conv6 = Residual(256,256, True)
            self.conv7 = UpsampleResidual(256,512,3)
            self.conv8 = Residual(512,512,True)
            self.pool = torch.nn.AvgPool2d(kernel_size=3)
            self.fc = nn.Linear(460800, num_classes)
            self.process = nn.Sequential(self.conv1,self.conv2,self.conv3,
                                         self.conv4,self.conv5,self.conv6,self.conv7,self.conv8)
        def forward(self,X):
            out = self.process(X)
            out = out.view(out.size(0), -1) # flatten each instance
            out = self.fc(out)
            return out
    

    实验结果

    二维卷积实验

    手动实现二维卷积

    手动定义的卷积没有进行矩阵优化,时间复杂度为 O ( n 4 ) \mathcal{O}\left(n^4\right) O(n4),对运算时间要求较高。经过手动验证,反向传播过程耗费时间过长,无法预计完成模型训练的时间;因此,这里不能提供具体的手动实现的卷积的结果图表,但是可以观察到loss的计算过程。
    在这里插入图片描述

    使用torch实现二维卷积

    在这里插入图片描述
    实验迭代次数为50次时,在测试集、训练集上的loss和准确率变化如上图所示。可以观察到loss的震荡变化和准确率的逐渐上升;但训练集上的表现始终优于测试集,说明模型存在一定的过拟合现象。在GPU环境下,训练两层卷积神经网络模型训练50次epoch的时间为7分钟左右。

    对不同超参数的实验结果对比分析

    卷积核大小的影响

    在这里插入图片描述
    可以观察到:尺寸相对较大的卷积核在训练时收敛更快、总体震荡较小,收敛时精度更高、loss更小。尺寸较小的卷积核在训练过程种震荡趋势明显。总体而言,不同尺寸卷积核的模型在此次训练时都存在着过拟合的趋势;可见,是否过拟合和卷积核大小无关。

    卷积层数的影响

    在这里插入图片描述
    可以观察到:随着卷积层数的增加:在训练阶段,训练集上的震荡更小;在收敛阶段,loss更低,在训练集上的准确率更高。在测试集上,三种网络的精确度表现近似,但卷积层数更多的网络相对收敛更快。

    复现AlexNet模型

    在这里插入图片描述
    在AlexNet上迭代50次的结果如上。可以观察到,随着层数的加深,网络收敛所需的epoch数明显增加。

    与前馈神经网络的效果进行对比

    在这里插入图片描述
    实验结果表明,在本实验所用的车辆分类数据集上,迭代20次时,前馈神经网络的效果适中,效果最优的是三层卷积神经网络。AlexNet在预测准确度的效果不佳,可能是原因是:(1)数据集过小,模型无法充分学习特征;(2)训练次数不够,模型没有收敛。但值得注意的是,AlexNet在测试集和训练集上的表现都非常接近,说明没有出现过拟合现象。

    空洞卷积实验

    空洞卷积实验结果

    在这里插入图片描述
    空洞卷积的实验结果如上。可以观察到:相比于振荡现象明显的普通卷积,空洞卷积模型没有出现过拟合现象,可能是由于空洞卷积能很好地同时提取远近距离特征。

    空洞卷积与普通卷积的效果对比

    在这里插入图片描述
    从图像可以看出:空洞卷积的准确度变化更平稳、在测试集上的精度和普通卷积类似;在同样训练次数下,空洞卷积模型训练集上的精度略低于普通卷积。可能原因是:空洞卷积提取了更多的层次特征,需要更多的迭代次数才能收敛。
    空洞卷积模型相比于普通卷积在时间上略有增加,每次训练平均实际在8分钟左右;但空洞卷积在不同超参数设定下,运行时间变化较大。经过实验验证,可以发现主要耗时的模块在于反向传播部分。

    超参数的对比

    卷积核大小的影响

    在这里插入图片描述
    实验结果表明:在空洞卷积模型训练前期,卷积核大小分别设置为3、3、2时在测试集上的表现较优、且变化趋势较稳定;在训练后期,模型逐渐收敛,卷积核大小对实验结果的影响减少。可能原因是:卷积核的尺寸增加等价于模型参数量增加,所以在训练前期可能会有更好的表达力。在空洞卷积中,尺寸大的卷积核并没有表现出普通卷积中出现的巨大性能提升。

    卷积层数的影响

    在这里插入图片描述
    可以观察到:在收敛阶段,深层的网络在训练集上准确度和loss上表现更好,但在测试集上没有突出的优势。

    残差网络实验

    残差网络实验结果

    在这里插入图片描述
    观察实验结果可知:残差网络在训练集上迭代20次即可达到接近99%的准确率;此外,模型收敛速度非常快。可见,转化后的函数逼近问题更容易学习。

    残差空洞卷积实验结果

    在这里插入图片描述
    实验结果显示,在训练集上,空洞残差卷积具有更高的精度;在测试集上,空洞残差卷积和普通残差卷积表现相似,两者均具有较高的精度。

    实验心得体会

    本次实验遇到的最大的问题是计算效率的问题;此外,在实验中,还有一些细节可以优化::

    • 进入卷积神经网络部分后,定义的网络在CPU上的训练时间已远远超出预期;因此,模型迁移到显存、使用GPU进行训练是必须的。在获取服务器使用权限后、进行模型训练后,我直观地体会到GPU带来的效率提升。
    • 手动实现的卷积时间复杂度太高,目前仍然无法使用。本实验主要使用torch的实现,没有采用手动卷积。如果后续有可能对此部分进行优化,需要对矩阵乘法部分进行Image to Column的并行化处理。
    • 数据集的生成。实验中采用的是OpenCV框架进行读取,但其实OpenCV的通道和RGB颜色的定义和torch中有较大的区别。因此,后续可以考虑使用其它的图片读取框架。
    • 超参数的导入。实验中每一层的超参数(卷积层数、卷积核通道数等)是固定的,但这不方便对超参数进行网格搜索。后续可以针对此问题,设置层数的传参。

    参考文献

    [1] Pytorch手撕经典网络之AlexNet. https://zhuanlan.zhihu.com/p/29786939
    [2] 邱锡鹏,神经网络与深度学习,机械工业出版社,https://nndl.github.io/ , 2020.
    [3] Krizhevsky A, Sutskever I, Hinton G E. Wang P, Chen P, Yuan Y, et al. Understanding convolution for semantic segmentation[C]//2018 IEEE Winter Conference on Applications of Computer Vision (WACV). IEEE, 2018: 1451-1460.
    [4] Zhang, Aston and Lipton, Zachary C. and Li, Mu and Smola, Alexander J. Dive into Deep Learning

    写文不易 欢迎投喂!

    在这里插入图片描述

    展开全文
  • 第五章 卷积神经网络

    千次阅读 多人点赞 2020-01-13 07:49:37
    卷积神经网络卷积一维卷积二维卷积互相关卷积的变种卷积的数学性质交换性导数卷积神经网络用卷积来代替全连接卷积层汇聚层(池化层)典型的卷积网络结构参数学习误差项的计算几种典型的卷积神经网络LeNet-5...
  • 将像素值(从0到255)缩放到[0,1]区间(如您所知,神经网络更喜欢处理小的输入值)。 这看起来可能有点令人畏惧,但是谢天谢地,Keras有一些实用程序来自动处理这些步骤。Keras有一个包含图像处理辅助工具的模块,位于...
  • 针对高光谱影像分类时光谱维数据量巨大的特点,提出一种基于三维空洞卷积残差神经网络的高光谱影像分类方法。该方法以高光谱像元立方体作为数据输入,使用三维卷积核同时提取高光谱数据的空间维和光谱维特征,并通过在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,005
精华内容 1,202
关键字:

空洞卷积神经网络