通道注意力机制keras_在TensorFlow+Keras环境下使用RoI池化一步步实现注意力机制

本文介绍了RoI池化在目标识别中的作用,以及如何在TensorFlow+Keras环境中使用RoI池化来实现注意力机制。通过RoI池化层,模型能关注输入的特定特征,实现端到端的可微架构。文章还提供了Keras自定义层的实现代码,展示了如何在没有权重的情况下构建RoI池化层。
摘要由CSDN通过智能技术生成

项目地址:https://gist.github.com/Jsevillamol/0daac5a6001843942f91f2a3daea27a7

理解 RoI 池化

RoI 池化的概念由 Ross Girshick 在论文「Fast R-CNN」中提出,RoI 池化是其目标识别工作流程中的一部分。

在 RoI 池化的一般用例中,我们会有一个类似图像的目标,以及用边界框指定的多个感兴趣区域。我们要从每个 RoI 中生成一个嵌入。

例如,在 R-CNN 的设定下,我们有一个图像和一个为图像中可能感兴趣的部分生成边界框的候选机制。接下来,我们要为每一个候选的图像块生成嵌入:

简单地裁剪每个候选区域是行不通的,因为我们想要将最终得到的嵌入叠加在一起,而候选区域的形状不一定相同!

因此,我们需要想出一种方法对每个图像块进行变换,以生成预定义形状的嵌入。我们要怎么实现这一点?

在计算机视觉领域,使用池化操作是缩小图像形状的一种标准做法。

最常见的池化操作是「最大池化」。此时,我们将输入图像划分成形状相同的区域(通常是不重叠的),然后通过取每个区域的最大值来得到输出。

最大池化操作将每个区域划分为若干大小相同的池化区域

这并不能直接解决我们所面临的问题——形状不同的图像块将被划分成数量不一的形状相同的区域,产生不同形状的输出。

但这为我们提供了一个思路。如果我们把每个感兴趣的区域划分成相同数量的形状不同的区域,并取每个区域的最大值呢?

RoI 的池化操作将所有区域划分为相同数量的池化区域网格。

这正是 RoI 池化层所做的工作。

使用注意力机制的好处

ROI 池化实现了所谓的「注意力机制」,它让我们的模型可以专注于输入的特定特征。

在目标识别任务的环境下,我们可以将任务工作流程划分为两部分(候选区域和区域分类),同时保留端到端的可微架构。

展示 RoI 池化层的 Fast R-CNN 架构。图源:Ross Girshick 的论文《Fast R-CNN》。

RoI 池化是一种泛化能力很强的的注意力工具,可以用于其他任务,比如对图像中预选区域的一次性上下文感知分类。也就是说,它允许我们对同一张图像的不同区域进行一次标记处理。

更一般而言,注意力机制受到了神经科学和视觉刺激研究的启发(详见 Desimone 和 Duncan 1995 年发表的论文「Neural Mechanism of Selective Visual Attention」。

如今,对注意力机制的应用已经超越了计算机视觉的范畴,它在序列处理任务中也广受欢迎。我觉得读者可以研究一下 Open AI 的注意力模型示例:《Better Language Models and their Implications》,该模型被成功地用于处理各种自然语言理解任务。

RoI 层的型签

在我们深入研究实现细节之前,我们可以先思考一下 RoI 层的型签(type signature)。

RoI 层有两个输入张量:一批图像。为了同时处理这些,所有图像必须具备相同的形状。最终得到的 Tensor 形状为(batch_size,img_width,img_height,n_channels)。

一批候选的感兴趣区域(RoIs)。如果我们想将它们堆叠在一个张量中,每张图像中候选区域的数量必须是固定的。由于每个边界框需要通过 4 个坐标来指定,该张量的形状为(batch_size,n_rois,4)。

RoI 层的输出应该为:为每章图像生成的嵌入列表,它编码了每个 RoI 指定的区域。对应的形状为(batch_size,n_rois,pooled_width,pooled_height,n_channels)

Keras 代码

Keras 让我们可以通过继承基本层类来实现自定义层。

「tf.keras」官方文档建议我们为自定义层实现「__init__」、「build」以及「call」方法。然而,由于「build」函数的目的是为层添加权重,而我们要实现的 RoI 层并没有权重,所以我们并不需要覆盖该方法。我们还将实现方便的「compute_output_shape」方法。

我们将分别对每个部分进行编码,然后在最后将它们整合起来。def __init__(self, pooled_height, pooled_width, **kwargs):

self.pooled_height = pooled_height

self.pooled_width = pooled_width

super(ROIPoolingLayer, self).__init__(**kwargs)

类的 constructor 很容易理解。我们需要指定待生成嵌入的目标高度和宽度。在 constructor 的最后一行中,我们调用 parent constructor 来初始化其余的类属性。def compute_output_shape

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值