Navigation

    Gpushare.com

    • Register
    • Login
    • Search
    • Popular
    • Categories
    • Recent
    • Tags
    1. Home
    2. 176****4500
    1
    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 5
    • Best 5
    • Groups 0

    176****4500

    @176****4500

    7
    Reputation
    2
    Profile views
    5
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    176****4500 Unfollow Follow

    Best posts made by 176****4500

    • 提升语义分割效果的方法 OHEM+LovaszSoftmax Loss

      论文:The Lovasz-Softmax loss: A tractable surrogate for the optimization of the intersection-over-union measure in neural networks
      Github:https://github.com/bermanmaxim/LovaszSoftmax
      CVPR2018
      论文提出了LovaszSoftmax,是一种基于IOU的loss,效果优于cross_entropy,可以在分割任务中使用。最终在Pascal VOC和 Cityscapes 两个数据集上取得了最好的结果。
      论文贡献:
      结合Lovasz hinge 和Jaccard loss 解决2值图片的分割问题
      提出了Lovasz-Softmax loss 对多个类别分割的参数设置
      设计了一个基于batch的IOU作为基于dataset IOU的高效代理
      分析和对比各种IOU测量方法
      基于本文的loss,对经典的分割方法的分割效果做出很大的提升

      OHEM
      Training Region-based Object Detectors with Online Hard Example Mining

      (1) 训练过程需要进行参数的空间搜索

      (2) 简单样本与难分辨样本之间的类别不平衡是亟需解决的问题

      (3) 自动地选择难分辨样本来进行训练不仅效率高而且性能好

      (4) 提出了OHEM算法,不仅效率高而且性能好,在各种数据集上表现优越Training Region-based Object Detectors with Online Hard Example Mining

      困难负样本挖掘的方法。困难负样本是指AI模型难以区分的负样本。在模型不断训练的过程中,模型通常会对正样本有着比较高的confidence,但少不了对某些负样本也留有余芥,给了一个不那么接近0的confidence。而困难负例挖掘就是找到这些负例,然后针对性地训练。OHEM提出是一种线上的困难负例挖掘解决方案。使用了这个trick以后,检测模型的准确性有一定提升。

      论文原本是在目标检测上 实际上分割领域用的更广泛
      Cityscapes数据集上的经典方法

      下面是本人实际使用的代码
      分割19类 忽略255
      效果还行 没做消融实验 不确定提升效果

      class OhemCrossEntropy_2D(nn.Module):
          def __init__(self, ignore_index=-1, thresh=0.6, min_kept=350000, weight=None):
              super(OhemCrossEntropy_2D, self).__init__()
              self.thresh = thresh
              self.min_kept = max(1, min_kept)
              self.ignore_index = ignore_index
              self.weight = weight
              self.criterion = nn.CrossEntropyLoss(
                  weight=weight, ignore_index=ignore_index, reduction="none"
              )
              self.ls = Lovasz_softmax(ignore=self.ignore_index)
              self.nll = nn.NLLLoss(weight=weight, ignore_index=self.ignore_index, reduction="none")
              print(weight)
      
          def forward(self, score, target, **kwargs):
              ph, pw = score.size(2), score.size(3)
              h, w = target.size(1), target.size(2)
              if ph != h or pw != w:
                  score = F.upsample(input=score, size=(h, w), mode="bilinear")
              pred = F.softmax(score, dim=1)
              pixel_losses = (self.criterion(score, target) + self.ls(pred, target)).contiguous().view(-1)
              mask = target.contiguous().view(-1) != self.ignore_index
      
              tmp_target = target.clone()
              tmp_target[tmp_target == self.ignore_index] = 0
              pred = pred.gather(1, tmp_target.unsqueeze(1))
              pred, ind = pred.contiguous().view(-1,)[mask].contiguous().sort()
              min_value = pred[min(self.min_kept, pred.numel() - 1)]
              threshold = max(min_value, self.thresh)
              pixel_losses = pixel_losses[mask][ind]
              pixel_losses = pixel_losses[pred < threshold]
              return pixel_losses.mean()
      
      posted in CV领域
      1
      176****4500
    • RE: 【有奖话题NO.1-进行中】你用来跑训练的第一张GPU?说出你的故事~

      @Alice_智享云

      那我可要好好讲讲我用GT 710 登顶Cityscapes Fake Benchmark的故事了

      反转了👊 👊👊 ,记错了捏,原来是用 i7-10700 登顶的。

      posted in 有奖话题
      1
      176****4500
    • 【已下载】SemantiKITTI Semantic Segmentation 数据

      公共数据集中的应该是Semantic Scene Completion的文件 即总大小3.9G的体素文件。
      可以的话 希望上传80G原始大小的Semantic Segmentation的Velodyne point clouds数据。本地上传的话太慢了
      区别如下:已经有的是下面那个 是场景完成分割任务

      posted in 求数据集👁‍🗨更新中
      1
      176****4500
    • MobileNeXT(ECCV 2020)

      在本文中,我们将深入探讨在ECCV 2020上发布的对最近流行的MobileNet体系结构(即MobileNeXt)进行的改造。

      尽管深度神经网络的许多最新进展都倾向于优先考虑性能而不是复杂性,但社区中仍然存在着使深度神经网络更便宜,更高效地用于较小设备的火花。高效神经网络的研究方向多种多样,从二进制神经网络和高效网络到基于组件的研究(例如PyConv和Depthwise卷积层)。经受时间考验的一项工作是MobileNet模型的集合,其中包括MobileNet,MobileNetV2和MobileNetV3。
      在本文中,我们将在ECCV 2020上发布新条目MobileNeXt,以继续在MobileNet系列模型中取得进步。我们将首先回顾一下残差网络和MobileNetV2的瓶颈结构,并讨论它们之间的差异。接下来,我们将介绍在MobileNeXt中提出的经过重新设计的瓶颈结构,然后再深入研究SandGlass块的PyTorch实现。我们将通过研究本文所观察到的结果来总结本文,并附上该模型的缺点。

      Bottleneck Structures
      高性能神经网络体系结构的第一个主要出现无疑是残差网络(称为ResNet)。残差网络一直是现代神经网络体系结构的基础和圣经。这些网络中提出的剩余层由于其改善信息传播的能力而存在于所有新颖的体系结构中。
      693b848e-bd07-4f53-ac79-d8329ab39f35-image.png
      ResNet提出了一个基本的基本可移植结构,称为“残差块”。残差块有两种变体,如上图所示;残差块v1和残差块v2。残差块v1主要用于在CIFAR数据集上评估的较小的ResNet模型,而残差块v2是用于基于ImageNet的模型的讨论最多的块结构。从现在开始,当我们提到残差块时,我们将参考残差块v2,以使讨论与基于ImageNet的模型相关。
      让我们将此“残差瓶颈”分解为它的核心组件,这些组件包括主分支(main branch)和残差连接( residual connection)(也称为“快捷连接”)。
      6784f153-f932-4aae-8fc3-739b501e2720-image.png

      Main Branch
      如上所示,在残差块中,输入首先经过(1x1)(1 x 1)(1x1)点向卷积运算符(注意:点向卷积不影响输入张量的空间尺寸,但用于操纵通道数在张量中)。随后是保留通道的空间(3x3)(3 x 3)(3x3)卷积,这实际上减小了输入张量中特征图的空间尺寸。最后,接着是另一个逐点(1x1)(1 x 1)(1x1)卷积层,该层将通道数增加到与主分支输入相同的数量。
      Residual Connection
      平行于主分支,将输入张量投影到与主分支的输出相同的尺寸。对于剩余连接,唯一需要更改输入的维是空间维,这是通过使用步幅增大的(1x1)(1 x 1)(1x1)卷积算符来实现的,以将空间维与输出的维相匹配。主分支。(注意:此(1x1)(1 x 1)(1x1)卷积不是点运算符。)
      然后,将残差添加到主分支输出中,最后将其传递给标准非线性激活函数(在这种情况下为ReLU)。

      Inverted Residual Connection

      5944351e-fbf2-49d4-a483-8bfe42026b69-image.png

      MobileNeXt
      通过继承倒置残差模块,MobileNetV2取代了其前身MobileNetV1,成为最广泛使用的轻量级体系结构之一。尽管残差块通过残差/快捷方式连接连接了较高维的张量(即,具有更多通道的那些张量),但MobileNetV2提出了通过残差连接来连接瓶颈并将较大的通道张量保持在主分支内的方法,从而对此进行了反转。这是减少所需参数和FLOP的关键重新设计因素之一。

      深度卷积层的使用进一步放大了这一点,每个通道本质上都有一个卷积滤波器。通过这种结构上的改革,MobileNet在诸如ImageNet数据集上的Top-1准确性之类的性能指标上无法胜过其ResNet同类产品(这主要是由于使用了深度卷积运算符,从而减少了特征空间)考虑到与ResNet系列产品相比轻巧,快速和高效,MobileNet仍然能够获得可观的性能。

      SandGlass Block
      0069a2ef-d5b5-420c-8b84-6c28864de6d2-image.png

      • (a) Residual Block (b) Inverted Residual Block © Sand Glass Block

      在我们之前对瓶颈结构的讨论的基础上,MobileNeXt本质上提出了对瓶颈结构的又一次大修,他们将其称为SandGlass块(如上图所示)。抽象而言,SandGlass是经典残差瓶颈和倒置残差瓶颈的简单组合,融合了两个方面的优势。让我们更详细地看一下:
      07ce75a9-de24-44c6-8aa9-2c90f8c404e9-image.png

      • (a) Inverted Residual Bottleneck (b) SandGlass Bottleneck

      SandGlass块本质上是一个经典的残差块,其中主分支中的第一个和最后一个卷积层是保留通道的空间深度卷积层。为了模拟瓶颈结构,它使用两个连续的逐点卷积运算符来首先减少然后增加通道数。这些点运算符堆叠在两个深度卷积层之间。由于现在更大的通道张量由深度内核操作,因此与例如MobileNetV2相比,参数数量大大减少。

      PyTorch代码

      import math
      import torch
      from torch import nn
      
      
      def _make_divisible(v, divisor, min_value=None):
          """
          This function is taken from the original tf repo.
          It ensures that all layers have a channel number that is divisible by 8
          It can be seen here:
          https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
          :param v:
          :param divisor:
          :param min_value:
          :return:
          """
          if min_value is None:
              min_value = divisor
          new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
          # Make sure that round down does not go down by more than 10%.
          if new_v < 0.9 * v:
              new_v += divisor
          return new_v
      
      
      class ConvBNReLU(nn.Sequential):
          def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1, norm_layer=None):
              padding = (kernel_size - 1) // 2
              if norm_layer is None:
                  norm_layer = nn.BatchNorm2d
              super(ConvBNReLU, self).__init__(
                  nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False),
                  norm_layer(out_planes),
                  nn.ReLU6(inplace=True)
              )
      
      
      class SandGlass(nn.Module):
          def __init__(self, inp, oup, stride, expand_ratio, identity_tensor_multiplier=1.0, norm_layer=None, keep_3x3=False):
              super(SandGlass, self).__init__()
              self.stride = stride
              assert stride in [1, 2]
              self.use_identity = False if identity_tensor_multiplier==1.0 else True
              self.identity_tensor_channels = int(round(inp*identity_tensor_multiplier))
      
              if norm_layer is None:
                  norm_layer = nn.BatchNorm2d
      
              hidden_dim = inp // expand_ratio
              if hidden_dim < oup /6.:
                  hidden_dim = math.ceil(oup / 6.)
                  hidden_dim = _make_divisible(hidden_dim, 16)
      
              self.use_res_connect = self.stride == 1 and inp == oup
      
              layers = []
              # dw
              if expand_ratio == 2 or inp==oup or keep_3x3:
                  layers.append(ConvBNReLU(inp, inp, kernel_size=3, stride=1, groups=inp, norm_layer=norm_layer))
              if expand_ratio != 1:
                  # pw-linear
                  layers.extend([
                      nn.Conv2d(inp, hidden_dim, kernel_size=1, stride=1, padding=0, groups=1, bias=False),
                      norm_layer(hidden_dim),
                  ])
              layers.extend([
                  # pw
                  ConvBNReLU(hidden_dim, oup, kernel_size=1, stride=1, groups=1, norm_layer=norm_layer),
              ])
              if expand_ratio == 2 or inp==oup or keep_3x3 or stride==2:
                  layers.extend([
                  # dw-linear
                  nn.Conv2d(oup, oup, kernel_size=3, stride=stride, groups=oup, padding=1, bias=False),
                  norm_layer(oup),
              ])
              self.conv = nn.Sequential(*layers)
      
          def forward(self, x):
              out = self.conv(x)
              if self.use_res_connect:
                  if self.use_identity:
                      identity_tensor= x[:,:self.identity_tensor_channels,:,:] + out[:,:self.identity_tensor_channels,:,:]
                      out = torch.cat([identity_tensor, out[:,self.identity_tensor_channels:,:,:]], dim=1)
                      # out[:,:self.identity_tensor_channels,:,:] += x[:,:self.identity_tensor_channels,:,:]
                  else:
                      out = x + out
                  return out
              else:
                  return out
      

      Results
      ImageNet分类任务的结果
      ca909e54-79d8-4b92-805e-6234c3703f81-image.png

      如上图所示,MobileNeXt在各个方面似乎都比MobileNet更好。就参数而言,它更轻巧,并且仍然获得比其同等MobileNetV2同类产品更高的精度。在随后的表格中,我们将展示MobileNeXt如何执行不同的任务,例如ImageNet数据集上的图像分类和Pascal VOC数据集上的对象检测。

      PASCAL VOC上的目标检测

      QQ截图20210326160814.png

      缺点和进一步的讨论

      • 列表该论文未能提供有关物体检测任务的结论性结果。它还没有进行MS-COCO实验以充分验证其物体检测性能。

      • 列表由于它与经典残差块更相关,因此它使用ResNets的训练方案,而不是MobileNets的训练方案,因此不是苹果与苹果的比较。使用MobileNetV2的训练方案在CIFAR数据集上进行测试时,MobileNeXt的性能比MobileNetV2模型差,如下图所示。
        892b6838-6897-4c33-a9e0-7f69e29d23c0-image.png
        mnetv2表示MobileNet v2,而mxnet表示MobileNeXt。在CIFAR-10分类任务上显示5次平均值。

      总体而言,这是一个非常简单的想法,但可以提供很好的结果,并且它可以很好地成为计算机视觉领域中的默认轻量级模型。

      References

      • MobileNetV2: Inverted Residuals and Linear Bottlenecks

      • MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications Searching for MobileNetV3

      • ReActNet: Towards Precise Binary Neural Network with Generalized Activation Functions

      • EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks

      • Pyramidal Convolution: Rethinking Convolutional Neural Networks for Visual Recognition

      • Xception: Deep Learning with Depthwise Separable Convolutions

      • Rethinking Bottleneck Structure for Efficient Mobile Network Design

      • Deep Residual Learning for Image Recognition

      • Official Implementation of MobileNeXt

      • Unofficial PyTorch implementation of MobileNeXt

      posted in CV领域
      1
      176****4500
    • Channel Attention and Squeeze-and-Excitation Networks (SENet)

      在计算机视觉注意力机制的早期,在CVPR 2018(和TPAMI),Squeeze and Excitation Networks上发表的一篇论文介绍了一种新颖的渠道注意力机制。可以将这种简单而有效的附加模块添加到任何基准体系结构中,以提高性能,而计算开销却可以忽略不计。

      在本文中,我们将分四个部分介绍挤压和激励网络。首先,我们将通过访问现代摄影技术的某些方面来理解为什么频道吸引很重要的直觉。然后,我们将继续介绍在挤压和激发(SE)块中计算频道注意力的方法。接下来,我们将剖析标准架构中的挤压和激发(SE)块的影响,同时评估它们在不同的计算机视觉任务上的作用。我们将对本文提出的方法的某些缺点进行评论。

      现代摄影中的镜框选择

      随着现代摄影技术在智能机制上的改进,以捕捉最佳照片而发展壮大,如今,雷达中最微妙的技术之一就是为静态照片选择最佳的照片。这是某些智能手机的常见功能。
      5a961e20-6f17-4037-938f-06b17e634fb1-image.png
      静止照片中有很多变量。在相同的条件下和相同的环境下,相距一秒的两张拍摄对象的照片仍可能相差很大。例如,在两张照片之一中,他们的眼睛可能闭着。为了获得最佳拍摄效果,最好在拍摄照片的瞬间捕获多个帧,以便摄影师可以选择从所有捕获的帧中选择最佳帧。如今,这是以自动化,智能的方式完成的。像Google Pixel这样的智能手机能够在拍摄一张照片时从所有可用的帧中选择最佳的帧。这种智能机制受光照,对比度,模糊,背景失真等不同因素的影响。

      就现代卷积神经网络体系结构而言,您可以将帧视为由卷积层计算的张量中的通道。该张量通常由(B,C,H,W)维表示,其中B表示批处理大小,C表示通道,H,W表示特征图的空间尺寸(H表示特征图高度和宽度代表宽度)。通道是卷积滤波器从输入中得出不同特征的结果。但是,渠道可能不具有相同的代表重要性。由于某些渠道可能比其他渠道更重要,因此在传播到下一层之前,根据其重要性对渠道施加权重是有意义的。

      我们将以此为基础来了解频道注意的重要性,我们将在以下各节中进行介绍。

      Channel Attention

      基于上一节中描述的直觉,让我们深入了解为什么通道注意力是提高深度卷积神经网络体系结构泛化能力的关键组成部分。
      回顾一下,在卷积神经网络中,有两个主要组成部分:

      • 列表由尺寸(B,C,H,W)表示的输入张量(通常是四维张量)。

      • 列表可训练的卷积滤波器,其中包含该层的权重。

      卷积滤波器负责根据这些滤波器中学习到的权重来构建特征图。一些过滤器学习边缘,其他过滤器学习纹理,并且共同学习由输入张量嵌入的图像内目标类信息的不同特征表示。因此,通道数表示学习输入的不同特征图的卷积滤波器的数量。从我们以前对摄影中的帧选择的理解来看,这些特征图的重要性也不同。这意味着某些功能图比其他功能图更重要。例如,与学习背景纹理转换的另一个特征图相比,包含边缘信息的特征图对于学习可能更为重要和关键。因此,这是引起频道关注的基础。我们希望将这种“注意力”集中在更重要的渠道上,这基本上是要比其他渠道更重视特定渠道。最简单的方法是通过将更重要的通道缩放为更高的值。这正是Squeeze-Excitation Networks提出的建议。

      Squeeze-and-Excitation Networks
      在2018年,Hu等。在CVPR 2018上发表了他们的论文《挤压和激发网络》,并在TPAMI中发布了期刊版本。该论文被认为是注意力机制领域最有影响力的著作之一,迄今已获得1000多次引用。让我们看一下论文的建议。
      ace6815d-cf93-4a77-ad11-35f0ef887024-image.png
      本文提出了一种新颖,易于插入的模块,称为“挤压和激发”模块(缩写为SE-block),该模块由三个组件组成(如上图所示):

      • Squeeze Module
      • Excitation Module
      • cale ModuleS
        让我们更详细地研究这些模块中的每个模块,并理解它们为什么在关注频道方面很重要。

      Squeeze Module
      为了获得最佳的频道关注度,人们希望特征图的缩放适应于特征图本身。概括地说,特征图集本质上是卷积层的输出张量(通常是维数(B,C,H,W)的4-D张量,其中的首字母代表批量的大小,通道,高度和宽度功能图)。为简单起见,我们仅将其视为形状(C,H,W)的3D张量-本质上,我们关注深度(张量中的通道/特征图的数量)和每个特征图的空间尺寸在那个张量中。因此,为了使频道注意力适应每个频道本身,我们有H × W总要关注的像素(或值)。从本质上讲,这意味着要使注意力真正具有适应性,您将总共使用C × H × W值进行操作。该值将变得非常大,因为在现代神经网络中,通道数量随着网络深度的增加而变大。因此,需要使用可以将每个特征图的信息分解为奇异值的特征描述符,将有助于降低整个操作的计算复杂度。
      这形成了挤压模块的动机。存在许多可用于将特征图的空间尺寸减小为奇异值的特征描述符,但是在卷积神经网络中用于减小空间尺寸的通用方法是合并。有两种非常流行的池化方法:平均池化和最大池化。前者计算定义的窗口内的平均像素值,而后者计算相同定义的窗口中的最大像素值。两者都有各自的优缺点。虽然最大池保留了最活跃的像素,但它也可能非常嘈杂,并且不会考虑相邻像素。另一方面,普通池不能保留信息。但是,它可以构造该窗口中所有像素的平滑平均值。
      Excitation Module
      4868b37e-a9f3-47ad-bf43-4a47327ddcd7-image.png
      现在,将输入张量分解为较小的大小(C×1×1),该模块的下一部分将学习这些通道的自适应缩放权重。对于“挤压和激发”模块中的“激发模块”,作者选择了完全连接的多层感知器(MLP)瓶颈结构来映射缩放比例权重。这个MLP瓶颈具有相同形状的单个隐藏层以及输入和输出层。隐藏层用作缩小块,其中将输入空间缩小到由缩小因子(默认设置为16)定义的较小空间。然后将压缩空间扩展回原始尺寸,作为输入张量。用更紧凑的术语来说,可以通过以下三点来定义MLP每一层的尺寸变化:
      1.输入的形状为(C ×1×1)。因此,在输入层中存在C个神经元。
      2…隐藏层将其减少了减少因子r,从而导致C / r神经元总数。
      3.最后,输出被投影回与输入相同的维数空间,总共返回到C个神经元。
      总的来说,您传递了(C ×1×1)张量作为输入,并获得了具有相同形状的加权张量–(C ×1×1)。
      理想情况下,为了改善信息传播和更好的跨通道交互(CCI),应将r设置为1,从而使其成为一个完全连接的正方形网络,每层宽度相同。但是,随着r的减小,在复杂度增加和性能提高之间需要权衡。因此,基于上表,作者使用16作为减速比的默认值。这是一个超参数,具有进一步调整范围以改善性能的范围。
      Scale Module
      从激励模块获得(C ×1×1)“激励”张量后,首先将其传递通过S型激活层,然后将其缩放到0-1的范围。随后,通过简单的广播逐元素乘法将输出直接应用于输入,该乘法使用来自激励模块中MLP的相应学习权重来缩放输入张量中的每个通道/特征图。

      作者对用作激励算子的不同非线性激活函数的影响进行了进一步的消融研究,根据结果​​,作者将Sigmoid确立为性能最佳的激活函数,并因此将其用作缩放模块中的默认激励算子。

      总而言之,挤压激励块(SE块)采用形状为(C × H × W)的输入张量x,通过全局平均池(GAP)将其减小为形状为(C ×1×1)的张量。将这个C长度向量传递到多层感知器(MLP)瓶颈结构中,并输出相同形状的加权张量(C ×1×1),然后对其进行广播并将其与输入x逐元素相乘。

      Code

      • PyTorch
      ### Import necessary packages
      from torch import nn
      
      ### Squeeze and Excitation Class definition
      class SE(nn.Module):
          def __init__(self, channel, reduction_ratio =16):
              super(SE, self).__init__()
              ### Global Average Pooling
              self.gap = nn.AdaptiveAvgPool2d(1)
              
              ### Fully Connected Multi-Layer Perceptron (FC-MLP)
              self.mlp = nn.Sequential(
                  nn.Linear(channel, channel // reduction_ratio, bias=False),
                  nn.ReLU(inplace=True),
                  nn.Linear(channel // reduction_ratio, channel, bias=False),
                  nn.Sigmoid()
              )
      
          def forward(self, x):
              b, c, _, _ = x.size()
              y = self.gap(x).view(b, c)
              y = self.mlp(y).view(b, c, 1, 1)
              return x * y.expand_as(x)
      
      • TensorFlow
      import tensorflow as tf
      
      __all__ = [
          'squeeze_and_excitation_block',
      ]
      
      
      def squeeze_and_excitation_block(input_X, out_dim, reduction_ratio=16, layer_name='SE-block'):
          """Squeeze-and-Excitation (SE) Block
          SE block to perform feature recalibration - a mechanism that allows
          the network to perform feature recalibration, through which it can
          learn to use global information to selectively emphasise informative
          features and suppress less useful ones
          """
      
      
          with tf.name_scope(layer_name):
      
              # Squeeze: Global Information Embedding
              squeeze = tf.nn.avg_pool(input_X, ksize=[1, *input_X.shape[1:3], 1], strides=[1, 1, 1, 1], padding='VALID', name='squeeze')
      
              # Excitation: Adaptive Feature Recalibration
              ## Dense (Bottleneck) -> ReLU
              with tf.variable_scope(layer_name+'-variables'):
                  excitation = tf.layers.dense(squeeze, units=out_dim/reduction_ratio, name='excitation-bottleneck')
              excitation = tf.nn.relu(excitation, name='excitation-bottleneck-relu')
      
              ## Dense -> Sigmoid
              with tf.variable_scope(layer_name+'-variables'):
                  excitation = tf.layers.dense(excitation, units=out_dim, name='excitation')
              excitation = tf.nn.sigmoid(excitation, name='excitation-sigmoid')
      
              # Scaling
              scaler = tf.reshape(excitation, shape=[-1, 1, 1, out_dim], name='scaler')
      
              return input_X * scaler
      

      缺点
      尽管本文本身具有革命性意义,但它在结构上存在某些概述的缺陷,并存在一些不确定的设计策略。

      • 该方法非常昂贵,并且在基线模型的基础上添加了大量参数和FLOPS。尽管在宏伟的方案中,开销可能很小,但是有许多新方法旨在以极低的成本提供频道关注,其效果要比SENets更好,例如ECANet(在CVPR 2020年发布)。

      • 尽管就参数和FLOP开销而言,通道注意似乎是有效的,但一个主要缺陷是缩放操作,在该操作中,广播加权通道矢量并将其逐元素地应用/乘以输入张量。该中间广播张量具有与输入相同的维数空间,从而导致存储器复杂度的大幅增加。这使训练过程变慢并且占用更多的内存。

      • 为了降低计算复杂度,该块的激励模块的MLP中存在瓶颈结构,其中通道数以指定的缩小率减少。这导致信息丢失,因此是次优的。

      • 由于SENet仅通过使用专用的全局特征描述符(在本例中为全局平均池(GAP))来提供频道关注,因此信息丢失并且提供的关注是针对性的。这意味着所有像素均均匀地映射在特征图的空间域中,因此无法区分重要或类别确定性像素与属于背景或不包含有用信息的像素。因此,将空间关注的重要性/需要与频道关注结合起来是合理的。相同的主要示例之一是CBAM(在ECCV 2018上发布)。

      • 有关SENet的设计策略尚无定论。作者指出,这超出了本文的范围,无法理解最佳设置,包括SE模块的位置集成策略和MLP中使用的缩小率。

      References
      Squeeze-and-Excitation Networks, TPAMI 2018.
      CBAM: Convolutional Block Attention Module, ECCV 2018.
      ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks, CVPR 2020.
      SENet original repository.

      posted in CV领域
      1
      176****4500

    Latest posts made by 176****4500

    • MobileNeXT(ECCV 2020)

      在本文中,我们将深入探讨在ECCV 2020上发布的对最近流行的MobileNet体系结构(即MobileNeXt)进行的改造。

      尽管深度神经网络的许多最新进展都倾向于优先考虑性能而不是复杂性,但社区中仍然存在着使深度神经网络更便宜,更高效地用于较小设备的火花。高效神经网络的研究方向多种多样,从二进制神经网络和高效网络到基于组件的研究(例如PyConv和Depthwise卷积层)。经受时间考验的一项工作是MobileNet模型的集合,其中包括MobileNet,MobileNetV2和MobileNetV3。
      在本文中,我们将在ECCV 2020上发布新条目MobileNeXt,以继续在MobileNet系列模型中取得进步。我们将首先回顾一下残差网络和MobileNetV2的瓶颈结构,并讨论它们之间的差异。接下来,我们将介绍在MobileNeXt中提出的经过重新设计的瓶颈结构,然后再深入研究SandGlass块的PyTorch实现。我们将通过研究本文所观察到的结果来总结本文,并附上该模型的缺点。

      Bottleneck Structures
      高性能神经网络体系结构的第一个主要出现无疑是残差网络(称为ResNet)。残差网络一直是现代神经网络体系结构的基础和圣经。这些网络中提出的剩余层由于其改善信息传播的能力而存在于所有新颖的体系结构中。
      693b848e-bd07-4f53-ac79-d8329ab39f35-image.png
      ResNet提出了一个基本的基本可移植结构,称为“残差块”。残差块有两种变体,如上图所示;残差块v1和残差块v2。残差块v1主要用于在CIFAR数据集上评估的较小的ResNet模型,而残差块v2是用于基于ImageNet的模型的讨论最多的块结构。从现在开始,当我们提到残差块时,我们将参考残差块v2,以使讨论与基于ImageNet的模型相关。
      让我们将此“残差瓶颈”分解为它的核心组件,这些组件包括主分支(main branch)和残差连接( residual connection)(也称为“快捷连接”)。
      6784f153-f932-4aae-8fc3-739b501e2720-image.png

      Main Branch
      如上所示,在残差块中,输入首先经过(1x1)(1 x 1)(1x1)点向卷积运算符(注意:点向卷积不影响输入张量的空间尺寸,但用于操纵通道数在张量中)。随后是保留通道的空间(3x3)(3 x 3)(3x3)卷积,这实际上减小了输入张量中特征图的空间尺寸。最后,接着是另一个逐点(1x1)(1 x 1)(1x1)卷积层,该层将通道数增加到与主分支输入相同的数量。
      Residual Connection
      平行于主分支,将输入张量投影到与主分支的输出相同的尺寸。对于剩余连接,唯一需要更改输入的维是空间维,这是通过使用步幅增大的(1x1)(1 x 1)(1x1)卷积算符来实现的,以将空间维与输出的维相匹配。主分支。(注意:此(1x1)(1 x 1)(1x1)卷积不是点运算符。)
      然后,将残差添加到主分支输出中,最后将其传递给标准非线性激活函数(在这种情况下为ReLU)。

      Inverted Residual Connection

      5944351e-fbf2-49d4-a483-8bfe42026b69-image.png

      MobileNeXt
      通过继承倒置残差模块,MobileNetV2取代了其前身MobileNetV1,成为最广泛使用的轻量级体系结构之一。尽管残差块通过残差/快捷方式连接连接了较高维的张量(即,具有更多通道的那些张量),但MobileNetV2提出了通过残差连接来连接瓶颈并将较大的通道张量保持在主分支内的方法,从而对此进行了反转。这是减少所需参数和FLOP的关键重新设计因素之一。

      深度卷积层的使用进一步放大了这一点,每个通道本质上都有一个卷积滤波器。通过这种结构上的改革,MobileNet在诸如ImageNet数据集上的Top-1准确性之类的性能指标上无法胜过其ResNet同类产品(这主要是由于使用了深度卷积运算符,从而减少了特征空间)考虑到与ResNet系列产品相比轻巧,快速和高效,MobileNet仍然能够获得可观的性能。

      SandGlass Block
      0069a2ef-d5b5-420c-8b84-6c28864de6d2-image.png

      • (a) Residual Block (b) Inverted Residual Block © Sand Glass Block

      在我们之前对瓶颈结构的讨论的基础上,MobileNeXt本质上提出了对瓶颈结构的又一次大修,他们将其称为SandGlass块(如上图所示)。抽象而言,SandGlass是经典残差瓶颈和倒置残差瓶颈的简单组合,融合了两个方面的优势。让我们更详细地看一下:
      07ce75a9-de24-44c6-8aa9-2c90f8c404e9-image.png

      • (a) Inverted Residual Bottleneck (b) SandGlass Bottleneck

      SandGlass块本质上是一个经典的残差块,其中主分支中的第一个和最后一个卷积层是保留通道的空间深度卷积层。为了模拟瓶颈结构,它使用两个连续的逐点卷积运算符来首先减少然后增加通道数。这些点运算符堆叠在两个深度卷积层之间。由于现在更大的通道张量由深度内核操作,因此与例如MobileNetV2相比,参数数量大大减少。

      PyTorch代码

      import math
      import torch
      from torch import nn
      
      
      def _make_divisible(v, divisor, min_value=None):
          """
          This function is taken from the original tf repo.
          It ensures that all layers have a channel number that is divisible by 8
          It can be seen here:
          https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
          :param v:
          :param divisor:
          :param min_value:
          :return:
          """
          if min_value is None:
              min_value = divisor
          new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
          # Make sure that round down does not go down by more than 10%.
          if new_v < 0.9 * v:
              new_v += divisor
          return new_v
      
      
      class ConvBNReLU(nn.Sequential):
          def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1, norm_layer=None):
              padding = (kernel_size - 1) // 2
              if norm_layer is None:
                  norm_layer = nn.BatchNorm2d
              super(ConvBNReLU, self).__init__(
                  nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False),
                  norm_layer(out_planes),
                  nn.ReLU6(inplace=True)
              )
      
      
      class SandGlass(nn.Module):
          def __init__(self, inp, oup, stride, expand_ratio, identity_tensor_multiplier=1.0, norm_layer=None, keep_3x3=False):
              super(SandGlass, self).__init__()
              self.stride = stride
              assert stride in [1, 2]
              self.use_identity = False if identity_tensor_multiplier==1.0 else True
              self.identity_tensor_channels = int(round(inp*identity_tensor_multiplier))
      
              if norm_layer is None:
                  norm_layer = nn.BatchNorm2d
      
              hidden_dim = inp // expand_ratio
              if hidden_dim < oup /6.:
                  hidden_dim = math.ceil(oup / 6.)
                  hidden_dim = _make_divisible(hidden_dim, 16)
      
              self.use_res_connect = self.stride == 1 and inp == oup
      
              layers = []
              # dw
              if expand_ratio == 2 or inp==oup or keep_3x3:
                  layers.append(ConvBNReLU(inp, inp, kernel_size=3, stride=1, groups=inp, norm_layer=norm_layer))
              if expand_ratio != 1:
                  # pw-linear
                  layers.extend([
                      nn.Conv2d(inp, hidden_dim, kernel_size=1, stride=1, padding=0, groups=1, bias=False),
                      norm_layer(hidden_dim),
                  ])
              layers.extend([
                  # pw
                  ConvBNReLU(hidden_dim, oup, kernel_size=1, stride=1, groups=1, norm_layer=norm_layer),
              ])
              if expand_ratio == 2 or inp==oup or keep_3x3 or stride==2:
                  layers.extend([
                  # dw-linear
                  nn.Conv2d(oup, oup, kernel_size=3, stride=stride, groups=oup, padding=1, bias=False),
                  norm_layer(oup),
              ])
              self.conv = nn.Sequential(*layers)
      
          def forward(self, x):
              out = self.conv(x)
              if self.use_res_connect:
                  if self.use_identity:
                      identity_tensor= x[:,:self.identity_tensor_channels,:,:] + out[:,:self.identity_tensor_channels,:,:]
                      out = torch.cat([identity_tensor, out[:,self.identity_tensor_channels:,:,:]], dim=1)
                      # out[:,:self.identity_tensor_channels,:,:] += x[:,:self.identity_tensor_channels,:,:]
                  else:
                      out = x + out
                  return out
              else:
                  return out
      

      Results
      ImageNet分类任务的结果
      ca909e54-79d8-4b92-805e-6234c3703f81-image.png

      如上图所示,MobileNeXt在各个方面似乎都比MobileNet更好。就参数而言,它更轻巧,并且仍然获得比其同等MobileNetV2同类产品更高的精度。在随后的表格中,我们将展示MobileNeXt如何执行不同的任务,例如ImageNet数据集上的图像分类和Pascal VOC数据集上的对象检测。

      PASCAL VOC上的目标检测

      QQ截图20210326160814.png

      缺点和进一步的讨论

      • 列表该论文未能提供有关物体检测任务的结论性结果。它还没有进行MS-COCO实验以充分验证其物体检测性能。

      • 列表由于它与经典残差块更相关,因此它使用ResNets的训练方案,而不是MobileNets的训练方案,因此不是苹果与苹果的比较。使用MobileNetV2的训练方案在CIFAR数据集上进行测试时,MobileNeXt的性能比MobileNetV2模型差,如下图所示。
        892b6838-6897-4c33-a9e0-7f69e29d23c0-image.png
        mnetv2表示MobileNet v2,而mxnet表示MobileNeXt。在CIFAR-10分类任务上显示5次平均值。

      总体而言,这是一个非常简单的想法,但可以提供很好的结果,并且它可以很好地成为计算机视觉领域中的默认轻量级模型。

      References

      • MobileNetV2: Inverted Residuals and Linear Bottlenecks

      • MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications Searching for MobileNetV3

      • ReActNet: Towards Precise Binary Neural Network with Generalized Activation Functions

      • EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks

      • Pyramidal Convolution: Rethinking Convolutional Neural Networks for Visual Recognition

      • Xception: Deep Learning with Depthwise Separable Convolutions

      • Rethinking Bottleneck Structure for Efficient Mobile Network Design

      • Deep Residual Learning for Image Recognition

      • Official Implementation of MobileNeXt

      • Unofficial PyTorch implementation of MobileNeXt

      posted in CV领域
      1
      176****4500
    • Channel Attention and Squeeze-and-Excitation Networks (SENet)

      在计算机视觉注意力机制的早期,在CVPR 2018(和TPAMI),Squeeze and Excitation Networks上发表的一篇论文介绍了一种新颖的渠道注意力机制。可以将这种简单而有效的附加模块添加到任何基准体系结构中,以提高性能,而计算开销却可以忽略不计。

      在本文中,我们将分四个部分介绍挤压和激励网络。首先,我们将通过访问现代摄影技术的某些方面来理解为什么频道吸引很重要的直觉。然后,我们将继续介绍在挤压和激发(SE)块中计算频道注意力的方法。接下来,我们将剖析标准架构中的挤压和激发(SE)块的影响,同时评估它们在不同的计算机视觉任务上的作用。我们将对本文提出的方法的某些缺点进行评论。

      现代摄影中的镜框选择

      随着现代摄影技术在智能机制上的改进,以捕捉最佳照片而发展壮大,如今,雷达中最微妙的技术之一就是为静态照片选择最佳的照片。这是某些智能手机的常见功能。
      5a961e20-6f17-4037-938f-06b17e634fb1-image.png
      静止照片中有很多变量。在相同的条件下和相同的环境下,相距一秒的两张拍摄对象的照片仍可能相差很大。例如,在两张照片之一中,他们的眼睛可能闭着。为了获得最佳拍摄效果,最好在拍摄照片的瞬间捕获多个帧,以便摄影师可以选择从所有捕获的帧中选择最佳帧。如今,这是以自动化,智能的方式完成的。像Google Pixel这样的智能手机能够在拍摄一张照片时从所有可用的帧中选择最佳的帧。这种智能机制受光照,对比度,模糊,背景失真等不同因素的影响。

      就现代卷积神经网络体系结构而言,您可以将帧视为由卷积层计算的张量中的通道。该张量通常由(B,C,H,W)维表示,其中B表示批处理大小,C表示通道,H,W表示特征图的空间尺寸(H表示特征图高度和宽度代表宽度)。通道是卷积滤波器从输入中得出不同特征的结果。但是,渠道可能不具有相同的代表重要性。由于某些渠道可能比其他渠道更重要,因此在传播到下一层之前,根据其重要性对渠道施加权重是有意义的。

      我们将以此为基础来了解频道注意的重要性,我们将在以下各节中进行介绍。

      Channel Attention

      基于上一节中描述的直觉,让我们深入了解为什么通道注意力是提高深度卷积神经网络体系结构泛化能力的关键组成部分。
      回顾一下,在卷积神经网络中,有两个主要组成部分:

      • 列表由尺寸(B,C,H,W)表示的输入张量(通常是四维张量)。

      • 列表可训练的卷积滤波器,其中包含该层的权重。

      卷积滤波器负责根据这些滤波器中学习到的权重来构建特征图。一些过滤器学习边缘,其他过滤器学习纹理,并且共同学习由输入张量嵌入的图像内目标类信息的不同特征表示。因此,通道数表示学习输入的不同特征图的卷积滤波器的数量。从我们以前对摄影中的帧选择的理解来看,这些特征图的重要性也不同。这意味着某些功能图比其他功能图更重要。例如,与学习背景纹理转换的另一个特征图相比,包含边缘信息的特征图对于学习可能更为重要和关键。因此,这是引起频道关注的基础。我们希望将这种“注意力”集中在更重要的渠道上,这基本上是要比其他渠道更重视特定渠道。最简单的方法是通过将更重要的通道缩放为更高的值。这正是Squeeze-Excitation Networks提出的建议。

      Squeeze-and-Excitation Networks
      在2018年,Hu等。在CVPR 2018上发表了他们的论文《挤压和激发网络》,并在TPAMI中发布了期刊版本。该论文被认为是注意力机制领域最有影响力的著作之一,迄今已获得1000多次引用。让我们看一下论文的建议。
      ace6815d-cf93-4a77-ad11-35f0ef887024-image.png
      本文提出了一种新颖,易于插入的模块,称为“挤压和激发”模块(缩写为SE-block),该模块由三个组件组成(如上图所示):

      • Squeeze Module
      • Excitation Module
      • cale ModuleS
        让我们更详细地研究这些模块中的每个模块,并理解它们为什么在关注频道方面很重要。

      Squeeze Module
      为了获得最佳的频道关注度,人们希望特征图的缩放适应于特征图本身。概括地说,特征图集本质上是卷积层的输出张量(通常是维数(B,C,H,W)的4-D张量,其中的首字母代表批量的大小,通道,高度和宽度功能图)。为简单起见,我们仅将其视为形状(C,H,W)的3D张量-本质上,我们关注深度(张量中的通道/特征图的数量)和每个特征图的空间尺寸在那个张量中。因此,为了使频道注意力适应每个频道本身,我们有H × W总要关注的像素(或值)。从本质上讲,这意味着要使注意力真正具有适应性,您将总共使用C × H × W值进行操作。该值将变得非常大,因为在现代神经网络中,通道数量随着网络深度的增加而变大。因此,需要使用可以将每个特征图的信息分解为奇异值的特征描述符,将有助于降低整个操作的计算复杂度。
      这形成了挤压模块的动机。存在许多可用于将特征图的空间尺寸减小为奇异值的特征描述符,但是在卷积神经网络中用于减小空间尺寸的通用方法是合并。有两种非常流行的池化方法:平均池化和最大池化。前者计算定义的窗口内的平均像素值,而后者计算相同定义的窗口中的最大像素值。两者都有各自的优缺点。虽然最大池保留了最活跃的像素,但它也可能非常嘈杂,并且不会考虑相邻像素。另一方面,普通池不能保留信息。但是,它可以构造该窗口中所有像素的平滑平均值。
      Excitation Module
      4868b37e-a9f3-47ad-bf43-4a47327ddcd7-image.png
      现在,将输入张量分解为较小的大小(C×1×1),该模块的下一部分将学习这些通道的自适应缩放权重。对于“挤压和激发”模块中的“激发模块”,作者选择了完全连接的多层感知器(MLP)瓶颈结构来映射缩放比例权重。这个MLP瓶颈具有相同形状的单个隐藏层以及输入和输出层。隐藏层用作缩小块,其中将输入空间缩小到由缩小因子(默认设置为16)定义的较小空间。然后将压缩空间扩展回原始尺寸,作为输入张量。用更紧凑的术语来说,可以通过以下三点来定义MLP每一层的尺寸变化:
      1.输入的形状为(C ×1×1)。因此,在输入层中存在C个神经元。
      2…隐藏层将其减少了减少因子r,从而导致C / r神经元总数。
      3.最后,输出被投影回与输入相同的维数空间,总共返回到C个神经元。
      总的来说,您传递了(C ×1×1)张量作为输入,并获得了具有相同形状的加权张量–(C ×1×1)。
      理想情况下,为了改善信息传播和更好的跨通道交互(CCI),应将r设置为1,从而使其成为一个完全连接的正方形网络,每层宽度相同。但是,随着r的减小,在复杂度增加和性能提高之间需要权衡。因此,基于上表,作者使用16作为减速比的默认值。这是一个超参数,具有进一步调整范围以改善性能的范围。
      Scale Module
      从激励模块获得(C ×1×1)“激励”张量后,首先将其传递通过S型激活层,然后将其缩放到0-1的范围。随后,通过简单的广播逐元素乘法将输出直接应用于输入,该乘法使用来自激励模块中MLP的相应学习权重来缩放输入张量中的每个通道/特征图。

      作者对用作激励算子的不同非线性激活函数的影响进行了进一步的消融研究,根据结果​​,作者将Sigmoid确立为性能最佳的激活函数,并因此将其用作缩放模块中的默认激励算子。

      总而言之,挤压激励块(SE块)采用形状为(C × H × W)的输入张量x,通过全局平均池(GAP)将其减小为形状为(C ×1×1)的张量。将这个C长度向量传递到多层感知器(MLP)瓶颈结构中,并输出相同形状的加权张量(C ×1×1),然后对其进行广播并将其与输入x逐元素相乘。

      Code

      • PyTorch
      ### Import necessary packages
      from torch import nn
      
      ### Squeeze and Excitation Class definition
      class SE(nn.Module):
          def __init__(self, channel, reduction_ratio =16):
              super(SE, self).__init__()
              ### Global Average Pooling
              self.gap = nn.AdaptiveAvgPool2d(1)
              
              ### Fully Connected Multi-Layer Perceptron (FC-MLP)
              self.mlp = nn.Sequential(
                  nn.Linear(channel, channel // reduction_ratio, bias=False),
                  nn.ReLU(inplace=True),
                  nn.Linear(channel // reduction_ratio, channel, bias=False),
                  nn.Sigmoid()
              )
      
          def forward(self, x):
              b, c, _, _ = x.size()
              y = self.gap(x).view(b, c)
              y = self.mlp(y).view(b, c, 1, 1)
              return x * y.expand_as(x)
      
      • TensorFlow
      import tensorflow as tf
      
      __all__ = [
          'squeeze_and_excitation_block',
      ]
      
      
      def squeeze_and_excitation_block(input_X, out_dim, reduction_ratio=16, layer_name='SE-block'):
          """Squeeze-and-Excitation (SE) Block
          SE block to perform feature recalibration - a mechanism that allows
          the network to perform feature recalibration, through which it can
          learn to use global information to selectively emphasise informative
          features and suppress less useful ones
          """
      
      
          with tf.name_scope(layer_name):
      
              # Squeeze: Global Information Embedding
              squeeze = tf.nn.avg_pool(input_X, ksize=[1, *input_X.shape[1:3], 1], strides=[1, 1, 1, 1], padding='VALID', name='squeeze')
      
              # Excitation: Adaptive Feature Recalibration
              ## Dense (Bottleneck) -> ReLU
              with tf.variable_scope(layer_name+'-variables'):
                  excitation = tf.layers.dense(squeeze, units=out_dim/reduction_ratio, name='excitation-bottleneck')
              excitation = tf.nn.relu(excitation, name='excitation-bottleneck-relu')
      
              ## Dense -> Sigmoid
              with tf.variable_scope(layer_name+'-variables'):
                  excitation = tf.layers.dense(excitation, units=out_dim, name='excitation')
              excitation = tf.nn.sigmoid(excitation, name='excitation-sigmoid')
      
              # Scaling
              scaler = tf.reshape(excitation, shape=[-1, 1, 1, out_dim], name='scaler')
      
              return input_X * scaler
      

      缺点
      尽管本文本身具有革命性意义,但它在结构上存在某些概述的缺陷,并存在一些不确定的设计策略。

      • 该方法非常昂贵,并且在基线模型的基础上添加了大量参数和FLOPS。尽管在宏伟的方案中,开销可能很小,但是有许多新方法旨在以极低的成本提供频道关注,其效果要比SENets更好,例如ECANet(在CVPR 2020年发布)。

      • 尽管就参数和FLOP开销而言,通道注意似乎是有效的,但一个主要缺陷是缩放操作,在该操作中,广播加权通道矢量并将其逐元素地应用/乘以输入张量。该中间广播张量具有与输入相同的维数空间,从而导致存储器复杂度的大幅增加。这使训练过程变慢并且占用更多的内存。

      • 为了降低计算复杂度,该块的激励模块的MLP中存在瓶颈结构,其中通道数以指定的缩小率减少。这导致信息丢失,因此是次优的。

      • 由于SENet仅通过使用专用的全局特征描述符(在本例中为全局平均池(GAP))来提供频道关注,因此信息丢失并且提供的关注是针对性的。这意味着所有像素均均匀地映射在特征图的空间域中,因此无法区分重要或类别确定性像素与属于背景或不包含有用信息的像素。因此,将空间关注的重要性/需要与频道关注结合起来是合理的。相同的主要示例之一是CBAM(在ECCV 2018上发布)。

      • 有关SENet的设计策略尚无定论。作者指出,这超出了本文的范围,无法理解最佳设置,包括SE模块的位置集成策略和MLP中使用的缩小率。

      References
      Squeeze-and-Excitation Networks, TPAMI 2018.
      CBAM: Convolutional Block Attention Module, ECCV 2018.
      ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks, CVPR 2020.
      SENet original repository.

      posted in CV领域
      1
      176****4500
    • RE: 【有奖话题NO.1-进行中】你用来跑训练的第一张GPU?说出你的故事~

      @Alice_智享云

      那我可要好好讲讲我用GT 710 登顶Cityscapes Fake Benchmark的故事了

      反转了👊 👊👊 ,记错了捏,原来是用 i7-10700 登顶的。

      posted in 有奖话题
      1
      176****4500
    • 【已下载】SemantiKITTI Semantic Segmentation 数据

      公共数据集中的应该是Semantic Scene Completion的文件 即总大小3.9G的体素文件。
      可以的话 希望上传80G原始大小的Semantic Segmentation的Velodyne point clouds数据。本地上传的话太慢了
      区别如下:已经有的是下面那个 是场景完成分割任务

      posted in 求数据集👁‍🗨更新中
      1
      176****4500
    • 提升语义分割效果的方法 OHEM+LovaszSoftmax Loss

      论文:The Lovasz-Softmax loss: A tractable surrogate for the optimization of the intersection-over-union measure in neural networks
      Github:https://github.com/bermanmaxim/LovaszSoftmax
      CVPR2018
      论文提出了LovaszSoftmax,是一种基于IOU的loss,效果优于cross_entropy,可以在分割任务中使用。最终在Pascal VOC和 Cityscapes 两个数据集上取得了最好的结果。
      论文贡献:
      结合Lovasz hinge 和Jaccard loss 解决2值图片的分割问题
      提出了Lovasz-Softmax loss 对多个类别分割的参数设置
      设计了一个基于batch的IOU作为基于dataset IOU的高效代理
      分析和对比各种IOU测量方法
      基于本文的loss,对经典的分割方法的分割效果做出很大的提升

      OHEM
      Training Region-based Object Detectors with Online Hard Example Mining

      (1) 训练过程需要进行参数的空间搜索

      (2) 简单样本与难分辨样本之间的类别不平衡是亟需解决的问题

      (3) 自动地选择难分辨样本来进行训练不仅效率高而且性能好

      (4) 提出了OHEM算法,不仅效率高而且性能好,在各种数据集上表现优越Training Region-based Object Detectors with Online Hard Example Mining

      困难负样本挖掘的方法。困难负样本是指AI模型难以区分的负样本。在模型不断训练的过程中,模型通常会对正样本有着比较高的confidence,但少不了对某些负样本也留有余芥,给了一个不那么接近0的confidence。而困难负例挖掘就是找到这些负例,然后针对性地训练。OHEM提出是一种线上的困难负例挖掘解决方案。使用了这个trick以后,检测模型的准确性有一定提升。

      论文原本是在目标检测上 实际上分割领域用的更广泛
      Cityscapes数据集上的经典方法

      下面是本人实际使用的代码
      分割19类 忽略255
      效果还行 没做消融实验 不确定提升效果

      class OhemCrossEntropy_2D(nn.Module):
          def __init__(self, ignore_index=-1, thresh=0.6, min_kept=350000, weight=None):
              super(OhemCrossEntropy_2D, self).__init__()
              self.thresh = thresh
              self.min_kept = max(1, min_kept)
              self.ignore_index = ignore_index
              self.weight = weight
              self.criterion = nn.CrossEntropyLoss(
                  weight=weight, ignore_index=ignore_index, reduction="none"
              )
              self.ls = Lovasz_softmax(ignore=self.ignore_index)
              self.nll = nn.NLLLoss(weight=weight, ignore_index=self.ignore_index, reduction="none")
              print(weight)
      
          def forward(self, score, target, **kwargs):
              ph, pw = score.size(2), score.size(3)
              h, w = target.size(1), target.size(2)
              if ph != h or pw != w:
                  score = F.upsample(input=score, size=(h, w), mode="bilinear")
              pred = F.softmax(score, dim=1)
              pixel_losses = (self.criterion(score, target) + self.ls(pred, target)).contiguous().view(-1)
              mask = target.contiguous().view(-1) != self.ignore_index
      
              tmp_target = target.clone()
              tmp_target[tmp_target == self.ignore_index] = 0
              pred = pred.gather(1, tmp_target.unsqueeze(1))
              pred, ind = pred.contiguous().view(-1,)[mask].contiguous().sort()
              min_value = pred[min(self.min_kept, pred.numel() - 1)]
              threshold = max(min_value, self.thresh)
              pixel_losses = pixel_losses[mask][ind]
              pixel_losses = pixel_losses[pred < threshold]
              return pixel_losses.mean()
      
      posted in CV领域
      1
      176****4500