643. FIDE & Google Efficient Chess AI Challenge | fide-google-efficiency-chess-ai-challenge
遵循 Kaggle 的惯例,我想分享我的方法。
如果其他团队也能在讨论区分享他们的方法就好了!
我的仓库在 这里。这份撰写内容是机器翻译的,你可以在里面找到 原始的日语版本。
编辑 (3/30):添加了 Kaggle Notebooks 部分,并将标题从“我的方法”改为“第四名解决方案”。
我的方法基于 Stockfish 16。通过在 HCE(启发式评估函数)中添加一个小型神经网络(非 NNUE),我将 Elo 等级分提高了约 30 分。
在 reviewing 了讨论区和 Discord 上的消息后,我决定使用 HCE 可以获得有竞争力的排名。因此,我选择了 Stockfish 16,这是最后一个支持 HCE 的版本。
我没有考虑 Stockfish 以外的引擎。这是因为在参加 Hungry Geese 竞赛期间,我研究了将棋 AI,了解到它深受 Stockfish 的影响。这激发了我对 Stockfish 的兴趣。
内存使用分解如下:
我减小了一些成员变量的大小,并将哈希表中的元素数量从原来的 131,072 减少到 8,192。
我将其替换为包含 262,144 个元素的哈希表。我没有为哈希实现冲突检查。
我保留了原始 Stockfish 允许的最小尺寸。这也适用于兵表和延续历史表,但我根据直觉确定了大小,并没有进行微调。
我还移除了原始 Stockfish 用于大页 (Large Pages) 的额外内存分配。(Kaggle 的环境可能无论如何都不支持大页。)
我移除了所有不必要的模块。
车的 Magic Bitboard 消耗了大量内存。然而,我发现 国际象棋编程维基 中描述的 CFish 的传统方法 (Classical Approach) 似乎是一个很好的替代方案,所以我替换了它。
由于程序链接到 glibc,其常驻集大小 (RSS) 应该需要约 3MB 的内存。但是,glibc 已经加载在 Kaggle 的环境中,所以它似乎不计入 5MB 的限制。
另一方面,libstdc++ 没有预加载。链接到它会增加内存使用量,所以我重写了 Stockfish 中几乎所有依赖 C++ 标准库的部分,以避免链接到 libstdc++。
虽然仍然可以提交链接了 libstdc++ 的代理,但移除依赖减少了超时失败的频率。(我在竞赛最后 17 天部署的代理仍然链接了 libstdc++。)
通过到目前为止描述的优化,以及高效的引擎使用(如时间管理、启用思考 (pondering)、避免在搜索开始时不必要的表初始化),我能够开发出一个平均排名在金牌范围内的代理。
(正如许多参与者可能同意的那样,)Stockfish 的代码经过多年的完善,已经没有多少可以改进的地方了。唯一看起来可行修改的部分是评估函数,因为 NNUE 被禁用了。
从 Discord 上的讨论来看,顶尖团队似乎在使用 NNUE。构建一个小型 NNUE 将是最直接的选择,但我认为用神经网络扩展 HCE 会更有趣,所以我选择了这种方法。
我使用了一个三层 MLP(多层感知机)。
原始的 HCE 将两个评估值——一个用于中局,一个用于残局——打包到一个 32 位变量中并对其进行计算。我通过添加 14 个额外的 16 位值扩展了这一点,使用 256 位寄存器同时计算它们,并将结果作为第一层的输出。(事后看来,我应该将这些计算与 HCE 分开。量化过程变得 unnecessarily 复杂。)
有 99 个输入特征,所以第一层有 1,400 个可训练参数,包括偏差 (99 × 14 + 14 = 1,400)。这些值分别针对白棋和黑棋计算,然后根据回合组合成一个 32 维向量。
该向量通过 Clipped ReLU(如 NNUE 中所用)、一个全连接 32×32 层、另一个 Clipped ReLU,以及最后一个全连接 32×1 层以产生输出。可训练参数总数为 2,489。
对于训练,我将目标值设置为 NNUE 评估与 HCE 评估之间的差异,并使用 MSE 作为损失函数。我还尝试了 QAT,但我不确定它有多有效。
我使用 kaggle-environments 运行了大约 70,000 场游戏,以 1/8,192 的概率保存搜索过程中遇到的位置用于训练。这些游戏中使用的代理包括基于 HCE 评估的代理、基于 NNUE 评估的代理以及我的实验性评估函数。训练和自我对弈完全在 Kaggle Notebooks 中进行。
在搜索期间使用此 NN 进行评估时,简单地将输出添加到 HCE 值会导致不到 10 个 Elo 的提升。然而,仅添加输出的一半会导致比单独使用 HCE 高出 30 个 Elo 的收益。
不幸的是,我只在竞赛的最后一天才意识到这一点,所以我没有时间尝试更大的 NN。
由于我不确定基于 NN 的改进是否在我的本地环境之外也能保持有效,我提交了一个 仅 HCE 的代理 和一个 增强 NN 的代理。
我已经公开了用于生成 NN 权重的 Kaggle notebooks。
构建机器人以便以 certain 概率保存搜索过程中遇到的位置作为特征。这包括使用 HCE、NNUE 和上述开发中的评估函数的机器人。
chess-042-f040-training-data-generator https://www.kaggle.com/code/nagiss/chess-042-f040-training-data-generator chess-052-f042-data-generator-use-hce https://www.kaggle.com/code/nagiss/chess-052-f042-data-generator-use-hce chess-058b-data-generator https://www.kaggle.com/code/nagiss/chess-058b-data-generator chess-058c-data-generator-060-params https://www.kaggle.com/code/nagiss/chess-058c-data-generator-060-params用于生成数据的机器人相互对弈。由于可以在 Kaggle 的 TPU 环境中使用许多 CPU 核心,一些 notebooks 在那里执行。
chess-043-generate-training-data-seed0 https://www.kaggle.com/code/nagiss/chess-043-generate-training-data-seed0 chess-043b-generate-training-data-seed400 https://www.kaggle.com/code/nagiss/chess-043b-generate-training-data-seed400 chess-043c-generate-training-data-seed800 https://www.kaggle.com/code/nagiss/chess-043c-generate-training-data-seed800 chess-043d-generate-training-data-seed1200 https://www.kaggle.com/code/nagiss/chess-043d-generate-training-data-seed1200 chess-043e-generate-training-data-seed1600 https://www.kaggle.com/code/nagiss/chess-043e-generate-training-data-seed1600 chess-043f-generate-training-data-seed2000 https://www.kaggle.com/code/nagiss/chess-043f-generate-training-data-seed2000 chess-043g-generate-training-data-seed2400 https://www.kaggle.com/code/nagiss/chess-043g-generate-training-data-seed2400 chess-043h-generate-training-data-seed2800 https://www.kaggle.com/code/nagiss/chess-043h-generate-training-data-seed2800 chess-043i-generate-training-data-seed3200 https://www.kaggle.com/code/nagiss/chess-043i-generate-training-data-seed3200 chess-043j-generate-training-data-seed3600 https://www.kaggle.com/code/nagiss/chess-043j-generate-training-data-seed3600 chess-043k-generate-training-data-seed4000 https://www.kaggle.com/code/nagiss/chess-043k-generate-training-data-seed4000 chess-043l-generate-training-data-seed4400 https://www.kaggle.com/code/nagiss/chess-043l-generate-training-data-seed4400 chess-043m-generate-training-data-seed4800 https://www.kaggle.com/code/nagiss/chess-043m-generate-training-data-seed4800 chess-043n-generate-training-data-seed5200 https://www.kaggle.com/code/nagiss/chess-043n-generate-training-data-seed5200 chess-043o-generate-training-data-seed5600 https://www.kaggle.com/code/nagiss/chess-043o-generate-training-data-seed5600 chess-053-f043l-datagen-hce-seed0 https://www.kaggle.com/code/nagiss/chess-053-f043l-datagen-hce-seed0 chess-053b-datagen-hce-seed400 https://www.kaggle.com/code/nagiss/chess-053b-datagen-hce-seed400 chess-053c-datagen-hce-seed800 https://www.kaggle.com/code/nagiss/chess-053c-datagen-hce-seed800 chess-053d-datagen-hce-seed1200 https://www.kaggle.com/code/nagiss/chess-053d-datagen-hce-seed1200 chess-053e-datagen-hce-seed1600 https://www.kaggle.com/code/nagiss/chess-053e-datagen-hce-seed1600 chess-053f-datagen-hce-seed2000-7999 https://www.kaggle.com/code/nagiss/chess-053f-datagen-hce-seed2000-7999 chess-053g-datagen-hce-seed8000-13999 https://www.kaggle.com/code/nagiss/chess-053g-datagen-hce-seed8000-13999 chess-059-f053g-datagen-058b-vs-hce-seed0 https://www.kaggle.com/code/nagiss/chess-059-f053g-datagen-058b-vs-hce-seed0 chess-059b-datagen-058c-vs-hce-seed0 https://www.kaggle.com/code/nagiss/chess-059b-datagen-058c-vs-hce-seed0由于相对于模型大小而言数据量很大,数据加载往往会成为训练期间的瓶颈。因此,对数据进行组织以便高效加载。为了绕过 Kaggle notebook 输出数据大小的限制,notebooks 被分成了八个部分。
chess-064-f060-split-data-0-8 https://www.kaggle.com/code/nagiss/chess-064-f060-split-data-0-8 chess-064b-f060-split-data-1-8 https://www.kaggle.com/code/nagiss/chess-064b-f060-split-data-1-8 chess-064c-f060-split-data-2-8 https://www.kaggle.com/code/nagiss/chess-064c-f060-split-data-2-8 chess-064d-f060-split-data-3-8 https://www.kaggle.com/code/nagiss/chess-064d-f060-split-data-3-8 chess-064e-f060-split-data-4-8 https://www.kaggle.com/code/nagiss/chess-064e-f060-split-data-4-8 chess-064f-f060-split-data-5-8 https://www.kaggle.com/code/nagiss/chess-064f-f060-split-data-5-8 chess-064g-f060-split-data-6-8 https://www.kaggle.com/code/nagiss/chess-064g-f060-split-data-6-8 chess-064h-f060-split-data-7-8 https://www.kaggle.com/code/nagiss/chess-064h-f060-split-data-7-8训练在 Kaggle 的 GPU 环境中进行。第 7 个单元格的输出用作最终提交的 params.h。
chess-065d-lr-1e-2-epoch-500 https://www.kaggle.com/code/nagiss/chess-065d-lr-1e-2-epoch-500