• 【2020暑假学习】第三次作业:卷积神经网络 part2


    问题总结

    • 当模型准确率已经较高时,如何判断自己的改动是否提升了性能。因为可能每一次准确率变化都不太大,而且每次训练的模型最后准确率也会有波动,多运行几次取准确率平均值做比较吗?
    • 在想要提高性能的改进过程中,有很多改变可能都对性能的提升有些许的帮助。这个过程是一种一种方法的尝试,不断累积提升了性能的改变吗。比如先改了batch_size,找到了一个合适的大小,然后就固定使用这个大小,再调整优化器损失函数之类的?在调整的时候总有一种虽然当前的尝试没有提高性能,但说不定和别的组合在一起可能会变好的想法,简直要进行排列组合。

    代码练习

    MobileNet V1

    • 如何判断nn.Conv2d(3, 3)是做的图一运算而不是图二?

      通过Conv2d函数中的groups参数区别。groups取值范围为1 - in_channels。groups=1时做图二运算,groups=3时做图一运算。

      若groups=x,则将输入通道分为x份,输出通道分为x份,对应每份分别做全卷积。

      举例:nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=3)

      卷积核大小为torch.Size([6, 2, 1, 1])

    参考:卷积层中的 group 参数理解

    pytorch的conv2d函数groups分组卷积使用及理解

    MobileNet V2

    • “MobileNet V1 的主要问题: Depthwise Conv确实是大大降低了计算量,但实际中,发现不少训练出来的kernel是空的。”

      因为Depthwise每个kernel dim 相对于vanilla conv要小得多, 过小的kernel dim, 加上ReLU的激活影响下, 使得神经元输出很容易变为0, 所以就学废了。ReLU对于0的输出的梯度为0, 所以一旦陷入了0输出, 就没法恢复了。

    HybridSN

    class HybridSN(nn.Module):
        def __init__(self):
            super(HybridSN, self).__init__()
            self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0)
            self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0)
            self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0)
            self.conv4 = nn.Conv2d(576, 64, kernel_size=3, stride=1, padding=0)
            self.bn1 = nn.BatchNorm2d(64)
            self.fc1 = nn.Linear(18496, 256)
            self.dropout1 = nn.Dropout(p=0.4)
            self.fc2 = nn.Linear(256, 128)
            self.dropout2 = nn.Dropout(p=0.4)
            self.fc3 = nn.Linear(128, class_num)
    
        def forward(self, x):
            out = self.conv1(x)
            out = self.conv2(out)
            out = self.conv3(out)
            #print(batch)
            out = out.reshape(batch, 576, 19, 19)
            out = self.conv4(out)
            out = self.bn1(out)
            out = F.relu(out)
            out = out.view(-1, 64 * 17 * 17)
            out = self.fc1(out)
            out = F.relu(out)
            out = self.dropout1(out)
            out = self.fc2(out)
            out = F.relu(out)
            out = self.dropout2(out)
            out = self.fc3(out)
            return out
    
    • 每次分类的结果都不一样

      在model(test)之前,需要加上model.eval(),其作用是为了固定BN和dropout层,使得偏置参数不随着发生变化。否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有batch normalization层所带来的的性质。

      BN的作用主要是对网络中间的每层进行归一化处理,并且使用变换重构Batch Normalization Transform保证每层提取的特征分布不会被破坏。

      训练时是针对每个mini-batch的,但是测试是针对单张图片的,即不存在batch的概念。在做one classification的时候,训练集和测试集的样本分布是不一样的。

      Dropout在train时随机选择神经元而predict要使用全部神经元并且要乘一个补偿系数。

      BN在train时每个batch做了不同的归一化因此也对应了不同的参数,相应predict时实际用的参数是每个batch下参数的移动平均。

      加上model.eval()后准确率不再变化,但第一次测试分类准确率会变,因为model.eval()固定了dropout层,使用全部神经元而不是随机选择,所以准确率会发生一次变化。

    • 进一步提升高光谱图像的分类性能

      • HybridSN准确率 95.28% 98.05% 97.75%

      • 二维卷积层改为深度可分离卷积 98.76% 98.59% 98.71%

      • 转为二维+三维 98.07% 98.48% 98.30%

      #二维卷积层改为深度可分离卷积
      class HybridSN(nn.Module):
          def __init__(self):
              super(HybridSN, self).__init__()
              self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0)
              self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0)
              self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0)
      
              # Depthwise 卷积,3*3 的卷积核,分为 in_planes,即各层单独进行卷积
              self.conv4 = nn.Conv2d(576, 576, kernel_size=3, stride=1, padding=0, groups=576, bias=False)
              self.bn1 = nn.BatchNorm2d(576)
              # Pointwise 卷积,1*1 的卷积核
              self.conv5 = nn.Conv2d(576, 64, kernel_size=1, stride=1, padding=0, bias=False)
              self.bn2 = nn.BatchNorm2d(64)
      
              self.fc1 = nn.Linear(18496, 256)
              self.dropout1 = nn.Dropout(p=0.4)
              self.fc2 = nn.Linear(256, 128)
              self.dropout2 = nn.Dropout(p=0.4)
              self.fc3 = nn.Linear(128, class_num)
      
          def forward(self, x):
              out = F.relu(self.conv1(x))
              out = F.relu(self.conv2(out))
              out = F.relu(self.conv3(out))
              out = out.reshape(batch, 576, 19, 19)
              
              out = F.relu(self.bn1(self.conv4(out)))
              out = F.relu(self.bn2(self.conv5(out)))
              
              out = out.view(-1, 64 * 17 * 17)
              out = self.fc1(out)
              out = F.relu(out)
              out = self.dropout1(out)
              out = self.fc2(out)
              out = F.relu(out)
              out = self.dropout2(out)
              out = self.fc3(out)
              return out
      
      #转为二维+三维
      class HybridSN(nn.Module):
          def __init__(self):
              super(HybridSN, self).__init__()
              self.conv4 = nn.Conv2d(30, 64, kernel_size=3, stride=1, padding=0)
              self.bn1 = nn.BatchNorm2d(64)
              self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0)
              self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0)
              self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0)
              self.fc1 = nn.Linear(480896, 256)
              self.dropout1 = nn.Dropout(p=0.4)
              self.fc2 = nn.Linear(256, 128)
              self.dropout2 = nn.Dropout(p=0.4)
              self.fc3 = nn.Linear(128, class_num)
      
          def forward(self, x):
              out = x.reshape(batch, 30, 25, 25)
              out = self.conv4(out)
              out = self.bn1(out)
              out = F.relu(out)
              
              out = out.reshape(batch, 1, 64, 23, 23)
              out = F.relu(self.conv1(out))
              out = F.relu(self.conv2(out))
              out = F.relu(self.conv3(out))
              
              out = out.view(-1, 32 * 52 * 17 * 17)
              out = self.fc1(out)
              out = F.relu(out)
              out = self.dropout1(out)
              out = self.fc2(out)
              out = F.relu(out)
              out = self.dropout2(out)
              out = self.fc3(out)
              return out
      

    论文笔记

    DnCNN

    第一次用深度学习来做图像去噪。

    残差学习:拟合H(x),由于网络退化问题难以训练出来,转为训练F(x),F(x)=H(x)-x,F(x)称为残差,然后H(x)=F(x)+x。

    根据ResNet中的理论,当残差为0时,堆积层之间等价于恒等映射,而恒等映射是非常容易训练优化的。作者注意到在图像复原领域(尤其是在噪音程度较小的情况下),噪音图片与纯净图片的残差非常小,所以理论上残差学习非常适合运用到图像复原上。

    DnCNN是将网络的输出直接改成residual image(残差图片),设纯净图片为x,带噪音图片为y,假设y=x+v,则v是残差图片。即DnCNN的优化目标不是真实图片与网络输出之间的MSE(均方误差),而是真实残差图片与网络输出之间的MSE。

    SENet

    解决了什么问题:注意力机制

    对各个特征图赋予权重,不再是简单的相加,而是加权求和。强调重要的部分,忽略不重要的部分。

    还可以用于哪些地方:可以把C抬平,强调在不同位置上的重要性。

    SE模块首先对卷积得到的特征图进行Squeeze操作,采用global average pooling来实现,然后对全局特征进行Excitation操作,学习各个channel间的关系,得到不同channel的权重,最后乘以原来的特征图得到最终特征。

    深度监督跨模态检索(DSCMR)

    跨模态检索是指在不同模态数据之间的检索,比如通过一张图片检索与之相关的文本、音视频等数据,或者通过一段文本检索与之相关的图片等数据。

    解决跨模态检索的主要方法有两种,一种是学习不同模态数据的实值表示,通过距离度量(如余弦距离、欧氏距离等)进行相关度排序的方法;另一种是学习不同模态数据的二值哈希码,通过度量汉明距离进行相关度排序的方法,这种方法又称为跨模态哈希,由于汉明距离计算的高效性,跨模态哈希在大规模跨模态检索中运用十分广泛,而利用深度学习进行的跨模态哈希,即为深度跨模态哈希。

    • 如何度量不同类型数据之间的内容相似性。

      深度监督跨模态检索(DSCMR):目的是找到一个共同的表示空间,在这个空间中可以直接比较来自不同模式的样本。

  • 相关阅读:
    npm的qs包的使用:stringify()将json对象序列化成表单数据
    git放弃本地某个文件或所有文件的修改
    git关联本地分支和远程分支, 在本地删除远程已经不存在的分支
    vs code代码提示的问题
    js BOM(二)offset系列,scroll系列,client系列,封装变速动画函数
    解决antd design的Modal组件弹出卡顿的问题
    js BOM(一)window、location、history、navigator、定时器setInterval,setTimeout,轮播图
    BizCharts渲染多条曲线时color的使用
    js DOM(三)节点、元素创建3种方式、为元素绑定多个事件addEventListener、attachEvent
    HDU 1081 To The Max
  • 原文地址:https://www.cnblogs.com/liuyifan0211065/p/13458237.html
Copyright © 2020-2023  润新知