【论文笔记】API-Net:Learning Attentive Pairwise Interaction for Fine-Grained Classification

article/2025/10/20 16:46:08

API-Net

  • 简介
  • 创新点
    • mutual vector learning(互向量学习)
    • gate vector generation(门向量生成器)
    • pairwise interaction(成对交互)
  • 队构造(Pair Construction)
  • 实验结果
  • 总结

简介

  • 2020年发表在AAAI的一篇细粒度分类论文。
  • 人类在区分不同子类的图像时,会成对地进行比较。本文模仿这一行为,同时提取并融合一对图片的特征,提高了网络辨别不同目标的能力。
  • 槽点:开源代码环境居然用的 pyton2.7 + torch0.4.1 的远古版本,实验室服务器CUDA10.0完全没法跑😓,以后有机会尝试自己复现吧。。。
  • 论文地址
  • 代码地址

整体框架
在这里插入图片描述

创新点

mutual vector learning(互向量学习)

  • 训练过程首先把两张图片输入骨干网络 (ResNet101),分别提取D维度的特征 x 1 x_1 x1 x 2 x_2 x2,即: x 1 a n d x 2 ∈ R D x_1\space and \space x_2\in \mathbb{R}^D x1 and x2RD
    示意图:
    在这里插入图片描述

  • 之后进入 互向量学习 阶段,将 x 1 x_1 x1 x 2 x_2 x2 连接,对其使用MLP,即两个全连接加一个Dropout,得到 x m ∈ R D x_m\in \mathbb{R}^D xmRD
    x m = f m ( [ x 1 , x 2 ] ) , f m 为 M L P 操 作 x_m=f_m([x_1,x_2]),f_m为MLP操作 xm=fm([x1,x2])fmMLP

代码:

# 定义
self.map1 = nn.Linear(2048 * 2, 512)
self.map2 = nn.Linear(512, 2048)
self.drop = nn.Dropout(p=0.5)# concat和两个全连接
mutual_features = torch.cat([features1, features2], dim=1)
map1_out = self.map1(mutual_features)
map2_out = self.drop(map1_out)
map2_out = self.map2(map2_out)

示意图:
在这里插入图片描述

gate vector generation(门向量生成器)

  • 先将 xm 与x1 和 x2 作比较,从单独的图片中进一步提取有区别的线索(clue),为后续区分这一对做准备。
    • 将 xm 和xi 做通道乘积,对结果用sigmoid,生成门函数(gate vector) g i ∈ R D g_i\in R^D giRD

g i = s i g m o i d ( x m ⊙ x i ) , i ∈ { 1 , 2 } g_i=sigmoid(x_m\odot x_i),i\in \left\{1,2 \right\} gi=sigmoid(xmxi),i{1,2}

gi 作为一种区分注意力( discriminative attention),原文说是通过每个个体 xi 的不同视角来突出语义差异。其实就是把 xm 和 xi 点乘后做 sigmoid,我不认为这一步有多大用🙄

代码:

gate1 = torch.mul(map2_out, features1) # 点乘
gate1 = self.sigmoid(gate1)gate2 = torch.mul(map2_out, features2)
gate2 = self.sigmoid(gate2)

示意图:

在这里插入图片描述

pairwise interaction(成对交互)

  • 原文:为了捕捉一对细粒度图像中的细微差异,人类检查每幅图像,不仅有其突出的部分,而且有与其他图像不同的部分。
  • 实现:将向量与门两两组合,进行一些操作,得到四个向量:
    • x i s e l f x^{self}_i xiself 用自己的门向量进行加强, x i o t h e r x_i^{other} xiother 用自己的门向量和pair中另一副图像进行激活。
    • 用来自这两幅图像的鉴别线索( discriminative clues)来增强 xi
      x 1 s e l f = x 1 + x 1 ⊙ g 1 , x 2 s e l f = x 2 + x 2 ⊙ g 2 , x 1 o t h e r = x 1 + x 1 ⊙ g 2 , x 2 o t h e r = x 2 + x 2 ⊙ g 1 , x_1^{self}=x_1+x_1\odot g_1,\\ x_2^{self}=x_2+x_2\odot g_2,\\ x_1^{other}=x_1+x_1\odot g_2,\\ x_2^{other}=x_2+x_2\odot g_1, x1self=x1+x1g1,x2self=x2+x2g2,x1other=x1+x1g2,x2other=x2+x2g1,

代码:

# 点乘后相加features1_self = torch.mul(gate1, features1) + features1features1_other = torch.mul(gate2, features1) + features1features2_self = torch.mul(gate2, features2) + features2features2_other = torch.mul(gate1, features2) + features2#全连接后dropout,得到结果logit1_self = self.fc(self.drop(features1_self))logit1_other = self.fc(self.drop(features1_other))logit2_self = self.fc(self.drop(features2_self))logit2_other = self.fc(self.drop(features2_other))

示意图:
在这里插入图片描述

之后便是常规的softmax以及计算损失,得到最终结果。
值得一提的是,计算损失过程中除了交叉熵损失,还添加了一个排序损失 L r k L_{rk} Lrk
作用是让 p i o t h e r p_i^{other} piother 的优先级更低。
其实就是MarginRankingLoss:

L r k = ∑ i ∈ { 1 , 2 } m a x ( 0 , p i o t h e r ( c i ) − p i s e l f ( c i ) + ξ ) L_{rk}=\sum_{i\in \left \{ 1,2 \right\}}max(0,p^{other}_i(c_i)-p^{self}_i(c_i)+\xi) Lrk=i{1,2}max(0,piother(ci)piself(ci)+ξ)

# 定义
criterion = nn.CrossEntropyLoss().to(device)
rank_criterion = nn.MarginRankingLoss(margin=0.05)# 实现
softmax_loss = criterion(logits, targets)
rank_loss = rank_criterion(self_scores, other_scores, flag)
loss = softmax_loss + rank_loss

示意图:
在这里插入图片描述

队构造(Pair Construction)

利用欧氏距离找到每张图像和batch中类间图象以及类内图像最接近的两对
细节如下:

  • 在一批(batch)中随机抽取 N c l N_{cl} Ncl 个类,在每个类中随机抽取 N i m N_{im} Nim 个训练图像;
  • 我们将所有这些图像输入CNN主干,生成它们的特征向量;
  • 根据欧氏距离,将每幅图像的特征和batch中其他图像的特征进行比较;
  • 对每张图像构造出1)类内/类间pair,包含本身的特征,2)batch中类内/类间最相近的特征组成;
  • 所以,每一个batch中有 2 × N c l × N i m 2\times N_{cl}\times N_{im} 2×Ncl×Nim 个pair;
  • 把它们所有的损失L进行总结并进行端到端训练。

代码:

def get_pairs(self, embeddings, labels): # 得到的结果不影响网络梯度distance_matrix = pdist(embeddings).detach().cpu().numpy() # detach():不计算梯度 转到numpylabels = labels.detach().cpu().numpy().reshape(-1,1)# 变成一列num = labels.shape[0] # 个数dia_inds = np.diag_indices(num) # 得到num维数组的对角线的索引lb_eqs = (labels == labels.T)lb_eqs[dia_inds] = Falsedist_same = distance_matrix.copy()dist_same[lb_eqs == False] = np.infintra_idxs = np.argmin(dist_same, axis=1) # 按行取最小值dist_diff = distance_matrix.copy()lb_eqs[dia_inds] = Truedist_diff[lb_eqs == True] = np.infinter_idxs = np.argmin(dist_diff, axis=1)intra_pairs = np.zeros([embeddings.shape[0], 2])inter_pairs  = np.zeros([embeddings.shape[0], 2])intra_labels = np.zeros([embeddings.shape[0], 2])inter_labels = np.zeros([embeddings.shape[0], 2])for i in range(embeddings.shape[0]):intra_labels[i, 0] = labels[i]intra_labels[i, 1] = labels[intra_idxs[i]]intra_pairs[i, 0] = iintra_pairs[i, 1] = intra_idxs[i]inter_labels[i, 0] = labels[i]inter_labels[i, 1] = labels[inter_idxs[i]]inter_pairs[i, 0] = iinter_pairs[i, 1] = inter_idxs[i]intra_labels = torch.from_numpy(intra_labels).long().to(device)intra_pairs = torch.from_numpy(intra_pairs).long().to(device)inter_labels = torch.from_numpy(inter_labels).long().to(device)inter_pairs = torch.from_numpy(inter_pairs).long().to(device)return intra_pairs, inter_pairs, intra_labels, inter_labels

实验结果

CUB-200-2011

在这里插入图片描述
其余不再列举。

总结

  • 我个人认为本文的实验结果不算惊艳,网络中的很多步骤我也不明白为啥能够得到正反馈,包括作者自己也只是概括地介绍。
  • 但必须承认API-Net的思路很有创新性,并且也能够取得较高的精度。

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

相关文章

白话点云dgcnn中的pairwise_distance

点云DGCNN中对于代码中pairwise_distance的分析与理解 2021年5月7日:已经勘误,请各位大佬不惜赐教。 一点一点读,相信我,我能讲清楚。 这个是本篇文章所要讨论的代码段 总体上把握,这个代码计算出了输入点云每对点之…

推荐系统[四]:精排-详解排序算法LTR (Learning to Rank): poitwise, pairwise, listwise相关评价指标,超详细知识指南。

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

【torch】torch.pairwise_distance分析

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 记录torch.pairwise_distance 1. 一维 1.1 元素个数相同 1.1.1 元素个数为1 生成代码: t torch.randn(1) f torch.randn(1)计算代码,下…

pairwise损失_triplet损失_提升精排模型的trick

01标签 import torch import torch.nn as nn# 输入x是一个二维张量,每一行表示一个样本的分数,每一列表示一个特征或维度 x torch.tensor([[0.5, 0.7], [0.9, 0.8], [0.6, 0.4], [0.3, 0.6], [0.8, 0.7], [0.4, 0.5]])# 标签y是一个一维张量&#xff0c…

LTR (Learning to Rank): 排序算法 poitwise, pairwise, listwise常见方案总结

目录 1 Learing to Rank介绍2 The Pointwise Approach3 The Pairwise Approach3.1 RankNet 4 The Listwise Approach4.1 直接优化评测指标4.1.1 LambdaRank4.1.2 LambdaMART 4.2 定义Listwise损失函数4.2.1 ListNet4.2.2 ListMLE 5 排序评估指标5.1 Mean Reciprocal Rank (MRR)…

【论文精读】Pairwise learning for medical image segmentation

Published in: Medical Image Analysis 2020 论文:https://www.sciencedirect.com/science/article/abs/pii/S1361841520302401 代码:https://github.com/renzhenwang/pairwise_segmentation 目录 Published in: Medical Image Analysis 2020 摘要 一…

pairwise相似度计算

做了一个比赛,其中为了更好的构建负样本,需要计算不同句子之间的相似性,句子大概有100w,句子向量是300维,中间踩了很多坑,记录一下。 暴力计算 最简单的idea是预分配一个100w x 100w的矩阵,一…

如何计算 Pairwise correlations

Pairwise Correlation的定义是啥?配对相关性?和pearson correlations有什么区别? Pairwise Correlation顾名思义,用来计算两个变量间的相关性,而pearson correlations只是计算相关性的一种方法罢了。 1、pearson相关系…

再谈排序算法的pairwise,pointwise,listwise

NewBeeNLP干货 作者:DOTA 大家好,这里是 NewBeeNLP。 最近因为工作上的一些调整,好久更新文章和个人的一些经验总结了,下午恰好有时间,看了看各渠道的一些问题和讨论,看到一个熟悉的问题,在这…

【推荐】pairwise、pointwise 、 listwise算法是什么?怎么理解?主要区别是什么?

写在前面:写博客当成了学习笔记,容易找到去完善,不用于商业用途。通过各种途径网罗到知识汇总与此,如有侵权,请联系我,我下掉该内容~~ 排序学习的模型通常分为单点法(Pointwise Approach&#…

软件测试用例设计之Pairwise算法

Pairwise算法简介 Pairwise是L. L. Thurstone(29 May1887 – 30 September 1955)在1927年首先提出来的。他是美国的一位心理统计学家。Pairwise也正是基于数学统计和对传统的正交分析法进行优化后得到的产物。 测试过程中,对于多参数参数多值的情况进行测试用例组…

磁盘配额中quotacheck不能创建aquota.user和aquota.group文件的问题

在centos6.5学习中有关磁盘配额的内容中,发现quotacheck -augv 命令无法创建aquota.group 和aquota.user文件, 操作系统挂载在/home下,经排查发现是SELinux的问题,使用setenforce 0命令将其关闭后,重新执行quotacheck…

Linux从入门到精通(八)——Linux磁盘管理

文章篇幅较长,建议先收藏,防止迷路 文章跳转Linux从入门到精通(八)——Linux磁盘管理goLinux从入门到精通(九)——Linux编程goLinux从入门到精通(十)——进程管理goLinux从入门到精…

Linux:Quota 的基本命令​​​​​​​

在开始进行 quota 的实作之前,我们得来了解一下 quota 要使用的指令啰! 基本上分为两种,一种是查询功能(quota, quotacheck, quotastats, warnquota, repquota),另一种则是编辑 quota 的内容( …

01_Linux系统管理_基础知识_高级文件系统管理_磁盘配额(quota)

环境 虚拟机:VMware-10.0.7 build-2844087Linux系统:CentOS 6.8远程工具:Xshell 6 (Build 0197) 01_Linux系统管理_基础知识_高级文件系统管理_磁盘配额 一、什么是磁盘配额(quota) 磁盘配额概念 对用户和用户组使用磁…

linux 系统配额管理功能,磁盘配额管理_Linux教程_Linux公社-Linux系统门户网站

在多用户系统中,如果没有对用户使用的磁盘空间做出限制,用户无限制地存放数据和文件,可能会导致系统磁盘空间告警。如果存放的是无用数据,就会导致磁盘空间白白浪费。磁盘配额可以限制用户或组在磁盘上存放文件的空间,…

Linux复习笔记

Linux复习笔记 常识说明 目录结构 Linux以树型结构管理文件,其最上层文件夹为 / ,也就是根目录。 如图所示,图中展示了一部分文件夹的结构: 所有的文件夹都属于根目录的子文件夹。 安装好系统后,根目录会挂载到一…

linux对目录空间使用限制,Linux quotacheck命令使用详解:检查磁盘的使用空间和限制...

quotacheck命令通过扫描指定的文件系统,获取磁盘的使用情况,创建、检查和修复磁盘配额(quota)文件。执行quotacheck指令,扫描挂入系统的分区,并在各分区的文件系统根目录下产生quota.user和quota.group文件,设置用户和…

Linux常用命令——quotacheck命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) quotacheck 检查磁盘的使用空间与限制 补充说明 quotacheck命令通过扫描指定的文件系统,获取磁盘的使用情况,创建、检查和修复磁盘配额(quota)文件。执行quotach…

Linux quotacheck失败

我找了多少个帖子才发现解决这个问题的啊...最终还是靠FQ找的这位大佬的文章 http://www.2daygeek.com/quotacheck-error/# 当我在执行quotacheck -avug的时候出现如下的错误: quotacheck: 无法从 /dev/sdb1 上的文件名猜测其格式,请在命令行中指定一个…