返回列表

3rd Place Solution (Triplet loss, Boosting, Clustering)

432. Shopee - Price Match Guarantee | shopee-product-matching

开始: 2021-03-09 结束: 2021-05-10 商品理解 数据算法赛
第三名方案 (Triplet loss, Boosting, Clustering)

第三名方案 (Triplet loss, Boosting, Clustering)

作者: Btbpanda | 排名: 第3名 | 发布时间: 2021-05-12

大家好,这里是第三名的解决方案。首先,感谢 Kaggle 和 Shopee 举办了这场精彩的比赛。有很多改进的方法,我相信没有人发现了所有的方法,所以不存在“完美”的解决方案。我的解决方案由 3 个主要部分组成:

通用方法与快速基线

让我们构建不同的(不可训练的)产品表示:EfficientNet 嵌入、BERT、TfIdf……任何你认为表现良好的方法,并在固定半径内搜索最近邻,阈值通过交叉验证(CV)选择,通常它是最佳的 F1 分数阈值加上一些小的余量。之后,对于每个对象,我们合并来自所有嵌入的候选邻居,并构建一个具有二元目标的样本对象对——即该对是否为真正的重复项。在我的例子中,训练样本大约有 300 万个点对,重复率为 4%。在该样本上,我使用以下特征构建了一个简单的梯度提升模型(我使用的是 catboost),这些特征针对每个嵌入分别计算:

  • 成对距离(余弦、欧几里得等)
  • 两点周围的密度(不同半径上的点频率)
  • 点排名

最后我有大约 500 个特征。模型训练完成后,只需根据重复概率对候选点进行阈值筛选,该概率通过 CV 搜索(对于测试集,我只通过公共 LB 搜索)。该方案获得了约 0.76+ 的 LB 分数,使用以下嵌入进行推理大约需要 30 分钟:Efficient Net B2、印尼 BERT cahya/bert-base-indonesian-522M、多语言 BERT setu4993/LaBSE、具有不同分词器的多个 TfIdf 和 CLIP。

使用度量学习微调嵌入

我还使用相同的方法添加了微调后的 Efficient Net、ViT (DINO) 和 2 个 BERT(cahya/bert-base-indonesian-522M, setu4993/LaBSE)模型:

  • 三元组损失(margin=0.1)
  • 每个 epoch 我从 label_groups 创建重复对,在每个 batch 中插入一对来自 label_group 的样本。使用了 128 的批量大小,所以我每个 batch 得到 64 个重复项,并将它们中的每一个与 5 个随机点进行比较
  • 5 折交叉验证,当我计算验证分数时,我不仅在验证折中寻找候选者,而且在完整的训练样本中寻找。该方案减少了 CV/LB 差距并使其更具相关性。我的 CV 模型 CV 分数约为 0.71,BERT 为 0.67。这种方法也很适合构建袋外预测,这对于拟合二级模型(在我的例子中是上述的 GBM)很重要。对于测试集,我对 CV 中的所有 5 个模型进行推理。最后,我认为更好的方法是在完整测试集上拟合一个模型而不进行验证以加快推理速度,但没有时间处理所有模型(只对推理时间最长的 DINO 模型做了这个)

我也尝试过 ArcFace 方法,但模型在 CV 上的得分要低得多,这让我很惊讶,因为 ArcFace 是本次比赛中微调的常用方法。也许我在这里做错了什么……将微调后的模型添加到通用方案中使我的 LB 分数达到了 0.781。

后处理 (聚类)

我进行聚类,不是基于嵌入而是基于成对距离。对我来说,距离(或者说是相似度)是 GBM 对重复项估计的概率。如果产品对没有预测结果,则假设重复概率为 0。我采用了凝聚聚类的思想并针对当前任务稍作修改。我们从每个单点作为一个簇开始,合并它们直到平均簇大小等于阈值(对于训练样本,平均簇大小为 2.8,对于 LB,最佳大小为 2.6)。如果聚类后点保持单一 - 将其合并到最近的簇。经过大量参数搜索后,该算法将我的分数提升至 0.79。

关于优化的几句话:我所有的模型都以半精度(torch AMP)进行训练和推理。对于图像模型,我使用 NVIDIA DALI 读取和调整图像大小,对于 GBM 模型推理,我使用 Rapids ForestInferenceLibrary。如果没有这一切,在 2 小时内推理所有这些模型是不可能的。

同比赛其他方案