本篇文章为比赛第一名方案解析,该比赛涉及到多模态-电商
介绍:在本次竞赛中,参赛者将应用机器学习技能来构建一个模型,以预测哪些商品是相同的产品。
网址:www.kaggle.com/competition...
第一名解决方案 - 从嵌入到匹配
恭喜所有获奖者,感谢主办方安排这个有趣的数据库和 Kaggle 举办这次比赛!还要向我的队友@limerobot表示衷心的感谢,他总是能想出绝妙的主意,从不停歇。我从他那里学到了很多。
标题是"从嵌入到匹配",因为我们从正确利用图像/文本嵌入来搜索匹配中获得了主要的计算机视觉/语言模型改进。另一方面,单个模型改进的帮助较小,也就是说,在我们获得了不错的模型之后,"从输入到嵌入"的重要性就降低了。即使每个图像/文本模型的计算机视觉提高了相当多,集成模型的计算机视觉和语言模型并没有显著提高。
我首先分享我们的公共排行榜得分历史。我只写那些显著提高我们得分的要点。请注意,模型/训练优化也在这里和那里提高了得分。
- 基准:0.7 (仅图片),0.64(仅文本)
- concat img_emb & txt_emb -> normalize: 0.724
- min2 :0.743
- normalize -> concat img_emb & txt_emb: 0.753
- 完整数据训练:0.757
- 联合组合,img,txt 匹配 & 调整阈值:0.776
- INB & 添加多样化的文本模型:0.784
- 使用 img、txt、comb emb 在 INB 阶段 1,并联合调整阈值:0.793
现在我将详细介绍我们的解决方案。
模型
我们使用了来自 timm
的两个 eca_nfnet_l1
作为图像编码器,以及来自 huggingface
的 xlm-roberta-large
、xlm-roberta-base
、 cahya/bert-base-indonesian-1.5G
、 indobenchmark/indobert-large-p1
、 bert-base-multilingual-uncased
。
我们使用了ArcFace
来训练模型。在从图像/文本编码器池化后,我们对输出嵌入应用了批量归一化和特征归一化。遵循ArcFace
论文,将归一化嵌入与归一化权重矩阵相乘以产生余弦值,然后我们应用弧度间隔和 softmax。
2. 调优 ArcFace
我们俩第一次使用 ArcFace,一开始调参比较困难。足够大的间隔对于嵌入质量很重要,但当我们增加它时,模型出现了收敛问题。我们找到了几种克服这个问题的方法,并最终在这些选项中应用了其中一种。
- 逐步增加训练过程中的边际收益
- 使用大预热步长
- 使用更大的学习率进行余弦头
- 使用梯度裁剪
0.81.0 的边缘对于图像模型是最佳的,0.60.8 对于文本模型是最佳的。在使用增加边缘的方法时,我们从 0.2 的边缘开始,将其增加到 1.0 用于图像模型和 0.8 用于文本模型。
此外,我们还尝试了类大小自适应边距,该边距是在谷歌地标识别竞赛解决方案中引入的(arxiv.org/pdf/2010.05...))。当边距设置为class_size^-0.1
时,对于图像模型效果最佳,而对于文本模型则设置为class_size^-0.2
。然而,由于类别不平衡程度低于谷歌地标识别竞赛,改进并不明显。
使用更大的学习率对 cosinehead 进行训练,并使用梯度裁剪不仅使模型收敛,还略微提高了 CV 分数。
在全局平均池化之后添加额外的 fc 层会损害模型性能,而在特征归一化之前添加批归一化提高了分数。
3. 结合图像与文本匹配 - 连接 & 并集
我们在这个比赛中既有图像输入也有文本输入,充分利用和有效结合这些模态至关重要。这些是我们尝试的方法。
- 生成文本嵌入的文本匹配,图像嵌入的图像匹配,然后合并文本匹配和图像匹配
- 文本嵌入与图像嵌入合并 -> 产生组合匹配
- 联合组合匹配 & 文本匹配 & 图像匹配
第二种方法比第一种方法好得多,最后一种方法比第二种方法好得多。
我们对图像嵌入和文本嵌入进行归一化,然后将它们连接起来计算组合相似度。实际上,这与从图像嵌入计算相似度,再从文本嵌入计算另一个相似度,然后取平均值相同。因此,我们可以将最后一种方法解释如下。
所以我们接受图像嵌入强烈建议的项目,文本嵌入强烈建议的项目,以及图像和文本嵌入都适度建议的项目。
我们也尝试了联合训练图像编码器和文本编码器。然而,即使我们用训练好的编码器初始化,多模态模型始终不如单独训练。
4. 迭代邻域融合(INB)
除了结合图像和文本匹配外,正确利用嵌入技术来生成匹配结果也非常关键。我们构建了一个非平凡的流程,用于从嵌入中搜索匹配项。
基于 QE(查询扩展)和 DBA(数据库端特征增强),我们创建了一个名为 INB(迭代邻域融合) 的管道。大部分想法与 QE 和 DBA 共享,但有些细节不同。INB 管道由以下组件组成。
K 最近邻搜索
我们使用 faiss(github.com/facebookres...)进行 knn 搜索,并将 k 设置为 51(最多 50 个非自身匹配+1 个自身匹配)。我们使用内积作为相似度度量(嵌入已归一化,因此相当于余弦相似度)。
阈值
我们将余弦相似度转换为余弦距离(= 1-余弦相似度
),以便于实现,并获得了满足距离 < 阈值
的(匹配项,距离)
对。对于每个项目 x,我们将这个(匹配项,距离)
对称为"x 的邻域"。
Min2
在进行阈值处理时,我们可以确保每个查询至少有 2 个匹配项,因为这是比赛描述所保证的。只有当距离超过 min2 阈值时,我们才会拒绝第二个最接近的匹配项仅当,我们将这个阈值设置得很高。
社区融合
邻里融合的直觉很简单。在执行 knn 和 min2 阈值处理后,我们为每个项目获得一个(匹配项,相似度)
对,我们有一个图,其中每个节点是一个项目,边权重是两个节点之间的相似度。只有邻里之间是相连的。也就是说,未通过查询节点阈值条件或 min2 条件的节点是断开的。
我们希望使用邻域物品的信息来细化查询物品的嵌入,使聚类更清晰。为了做到这一点,我们简单地以相似度为权重对邻域嵌入进行加权求和,并将其添加到查询嵌入中。因此,我们混合邻域 嵌入。我们称之为NB(邻域混合) 。
上图展示了在玩具示例中如何执行邻域融合的一个步骤。让我们看看节点 A。它的嵌入是[-0.588, 0.784, 0.196]
,它与节点 B、C、D 的相似度分别为 0.94、0.93、0.52。红色线条表示两个节点是邻居,因此它们是相连的。虚线表示两个节点未通过阈值,因此是断开的。我们应用邻域融合后:
在应用此方法后,希望如图像中正确的图表所示,我们得到更紧密、更精细的嵌入。
我们可以迭代地应用 NB。在融合阶段 1 嵌入的邻域后,我们进行 knn 搜索和'min2'阈值处理以获取阶段 2 的(匹配项,相似度)
。我们再次应用 NB,以进一步细化嵌入。我们可以迭代,直到评估指标停止改进。这就是迭代一词的由来。
代码相当简单。(你需要实现你的 neighborhood_search
函数)
ini
def blend_neighborhood(emb, match_index_lst, similarities_lst):
new_emb = emb.copy()
for i in range(emb.shape[0]):
cur_emb = emb[match_index_lst[i]]
weights = np.expand_dims(similarities_lst[i], 1)
new_emb[i] = (cur_emb * weights).sum(axis=0)
new_emb = normalize(new_emb, axis=1)
return new_emb
def iterative_neighborhood_blending(emb, threshes):
for thresh in threshes:
match_index_lst, similarities_lst = neighborhood_search(emb, thresh)
emb = blend_neighborhood(emb, match_index_lst, similarities_lst)
return match_index_lst
完整 INB 管道在以下图像中总结。
我们应用 3 阶段 INB。
要获取详细信息,我们首先分别从图像嵌入、文本嵌入和组合嵌入中找到 (匹配项,相似度)
对。然后我们将匹配项合并。(对于相似度,如果存在,使用组合相似度;如果不存在,使用图像相似度;如果不存在,使用文本相似度)
使用联合 (匹配项,相似度)
和组合嵌入,我们进行邻域融合以获得阶段 2 嵌入。然后我们找到 (匹配项,相似度)
对并应用 NB 以获得阶段 3 嵌入。我们从该嵌入中获得阶段 3 匹配项。
我们将仅通过图像嵌入找到的匹配项与仅通过文本嵌入找到的匹配项合并,以获得最终的匹配项,并将其提交。
关于阈值调整
请注意,我们有 10 个不同的阈值需要调整。3 个用于阶段 1 的 txt、img、comb 阈值,1 个用于阶段 2 的阈值,1 个用于阶段 3 的阈值,2 个用于阶段 1 的 img、txt 阈值,这些阈值直接连接到最终的合并,3 个用于阶段 1~3 的 min2 阈值。但在我们将其他阈值调整到合理范围之后,主要的分数提升来自<强 id=0>阶段 2 和阶段 3 的阈值。(当我们将阶段 1 的 comb 阈值固定为 0 - 只使用 comb 的 min2)所以<强 id=1>最后我们只需要调整这两个数字与 LB 进行比较。
嵌入前后可视化
2021/05/13 编辑
我们制作了一个笔记本,用于可视化 INB 对嵌入的影响。
www.kaggle.com/harangdev/s...
以下是一些示例
5. 以太坊经典
- 对于图像模型,以 0.1 的概率使用 cutmix 有助于
- 用于图像增强,仅使用水平翻转效果更好
- madgrad 优化器(github.com/facebookres...)与 Adam 和 SGD 相比表现更佳或相似
- 使用全部数据进行训练提高了性能
- Limerobot 深入研究了三元组损失,但他从未击败过 arcface 损失😿