如何给模型加入先验知识?

article/2025/10/26 12:46:58

6bbbba13e058f4023f7c1e0497e01f42.jpeg

来源:PaperWeekly

作者:Billy Z

df597447807d9d852ba5ede670abfd0d.jpeg

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

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

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

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

51a51e654ff5b8fc856c2267e2e9497a.jpeg

▲ 鸮(xiāo)鹦鹉

这种鸟有个特点:

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

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

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

94e42d9814253fd304074651784d926d.jpeg

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

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

2e956f11431730af8eac5053617585a4.jpeg

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

ceebf2e4df673970caeeb8169ceb2175.jpeg

基于输入给模型加入先验

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

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

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

433b4bd7251e354192c1e40a18ae016d.jpeg

3f5f7848f4d97610fba99e2388ecfed3.jpeg

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

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

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

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

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

43934846eaaad514d4875abac1a1de25.jpeg

775c6ed407d546beb18dd4c6e5d01bc4.jpeg

▲ 测试的时候不增加计算量

1114b8aa0ed8a58d27c93ae135b1462f.jpeg

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

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

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

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

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

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

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

3b5b564dce9368622a7ce0b3a0409683.jpeg

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

CAM [1] 激活图是基于分类网络的倒数第二层卷积层的输出的 feature_map 的线性加权,权重就是最后一层分类层的权重,由于分类层的权重编码了类别的信息,所以加权后的响应图就有了基于不同类别的区域相应。

具体的介绍可以看:

https://zhuanlan.zhihu.com/p/51631163

具体的激活图生成方式可以如下表示:

be47cd0939d5705444d0008c35468f6e.jpeg

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

9eba5bec9b8c2a19493fb804fa4a6b7a.jpeg

0f9d77d8f5869f29d80709db862be7d1.jpeg

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

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

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

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

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

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

402e50385421f9430b19629df75119a0.jpeg

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

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

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

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

17e782c064a17d90413b01754f916152.jpeg

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

39982065f9d5e8091c8d9df66172186d.jpeg

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

084854e15e0f13af731f99b1446ecd76.jpeg

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

e38914ffb26a0c9f5675c5bb9c903a69.jpeg


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

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

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

16b3eaf62620522721b287a73b121685.jpeg

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

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

c90b27e6c052d9c84d435038b14dc41b.jpeg

上图的左侧是多任务学习的例子,右侧是辅助学习的例子。左侧是个典型的 face attribute 的 task,意思是输入一张人脸,通过多个 branch 来输出这一张人脸的年龄,性别,发型等等信息,各个 branch 的任务是独立的,同时又共享同一个 backbone。

右边是一个典型的辅助学习的 task,意思是出入一张人脸,判断这一张人脸的性别,同时另外开一个(或几个)branch,通过这个 branch 来让网络学一些辅助信息,比如发型,皮肤等等,来帮助网络主任务(分男女)的判别。

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

a9b93aa9fe1b53ecbe821b4d2fa6a482.jpeg

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

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

94b0a8c2e69427bc21fe7cc2bb022e3d.jpeg

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

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

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

ca9b97dc8d9d313143537fe7e95e3bbc.jpeg

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

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

82817416898bf42eb84a978b74b605bc.jpeg

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

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

5643f2d493019dbede801e8f2b44942f.jpeg

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

af07fc25f9451947318be786c654eb66.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。


3fae9e84c756403412c722cc8aa6b057.jpeg

结语

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

c5beaa87b8cfba05387d47f7100dce3a.jpeg

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

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

outside_default.png

参考文献

outside_default.png

[1] CAM https://arxiv.org/abs/1512.04150

[2] maxl https://arxiv.org/abs/1901.08933

未来智能实验室的主要工作包括:建立AI智能系统智商评测体系,开展世界人工智能智商评测;开展互联网(城市)大脑研究计划,构建互联网(城市)大脑技术和企业图谱,为提升企业,行业与城市的智能水平服务。每日推荐范围未来科技发展趋势的学习型文章。目前线上平台已收藏上千篇精华前沿科技文章和报告。

  如果您对实验室的研究感兴趣,欢迎加入未来智能实验室线上平台。扫描以下二维码或点击本文左下角“阅读原文”

c6a95e48c5e1ec4c522d70d72651d8c8.jpeg


http://chatgpt.dhexx.cn/article/b0TYZopk.shtml

相关文章

几何深度学习 - 利用几何先验知识的深度学习

深度学习很难。 虽然通用逼近定理表明足够复杂的神经网络原则上可以逼近“任何东西”,但不能保证我们可以找到好的模型。 尽管如此,通过明智地选择模型架构,深度学习取得了巨大进步。 这些模型架构对归纳偏差进行编码,为模型提供…

如何向深度学习模型中加入先验知识?

链接:https://www.zhihu.com/question/279012198 编辑:深度学习与计算机视觉 声明:仅做学术分享,侵删 作者:采石工https://www.zhihu.com/question/279012198/answer/1298985606 1) CNN 中使用的卷积层就是利用了图像像…

浅谈模型中加入先验知识

必要性 端到端的神经网络是个黑盒,虽然能够学习到一些可区分度好的特征,但是也会拟合到一些非重要特征,导致模型局部地区会有一些不好的特征表现,所以可以加入一些先验知识来优化这些区域表现。 首先给出可以有效的加入先验信息的…

综述:如何给模型加入先验知识

转载自:https://zhuanlan.zhihu.com/p/188572028 这里写目录标题 为什么要给模型加入先验知识?1 基于pretrain模型给模型加入先验2 基于输入给模型加入先验3 基于模型重现给模型加入先验4 基于CAM图激活限制给模型加入先验 为什么要给模型加入先验知识&a…

1 先验知识

目录 1. 脑的解剖学结构 (1)额叶Frontal lobe (2)顶叶Parietal lobe (3)颞叶Temporal lobe (4)枕叶Occipital lobe 2. 脑区命名 3. 脑组织定位 (转载请注明来自Re…

给模型加入先验知识

‍ 点‍击上方“机器学习与生成对抗网络”,关注星标 获取有趣、好玩的前沿干货!‍ ‍ 来源|知乎 作者|Billy Z 链接|https://zhuanlan.zhihu.com/p/188572028 报道|人工智能前沿讲习 01 模型加入先验知识的…

神经网络基础--指数加权移动平均ewma

因为神经网络中的常用优化算法都会涉及到指数加权移动平均(exponential weighted moving average, ewma;也可称为exponential moving average,ema),所以这里单独写下这个知识点。 ewma通过将历史的值和当前…

EWMA 指数加权移动平均 模型

Exponentially Weighted Moving Average(EWMA)指数加权移动平均是一种常用的序列数据处理方式,如下: 在时间 t, 根据实际的观测值(或量测值)我们可以求取 EWMA(t)如下: EWMA(t ) λY(t) ( 1-λ…

时间序列分析 - 移动平均SMA, EMA(EWMA) 之python

pandas: pandas.DataFrame.rolling pandas.DataFrame.ewm pandas.DataFrame.mean 其中rolling可以指定窗口类型win_type,比如boxcar, boxcar, triang, blackman, hanning, bartlett 以hanning window为例,其窗口形状为钟型,曲线函数为: p…

线性和EWMA指数加权移动平均模型

线性和EWMA指数加权移动平均模型 模型应用场景: 对历史测量值赋权重,对现在t时刻的数值做估计。 1 移动平均 移动平均是是技术分析其中一种分析时间序列数据的工具移动平均可抚平短期波动,将长线趋势或周期显现出来。数学上,移…

(四十八)用EWMA和GARCH模型估计波动率和相关系数

ARCH、EWMA、GARCH介绍 案例 对2016年至2018年沪深300指数的涨跌幅数据建立ARCH(1)、EWMA和GARCH(1,1)三种波动率模型,并以30天前的数据为起点,逐一预测后一天的波动率。 ARCH(1) import numpy as np import pandas as pd dfpd.read_excel(C:/Users/De…

Matlab正态分布、历史模拟法、加权移动平均线 EWMA估计风险价值VaR和回测Backtest标准普尔指数 SP500时间序列

最近我们被客户要求撰写关于风险价值的研究报告,包括一些图形和统计输出。 此示例说明如何使用三种方法估计风险价值 (VaR) 并执行 VaR 回测分析。这三种方法是: 正态分布 历史模拟 指数加权移动平均线 (EWMA) 视频:风险价值VaR原理与Py…

指数加权移动平均法(EWMA)

指数加权移动平均法(EWMA) https://www.cnblogs.com/jiangxinyang/p/9705198.html ** 本文内容来自于吴恩达深度学习公开课 1、概述 加权移动平均法,是对观察值分别给予不同的权数,按不同权数求得移动平均值,并以最…

R语言指数加权模型EWMA预测股市多变量波动率时间序列

最近我们被客户要求撰写关于波动率的研究报告,包括一些图形和统计输出。 从广义上讲,复杂的模型可以实现很高的预测准确性。 但是您的读者需要快速理解。他们没有意愿或时间去处理任何太乏味的事情,即使它可以稍微准确一些。简单性是商业中…

pandas 0.23.4 :'pd.ewma'没有这个模块,改用`Series.ewm` 或 降低版本到 pandas 0.21.0

问题: 在进行画出指数平滑移动平均线,遇到如下问题: # pd.ewma(comNone, spanone) # 指数平均线。com:数据;span:时间间隔AttributeError: module pandas has no attribute ewma解决办法: 方…

java 移动平均_EWMA之——EWMA指数加权移动平均模型的Java实现

具体代码如下: package com.lyz.storm.ewma; import java.io.Serializable; /** * 实现指数移动平均值计算 * 实现中使用了流式风格的builder API * author liuyazhuang * */ public class EWMA implements Serializable { private static final long serialVersion…

EWMA模型估计波动率

#tushare ID:474220 指数移动平均(Exponential Moving Average, EMA或EWMA)是以指数式递减加权的移动平均。各数值的加权而随时间而指数式递减,越近期的数据加权越重,但较旧的数据也给予一定的加权。加权的程度以常数λ…

史上最通俗易懂的EWMA(指数加权移动平均)的参数解释以及程序代码

文章目录 一、EWMA(指数加权移动平均)是什么?二、详细的参数解释3、使用Python pandas库中的ewm()函数实现指数加权移动平均(EWMA)的示例代码总结 一、EWMA(指数加权移动平均)是什么&#xff1f…

用计算器来进行计算10的几次方的问题

一、首先找到计算器,然后就是找到科学,如图: 二、比如说进行10的2次方,先进行CE清除,然后就是选中10,然后就是选中如下:10^x,如图: 选择10的平方为100,如图: …

十次方项目登陆问题 token令牌解析,claims获取不到userid,求大神帮忙看下代码解决问题

十次方项目登陆问题 token令牌解析,claims获取不到userid 这个是拦截器: 判断角色是用户还是管理员,如果是用户就存入(“claims_user”,token);到controller控制层 此时clims为空,所以下面取值为权限不足