631. UM - Game-Playing Strength of MCTS Variants | um-game-playing-strength-of-mcts-variants
首先,我们要向 Kaggle 工作人员和所有比赛主办方表示诚挚的感谢,感谢你们组织了如此精彩的比赛。
我们想分享我们的解决方案。
我们采用的策略是三名成员各自创建独立的单模型,然后将它们进行堆叠(Stacking)。
我们使用了基于游戏总数的 StratifiedGroupKFold。我们按游戏总数进行分层,因为我们担心分布可能会因游戏数量而异,正如在这个讨论中所提到的那样。
由于主办方澄清测试数据包含未见过的 GameRulesetName 值,因此对 GameRulesetName 使用 TF-IDF 特征是有风险的。至于 EnglishRules,我们发现描述存在噪声,存在诸如 Ludus Coriovalli 之类的变体。因此,我们决定不使用 GameRulesetName 或 EnglishRules 作为特征。
基于 '[UM] Gradient Boosting Models Train&Infer'。这段代码是一个非常有用的 notebook,使得实验 LightGBM (lgb)、XGBoost (xgb) 和 CatBoost (ctb) 变得容易。最终,仅使用 CatBoost 产生了最好的结果,所以我使用了它。
_components 列。我们没有移除所有它们;我们检查了分布并保留了那些似乎具有合理信息量的特征。详情如下:
['DrawFrequency', 'StepDecisionFrequency', 'FromToDecisionEmptyFrequency', 'SetNextPlayerFrequency', 'RemoveEffectFrequency', 'MoveAgainFrequency', 'StepDecisionToEmptyFrequency']['NumStartComponentsBoard', 'NumStartComponentsHand', 'NumStartComponents', 'NumStartComponentsBoardPerPlayer', 'MarkerComponent']'ScoreDifferenceVariance' 并移除了其他特征:['ScoreDifferenceVariance', 'ScoreDifferenceMedian', 'ScoreDifferenceMaximum', 'ScoreDifferenceChangeAverage', 'ScoreDifferenceMaxDecrease', 'ScoreDifferenceAverage', 'ScoreDifferenceMaxIncrease', 'ScoreDifferenceChangeLineBestFit']start、play 和 end 部分创建特征(详情见 2g 部分)'Draw'、'Win' 或 'Loss' 的出现次数。
| 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 |
'utility_agent1' 和 'draw_ratio'。| 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 | ✓ | ✓ |
基于 MCTS Starter。更改如下。我们通过变化是否应用以下内容准备了多个模型:
agent1 和 agent2 添加数据utility_agent1 设置为 0。LudRules 分为 start、play 和 end 部分,并对每个部分应用 TF-IDFLudRules 的 start、play 和 end 部分创建特征(例如):
depth_nest:部分中的嵌套深度(使用 () 和 {} 的数量计算)num_condition:部分中 "if" 语句的数量chr_len:部分的长度unique_start_pieces:部分中 "place" 出现的次数| 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 |
这部分显著提高了我们的分数。我们遇到了 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 之间的良好相关性。因此,我们最终选择了以下两个提交:
我们使用 Nelder-Mead 方法优化每个提交的权重来进行集成。当我们进行集成而不约束权重之和等于 1 时,CV/LB 分数提高了(当时的权重之和约为 1.14)。正如其他人的解决方案中提到的,将预测乘以一个常数可能很重要。