一场让小型神经网络玩策略游戏的比赛

查看原文 HN 讨论

文章摘要

TinyBrains 的口号是”造出能把游戏玩好的最小大脑”(build the smallest brain that plays well)。这是一个给小型神经网络用的排位天梯:你训练一个模型,写一份描述输入输出的清单文件,上传两个文件,平台就会测量模型体积,把它分到对应的”重量级别”里,最小的级别从几 KiB 起步,然后让它和别人的模型不停对战。(网站本身是客户端渲染的单页应用,本文内容综合自站点元信息、FAQ、更新日志、项目 GitHub 仓库的 README 以及作者在 HN 上的自述。)

缘起是 15 年前的一场比赛。 作者 codetiger 在 HN 上说,2011 年他参加了由滑铁卢大学主办的”Google Ants AI Challenge”,排名第 127,是他所在国家的第一名。那场比赛让他学到很多,全世界的开发者聚在论坛里讨论各种技巧。现在他做了一个类似的平台,想把”造一个能玩好游戏的小型神经网络”的乐趣带回来,而且他觉得”神经网络优化似乎有趣得多”。

游戏:Ants(蚂蚁)。 目前天梯上唯一的游戏就是 Ants,规则完全沿用 2011 年那场比赛:多个蚁群在一张首尾相接、四边环绕的网格地图上争夺食物和蚁丘,是一个确定性的对抗游戏。每回合,你的模型收到一个 JSON 对象,里面有地图尺寸、己方存活的蚂蚁、视野内的敌方蚂蚁、食物和蚁丘,以及迄今为止发现的水域(用游程编码的掩码表示)。它拿不到分数,拿不到回合数,回合之间也没有记忆;所有者编码都是相对于自己的,所以一局里每个席位看到的编码方式一样。模型必须按观察里列出的顺序,给每只蚂蚁回答 N、E、S、W 或”-“(原地不动)。漏答一只就记一次”犯规”(strike)。

只限体积,不限算力。 体积的定义非常干脆:model.onnx 的字节数加上 manifest.json 的字节数,平台会重新计算哈希,不压缩也不估算,所以任何权重打包技巧都没法少报体积。FAQ 特别提示,用 float16 存初始化参数能让文件减半,同样体积下可以塞进大约两倍的参数。算力没有上限,只受每回合时限约束(Ants 是 1000 毫秒):输入适配、推理和输出适配共享这个时限,太慢的模型错过回合就记一次犯规。HN 评论里有人贴出了当时首页列出的级别:nano 最高 16 KiB、micro 128 KiB、mini 1 MiB、small 8 MiB、large 64 MiB,外加一个不分体积的 Open 级别;作者补充说每个赛季的体积上限都会不同。每个模型都会同时参加所属级别的天梯和 Open 天梯。

清单文件(manifest)为什么不是代码。 选手提交的是一个自包含的 ONNX 模型,用 PyTorch、JAX 还是别的框架训练都可以,允许 ONNX opset 13 到 19,外加一份算子白名单(Conv、MatMul、Gemm、常见激活和归约、Resize、Gather、Slice 等,ConvTranspose 不在其中,要上采样请用 Resize)。清单文件声明计算图的输入输出名称、数据类型和形状,并为每个输入附带一段”适配器表达式”:一个小小的 JSON 程序,负责把观察数据转换成张量。之所以设计成数据而不是代码,是为了让求值器能在预算内统计它的操作数,也能把它的字节数计入模型体积。输出一侧不用选手写,裁判直接读取策略头,因为通道顺序本身就是游戏规则的一部分。

提交与评分流程。 提交后平台给出两个一次性上传地址,你用 PUT 把两个文件传上去。平台重新校验哈希、测量级别,然后让新版本和一个基线模型打一场试训赛:只要在犯规上限内打完,输赢都算通过。之后新版本进入天梯持续对战,旧版本会一直打到新版本通过为止。排名显示的是 μ − 3σ 这种保守估计,所以新版本起步分低,随着评分稳定逐渐上升。

基线模型与入门套件。 官方用行为克隆训练了三个基线:从同一个脚本化”老师”在 25 万个席位回合上蒸馏出来的 nano-bc(2,930 个参数,5.9 KiB)和 micro-bc(24,001 个参数,44.6 KiB),以及一个感受野只有一格的对照组 micro-percell。ants-starter 仓库里有一个可以原样提交的 nano 级模型,和老师的动作一致率为 85.8%,train.py 一条命令大约一小时就能重新训练。配套的命令行工具 tinybrains 可以通过 Homebrew 安装,tinybrains check 在本地模拟准入检查,tinybrains adapt 输出适配器生成的张量方便和训练代码对比,还能用对局文件让模型和基线在真实引擎上对打,并回放观看。

引擎的工程细节相当讲究。 Ants 引擎用 Rust 编写,编译成 WebAssembly 组件;游戏逻辑只允许整数运算(有脚本专门拒绝浮点数),这样平台和浏览器能逐位一致,回放只需要存动作流,浏览器里的查看器通过同一个组件重新模拟对局,而不是用 JavaScript 重写一遍规则(”那就成了第二个引擎”)。仓库里有五张基础地图,从 24×24 的双人图到 120×124 的八人图;每张地图都会校验对称公平、陆地连通、每个蚁丘都有出路。赛季用的地图在赛季结束前不公开,由平台选择地图和随机种子,选手没法针对某张自己挑的地图专门训练。作者说目前的赛季是公开测试,月底结束,之后打算每个赛季持续三个月。

HN 评论精华

41 条评论,整体友好。主要话题有三个:2011 年那场比赛的老选手来叙旧,网站文案”一股 AI 味”被点名批评,以及大家列举历史上类似的 AI 编程竞赛。

老选手重聚。 AnotherGoodName 说他当年排第 72,现在从事 AI 研究,业余仍在给游戏写 AI(给自己最喜欢的桌游《殖民火星》做了 tfmbot.com)。codetiger 回忆说,当年第一名 xathis 的分数遥遥领先,前 100 名之间的技术其实大同小异。awfm9 也说自己 2011 年参加过:”当时所有人都是某种手写策略,我玩得很开心。”

文案被批”AI 味”,作者当场认错。 lostdog 的建议很直接:”最好把页面上的文字全删了,不用 AI 重写一遍。”他举的例子是”model and manifest bytes together pick the class; every version also plays on Open”。vova_hn2 引用了”Your class is measured, not chosen”(你的级别是量出来的,不是选出来的)这句,反问:”写一句’你的重量级别由模型和清单文件的总大小决定’有多难?”他说现在的写法既像 AI 垃圾又有歧义,文档页读起来更痛苦。FrustratedMonky 替作者说了句公道话:”不是所有糟糕的文字都是 AI 写的,很多人类也写得含糊不清。”codetiger 坦承之前赶时间用 AI 生成了文档,现在已经把大部分文字清理过了。

关于每只蚂蚁都是一个智能体。 nickledave 说他对科技行业所谓的”智能体 AI”不感兴趣,但对集体智能很感兴趣,推荐了 David Ha 在这方面的研究,并提议”如果每只蚂蚁本身就是一个智能体会很酷”。codetiger 说他试过为每只蚂蚁单独做决策的模型,但训练时间比现在的基线长得多,就放弃了,”我应该重新考虑这个想法”。他还说当年比赛的官网基本已经下线,想了解规则可以搜”Google Ants AI Challenge post mortem”,能找到不少参赛者写的复盘文章。

是否只能用 PyTorch? cookiengineer 说他前一天刚发布了重写的 GoNEAT 库(HyperNEAT 结合分阶段搜索和反向传播),但以为平台硬性要求 PyTorch 所以没法参加,希望平台能做成一个 gym,让人跑自己的神经网络设计算法,”进化计算的世界大多在 C++ 和其他原生语言里”。codetiger 澄清说平台只要求 ONNX 格式,怎么构建模型完全随意,只检查格式、推理时间和模型大小;看过他的仓库后又补充说,真正的限制是必须是神经网络,不能直接提交算法实现。

评估方式。 adityamishra241 问是只看比赛表现,还是也考虑体积和推理速度。作者回答说评分纯粹基于比赛表现,但每个重量级别单独排名:nano、micro、mini、small、large 和 open。问到为什么选策略游戏而不是经典棋类,作者说他想做”每回合需要多次决策、同时控制很多单位”的游戏。willmarch 问比赛会办多久,得知赛季安排后当场注册并提交了一个测试模型:”现在真正的训练开始了!”

历史上的同类竞赛。 评论区顺手列了一串:lokar 提到 Core War,cheschire 提到 Screeps,RomanKornev 提到 MIT Battlecode(”同样的想法,但面向人类团队”),Qworg 想起 UIUC 的 MechMania,b800h 回忆 1997 年左右流行过一个叫 AI Wars 的东西,”印象中比拼的是代码而不是权重,但这个对照挺有意思。30 年了!天哪我真老”。euroderf 贴了一篇用强化学习和循环神经网络玩六角格兵棋的论文,说”来玩点真东西”。TeMPOraL 误以为说的是 Hex 棋(一种常用于 AI 课程练习的棋类),euroderf 解释说指的是在六角格地图上移动单位的兵棋游戏类型。WanderZil 则好奇把康威生命游戏和神经网络结合会有什么惊喜。