返回列表

11th place solution

631. UM - Game-Playing Strength of MCTS Variants | um-game-playing-strength-of-mcts-variants

开始: 2024-09-05 结束: 2024-12-02 游戏AI 数据算法赛
第 11 名解决方案 - kansai-kaggler

第 11 名解决方案

团队: kansai-kaggler (@tmhrkt, @ystsuji, @ryushisa)
发布时间: 2024-12-03

首先,我们要向 Kaggle 工作人员和所有比赛主办方表示诚挚的感谢,感谢你们组织了如此精彩的比赛。

我们想分享我们的解决方案。

概述

我们采用的策略是三名成员各自创建独立的单模型,然后将它们进行堆叠(Stacking)。

交叉验证策略 (CV Strategy)

我们使用了基于游戏总数的 StratifiedGroupKFold。我们按游戏总数进行分层,因为我们担心分布可能会因游戏数量而异,正如在这个讨论中所提到的那样。

GameRulesetName 和英文规则

由于主办方澄清测试数据包含未见过的 GameRulesetName 值,因此对 GameRulesetName 使用 TF-IDF 特征是有风险的。至于 EnglishRules,我们发现描述存在噪声,存在诸如 Ludus Coriovalli 之类的变体。因此,我们决定不使用 GameRulesetName 或 EnglishRules 作为特征。

Ryushi 部分

基于 '[UM] Gradient Boosting Models Train&Infer'。这段代码是一个非常有用的 notebook,使得实验 LightGBM (lgb)、XGBoost (xgb) 和 CatBoost (ctb) 变得容易。最终,仅使用 CatBoost 产生了最好的结果,所以我使用了它。

特征

  • 最好的单模型只使用了大约 180 个特征。
  • 被移除的特征
    • 只有一个唯一值的特征
    • 包含超过 95% 缺失值的特征
    • 基于频率的和 _components 列。我们没有移除所有它们;我们检查了分布并保留了那些似乎具有合理信息量的特征。详情如下:
      • 保留的频率特征
        ['DrawFrequency', 'StepDecisionFrequency', 'FromToDecisionEmptyFrequency', 'SetNextPlayerFrequency', 'RemoveEffectFrequency', 'MoveAgainFrequency', 'StepDecisionToEmptyFrequency']
      • 保留的 Components 特征
        ['NumStartComponentsBoard', 'NumStartComponentsHand', 'NumStartComponents', 'NumStartComponentsBoardPerPlayer', 'MarkerComponent']
    • 考虑到多重共线性而移除
      • 例如,以下七个特征的相互相关性超过 90%。我们只保留了 'ScoreDifferenceVariance' 并移除了其他特征:
        ['ScoreDifferenceVariance', 'ScoreDifferenceMedian', 'ScoreDifferenceMaximum', 'ScoreDifferenceChangeAverage', 'ScoreDifferenceMaxDecrease', 'ScoreDifferenceAverage', 'ScoreDifferenceMaxIncrease', 'ScoreDifferenceChangeLineBestFit']
      • 有多列需要进行此类处理。
        通过执行到此为止的特征选择和参数调整,我们能够将公共 LB 分数从 0.464( baseline)提高到 0.422(我的单模型)。
  • 添加的特征
    • LudRules 的长度
    • 从 LudRules 的 startplayend 部分创建特征(详情见 2g 部分)
    • 从 LudRules 中提取单词 'Draw''Win''Loss' 的出现次数。
      • 这是基于这样的假设:除了超时条件外,还存在游戏本身设定为平局的模式。
        我这部分的特征相对较少,但由于其他成员有很多特征,我们相信这最终有助于多样性。

CV/LB

CV 公共 LB 私有 LB
exp057 0.4092 0.422 0.432
exp058 0.4087 0.422 0.432
exp059 0.4070 0.422 0.432
exp069 0.4082 0.424 0.432
exp071 0.4079 0.424 0.432

无效实验

  • 神经网络模型
    我在比赛期间进行了许多实验,但最终是中期进行的实验起了作用。
    在这次比赛中,复杂的特征和模型实际上导致准确率下降。
  • 使用 CatBoost 进行多回归
    在 CatBoost 中执行多回归以同时预测 'utility_agent1''draw_ratio'

ktm 部分

  • 增强 (Augmentation):正如其他参与者提到的,交换 agent1 和 agent2,使用 1 - AdvantageP1, -utility_agent1 并添加 swapped 标志列。在推理时,应用 TTA。
  • 多目标预测:使用 catboost MultiRMSE loss 预测 utility_agent1 和 draw_ratio。
  • 数据生成:我们生成了训练数据中未出现的额外训练数据。我们使用了 Ludii Portal 上的公开规则,并使用 colab cpu 和 vastai 实例生成。(我从未想过我会为了 CPU 而租用 vast.ai 实例。)生成的总数据约为 30k~40k 行。这改善了 CV 但 LB 没有变化。
  • 目标编码 (target encoding)

CV/LB

exp CV LB 私有 目标编码 多目标 额外数据
exp084 0.4015 0.429 0.434
exp088 0.4006 0.427 0.433
exp094 0.4034 0.43 0.436
exp101 0.4016 0.429 0.435

2g 部分

基于 MCTS Starter。更改如下。我们通过变化是否应用以下内容准备了多个模型:

  • 通过交换 agent1agent2 添加数据
  • 使用二元分类预测是否为平局。对于可能为平局的预测,将 utility_agent1 设置为 0。
  • LudRules 分为 startplayend 部分,并对每个部分应用 TF-IDF
  • LudRulesstartplayend 部分创建特征(例如):
    • depth_nest:部分中的嵌套深度(使用 (){} 的数量计算)
    • num_condition:部分中 "if" 语句的数量
    • chr_len:部分的长度
    • unique_start_pieces:部分中 "place" 出现的次数
    • 等等...

CV/LB

CV 公共 LB 私有 LB
017-1 0.4092 unknown unknown
018-1 0.4073 0.422 0.431
024-1 0.4070 0.422 0.431
025-1 0.4094 0.422 0.430

堆叠部分 (Ryushi & ktm 部分)

这部分显著提高了我们的分数。我们遇到了 CV 在各折之间变化很大的问题,甚至仅在折之间改变模型的种子时预测也会变化。为了解决这个问题,我们认为堆叠可能比简单的集成更有效。此外,由于各折之间的分数差异很大,我们使用 Optuna 为每一折优化了权重(特征)。我们最好的模型堆叠如下:

CV 公共 LB 私有 LB 堆叠训练中使用的实验 折 0 折 0 CV 折 1 折 1 CV 折 2 折 2 CV 折 3 折 3 CV 折 4 折 4 CV
0.3912 0.419 0.424 ['ryushi_exp057', 'ryushi_exp058', 'ryushi_exp059', 'ryushi_exp069', 'ryushi_exp071', 'tsuji_017-1', 'tsuji_018-1', 'tsuji_024-1', 'tsuji_025-1', 'ktm084', 'ktm088', 'ktm094', 'ktm101', 'ktm084_draw', 'ktm088_draw', 'ktm101_draw'] ['tsuji_025-1', 'ktm101', 'ktm088_draw'] 0.3977 ['ryushi_exp057', 'ryushi_exp058', 'ryushi_exp059', 'ryushi_exp069', 'tsuji_018-1', 'tsuji_024-1', 'tsuji_025-1', 'ktm084', 'ktm088', 'ktm094', 'ktm088_draw', 'ktm101_draw'] 0.3677 ['ryushi_exp059', 'tsuji_018-1', 'ktm084_draw', 'ktm101_draw'] 0.38142 ['ryushi_exp057', 'tsuji_017-1', 'ktm084', 'ktm088', 'ktm084_draw', 'ktm101_draw'] 0.40944 ['tsuji_017-1', 'tsuji_024-1', 'ktm088', 'ktm094', 'ktm101', 'ktm084_draw', 'ktm088_draw'] 0.39866

最终提交选择策略

我们使用游戏总数拆分折,但无法实现 CV 和 LB 之间的良好相关性。因此,我们最终选择了以下两个提交:

  • CV+LB 最佳:在堆叠中选择具有良好 CV 和 LB 的堆叠模型。
  • CV 最佳:在使用 Nelder-Mead 优化权重的提交中选择具有最佳 CV 的提交。
    (注意:由于担心过拟合,我们没有选择 LB 最佳。)
    结果,虽然私有分数与公共分数相关,但我们选择的 CV+LB 最佳提交具有最好的私有分数。

技巧

Nelder-Mead

我们使用 Nelder-Mead 方法优化每个提交的权重来进行集成。当我们进行集成而不约束权重之和等于 1 时,CV/LB 分数提高了(当时的权重之和约为 1.14)。正如其他人的解决方案中提到的,将预测乘以一个常数可能很重要。

同比赛其他方案