返回列表

20th place solution (Transformer inside)

532. OTTO – Multi-Objective Recommender System | otto-recommender-system

开始: 2022-11-01 结束: 2023-01-31 商品推荐 数据算法赛
第20名方案 (内含Transformer)

第20名方案 (内含Transformer)

作者: Mikhail Kamenshchikov | 比赛排名: 18 | 投票数: 29

首先,我要感谢 OTTO 组织了这场精彩的比赛。它非常有挑战性且数据干净 :)
其次,我要感谢所有在 kernels 或论坛中分享想法的人。这对我帮助很大。
我会在几天内把代码放到 GitHub 上,需要清理一下截止日期前的混乱代码。

太长不看版 (TL;DR)

  • 使用了 3 种共现矩阵(与公开 notebook 的思路有些相似,但实现和细节不同)
  • Bert MLM (Masked Language Model)
  • 矩阵分解
  • Catboost + PairLogitPairwise

LB 进度 (公开榜)

  • 0.576 - 历史记录 + 60 个候选者的全对全共现矩阵 + lightgbm ranker
  • 0.579 - 同上,但增加到 200 个候选者
  • 0.583 - 添加了一堆物品特征(转化率、流行度等)
  • 0.593 - 优化共现矩阵(切换到会话 sessions,增加了时间权重)
  • 0.595 - 添加 buy2buy 特征和 Transformer 候选者,切换到 catboost
  • 0.597 - 添加 buy2buy 和类型加权的共现候选者,使用更多数据进行训练 (16/32 块)
  • 0.598 - 使用全量数据进行训练
  • 0.599 - 对点击/购买使用不同的候选者配置,添加 MF (矩阵分解) 候选者和分数
  • 0.600 - 使用不同的 transformers
  • 0.601 - 对购物车/订单的每个来源使用 x1.5 倍的候选者

候选召回

我使用 max-recall@200 作为召回质量指标,但来自不同来源的候选者可能与用户历史的重合度不同,因此将候选者与历史记录进行外连接来计算 max-recall 似乎更公平。仅使用共访候选者即可达到 0.598 LB

我对点击和购物车/订单使用了不同的候选者组合。

clicks:
    history_rank: 100
    cooc_rank: 200
    buy2buy_rank: 0
    cooc_tw_rank: 0
    mfc_rank: 100
    transformer_rank: 50
  carts/oders: # 平均约 190 个候选者, 0.685+ WR
    history_rank: 100
    cooc_rank: 100
    cooc_tw_rank: 100
    buy2buy_rank: 100
    mfc_rank: 50
    transformer_rank: 50

共访矩阵 (全对全)

  • 使用用户的实际“会话” - 连续的事件序列,如果间隔 > 900 秒,则视为另一个会话。
  • 使用指数时间加权(越远的事件越不重要) 0.99995^(abs(ts.x - ts.y))
  • 对用户历史事件使用逆排名加权

会话间隔、时间基数和排名权重函数等超参数是通过 optuna 优化的,因此该方法的 max-recall@200 大约为 67.6

共访矩阵 (类型加权)

  1. 使用 1 天间隔和指数时间加权(无“会话”概念)
  2. 购物车事件权重 x10,订单权重 x3

共访矩阵 (buy2buy)

  1. 使用 2 周间隔,指数时间加权
  2. 仅使用购物车和订单来计算统计信息

Transformer (小型 BERT)

这很大程度上受到了最近 Yandex.Cup Recsys 赛道冠军方案 (by @chubasik) 的启发(我在那里用经典的二阶段方法拿了第2名)。

其思想是训练一个掩码语言模型 (MLM),然后预测用户会话中“伪造”的最后一个被掩盖的物品。此外,我将动作类型(点击、订单、购物车)作为 token_type_ids 输入(主要用于 NLP 任务中的上下文分离)。

我在训练会话上训练了 MLM,使用了

同比赛其他方案