ECCV2020
Paper: http://mftp.mmcheng.net/Papers/20EccvSal100k.pdf
Code: https://github.com/MCG-NKU/SOD100K

主要创新点

  1. We propose a flexible convolutional module, namely gOctConv, to efficiently utilize both in-stage and cross-stages multi-scale features for SOD task, while reducing the representation redundancy by a novel dynamic weight decay scheme. 通用八度卷积模块----可以有效地利用阶段内和跨阶段的多尺度特征进行SOD任务,同时通过一种新颖的动态权重衰减方案来减少特征表示的冗余性。
  2. Utilizing gOctConv, we build an extremely light-weighted SOD model, namely CSNet, which achieves comparable performance with ∼ 0.2% parameters (100k) of SOTA large models on popular SOD benchmarks. 构造轻量级网络,参数量只有100K。

SOD任务需要为每个图像像素生成准确的预测分数,因此既需要大尺度的高层次特征表示来正确定位突出的物体,也需要精细的低层次表示来精确细化边界。构建超轻量级的SOD模型有两个主要的挑战:首先,当高层次特征的低频性满足了显著性特征图的高输出分辨率时,可能会出现严重的重冗余。其次,SOTA SOD模型通常依靠ImageNet预训练的主干网络架构来提取特征,而这本身就很耗费资源。

Generalized OctConv

OctConv: (Paper: https://export.arxiv.org/pdf/1904.05049)

核心原理就是利用空间尺度化理论将图像高频低频部分分开,下采样低频部分,可以大大降低参数量,并且可以完美的嵌入到神经网络中。降低了低频信息的冗余。
(传入的data是分高频和低频数据的。OctCon是训练四个卷积核,分别为hh,hl,lh,ll)
高频分量,是指不经过高斯滤波的原始通道(或图像);
低频分量,是指经过t=2的高斯滤波得到的通道(或图像)------------冗余的
比较好的blog: https://www.cnblogs.com/RyanXing/p/10720182.html

原来的OctConv:1)仅利用OctConv中的低和高分辨率两个尺度不足以完全减少SOD任务中的冗余问题,而SOD任务比分类任务需要更强大的多尺度表示能力。2)在OctConv中,每个scale的通道数是手动选择的,因为SOD任务需要的类别信息较少,因此需要为模型进行大量的调整。

gOctConv改进:1)支持任意输入和输出尺寸,多尺度表示; 2)内阶段和跨阶段的特征都可表示; 3)通过动态权重衰减和剪枝策略,可以学到不同尺度的通道信息;4)如果考虑大复杂度的灵活性,可以不用跨尺寸的特征交互。

Light-weighted Model

该轻量级网络由特征提取器和跨阶段融合部分组成,可以同时处理多个尺度的特征。特征提取器与提出的层级多尺度块(即ILBlock)堆叠在一起,并根据特征图的分辨率分为4个阶段,每个阶段分别具有3、4、6和4个ILBlock。由gOctConv组成的跨阶段融合部分处理来自特征提取器各阶段的特征,以获得高分辨率输出。

层级多尺度块(In-layer Multi-scale Block,ILBlock)-----增强了阶段性特征的多尺度表示,gOctConvs被用来引入ILBlock内的多尺度。原本的OctConv需要大约60%的FLOPs才能达到与标准卷积相似的性能,这对于我们设计一个高轻量级模型的目标来说是不够的。为了节省计算成本,在每一层中都没有必要使用不同尺度的交互特征。因此,本文方法应用gOctConv消除跨尺度操作,使每个输入通道对应于具有相同分辨率的输出通道。在每个尺度内利用深度运算来进一步节省计算成本。与原始的OctConv相比,gOctConv的这个实例只需要1/channel的FLOPs。ILBlock由一个原始的OctConv和两个3×3的gOctConv组成,如图3所示。原始的OctConv与两个尺度的特征进行交互,gOctConvs在每个尺度内提取特征。一个区块内的多尺度特征被单独处理,交替进行内交互。每一次卷积之后都要进行BatchNorm和PRelu。最初,随着分辨率的降低,将ILBlocks的通道大致翻倍,除了最后两个阶段的通道数相同。

跨层级融合(Cross-stages Fusion)为了保持高输出分辨率,常规方法在特征提取器的高层级上保持高特征分辨率,不可避免地增加了计算冗余。相反,本文的方法仅使用gOctConvs从特征提取器的各个阶段融合多尺度特征,并生成高分辨率输出。作为效率和性能之间的折衷,使用了来自最后三个阶段的特征。gOctConv中1×1卷积将具有与每个阶段的最后一个卷积不同尺度的特征作为输入,并进行跨阶段卷积以输出具有不同尺度的特征。为了在粒度级别上提取多尺度特征,特征的每个尺度都由一组具有不同扩展率的并行卷积处理。然后将特征发送到另一个gOctConv 1×1卷积以生成最高分辨率的特征。另一个标准1×1卷积输出了显著性图的预测结果,还获得了gOctConvs的可学习通道。

class PallMSBlock(nn.Module):def __init__(self,in_channels, out_channels, alpha=[0.5,0.5], bias=False):super(PallMSBlock, self).__init__()self.std_conv = Falseself.convs = nn.ModuleList()for i in range(len(alpha)):self.convs.append(MSBlock(int(round(in_channels*alpha[i])), int(round(out_channels*alpha[i]))))self.outbranch = len(alpha)def forward(self, xset):if isinstance(xset,torch.Tensor):xset = [xset,]yset = []for i in range(self.outbranch):yset.append(self.convs[i](xset[i]))return ysetclass MSBlock(nn.Module):def __init__(self, in_channels, out_channels, dilations = [1,2,4,8,16]):super(MSBlock,self).__init__()self.dilations = dilationseach_out_channels = out_channels//5self.msconv = nn.ModuleList()for i in range(len(dilations)):if i != len(dilations)-1:this_outc = each_out_channelselse:this_outc = out_channels - each_out_channels*(len(dilations)-1)self.msconv.append(nn.Conv2d(in_channels, this_outc,3, padding=dilations[i], dilation=dilations[i], bias=False))self.bn = nn.GroupNorm(32, out_channels)self.prelu = nn.PReLU(out_channels)def forward(self, x):outs = []for i in range(len(self.dilations)):outs.append(self.msconv[i](x))out = torch.cat(outs, dim=1)del outsout = self.prelu(self.bn(out))return outclass CSFNet(nn.Module):def __init__(self, num_classes=1):super(CSFNet, self).__init__()self.base = Res2Net(Bottle2neck, [3, 4, 6, 3], baseWidth = 26, scale = 4)# self.base.load_state_dict(model_zoo.load_url(model_urls['res2net50_v1b_26w_4s']))fuse_in_channel = 256+512+1024+2048fuse_in_split = [1/15,2/15,4/15,8/15]fuse_out_channel = 128+256+512+512fuse_out_split = [1/11,2/11,4/11,4/11]self.fuse = gOctaveCBR(fuse_in_channel, fuse_out_channel, kernel_size=(1,1), padding=0, alpha_in = fuse_in_split, alpha_out = fuse_out_split, stride = 1)self.ms = PallMSBlock(fuse_out_channel, fuse_out_channel, alpha = fuse_out_split)self.fuse1x1 = gOctaveCBR(fuse_out_channel, fuse_out_channel, kernel_size=(1, 1), padding=0, alpha_in = fuse_out_split, alpha_out = [1,], stride = 1)self.cls_layer = nn.Conv2d(fuse_out_channel, num_classes, kernel_size=1)def forward(self, x):features = self.base(x)fuse = self.fuse(features)fuse = self.ms(fuse)fuse = self.fuse1x1(fuse)output = self.cls_layer(fuse[0])output = F.interpolate(output, x.size()[2:], mode='bilinear', align_corners=False)return outputdef build_model():return CSFNet()def weights_init(m):if isinstance(m, nn.Conv2d):m.weight.data.normal_(0, 0.01)if m.bias is not None:m.bias.data.zero_()

Learnable channels with model compression

通过在训练过程中利用提出的动态权重衰减辅助剪枝过程,为gOctConv中的每个尺度获取可学习的通道数。 动态权重衰减可在引入稀疏性的同时保持通道之间的权重分布稳定,从而有助于剪枝消除冗余通道。

常用的正则化技巧权重衰减使CNN具有更好的泛化性能。通过权重衰减进行训练使得CNN中不重要的权重值接近于零。因此,权重衰减已被广泛用于剪枝中以引入稀疏性。权重衰减的常见实现方式是在损失函数中添加L2正则化:

多样化输出主要是由对权重的衰减项的不加区分的抑制造成的。因此,可以根据某些通道的特定特征来调整权重衰减。具体来说,在反向传播期间,衰减项会根据某些通道的特征动态变化。动态权重衰减的权重更新写为:

λ是动态权重衰减的权重,xix_ixi​表示由wiw_iwi​计算的特征,而S(xi)S(x_i)S(xi​)是特征的度量,根据任务可以具有多个定义。在本文中,目标是根据稳定通道之间的特征进行权重分配。因此,可以仅使用全局平均池(GAP)作为特定通道的指标:

def updateWeight(self, s=0.001):for m in self.modules():if isinstance(m, gOctaveCBR):for n in list(m.modules()):if isinstance(n, nn.BatchNorm2d):n.weight.grad.data.add_(s * torch.sign(n.weight.data))  # L1# hook for dynamic weight decay #
def Oct_bn_hook(module, input, output):all_weights = []branches = len(output)this_flop_weight = []init_flop = module.baseflop * (module.expandflop**(branches - 1))for k in range(branches):this_flop_weight.append(init_flop)init_flop /= module.expandflopgap_id = 0for name, m in module.named_modules():# print(name)if isinstance(m, nn.BatchNorm2d):gap_vet = torch.nn.functional.adaptive_avg_pool2d(output[gap_id].detach(), 1).squeeze().abs()gap_id += 1bn_id = int(name.split('.')[-1])all_weights.append((this_flop_weight[bn_id] * gap_vet *torch.pow(m.weight, 2)).sum())  #l2 reg.# print(all_weights)module.all_flops += 0.5 * sum(all_weights)

实验

Details: CSNet仍可以达到与基于预训练主干的大模型相当的性能。最初将学习率设置为1e-4,然后在200个epoch和250个epoch时衰减10倍。本文仅使用了随机翻转和裁剪的数据增强。gOctConvs之后的BatchNorms权重衰减,作者建议使用动态的权重衰减替代,默认权重为3,而其他权重的权重衰减默认设置为5e-3。

Highly Efficient Salient Object Detection with 100K Parameters论文解读相关推荐

  1. Deeply supervised salient object detection with short connections 论文复现

    DSS Model论文复现 <Deeply supervised salient object detection with short connections>这篇文章是南开大学程明明教 ...

  2. Minimum Barrier Salient Object Detection at 80 FPS 论文阅读笔记

    这几天帮学长研究这篇论文,整理了这些笔记,由于我在CV方面刚刚入门,博客中可能会有很多错误与不当之处,希望大家能多多指正. 附上我自己修改的C++代码,可以运行在windows环境下: 链接:http ...

  3. [论文阅读] Looking for the Detail and Context Devils: High-Resolution Salient Object Detection

    论文地址:https://dx.doi.org/10.1109/TIP.2020.3045624 发表于:TIP 2021 Abstract 近年来,随着大规模基准测试与深度学习技术的成就,显著目标检 ...

  4. 『译』RGB-D Salient Object Detection, A Review『译』

    RGB-D显著性目标检测回顾 (文章由我个人翻译,请勿擅自转载) 文章结构 introduce:介绍了RGB-D显著性目标检测的任务和关键概念 review:回顾显著性目标检测的演化过程,尤其是对于R ...

  5. Revisiting Salient Object Detection: Simultaneous Detection, Ranking, and Subitizing of Multiple Sal

    问题: 作者认为,显著性目标检测领域迄今为止的工作解决的是一个相当病态的问题.即不同的人对于什么是显著性目标没有一个普遍的一致意见.这意味着一些目标会比另一些目标更加显著,并且不同的显著性目标中存在着 ...

  6. 《Revisiting Salient Object Detection! Simultaneous Detection, Ranking, and Subitizing of Multiple Sa

    <Revisiting Salient Object Detection! Simultaneous Detection, Ranking, and Subitizing of Multiple ...

  7. 【Salient Object Detection】显著性物体检测资料汇总

    显著性物体检测的一系列资料汇总 v1.0 研究小组&people 南开大学媒体计算, Salient object detection datasets,全面的方法总结评测+一系列此领域研究工 ...

  8. [论文阅读] Boosting Salient Object Detection with Transformer-based Asymmetric Bilateral U-Net

    论文地址:https://arxiv.org/abs/2108.07851 发表于:Arxiv 2021.08 Abstract 现有的显著目标检测(SOD)方法主要依靠基于CNN的U型结构,通过跨层 ...

  9. [论文阅读] Stereoscopically Attentive Multi-scale Network for Lightweight Salient Object Detection

    论文地址:https://dx.doi.org/10.1109/TIP.2021.3065239 代码:https://mmcheng.net/SAMNet 发表于:TIP 2021 Abstract ...

最新文章

  1. python怎么发送代码文件_python 通过 socket 发送文件的实例代码
  2. 日志库EasyLogging++学习系列(4)—— 格式说明符
  3. android 消除标题,Android Activity 去掉标题栏及全屏显示
  4. JVM内存管理------杂谈(借此也论一论obj=null)
  5. Java黑皮书课后题第4章:*4.14(转换字母等级为数字)编写程序,提示用户输入一个字母等级A、B、C、D或者F,显示对应的数字值4、3、2、1或者0。对其它输入,提示非法等级
  6. [Swift]多维数组的表示和存储:N维数组映射到一维数组(一一对应)!
  7. 小幽默也有大道理:哲理幽默15则
  8. 英特尔预计5年内将成智能手机芯片大厂
  9. 三、Java 面向对象高级——数据结构、List、Set、Collection
  10. python群发邮件1000人-python读取excel群发邮件(一)
  11. OCIEnvCreate 失败,返回代码为 -1的解决方法
  12. 6 Linux之bash环境配置
  13. 《编码-隐匿在计算机软硬背后的语言》第七章我们的十个数字
  14. java byte 图片浏览器直接显示_在imge控件中直接显示图片(图片是byte[]格式)
  15. 一个专为推荐系统定制的BERT!
  16. [C++] 关于delete和delete[]
  17. m126a linux驱动下载,惠普hp M126a打印机驱动
  18. 历史上水平最高的三十首七律
  19. 微信小程序及其兼容性
  20. python爬虫面试题集锦及答案

热门文章

  1. python笔记05: 程序结构
  2. android高德地图绘制多边形_android 高德地图画多边形,已知中心点 宽高画矩形 ,实际距离 千米转地图坐标距离...
  3. 《图解TCP/IP》读书笔记二:TCP/IP基础知识
  4. 【116】Python 保留字(关键字)、标识符
  5. 未来两周目标计划---C++ and Disassembly(不积跬步无以至千里,不积小流无以成江海)...
  6. m1卡工作原理和相关总结
  7. python画行向日葵,基于matplotlib的向日葵散点图
  8. Try HP DL388 Gen9 and Dell PowerEdge R320 (by joshua)
  9. 手机点餐系统概述_实训答辩安卓点餐系统ppt课件
  10. 2018年图灵奖--约书亚·本吉奥、杰弗里·埃弗里斯特·辛顿和Yann LeCun简介