IBN-Net: 提升模型的域自适应性
本文解读内容是IBN-Net, 笔者最初是在很多行人重识别的库中频繁遇到比如ResNet-ibn这样的模型,所以产生了阅读并研究这篇文章的兴趣,文章全称是: 《Two at Once: Enhancing Learning and Generalization Capacities via IBN-Net》。IBN-Net和SENet非常相似:
- 可以方便地集成到现有网络模型中。
- 在多个视觉任务中有着出色的表现,如分类、分割。
- 拿到了比赛第一名,IBN-Net拿到了 WAD 2018 Challenge Drivable Area track ,一个分割比赛的第一名。SENet拿到了最后一届ImageNet比赛的冠军。
1. 概述
IBN-Net出发点是:提升模型对图像外观变化的适应性。在训练数据和测试数据有较大的外观差异的时候,模型的性能会显著下降,这就是不同域之间的gap。比如训练数据中的目标光线强烈,测试数据中的目标光线昏暗,这样一般效果都不是很好。
之前有一个群友就是在研究一个域的数据如何迁移到另外一个分布不一致的域中的问题,当时认为在机器学习中训练的数据和测试数据的分布应该尽可能一致,这样才符合要求。但是实际应用中不可避免遇到训练数据无法将所有情况下(色调变化,明暗变化 )的数据都收集到,所以如何提升模型对图像外观变化的适应性、如何提高模型在不同域之间的泛化能力也是一个非常值得研究的课题。
IBN-Net能够有效提升模型在一个域中的效果(比如cityscapes-真实场景的数据),同时可以做到不fine-tuning就可以泛化到另外一个域中(比如GTA5-非真实场景的数据)。
文章主要有三个贡献:
- 通过深入IN和BN,发现IN对目标的外观变化具有不变性,比如光照、颜色、风格、虚拟和现实,BN可以保存内容相关的信息。
- IBN-Net可以应用到现有的STOA网络架构中,比如DenseNet, ResNet, ResNeXt, SENet等网络中,可以再不增加模型计算代价的情况下,有效提升模型的效果。
- IBN-Net域适应能力非常强,在cityscape数据集训练的模型,不需要再GTA5上fine-tuning就可以有比较可观的效果。


2. 方法
(b) 图是对原图进行亮度调整和色彩平移(c)图是对原图使用了两种风格化方法 (d)图是对(c)图使用Instance Norm以后的结果,这说明IN可以过滤掉复杂的外观差异。
通常IN用于处理底层视觉任务,比如图像风格化,而BN用于处理高层视觉任务,比如目标检测,图像识别等。IBN-Net首次将BN和IN集成起来,同时提高了模型的学习能力和泛化能力。
此外,IBN-Net设计原则是:
- 在网络的浅层同时使用IN和BN
- 在网络的深层仅仅使用BN
作者做了一个实验,下图展示了随着网络深度的变化,特征差异的变化情况:
蓝色代表外观差异带来的特征差异,橙色代表图片内容之间的特征差异。可以看出在浅层是由外观差异带来的特征差异,这部分可以使用BN和IN联合起来解决;在深层网络,外观差异带来的特征差异已经非常小了,内容之间的差异是主导地位,所以这部分使用BN来解决。

这部分是论文的核心,作者提出了两个结合BN和IN的模块,IBN-a和IBN-b。(a)图其实是ResNet中的一个残差模块,(b)和(c)图都是在此基础上融入了IN和BN

- 具体哪个算浅层哪个算深层?
ResNet由4组残差块组成,在IBN-Net的改进中,仅仅在Conv2_x, Conv3_x, Conv4_x三个块中加入IN,Conv5_x不进行改动。
- IBN-a的改动理由:
第一,在ResNet论文中说明了恒等映射路径的必要性,所以IN应该添加在残差路径上。
第二,残差网络可以用以下公式来表达:
\]
其中的\(F(x,\{W_i\})\)是为了能够得到与恒等映射路径对齐的特征,所以IN被添加在残差模块中第一个卷积以后,而不是最后一个卷积以后,这样可以防止特征出现不对齐的问题。
第三,根据之前提到的设计原则,浅层应当同时使用BN和IN,所以选择将一半通道通过BN计算,另一半通道通过IN进行计算。
- IBN-b的改动理由:
为了更充分地利用IN来提高模型的泛化的能力,对IBN-a进行了改进。作者认为目标的表观信息将保留在残差路径或者恒等映射路径上,所以可以考虑将IN直接添加在加法之后。同时需要说明的是和IBN-a不同,IBN-b使用的范围是(Conv2_x和Conv3_x)
除了上述两种BN和IN结合方法,作者还探索出更多变体,如下图所示:

(a)图中,IBN-c的做法是将IN和BN分成两路,然后将得到的特征进行concate。
(b)图中,IBN-d的做法是在IBN-b基础上进行了改动,对其中一半通道的feature map施加IN。
(c)图中,IBN-a&d的做法很显然结合了IBN-a和IBN-d
(d)图中,IBN-ax2在IBN-a基础上,多增加了一对BN和IN,用于测试添加更多BN和IN是否能够提升模型泛化能力。
IBN-a和IBN-b代码:
这部分代码来自: https://github.com/pprp/reid_for_deepsort
IBN-a:
class IBN(nn.Module):
def __init__(self, planes):
super(IBN, self).__init__()
half1 = int(planes / 2)
self.half = half1
half2 = planes - half1
self.IN = nn.InstanceNorm2d(half1, affine=True)
self.BN = nn.BatchNorm2d(half2)
def forward(self, x):
split = torch.split(x, self.half, 1)
out1 = self.IN(split[0].contiguous())
out2 = self.BN(split[1].contiguous())
out = torch.cat((out1, out2), 1)
return out
IBN-b:
class Bottleneck(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, stride=1, downsample=None, IN=False):
super(Bottleneck, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(
planes,
planes,
kernel_size=3,
stride=stride,
padding=1,
bias=False
)
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = nn.Conv2d(
planes, planes * self.expansion, kernel_size=1, bias=False
)
self.bn3 = nn.BatchNorm2d(planes * self.expansion)
self.IN = None
if IN:
self.IN = nn.InstanceNorm2d(planes * 4, affine=True)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out)
out = self.conv3(out)
out = self.bn3(out)
if self.downsample is not None:
residual = self.downsample(x)
out += residual
if self.IN is not None:
out = self.IN(out)
out = self.relu(out)
return out
3. 实验

可以看到,IBN-a可以提升在原先域(训练数据)内的泛化能力,比原来ResNet50要高1-2个百分点。IBN-b可以提升在目标域(训练数据中未出现的数据)的泛化能力,可以看到要比ResNet50提高4个百分点。

上图是采用了不同的外观转换比如RGB直接+50,R+50等方法,可以发现,依然遵从上一条发现,IBN-a可以提升原有域的泛化能力,IBN-b可以提升目标域的泛化能力,可以看到除了Monet风格化对IBN-b影响稍大,其他几种影响非常之小。

可以看到,IBN-a最好是施加在前三个block中,效果最好。

这个比例是IN/BN, 可以看出IN/BN=0.25的时候top1 最好,IN/BN=0.5的时候top5最好,一般默认还是设置为0.5.
以上是分类问题,再来看看分割问题,cityscape数据集和GTA5数据集上的结果如下:

可以看到,训练集和测试集来自同一个数据的时候,IBN-a模型的mIoU是能够比原模型ResNet50高4个百分点。而训练集和测试集不同的时候,IBN-b模型更占优势,说明IBN-b能够在跨域的问题上表现更好。

上图的实验还可以证明IBN-a和ResNet50同时在目标域进行fine tuning, IBN-a微调的效果要远远好于ResNet50。
4. 总结
IBN-Net中有几个重要结论,在总结部分梳理一下:
IBN-Net在浅层同时使用IN和BN,深层网络仅仅使用BN。
IBN-Net中有两个出色的模型IBN-a和IBN-b,IBN-a适用于当前域和目标域一致的问题,比如说提升ResNet50的分类能力,可以用IBN-a,并且IBN-a微调以后结果是比原模型结果更好的。
IBN-b适合使用在当前域和目标域不一致的问题,比如说在行人重识别中,训练数据是在白天收集的,但是想在黄昏的时候使用的时候。这也是为何IBN-Net在行人重识别领域用的非常多的原因。
cityscape和GTA5这个实验非常有说服力,证明了IBN-Net的泛化能力,效果提升非常明显,在分割问题上对模型带来的提升效果更大。
5. 参考
https://arxiv.org/pdf/1512.03385
https://arxiv.org/pdf/1807.09441
https://github.com/XingangPan/IBN-Net
https://github.com/pprp/reid_for_deepsort/tree/master/models
IBN-Net: 提升模型的域自适应性的更多相关文章
- Bert文本分类实践(三):处理样本不均衡和提升模型鲁棒性trick
目录 写在前面 缓解样本不均衡 模型层面解决样本不均衡 Focal Loss pytorch代码实现 数据层面解决样本不均衡 提升模型鲁棒性 对抗训练 对抗训练pytorch代码实现 知识蒸馏 防止模 ...
- NLP(十八)利用ALBERT提升模型预测速度的一次尝试
前沿 在文章NLP(十七)利用tensorflow-serving部署kashgari模型中,笔者介绍了如何利用tensorflow-serving部署来部署深度模型模型,在那篇文章中,笔者利用k ...
- 【漏洞复现篇】CVE-2020-1472-微软NetLogon权限提升-手把手教学-简单域环境搭建与Exp执行
一.漏洞简介 NetLogon 远程协议是一种在 Windows 域控上使用的 RPC 接口,被用于各种与用户和机器认证相关的任务.最常用于让用户使用 NTLM 协议登录服务器,也用于 NTP 响应认
- Java内存模型-final域的内存语义--没明白,预留以后继续理解
https://www.cnblogs.com/yuanfy008/p/9349275.html 来自 Java并发编程(1)-Java内存模型
- Java内存模型-final域的内存语义
一 引言 说到final你肯定知道它是Java中的关键字,那么它所在Java中的作用你知道吗?不知道的话,请前往这篇了解下https://www.cnblogs.com/yuanfy008/p/802 ...
- (转载)ECCV 2018:IBN-Net:打开域适应的新方式
(本文转自极视角) 本文由香港中文大学发表于ECCV2018,论文探索了IN和BN的优劣,据此提出的IBN-Net在语义分割的域适应任务上取得了十分显著的性能提升. 论文地址:https://arxi ...
- .net架构设计读书笔记--第三章 第8节 域模型简介(Introducing Domain Model)
一.数据--行为转变 很长的时间,典型的分析方法或多或少是以下两种,第一,收集需求并做一些分析,找出有关实体 (例如,客户. 订单. 产品) 和进程来实现. 第二,手持这种理解你尝试推断一个物 ...
- django “如何”系列3:如何编写模型域(model filed)
django自带很多的域类--CharField,DateField等等--,如果django的这些域都不能满足你精确的要求,那么你可以编写自己的模型域. django自带的域没有和数据库列类型一一对 ...
- C++11 并发指南七(C++11 内存模型一:介绍)
第六章主要介绍了 C++11 中的原子类型及其相关的API,原子类型的大多数 API 都需要程序员提供一个 std::memory_order(可译为内存序,访存顺序) 的枚举类型值作为参数,比如:a ...
随机推荐
- 关于在elasticSearch中使用聚合查询后只显示10个bucket的问题
先看下面es查询语句 { "size": 0, "aggs" : { "all_articleId" : { "terms&quo ...
- npm项目创建初始过程详解
npm install 就是安装模块,npm run dev 就是执行npm script中的命令.当我们执行npm命令的时候,它到哪里去找,这就要说到每个node项目中都有的核心文件package ...
- 安装ArchLinux时遇到的部分问题
目录 一.网络问题 1.安装刚开始时连接wifi 2.安装完桌面后 二.卸载gnome桌面 三.启动桌面(以kde桌面为例) 1.立即启动桌面(start , stop) 2.设置开启自启动 (ena ...
- redis 出现(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details
如果在ubuntu安装的redis含端口使用,但是某些时候常常出现 (error) MISCONF Redis is configured to save RDB snapshots, but is ...
- 【MySQL】Docker搭建MySQL8.0
目录 Docker搭建MySQL8.0 目的: 1.安装Docker 2.查看docker镜像 3.拉取mysql官方镜像 4. 查看目前的镜像 5.运行docker mysql镜像 6.查看目前运行 ...
- jQuery实现鼠标移入切换图片
初始效果: 鼠标移入效果: 首先添加jQuery库,我这边直接引用百度CDN地址 <script src="https://apps.bdimg.com/libs/jquery/2.1 ...
- consoleInfo 输出 数组套对象 不显示...的方法 序列化 再反序列化
consoleInfo (...args) { // console.info('this', this) const name = this.$options.name let outName = ...
- 在Servlet端获取html页面选中的checkbox值,request获取页面checkbox(复选框)值
html端代码: 选项框: <input type="checkbox" name="crowd" value="选项一">选项 ...
- nmon使用问题汇总(不定期更新)
nmon使用问题汇总 1.nmon常用命令: ./nmon -s1 -c300 -f -m /root/nmon-test-result/项目-50并发/ 2.设置nmon参数为-s1 -c720,发 ...
- 玩转控件:封装Dev的LabelControl和TextEdit
俗话说的好:"工欲善其事必先利其器",作为软件攻城狮也是同样道理,攻城狮开发的软件目的是简化客户的操作,让客户动动手指就可以完成很多事情,减少人力成本.这也是系统/软件存在的目的. ...