神经网络加上注意力机制,精度反而下降?

 
 

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

编者荐语

 

CNN模型,二分类问题,2层卷积层,加上CBAM之后,模型精度反而不如不加(已排除过拟合和欠拟合)。不知道为什么会出现这个问题?

转载自丨计算机视觉CV

整理自丨知乎

回答1

添加注意力不起作用无外乎两个原因,一是代码错误,二是注意力不适合。代码错误就不说了,需要注意激活函数,残差连接等。而注意力不适合,需要明白:

(1)注意力本身就是一种特征,通过附加到源特征上,实现一种类似特征增强的效果,因此从原理上讲,添加注意力,即使结果不变好,也不见得变差,但实际却经常遇到结果变差的情况(原理上学不到全部置0就跟没添加一样了,但现实网络学习不会将其全部置0,因此会出现学不好就变差的情况);

(2)换一种说法,注意力是一组权重,权重附加到特征上,有增强的也有不增强的,当大量权重附加都达到增强效果,而只有少量特征造成负面影响,注意力就整体上增强了。这也是我们常说的注意力强化有用特征而弱化无用特征的作用,但其实鬼知道它强化的是什么特征,它也不可能强化的都是有用特征。

(3)注意力的提升是不明显的,注意力的增强效果是多层堆叠的整体效果。需要知道,我们常用的resnet模型虽然添加注意力就一个位置,但注意力与网络层的数量是正相关的,更深的resnet模型注意力效果更好归根结低是注意力的层数增多了。

理解了注意力是什么,注意力通过什么方式增强网络,注意力怎么变得更强,也自然明白为什么添加注意力没有效果?或效果变差了?

该学的没学习到:

(1)自己设计时,理论很完美,但神经网络归根结低是个黑盒,它不一定能按照个人的意愿来走;

(2)注意力层数过少,增强效果不明显,网络有很多参数需要学习,冗余参数更不下少数,效果不明显导致结果变化很正常,即使换个随机种子结果也会变化呢;

(3)过拟合太严重,过拟合时给网络添加任何组件时都有可能时导致结果变差。

任务不合适:

注意力机制的兴起,self-attention的推力功不可没,因此有不少在CV和NLP转来转去的方法,这也是未来的一大趋势,特别是自监督、注意力、transformer这些方法结构。如目标检测用的比较多的no-loal、DaNet这类self-attention变体。针对这些特定领域、特定任务下有突出效果的注意力机制,在应用与自己模型时,特别要注意任务适不适合,原始设计目的是否符合自身的需求?比如说,你想用self-attention,就要知道self-attention的目的是建立大的全局感受野,那么对于只有局部信息或者引入全局信息会引起歧义的情况下,就不应使用它。再如noloca-attention默认是建立时间前后维度的联系,将其应用与图像时就需要单独的注意设计。

68199ff86e2370eb5f2ff0e0db048105.jpeg
位置不合理:包括注意力提取的位置和注意力施加的位置

还是拿resnet来说,SE、CBAM这些注意力为什么不添加到网络的开头和结尾?

从结构上看,CBAM包括一个空间和一个通道注意力,两者主要都是利用全局平均池化将特征抽象到一系列点注意力权重,然后建立这些权重的联系并附加到原空间或通道特征上。然后,从提取位置看,在网络的开头(如图像级)提取,从rgb图像提取CBAM注意力,得到的是rgb3个权重的通道注意力和整幅图像大小的空间注意力,常识能很坚定推断这是没有意义的。那么稍往后一些层也是一样的,空间特征图太大,通道数太少。提取的通道权重概括性太大没有落到一些具体特征上,提取的空间注意力由于通道数较少,概括性不足,且空间注意力敏感且难学,更容易造成负面影响。

85dba433628eb8a6d82ae208165e26bd.jpeg

那么网络靠后的层呢?为什么也不添加注意力?

将通道和空间反过来原因其实跟上面是一样的,太靠后的层,通道数过多,容易引起过拟合;特征图太小,使用卷积,操作不当反而会引入大比例非像素信息,特别地,如果特征图小到1x1,那注意力就变成了一层奇怪的全连接层。更重要的是,靠近分类层,注意力的效果对分类结果更敏感,容易影响分类层决策。

因此,像CBAM这种注意力机制一般适用于通道与空间都比较适中的网络中间层。在这里,很多空间特征图可以代表原图的一个特征(纹理,结构,颜色等),因此可以概括为一个权重,若某些特征比较重要,那么简单地加大对应的注意力权重即可达到目的。正常情况下,注意力还会随着通道的增多而增强,这是效果的叠加的结果。

最后,每种注意力机制都需要考虑各种设计细节,包括注意力权重的产生方式、注意力的作用方式、注意力的提升原理,才能更好发挥注意力的作用。以上结论并不严谨,欢迎一起探讨。

回答2

模型复杂度和精度本身就不一定成正比。

举个最简单的例子:二分类问题时,如果数据本身就可以用一条直线划分成两类,但非要去弄个复杂的曲线去划这个界限,那就必然会出问题。

0b50e58a2213de6f8a0b49fc9c6ccf0e.png

另外还是再仔细检查一下过拟合和欠拟合。如果是过拟合,那么训练误差应该会非常低。简单的排除方法就是看看增加注意力之后是不是比不增加时训练误差更小。如果是,那就是过。反之,欠拟合。

如果完全排除了上述可能,那么最简单的解释就是:当前的数据不适合用注意力机制来刻画。

目前比较公认的观点是:模型性能 = 模型特性+数据特征。从统计学的角度来解释最简单:模型的特性刚好适合数据的分布。

比如数据本身服从高斯分布,噪声较小。那么普通的模型通常就能达到比较好的效果。但数据本身不服从高斯,有大量的躁声。尤其还可能服从泊松一类的分布,那么普通模型通常都不咋地。因为从统计上讲这样的估计是有偏的。最典型的例子就是持续爆炸式增长的时间序列,用普通的AR模型通常预测效果都很差。又或者周期型数据,如果不用周期型模型就很难达到好的预测。具体模型在何时有效,何时无效,其原因是什么,哪怕给出一点点更深入的解释,都是进步。

回答3

一个模型精度是否提高会受到非常多因素影响,需要考虑的因素包括模型的参数量、训练策略、用到的超参数、网络架构设计、硬件以及软件使用(甚至pytorch版本都会有影响,之前在某个版本卡了半天,换了版本问题就解决了)等等。

注意力机制到底work不work,可以从两个角度来解释。

第一个角度是模型的欠拟合与过拟合。大部分注意力模块是有参数的,添加注意力模块会导致模型的复杂度增加。

  • 如果添加attention前模型处于欠拟合状态,那么增加参数是有利于模型学习的,性能会提高。

  • 如果添加attention前模型处于过拟合状态,那么增加参数可能加剧过拟合问题,性能可能保持不变或者下降。

为了验证以上猜想,使用cifar10数据集中10%的数据进行验证,模型方面选择的是wideresnet,该模型可以通过调整模型的宽度来灵活调整模型的容量。

构建了模型族:

f4ad2eb954e8f99136f5a36800c4ad09.png

具体来说,从上到下模型容量越来越高,下图展示了各个模型在训练集和验证集上的收敛结果。

57420fab18dd0e0fde11da7772508513.png

可以发现一下几个现象:

  • 随着宽度增加,模型过拟合现象会加剧,具体来说是验证集准确率变低。

  • cbam与norm进行比较可以发现,在8d(可能还处于欠拟合)基础上使用cbam可以取得验证集目前最高的结果,而在64d(可能出现过拟合)基础上使用cbam后准确率几乎持平。

  • 还有一个有趣的现象,就是收敛速度方面,大体符合越宽的模型,收敛速度越快的趋势(和我们已知结论是相符的,宽的模型loss landscape更加平滑,更容易收敛)

以上是第一个角度,另外一个角度可能没那么准确,只是用来分析。

第二个角度是从模型感受野来分析

我们知道CNN是一个局部性很强的模型,通常使用的是3x3卷积进行扫描整张图片,一层层抽取信息。而感受野叠加也是通过多层叠加的方式构建,比如两个3x3卷积的理论感受野就是5x5, 但是其实际感受野并没有那么大。

各种注意力模块的作用是什么呢?他们能够弥补cnn局部性过强,全局性不足的问题,从而获取全局的上下文信息,为什么上下文信息重要呢?可以看一张图来自CoConv。

a812efcf025f79fc7502974ca90cfd77.png
单看图a,你能区分该目标是什么吗?

单纯看图a可能完全不知道该目标是什么,但是有了图b的时候,指导这是厨房以后,就可以指导该目标是厨房用手套。

因此注意力模块具有让模型看的更广的能力,近期vision transformer的出现和注意力也有一定关联,比如Non Local Block模块就与ViT中的self-attention非常类似。vision transformer在小数据集上性能不好的也可以从这个角度解释,因为太关注于全局性(并且参数量比较大),非常容易过拟合,其记忆数据集的能力也非常强,所以只有大规模数据集预训练下才能取得更好的成绩。(感谢李沐老师出的系列视频!)

跑原来,再回到这个问题,注意力模块对感受野的影响,直观上来讲是会增加模型的感受野大小。理论上最好的情况应该是模型的实际感受野(不是理论感受野)和目标的尺寸大小相符。

  • 如果添加注意力模块之前,模型的感受野已经足够拟合数据集中目标,那么如果再添加注意力模块有些画蛇添足。但是由于实际感受野是会变化的,所以可能即便加了注意力模块也可以自调节实际感受野在目标大小附近,这样模型可能保持性能不变。

  • 如果添加注意力模块之前,模型的感受野是不足的,甚至理论感受野都达不到目标的大小(实际感受野大小<理论感受野大小),那么这个时候添加注意力模块就可以起到非常好的作用,性能可能会有一定幅度提升。

从这个角度来分析,题主只用了两个卷积层,然后就开始使用CBAM模块,很有可能是感受野不足的情况。但是为什么性能会下降呢,可能有其他方面因素影响,可以考虑先构建一个差不多的baseline,比如带残差的ResNet20,或者更小的网络,然后再在其基础上进行添加注意力模块。

参考链接

  • https://www.zhihu.com/question/478301531

本文章来源于知乎,如有侵权请联系删除。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。


下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。


下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
在卷积神经网络中添加注意力机制,可以通过以下代码实现: ```python import tensorflow as tf class AttentionLayer(tf.keras.layers.Layer): def __init__(self, **kwargs): super(AttentionLayer, self).__init__(**kwargs) def build(self, input_shape): self.W = self.add_weight(name="att_weight", shape=(input_shape[-1], 1), initializer="normal") self.b = self.add_weight(name="att_bias", shape=(input_shape[1], 1), initializer="zeros") super(AttentionLayer, self).build(input_shape) def call(self, x): e = tf.keras.backend.dot(x, self.W) + self.b a = tf.keras.backend.softmax(e, axis=1) output = x * a return tf.keras.backend.sum(output, axis=1) ``` 以上代码实现了一个自定义的 AttentionLayer 类,通过该类可以将注意力机制加入到卷积神经网络中。在该类中,`build` 方法用于构建权重,`call` 方法用于计算注意力向量并输出加权后的特征向量。 使用该 AttentionLayer 类,可以在卷积神经网络中添加注意力机制,具体代码如下: ```python import tensorflow as tf input_layer = tf.keras.layers.Input(shape=(32, 32, 3)) conv_layer = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation="relu")(input_layer) pooling_layer = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv_layer) flatten_layer = tf.keras.layers.Flatten()(pooling_layer) attention_layer = AttentionLayer()(flatten_layer) output_layer = tf.keras.layers.Dense(units=10, activation="softmax")(attention_layer) model = tf.keras.models.Model(inputs=input_layer, outputs=output_layer) ``` 以上代码实现了一个简单的卷积神经网络,其中包含一个卷积层、一个池化层、一个展平层、一个自定义的 AttentionLayer 层和一个全连接层。在 AttentionLayer 层后面使用了一个全连接层,用于最终的分类任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值