Kaggle Learning Equality - Curriculum Recommendations Top3 賽後分享!

Kaggle Learning Equality - Curriculum Recommendations Top3 賽後分享!

賽題鏈接

https://www.kaggle.com/competitions/learning-equality-curriculum-recommendations

數據說明

拿了Kaggle Top3。

  • topic: 在本推薦問題中可以理解為 user
  • content: 在本推薦問題中可以理解為 item

賽題任務基本可以理解為(wei) :為(wei) 某個(ge) topic 推薦相關(guan) 度最高的若幹個(ge) content;也可以理解為(wei) 從(cong) 海量的 content 中檢索出若幹個(ge) 與(yu) topic 相關(guan) 度最高的 content。

賽題難點

  • 多語言文本
  • 數據量較大
  • bias 推薦問題,數據集中大部分 category == 'source' 的 topic 並不會出現在測試集中

最終名次

LB 3rd / PB 3rd

拿了Kaggle Top3。

感謝四位極其出色及非常能肝的隊友 @xiamaozi11 @syzong @sayoulala @yzheng21

其中 @syzong @sayoulala 為(wei) Zlab 成員,歡迎大家關(guan) 注 「Z Lab數據實驗室」 公眾(zhong) 號。

我們(men) 的代碼將由 @syzong 整理後在「Z Lab數據實驗室」 公眾(zhong) 號上發布。

以下是我們(men) 的賽後 solution write-up。


提綱

  • CV 策略
  • 召回階段
  • 排序階段
  • 閾值處理
  • 後處理
  • 模型融合

訓練 pipeline

拿了Kaggle Top3。

CV 策略

我們(men) 隨機從(cong) topics.csv 裏采樣了 4000 個(ge) category != 'source' 的 topic 作為(wei) holdout set,這部分 topics 在所有訓練過程中都不參與(yu) 其中,僅(jin) 作為(wei) 驗證集使用。這個(ge) 簡單的 CV 策略在除了後期融合階段外的整個(ge) 比賽過程,線上線下相當一致。

在比賽的最後一個(ge) 月,我們(men) 將 4000 個(ge) topic 再從(cong) 中采樣出來 1000 個(ge) topic 作為(wei) 驗證集,單模提交時線上下 gap 還是相當穩定的,但在融合階段,隨著加入的模型越來越多,失去了一致性,導致我們(men) 在最後十一天裏沒有得到任何提升。

召回階段

我們(men) 使用了 SimCSE (Simple Contrastive Learning of Sentence Embeddings: https://github.com/princeton-nlp/SimCSE) 對比學習(xi) 來訓練召回模型。

  • 隻使用正樣本構建輸入對
  • 驗證集需要從相同語言中隨機采樣一定的負樣本來構建
  • content 文本輸入格式: title [SEP] kind [SEP] description [SED] text, maxlen = 256 (string level)
  • topic 文本輸入格式: title [SEP] channel [SEP] category [SEP] level [SEP] language [SEP] description [SEP] context [SEP] parent_description [SEP] children_description, maxlen = 256 (string level)
  • simcse_loss

def simcse_loss(feature_topic, feature_content) -> 'tensor': y_true = torch.arange(0, feature_topic.size(0), device=device) sim = F.cosine_similarity(feature_topic.unsqueeze(1), feature_content.unsqueeze(0), dim=2) sim = sim / 0.05 loss = F.cross_entropy(sim, y_true) loss = torch.mean(loss) return loss

from: https://github.com/yangjianxin1/SimCSE/blob/master/model.py

  • 訓練代碼

for step, (inputs_topic, inputs_content, labels) in enumerate(train_loader): inputs_topic = collate(inputs_topic) for k, v in inputs_topic.items(): inputs_topic[k] = v.to(device) inputs_content = collate(inputs_content) for k, v in inputs_content.items(): inputs_content[k] = v.to(device) batch_size = labels.size(0) with torch.cuda.amp.autocast(enabled=CFG.apex): feature_topic = model(inputs_topic) feature_content = model(inputs_content) loss = simcse_unsup_loss(feature_topic, feature_content)

召回指標 (1000 topic 驗證集)

model F2@5 max positive score top50 max positive score top100
paraphrase-multilingual-mpnet-base-v2 0.5250 0.9135 0.9443
all-MiniLM-L6-v2 0.4879 0.9045 0.9353
mdeberta-v3-base 0.4689 0.8938 0.9187

執行召回時,我們(men) 計算了每一個(ge) topic 跟本語言內(nei) 所有 content 的 cosine similarity,然後選取 topN 個(ge) 候選。

我們(men) 也嚐試了通過帶有權重的 cosine similarty 融合來進行三個(ge) 召回模型的集成,雖然線下的 max positive score@50 提升到 0.9235,但是很奇怪,線上並沒有得到提升,所以最終我們(men) 還是用了單模的 paraphrase-multilingual-mpnet-base-v2 用作召回。

排序階段

排序模型基本上就是個(ge) 文本二分類模型。

  • 數據集構建:使用召回階段用 SimCSE 訓練好的模型對訓練集數據執行召回 top100 個候選集,同時我們也添加了沒有命中到的所有正樣本。
  • 文本處理:與召回階段一致,最後構建語句對,格式:topic [SEP] content
  • hard negative 樣本能極大提升排序模型的性能。
retrieve model (max positive score top100) ranker f2 score (LB)
0.80 0.585
0.94 0.688
  • 權重加載方式,可以用 huggingface 原生模型權重,也可以用經過召回階段用 SimCSE 微調過的權重,兩者相差並不大,但後者稍微好點且收斂明顯較快。
  • FGM, EMA 等通用的 trick 在本比賽中依然能發揮較大的提升作用,能提升 0.01,但 FGM 訓練時間翻倍。

部分模型指標:

model validation (1,000 topics) LB score PB score
mdeberta-v3-base (simcse weights, FGM+EMA) 0.7149 0.688 0.727
mdeberta-v3-base 0.6378 0.669 0.693

閾值處理

基本上完全依賴線下 1000 個(ge) 驗證 topic,循環計算各個(ge) 閾值的 score,使用最優(you) score 的閾值,同時限製了最大的召回個(ge) 數 (避免取的候選太多)。

best_thres = 0. best_score = 0. best_n_rec = 10 for thres in tqdm(np.arange(0.01, 0.2, 0.005)): for n_rec in range(30, 50): test_sub = test_data[test_data['score'] >= thres].reset_index(drop=True) sub_df = test_sub.groupby('topic_id').apply(lambda g: g.head(n_rec)).reset_index(drop=True) score = calc_f2(sub_df, label_df) if score > best_score: best_score = score best_thres = thres best_n_rec = n_rec

後處理

由於(yu) 我們(men) 隻是使用了一個(ge) 閾值來劃分是否取候選,會(hui) 導致有部分 topic 完全沒有候選 content 的情況。

這部分我們(men) 後處理應該還有提升的空間,我們(men) 最終的方案隻是將這部分 topic 原來召回的 content 取 top4 填充回去。

嚐試過的其他方式:

  1. 不同語言使用不同的閾值,線上線下都輕微掉分;
  2. 對這部分 topic 召回更多個數的 content (按我的理解是極有可能沒有召回到正樣本,畢竟召回命中率也沒有 100%),再進行排序,線下明顯提升了 0.005,但線上並沒有得到提升。

模型融合

我們(men) 訓練了二十來個(ge) 模型,基於(yu) 不同的召回數/加載原生權重還是 SimCSE 微調權重/是否加FGM 等。

  • mdeberta (simcse weights, 4,000 validate topics)
  • mdeberta (simcse weights, 4,000 validate topics, with FGM,EMA)
  • mdeberta (simcse weights, 1,000 validate topics)
  • mdeberta (simcse weights, 1,000 validate topics, with FGM,EMA)
  • mdeberta (1,000 validate topics, with FGM,EMA)
  • xlm-roberta-large (simcse weights, 1,000 validate topics, with FGM,EMA)
  • xlm-roberta-base (simcse weights, 1,000 validate topics, with FGM,EMA)

模型融合權重的確定:用 LR 來擬合驗證集 prob,將 LR 的 coef_ 作為(wei) 融合的權重

pcols = [c for c in valid_data.columns if c.startswith('score')] for cols in tqdm([i for i in combinations(pcols, 10)]): cols = list(cols) X = valid_data[cols].values y = valid_data['label'].values lr = LinearRegression().fit(X, y) coef = lr.coef_ print(get_score(valid_data, df_target_metric, cols, coef))

一開始我們(men) 是使用了召回數 100 來做融合,由於(yu) 提交時長限製,最多隻能融合 6 個(ge) 模型,所以嚐試了將召回數改為(wei) 70 或者 50,用來融合更多的模型。

number of recall samples per topic models validation (1,000 topics) LB score PB score
100 6 0.725 0.705 0.738
70 10 0.738 0.714 0.749
50 12 0.743 0.715 0.751

【競賽報名/項目谘詢+微信:mollywei007】

上一篇

2023年安省省考考試詳細介紹

下一篇

IBDP數學為啥要分AA和AI方向?AA和AI學什麽?

你也可能喜歡

  • 暫無相關文章!

評論已經被關(guan) 閉。

插入圖片
返回頂部