模型先验是个啥?五种添加模型先验的方法一览!

作者 | Billy Z  编辑 | 极市平台

原文链接:https://zhuanlan.zhihu.com/p/188572028

点击下方卡片,关注“自动驾驶之心”公众号

ADAS巨卷干货,即可获取

点击进入→自动驾驶之心【全栈算法】技术交流群

导读

 

端到端的深度神经网络虽然能够自动学习到一些可区分度好的特征,但是往往会拟合到一些非重要特征,导致模型会局部坍塌到一些不好的特征上面。本文通过一个简单的鸟类分类案例来总结了五个给模型加入先验信息的方法。

模型加入先验知识的必要性

端到端的深度神经网络是个黑盒子,虽然能够自动学习到一些可区分度好的特征,但是往往会拟合到一些非重要特征,导致模型会局部坍塌到一些不好的特征上面。常常一些人们想让模型去学习的特征模型反而没有学习到。

为了解决这个问题,给模型加入人为设计的先验信息会让模型学习到一些关键的特征。下面就从几个方面来谈谈如何给模型加入先验信息。

为了方便展示,我这边用一个简单的分类案例来展示如何把先验知识加入到一个具体的task中。我们的task是在所有的鸟类中识别出一种萌萌的鹦鹉,这中鹦鹉叫鸮(xiāo)鹦鹉,它长成下面的样子:

369e41964eaab68b488e276d90b6f72e.jpeg
鸮(xiāo)鹦鹉

这种鸟有个特点:

就是它可能出现在任何地方,但就是不可能在天上,因为它是世界上唯一一种不会飞的鹦鹉(不是唯一一种不会飞的鸟)。

好,介绍完task的背景,咱们就可以分分钟搭建一个端到端的分类神经网络,可以选择的网络结构可以有很多,如resnet, mobilenet等等,loss往往是一个常用的分类Loss,如交叉熵,高级一点的用个focal loss等等。确定好了最优的数据(扰动方式),网络结构,优化器,学习率等等这些之后,往往模型的精度也就达到了一个上限。

然后你测试模型发现,有些困难样本始终分不开,或者是一些简单的样本也容易分错。这个时候如果你还想提升网络的精度,可以通过给模型加入先验的方式来进一步提升模型的精度

基于pretrain模型给模型加入先验

给模型加入先验,大家最容易想到的是把网络的weight替换成一个在另外一个任务上pretrain好的模型weight。经过的预训练的模型(如ImageNet预训练)往往已经具备的识别到一些基本的图片pattern的能力,如边缘,纹理,颜色等等,而识别这些信息的能力是识别一副图片的基础。如下图所示:

0eeb8c57ffe20370658a7de935a7d95b.jpeg

但这些先验信息都是一些比较general的信息,我们是否可以加入一些更加high level的先验信息呢。

基于输入给模型加入先验

假如你有这样的一个先验:

你觉得鸮鹦鹉的头是一个区别其他它和鸟类的重要部分,也就是说相比于身体,它的头部更能区分它和其他鸟类。

这时怎么让网络更加关注鸮鹦鹉的头部呢。这时你可以这样做,把整个鸮鹦鹉和它的头部作为一个网络的两路输入,在网咯的后端再把两路输入的信息融合。以达到既关注局域,又关注整体的目的。一个简单的示意图如下所示。

befd65b842960bedc01c4a42c9c0a508.jpeg

基于模型重现给模型加入先验

接着上面的设定来,假如说你觉得给模型两路输入太麻烦,而且增加的计算量让你感觉很不爽。

这时,你可以尝试让模型自己发现你设定的先验知识

假如说你的模型可以自己输出鸟类头部的位置,虽然这个鸟类头部的位置信息是你不需要的,但是输出这样的信息代表着你的网络能够locate鸟类头部的位置,也就给鸟类的头部更加多的attention,也就相当于给把鸟类头部这个先验信息给加上去了。

当然直接模仿detection那样去回归出位置来这个任务太heavy了,你可以通过一个生成网络的支路来生成一个鸟类头部位置的Mask,一个简单的示意图如下:

f486e8bba5bb7cd4baf0b5fddb1635c5.jpeg 19910cfd16d8bc36fa508cd894bd3cf1.jpeg
测试的时候不增加计算量

基于CAM图激活限制给模型加入先验

针对鸮鹦鹉的分类,我在上面的提到一个非常有意思的先验信息:

那就是鸮鹦鹉是世界上唯一一种不会飞的鹦鹉。

这个信息从侧面来说就是,鸮鹦鹉所有地方都可能出现,就是不可能出现在天空中(当然也不可能出现在水中)。

也就是说不但鸮鹦鹉本身是一个分类的重点,鸮鹦鹉出现的背景也是分类的一个重要参考。假如说背景是天空,那么就一定不是鸮鹦鹉,同样的,假如说背景是海水,那么也一定不是鸮鹦鹉,假如说背景是北极,那么也一定不是鸮鹦鹉,等等。

也就是说,你不能通过背景来判断一只未知的鸟是鸮鹦鹉,但是你能通过背景来判断一只未知的鸟肯定不是鸮鹦鹉(是其他的鸟类)。

所以假如说获取了一张输入图片的激活图(包含背景的),那么这张激活图的鸟类身体部分肯定包含了鸮鹦鹉和其他鸟类的激活,但是鸟类身体外的背景部分只可能包含其他鸟类的激活。

2ca2293eb1a2d43571daaba4cbc11c7b.jpeg

所以具体的做法是基于激活图,通过限制激活图的激活区域,加入目标先验

CAM[1]激活图是基于分类网络的倒数第二层卷积层的输出的 feature_map 的线性加权,权重就是最后一层分类层的权重,由于分类层的权重编码了类别的信息,所以加权后的响应图就有了基于不同类别的区域相应。(具体的介绍可以看 https://zhuanlan.zhihu.com/p/51631163),具体的激活图生成方式可以如下表示:

cc39d3a9dfb01945aba9ddb8ee546604.jpeg

说了这么多,下面就展示展示激活图的样子:

f03d7722e8e3a07acd66d951dd5087b5.jpeg 7f23b375eb386791686b2ef4321546e7.jpeg

大家可以看到,上面一张是一只鸮鹦鹉的激活图,下面是一只在天空飞翔的大雁的激活图。

因为鸮鹦鹉的Label是0,其他鸟类的Label是1,所以在激活图上,只要是负值的激活区域都是鸮鹦鹉的激活,也就是Label为0的激活,只要是正值的激活都是其他鸟类的激活,也就是Label为1的激活。

为了方便展示,我把负值的激活用冷色调来显示,把正值的激活用暖色调来显示,所以就是变成了上面两幅激活图的样子。而右边的数字是具体的激活矩阵(把激活矩阵进行GAP就可以变成最终输出的Logits)。

到这里不知道大家有没有发现一个问题,就是无论对于鸮鹦鹉还是大雁的图片,它们的激活图除了分布在鸟类本身,也会有一部分分布在背景上。 对于大雁我们好理解,因为大雁是飞在天空中的,而鸮鹦鹉是不可能在天空中的,所以天空的正激活是非常合理的。但是对于鸮鹦鹉来说,其在鸟类身体以外的负激活就不是太合理,因为,大雁或者是其他的鸟类,也可能在鸮鹦鹉的地面栖息环境中(但是鸮鹦鹉却不可能在天空中)。

所以环境不能提供任何证据来证明这一次鸟类是一只鸮鹦鹉,鸮鹦鹉的负激活只是在鸟类的身体上是合理的。而其他鸟类的正激活却可以同时在鸟类身体上又可能在鸟类的背景上(如天空或者海洋)。

所以我们需要这样建模这个问题,就是在除鸟类身体的背景上,不能出现鸮鹦鹉的激活,也就是说不能出现负激活(Label为0的激活)。 所以下面的激活才是合理的:

9cbbac73b9315bb5e16237d28c6a08fb.jpeg

从上面来看,在除鸟类身体外的背景部分是不存在负激活的,虽然上面的背景部分有一些正的激活(其他鸟类的激活),但是从右边的激活矩阵来看,负激活的scale是占据绝对优势的,所以完全不会干扰对于鸮鹦鹉的判断。

所以问题来了,怎么从网络设计方面来达到这个目的呢?

其实可以从Loss设计方面来达到这个效果。我们假设每一个鸟都有个对应的mask,mask内是鸟类的身体部分,mask外是鸟类的背景部分。那么我们需要做的就是抑制mask外的背景部分激活矩阵的负值,把那一部分负值给抑制到0即可。

鸟类的激活矩阵和mask的关系如下图(红色的曲线代表鸟的边界mask):

65920ef21a0cbbff1e40837688c042bd.jpeg

我们的Loss设计可以用下面的公式表示:

Loss_cam = -sum(where(bird_mask_outside<0))

具体的网络的framework可以如下所示:

1043c774e8ea059c742a865f8b4aef50.jpeg

其中虚线部分只是训练时候需要用到,inference的时候是不需要的,所以这种方法也是不会占用任何在inference前向时候的计算量。

基于辅助学习给模型加入先验知识

到现在为止,咱们还只是把我们的鸟类分类的task当成一个二分类来处理,即鸮鹦鹉是一类,其他的鸟类是一类。

但是我们知道,世界的鸟类可不仅仅是两类,除了鸮鹦鹉之外还有很多种类的鸟类。而不同鸟类的特征或许有很大的差别,比如鸵鸟的特征就是脖子很长,大雁的特征就是翅膀很大。

afd780444cccab51eb934332bb45d75f.jpeg

假如只是把鸮鹦鹉当做一类,把其他的鸟类当做一类来学习的话,那么模型很可能不能学到可以利用的区分非鸮鹦鹉的特征,或者是会坍塌到一些区分度不强的特征上面,从而没有学到能够很好的区分不同其他鸟类的特征,而那些特征对去区别鸮鹦鹉和其他鸟类或许是重要的。

所以我们有必要加入其他鸟类存在不同类别的先验知识。而这里,我主要介绍基于辅助学习的方式去学习类似的先验知识。首先我要解释一下什么是辅助学习,以及辅助学习和多任务学习的区别:

c36bb96f7ef1a44261511eb87408821f.jpeg

上图的左侧是多任务学习的例子,右侧是辅助学习的例子。左侧是个典型的face attribute的task,意思是输入一张人脸,通过多个branch来输出这一张人脸的年龄,性别,发型等等信息,各个branch的任务是独立的,同时又共享同一个backbone。右边是一个典型的辅助学习的task,意思是出入一张人脸,判断这一张人脸的性别,同时另外开一个(或几个)branch,通过这个branch来让网络学一些辅助信息,比如发型,皮肤等等,来帮助网络主任务(分男女)的判别。

好,回到我们的鸮鹦鹉分类的task,我们可能首先会想到下面的Pipeline:

129e7368262928a8cb8420fb8f2e1d3c.jpeg

这样虽然可以把不同类别的鸟类的特征都学到,但是却削弱了网络对于鸮鹦鹉和其他鸟类特征的分别。

经过实验发现,这种网络架构不能很好的增加主任务的分类精度。为了充分的学到鸮鹦鹉和其他鸟类特征的分别,同时又能带入不同种类鸟类类别的先验,我们引入辅助任务:

60369cdaf70c64863dd8b00fa60041c4.jpeg

在上面的Pipeline中,辅助任务相比如主任务,把其他鸟类做更加细致的分类。这样网络就学到了区分不同其他鸟类的能力。

但是从实验效果来看这个Pipeline的精度并不高。经过分析原因,发现在主任务和辅助任务里面都有鸮鹦鹉这一类,这样当回传梯度的时候,相当于把区分鸮鹦鹉和其他鸟类的特征回传了两次梯度,而回传两次梯度明显是没用的,而且会干扰辅助任务学习不同其他鸟类的特征。

所以我们可以把辅助任务的鸮鹦鹉类去除,于是便形成了下面的pipeline:

95885623e70f9898c790a797c7502c28.jpeg

经过实验发现,这种pipeline是有利于主任务精度提升的,网络对于特征明显的其他鸟类的分类能力得到了一定程度的提升,同时对于困难类别的分类能力也有一定程度的提升。

当然,辅助任务的branch可以不只是一类,你可以通过多个类别来定义你的辅助任务的branch:

65536595f675ed14a74be9b4177bf5fa.jpeg

这时候你会想,上面的pipeline好是好,但是我没有那么多的label啊。是的,上面的pipeline除了主任务的label标注,它还同时需要很多的辅助任务的label标注,而标注label是深度学习任务里面最让人头疼的问题(之一)。

别怕,我下面介绍一个work,它基于meta-learning的方法,让你不再为给辅助任务标注label而烦恼,它的framework如下:

2f652c52870a76897a074d8e496fc5f4.jpeg

这个framework采用基于maxl[2]的方案(https://github.com/lorenmt/maxl),辅助任务的数据和label不是由人为手工划分,而是由一个label generator来产生,label generator的优化目标是让主网络在主任务的task上的loss降低,主网络的目标是在主任务和辅助任务上的loss同时降低。

ad0ef0f51ea411f16653d03d290b33dd.jpeg

但是这个framework有个缺点,就是训练时间会上升一个数量级,同时label generator会比较难优化。感兴趣的同学可以自己尝试。但是不得不说,这篇文章有两个结论倒是很有意思:

  1. 假设 primary 和 auxiliary task 是在同一个 domain,那么 primary task 的 performance 会提高当且仅当 auxiliary task 的 complexity 高于 primary task。

  2. 假设 primary 和 auxiliary task 是在同一个 domain,那么 primary task 的最终 performance 只依赖于 complexity 最高的 auxiliary task。

结语

先总结一下所有可以有效的加入先验信息的框架:

0b6796ddb0e266658fdf745461661777.jpeg

你可以通过上述框架的选择来加入自己的先验信息。

给神经网络的黑盒子里面加入一些人为设定的先验知识,这样往往能给你的task带来一定程度的提升,不过具体的task需要加入什么样的先验知识,需要如何加入先验知识还需要自己探索。

来自我自己的博客:https://zhengtq.github.io/2020/07/30/pri-knowledge-1/

参考

  1. ^CAM https://arxiv.org/abs/1512.04150

  2. ^maxl https://arxiv.org/abs/1901.08933

视频课程来了!

自动驾驶之心为大家汇集了毫米波雷达视觉融合、高精地图、BEV感知、传感器标定、自动驾驶协同感知、语义分割、自动驾驶仿真、L4感知等多个方向学习视频,欢迎大家自取(扫码进入学习)

938e6f62e82bf038b475aedb9ae94cdd.png

(扫码学习最新视频)

国内首个自动驾驶学习社区

近1000人的交流社区,和20+自动驾驶技术栈学习路线,想要了解更多自动驾驶感知(分类、检测、分割、关键点、车道线、3D目标检测、Occpuancy、多传感器融合、目标跟踪、光流估计、轨迹预测)、自动驾驶定位建图(SLAM、高精地图)、自动驾驶规划控制、领域技术方案、AI模型部署落地实战、行业动态、岗位发布,欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频,期待交流!

d18208fb26eb1962965a95ca68f93665.jpeg

自动驾驶之心】全栈技术交流群

自动驾驶之心是首个自动驾驶开发者社区,聚焦目标检测、语义分割、全景分割、实例分割、关键点检测、车道线、目标跟踪、3D目标检测、BEV感知、多传感器融合、SLAM、光流估计、深度估计、轨迹预测、高精地图、NeRF、规划控制、模型部署落地、自动驾驶仿真测试、产品经理、硬件配置、AI求职交流等方向;

17e8489b8384696874665d1c91b3d056.jpeg

添加汽车人助理微信邀请入群

备注:学校/公司+方向+昵称

### 回答1: 机器学习先验模型都是用于建立模型和预测的方法,但是它们的原理和应用场景有所不同。 机器学习是一种数据驱动的方法,通过对大量数据的分析和学习,来构建模型并进行预测。机器学习不依赖于任何先验知识,它是一种通过数据来发现规律和模式的方法。 而先验模型则是一种基于已有的先验知识或经验,来建立模型和预测的方法先验模型通常是基于专家知识或领域知识来建立的,它可以在数据量较小或数据质量不高的情况下提供可靠的预测。 总的来说,机器学习更适合处理大量数据和复杂模型,而先验模型则更适合处理数据量较小或数据质量较低、需要依赖先验知识的情况。 ### 回答2: 机器学习先验模型之间的区别在于其建模的方式和使用的数据。 机器学习是一种基于数据的方法,通过训练模型来从数据中学习规律和模式。它通过算法自动从数据中学习,并使用这些学习来做出预测或分类。机器学习基于数据的特征和标签,通过反复的训练和调整模型的参数,使其能够适应数据的规律和变化。机器学习的好处是可以处理大量的、复杂的数据,并能够从中发现隐藏的关联和模式。 而先验模型是一种假设或预先设定的模型,基于领域知识或经验来建立。它是基于主观判断或领域专家的经验,将问题的特征和模式抽象为数学模型先验模型使用预设的参数和假设,可以从一小部分数据中进行建模。先验模型一般由人工设定,并且无法自动地进行优化和调整。 因此,机器学习先验模型的区别在于建模精度、数据需求和建模方式。机器学习可以通过大量的数据自动学习和优化模型,对于复杂、高维的数据有很好的适应性。而先验模型则是基于领域知识和经验建立的,适用于数据较少或对于领域知识要求较高的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值