AlphaZero 五子棋实战(一):单卡从零自举,我的v36 最终版配置

AlphaZero 五子棋实战(一):单卡从零自举,我的v36 最终版配置

这是一个用消费级显卡跑了2个月多的 AlphaZero 五子棋自举实验:不喂棋谱、不装外部引擎当老师、不用开局库 ,就靠"网络 + MCTS + 自己跟自己下"从零长棋力。这篇文章把最终版 v36 的全套配置、参数、训练策略一次性摊开------包括每个参数现在是多少、为什么是这个值、以及它把外部引擎 Rapfi 打到了什么水平。

全文约 6000 字,所有配置都来自线上训练脚本的真实取值,所有战绩都有对局记录,无水分。

适合人群

  • 想动手复现 AlphaZero 但卡在"配置不知道填多少"的朋友
  • 自己训过自对弈,被"棋力不涨 / 后手崩盘 / loss 降了棋力却降了"折磨过的朋友
  • 对分布式自对弈工程落地(单卡怎么榨出产局效率)感兴趣的朋友

你将收获

① 一套可直接复现的 15×15 五子棋 AlphaZero 完整配置(网络 / MCTS / 训练 / 开局规则逐项列全)

② 单张消费级显卡 + 9 个工兵进程的分布式产局工程细节

③ 一套"打 PK 不算白打"的评估方法论(20 局、ring 规则、黑白拆解)

④ 一条真实的外部棋力锚点曲线:同一个引擎,从"我们被虐"到"我们稳赢"

目录

  • [1. 先说清楚:这个项目到底在验证什么](#1. 先说清楚:这个项目到底在验证什么)
  • [2. 工程架构:一张 2080Ti + 9 个工兵](#2. 工程架构:一张 2080Ti + 9 个工兵)
  • [3. 网络结构:4 通道输入 + 8 个残差块](#3. 网络结构:4 通道输入 + 8 个残差块)
  • [4. MCTS:为什么死死定在 800 次搜索](#4. MCTS:为什么死死定在 800 次搜索)
  • [5. 训练循环:32 批次 × 512 样本](#5. 训练循环:32 批次 × 512 样本)
  • [6. 开局规则:前 3 手随机落子(整套配置最关键的一条)](#6. 开局规则:前 3 手随机落子(整套配置最关键的一条))
  • [7. 诊断体系:别只盯着 loss](#7. 诊断体系:别只盯着 loss)
  • [8. 评估方法论:怎么打 PK 才不算白打](#8. 评估方法论:怎么打 PK 才不算白打)
  • [9. 外部锚点 Rapfi:从被打崩到稳赢 depth10](#9. 外部锚点 Rapfi:从被打崩到稳赢 depth10)
  • [10. 训练结果:白棋终于不崩了,但故事没这么简单](#10. 训练结果:白棋终于不崩了,但故事没这么简单)
  • [11. 踩坑速查表(建议收藏)](#11. 踩坑速查表(建议收藏))

1. 先说清楚:这个项目到底在验证什么

2017 年 AlphaZero 出来的时候,我正好在 Leela Zero 那个众筹项目里帮忙------但干的是算账的活,收钱、租机器、记账,技术讨论插不上嘴。那种感觉挺难受的:眼看着一个"纯自对弈就能长棋力"的命题摆在面前,自己却只能在外面看着。

后来有了时间和卡,就想把当年那个问题亲手验证一遍:

一个网络,喂给它的只有棋盘和规则,没有人类棋谱、没有引擎当陪练,它到底能长到多强?

所以这个项目有一条自始至终没破过的铁律:训练闭环里禁止任何外部知识注入

  • ❌ 不拿 Rapfi(开源五子棋引擎)当训练对手------那是"复制外部能力",不是自举
  • ❌ 不喂人类棋谱当开局库
  • ❌ 不用求解器给败局标注"正确应手"
  • ✅ 能用的是:开局规则、网络结构、超参、经验池管理、搜索次数(这些都在"自举"命题之内)

Rapfi 在这个项目里只有一个身份:期末考卷。平时绝对不碰,只在需要知道"现在到底多强"的时候拉出来考一次。

这个原则听起来有点轴,但它决定了后面所有的设计------包括最关键的那条"随机开局"规则(v36 的解),其实也是这条原则逼出来的。


2. 工程架构:一张 2080Ti + 9 个工兵

先把硬件摊开,免得后面看数据没感觉。

配置
训练卡 RTX 2080 Ti 22GB(云上按小时租)
CPU 多核(用于并行产局)
系统 Linux + miniconda + PyTorch 2.x
本轮训练周期 09-06 08:18 起,连续约 144 小时

产局方式:1 个主进程 + 9 个工兵进程。

角色 每代局数 说明
主进程 10 局 自己也要下,顺便维护经验池和存档
工兵 × 9 9 × 10 = 90 局 只负责产局存盘,不训练
合计 100 局/代 每代约 33 分钟,主要时间花在自对弈搜索上

为什么是"每代 100 局"这个量级?

因为 MCTS 是 CPU 上的串行搜索,自对弈产局是整条链路上最慢的一环------800 次模拟 × 每局几十手,一局下来就是几十秒到一分多钟(棋力越强对局越长,后期单局能到 71 秒)。所以工程上的核心思路就一句话:让 GPU 只负责前向推理和训练,自对弈的搜索活儿全部摊给并行进程

工兵的设计上有个坑值得先提一句:工兵是通过 importlib 从主脚本里导入网络定义的,必须和主脚本放在同一个目录,否则导入直接失败。这种"看起来像没问题的路径问题",半夜挂训练的时候特别容易卡住你。


3. 网络结构:4 通道输入 + 8 个残差块

这是 v36 的网络全貌:

模块 结构 参数量
输入 4 通道 15×15 ---
主干入口 Conv2d(4→128, k3, pad1) + BN + ReLU ~4.6K
残差主干 8 × ResBlock(conv3×3 → BN → ReLU → conv3×3 → BN → 加法 → ReLU) ~2.36M
Policy 头 双分支:conv(128→1, k3) + conv(128→1, k1) → concat(2ch) → Linear(450→225) → log_softmax ~101K
Value 头 conv(128→1, k3) + BN → fc1(225→128) → ReLU → fc2(128→1) → tanh ~29K
合计 约 240 万参数

3.1 4 个输入通道分别是什么

通道 含义
ch0 当前行动方的棋子(1 = 有子)
ch1 对手的棋子
ch2 恒为 1.0(常量平面)
ch3 上一步落子位置

第 2 个通道恒为 1 看着很奇怪,这是踩过大坑之后的取舍------早期版本曾经在这里编码"我是黑还是白",结果网络学会了"抄执色"这条捷径。这块血泪史第二篇会专门讲。

颜色对称性是这套编码的核心收益:棋盘和棋子做颜色翻转,等价于把 ch0 和 ch1 交换。也就是说,网络对"我执黑"还是"我执白"在结构上就是对称的------白棋视角不需要网络额外学一遍。

3.2 Policy 头为什么长这样

它的形状有点怪:两个分支(一个 3×3 卷积、一个 1×1 卷积)拼成 2 通道,再 flatten 成 450 维,过一个 Linear(450→225) 输出 225 个落点。

  • 3×3 分支负责局部棋形感知(活三、冲四这种形状得看邻域)
  • 1×1 分支负责"当前点本身"的信息
  • 那层 Linear 是全局组合层------它让网络能把"左边有个活三"和"右下角有个冲四"这两件事组合起来判断,而不是各看各的

⚠️ 注意一个细节:policy 输出是 log_softmax(对数概率域)。这在所有下游都要小心------搜索里想拿概率,必须先 exp 一次。这个细节后来炸出了一个污染 7 个版本的 bug(第二篇详述)。

3.3 Value 头

conv → BN → fc1(225→128) → fc2(128→1) → tanh,输出当前局面在当前行动方视角下的胜率期望 -1, 1

中间那层 128 维隐藏层是有来历的:最早是单层 fc(225→1) 直出,后来换成了带隐藏层的版本,再后来又试过把它压到只有 226 个参数的极简版------结论是容量不是瓶颈,真正的瓶颈在标签怎么给(也是第二篇的内容)。


4. MCTS:为什么死死定在 800 次搜索

搜索这块的参数不多,但每一个都有故事。

参数 v36 取值 备注
模拟次数 sim 800,全程固定不变 从第 0 代到第 288 代都是 800
c_init 1.25 PUCT 常数,标准值
c_base 19652 标准值
根节点噪声比例 0.25 标准值
Dirichlet α 0.05 α × 225 ≈ 11.25
噪声注入次数 每步只注入一次(根先验),800 次模拟共用 关键
每步搜索量 for _ in range(800) 真跑满 800 次 关键
树复用 每局开始必须 reset_mcts() 关键

4.1 sim 为什么是 800

一个直觉问题:搜索次数越大,老师越强,数据质量越好------那为什么不往 8000 冲?

因为搜索次数和训练速度是直接对立的两端,我们做过完整的对照:

版本 sim 策略 结果
v1 动态 50→200→400→800 早期 50 次模拟时,搜索出来的落点分布接近均匀,网络从这种数据里学不到任何东西(policy 熵 96 代没动过)
v2 固定 400 稳定下来了,但 400 次模拟给出的信号还是偏"糊"
v6 固定 800 只用了 18 代就追平了 v2 跑 202 代的水平

"18 代追平 202 代"这个数据是决定性的------它说明在 400 到 800 这个区间,搜索质量对训练效率的边际收益还是正的,所以直接把 800 定成常数。至于 1600 / 3200,每代耗时直接翻倍,而当时试验预算不支持,就留成了"后面再说的选项"。

一句话总结:800 不是拍脑袋,是"再低一点数据就糊了,再高一点跑不动了"的甜点。

4.2 温度调度:三段式快速降温

自对弈里每一步都要"从 MCTS 的访问分布里采样落子",温度决定采样的随机程度。v36 用的是一条手动设计的三段曲线:

手序 温度 设计意图
第 0 手 1.00 开局放开探索
第 1 手 0.87
第 2 手 0.73
第 3 手 0.60 开局结束,快速收
第 4 手 0.49
第 5 手 0.38
第 6 手 0.26
第 7 手 0.15 进入稳定段
第 8 手及以后 0.15(平台) 一直到开局阶段结束

为什么要搞这么激进的前段降温?这来自一次很实在的数据:有一版训练里 42% 的对局在第 11 手之前就结束了------双方像背了定式一样互相速杀,中盘根本没机会展开。

调完温度之后:

指标 调之前 调之后
超短局(≤11 手)占比 42% 7%
中位手数 14 手 23 手

对局变长,意味着网络真正在有来有回的局面里积累经验------这个改动的收益是全局性的。

4.3 三个"必须小心"的实现细节

这三条都是踩出来的,不是抄来的:

  1. 噪声只注入一次 。Dirichlet 噪声要在根节点的先验上加,一次就够,800 次模拟共用这个根先验。早期版本照着某本书的写法"每次模拟都重新采样噪声覆盖根先验",等于把探索放大了 800 倍------树根本稳定不下来,最后把 value 网络教成了只会分"赢/输"两类的分类器。
  2. 每步必须真跑满 800 次 。判断循环条件如果用 while count.sum() < 800,当这个局面在之前的搜索里已经被访问过(父节点搜索灌了不少次数进来),循环会直接跳过------等于这一步 0 次搜索 ,直接复用旧分布。正确写法是 for _ in range(800),树可以复用,但搜索量一次都不能打折。
  3. 每局开始清空搜索树 。局与局之间必须 reset_mcts(),否则第 2 局开局时会发现问题被"上一局的搜索结果"污染了。

5. 训练循环:32 批次 × 512 样本

参数 v36 取值 说明
每代自对弈局数 100 局(主 10 + 工兵 90)
每代训练批次 32
批大小 512
优化器 Adam
学习率 0.001,全程固定
weight_decay 1e-4 但 BatchNorm 参数单独分组,wd = 0
经验回放池 最近 5 代数据混合
数据增强 8 方向对称(4 旋转 × 2 翻转)
Value 标签 该步搜索 Q 值(软标签) 不是终局的 ±1
Policy 标签 该步 MCTS 访问计数分布
代间是否冻结 不冻结,全网络一起训

这里面有三个点值得单独说。

5.1 BatchNorm 参数必须单独分组、weight_decay 设 0

这是用一次"0:10 惨败"换来的结论。

BatchNorm 里有 γ(缩放)和 β(平移)两组参数。如果让它们和卷积权重一起吃 weight_decay,会出现一个死亡螺旋:γ 被持续往 0 压 → 深层 BN 归一化失效 → 某些通道反相(γ 变负数)→ 网络表达力崩塌

我们做过一次反向实验:把一个已经训练好的强权重里最深那层 BN 的 γ 复位成 1,看会怎样------被 0:10 碾压 。这说明深层 γ 收缩是网络自己学到的必要机制,不是病。所以正确的做法不是"禁止它收缩",而是:把 BN 参数单独分组,weight_decay 设为 0,让网络自己决定收缩到什么程度

5.2 Value 标签用"搜索 Q 值",不用终局 ±1

这是 v33 之后才定下来的,也是治好一个慢性病的关键。

早期 value 标签是"这局最后我是赢还是输"→ ±1。问题在于:一盘棋输掉,不代表这一步下得差;反过来赢的棋里也有一堆烂手。网络拿着"整局结果"去拟合"每一步的价值",学到的是噪声。

改成 Q 软标签 之后:每一步的 value 目标 = 这一步 800 次搜索给出的 Q 值(即"在当前局面下,下这里大概能赢多少")。这个信号是密集的、和具体局面绑定的

效果立竿见影:空盘局面的 value 极端化从 52.8% 直接掉到 0%------网络不再无脑输出"必胜/必败",而是学会了给中间局面一个合理的胜率。

5.3 8 方向对称增强

棋盘本身有 8 种对称变换(4 个旋转 × 2 个翻转),对每一步训练样本都做这个增强,等于样本量直接放大 8 倍

有个小坑顺嘴一提:早期实现里翻转是用 fliplr 对四维张量操作的,实际上没生效 ------等于 8 个分支里有 4 个是重复的。后来改成显式 np.flip(axis=-1) 才真正对齐。


6. 开局规则:前 3 手随机落子(整套配置最关键的一条)

如果整篇文章你只记住一条,记这条。

v36 相比 v35 的唯一改动就是它:

前 3 手(黑 1、白 1、黑 2)100% 随机落子,不经过任何网络或搜索决策。

  • 黑 1:落在距天元 ≤ 4 的范围内(9×9,81 个点)
  • 白 1 / 黑 2:落在距天元 ≤ 3 的范围内(中心 7×7,49 个点)
  • 三个点互不重合

6.1 为什么这么干

五子棋 15×15 没有贴目,黑棋先手在顶级搜索下是必胜 的。我们实测过:两个同代强权重,sim 800 对打,执黑方 100% 机械必胜

这个"先手红利"给训练带来的灾难是:白棋赢的样本越来越少 → 网络越学越觉得"白棋没救" → 白棋下得更烂 → 白棋赢的样本更少。这就是个数据单边化的死亡螺旋。在 v18 到 v35 的六个大版本里,"白棋崩盘"反复出现,怎么调都按不住。

而"随机开局"这一招的逻辑非常直接:

既然胜负被"谁执黑"决定了,那就把这个决定权交给随机数 ------开局前三手随机撒在中心区,局面质量从一开始就是随机的,谁赢取决于接下来怎么下 ,而不是取决于谁执黑

6.2 效果

指标 随机开局之前(v35) 随机开局之后(v36)
白棋胜率 反复崩到 < 30%(最差个位数) 稳定在 39-51%
黑胜样本占比 严重单边化 恢复平衡
连续不崩 最长也就几十代 近 290 代没崩

更狠的证据在 PK 上:v36 的 it11(才训了 11 代)就以 20:0 完封了历史最强版本 v18 的王座权重 ------包括执白 10:0。也就是说,这个改动不是在"慢慢改善",而是直接把一个长期困局解开了

随机范围的量也调过:一开始用 7×7,试过放大到 13×13(发现太散,白棋胜率被推到 56-64% 过头了),最后回调成"黑 1 用 9×9、白 1 和黑 2 用 7×7"------刚好落在 45% 左右的平衡带。


7. 诊断体系:别只盯着 loss

这部分是我觉得最有价值、也最容易被人忽略的。loss 降了棋力不涨、甚至棋力下降,在这个项目里发生过不止一次。

所以除了最基础的 loss,我们搭了一套"体检"工具,每次想知道网络什么状态,跑这几项:

项目 看什么 v36 后期实测
做题集 40-43 道固定题(活三该不该堵、冲四该不该防),看 top1 命中率 67.4%
败局库静态 257 个已知败局局面,看网络给的分 31.9%,均值 +0.338(⚠️ 偏乐观)
威胁分级 网络对不同威胁等级(活三/冲四/活四)的敏感度 0.985 / 0.989 / 0.997(⚠️ 接近饱和)
有效秩 关键层权重矩阵的有效秩,看是否塌缩成低秩 value_fc1 = 33.3(≈26%)⚠️ 单调低秩化
D60/D80 用当前权重跑 MCTS,能提前多少步发现必败 12-13 步 / 7 步(⚠️ 停滞)

三个"⚠️"是有意标的:这些指标到了后期全都显示"停滞"或"有偏",但实际棋力还在涨(下一节讲)。

还有一个教训特别值得写下来:探针喂数据必须走正规的输入构造路径 。我们有一次直接拿全零张量喂进网络做"空盘评估",得出的结论是"空盘 value +0.74,病态!"------结果正确的 4 通道构造方式一跑,实际是 -0.001,完全正常。探针自己写错了,比不做探针更危险


8. 评估方法论:怎么打 PK 才不算白打

"两个权重打 20 局谁赢"这件事,我们踩了太多坑,最后沉淀成六条硬规矩。你如果要自己训,这六条可以直接抄。

# 规矩 为什么
1 必须 20 局/场 10 局口径的噪声有 ±1~2 局。实测 6 场里就有 1 场结论被反转
2 必须开 ring(换先手)规则 标准规则下,两个强权重执黑 100% 必胜,那还测什么棋力------测的是谁运气好抽到黑
3 必须拆黑白看 就算用了 ring,执黑方仍然占 55-75% 胜率,不拆开看会被平均数骗
4 静态指标平坦 ≠ 训练无效 白胜率、做题分数都会被自对弈的自我平衡吸收掉,只有对外 PK 能照出真实成长
5 单代 PK 不能判定进步 实力曲线是锯齿状的:it120 垫底,it150 反而反超 it100
6 链式推理会失效 存在"非传递环":A 赢 B、B 赢 C、C 又赢 A。"最强"这个词依赖对手是谁

第 6 条不是理论------我们实测出了一个完整的环:

复制代码
it190 > it160 > it259 > it240 > it230 > it210 > it190  ⟲

it160 以 14:6 碾压 it259,自己却输给 it190。所以任何"it_X 比 it_Y 强所以我用 X"的链条推理,在自对弈里都可能翻车。


9. 外部锚点 Rapfi:从被打崩到稳赢 depth10

前面说了,Rapfi 在这个项目里是唯一的期末考卷------不作为训练对手,只在做评估时拉出来考。

Rapfi 有个 max_search_depth 参数,可以理解成"限制它想几步",depth 越大越强。我们用这条阶梯做绝对棋力锚点。

9.1 战绩进化线

时间 权重 Rapfi depth 结果
08-25 v18 it156 d1 首次真实击败(历史性突破)
09-08 v36 it81 d1 / d2 ❌ 0:2 / 0:2 告负
09-08 v36 it81 d3 ✅ 1 胜(执黑 33 手取胜)
09-10 v36 it167 d10 ❌ 重大失误
09-10 v36 it193 d10 🟡 势均力敌
09-11 v36 it241 d10 🟡 棋差一招
09-12 v36 it283 d10 开局杀(29 手) / 开局爆杀(35 手)------执黑基本稳赢

看这条线最有意思的地方:从 it167 到 it283,只隔了 116 代训练 ,而且这 116 代在"自己人打自己人"的口径下完全看不出进步------但对固定标尺 Rapfi d10,从"重大失误"一路走到了"稳赢"。

9.2 一个坦白的限定

上面这些 d10 战绩全是执黑(先手)打的,执白对 d10 还没测。

这不是疏忽,是实事求是------五子棋先手优势太大,"执黑稳赢 d10"和"棋力已经稳赢 d10"是两句话。执白那边等到有结果再报。

9.3 所以现在是什么水平

按"能稳定击败 Rapfi depth10"这个口径,基本可以算摸到了中级水平------离引擎的全力深度还差得远,但已经不是"三岁小孩"了。

顺便说个对比:早期版本(还是 v12 那会儿)拿 Rapfi 最弱档测,棋谱存下来文件名直接就是诊断报告------黑棋无视白棋看不见活三活三不堵。那时候是真的连防守都不会。


10. 训练结果:白棋终于不崩了,但故事没这么简单

10.1 好消息:白棋不崩了

阶段 白胜率 状态
it0-13 39-47% 健康
it14-21 32-39% 轻微回落
it35-44 56-58% 反超(黑反而弱了)
it64-108 39-46% 稳定
it184-241 37-51% 稳定
总结 ~290 代没有崩过 家族史上第一个稳定版本

10.2 能力曲线:it160 是个真峰值

四轮 PK(每场 20 局、ring 规则、sim 800)打下来:

复制代码
it0 (继承的起点)
 → it60  (十局赛 7:3 拿下)
 → it70  (13:7 大胜 it60)
 → it100 / 110 / 120 / 130 / 140 / 150  (对 it60 净胜 2~4 局)
 → it160 ★ 真峰值(循环赛 61.3%,3 胜 1 平)
 → it190 / it210 / it230 / it240  (链条上各有胜负)

20 局直接对战排序:it160 > it259 > it240

10.3 不太好听的部分:内部对抗饱和了

it160 之后的约 100 代,在"自己人打自己人"这个口径下,没能产出比 it160 更强的通用棋力:

复制代码
it160 vs it240 = 11:9   (it160 胜)
it160 vs it259 = 14:6   (it160 碾压)
it190 vs it160 = 12:8   (it190 胜)  ← 非传递

三线证据都指向同一件事:D80 停滞(it165 → it282 全是 7 步)、value_fc1 有效秩持续走低、白胜率和做题分数平坦。

我的理解是:自对弈在"追一个移动靶"------网络不断适应自己最新的棋风,产出的更多是"横向的风格差异",而不是"纵向的绝对提升"。

10.4 但这一条才是最值钱的发现

上面那个"100 代没进步"的结论,被 Rapfi 推翻了

同一批权重,内部对抗看不出增长,对固定标尺 Rapfi 却在实打实地变强(116 代从重大失误到稳赢 d10)。

📌 结论修正:"100 代无增益"应该理解成**"内部对抗饱和"**,而不是"训练无效"。

Rapfi 是固定标尺,内部对手是移动标尺。 只跟自己打,你会误判自己停了;有一个不动的参照物,才看得见真实的进步。

这条是我做这个项目最大的方法论收获,也是下一篇文章要重点展开的------整个 v1 到 v36 的配置,几乎每一行都是被类似的实验纠正过来的


11. 踩坑速查表(建议收藏)

# 一句话修复
1 搜索里把 log 概率当概率用 先验反转 → MCTS 退化纯 value → policy 饿死 99 代;所有 log_softmax 输出用前必须 exp
2 每次模拟都重采样 Dirichlet 噪声 探索被放大 800 倍,树不稳定;噪声只在根节点注入一次,全部模拟共用
3 while count.sum() < 800 判搜索量 局面被访问过时直接跳过 = 0 次搜索;改 for _ in range(800) 真跑满
4 局与局之间不重置搜索树 第 2 局开局就被上一局污染;每局开头必须 reset_mcts()
5 BN 参数跟着吃 weight_decay γ 被压进死亡螺旋、深层通道反相;BN 参数单独分组,wd = 0
6 value 标签用终局 ±1 输局里的好手也吃 -1;改成该步搜索 Q 软标签,密集监督
7 强权重 PK 用 greedy=True 每局走出完全一样的棋,10:0 实际只有 1 局;强权重必须采样
8 10 局就下结论 噪声 ±1~2 局,实测 6 场里 1 场结论反转;至少 20 局
9 标准规则下测强权重棋力 执黑 100% 必胜,测的是抽签;必须开 ring 换先手
10 权重按文件名判"已存在" 截断文件被永久跳过,还以为"已最新";必须校验大小 + zip 完整性
11 新目录继承种子只拷 weights.pt 工兵等 metadata.json 死等、主进程等工兵,互相死锁;先写 metadata 再启主进程
12 8 方向增强用 fliplr 对 4D 张量 反射分支根本没生效,样本只放大 4 倍;改 np.flip(axis=-1)
13 探针直接喂全零张量 得出"空盘 value +0.74 病态"的假结论,正确构造实际是 -0.001;探针必须走正规输入构造
14 只看 loss 判断训练好坏 loss 创新低而棋力下降是常态;必须配合 PK 和做题集
15 静态指标平坦就说"训练无效" 可能只是内部对抗饱和;换一个固定外部标尺再看

写在最后

这个项目从 v1 跑到 v36,中间经历过"白棋崩盘 → 换网络 → 换超参 → 换标签 → 全都不管用"的漫长阶段,一直到 v36 那条"前 3 手随机"的规则落地,才第一次看到白棋胜率稳稳停在 40% 出头不动。

回头看最有意思的一点:真正解决问题的不是更深的网络、更聪明的搜索、更精细的损失函数,而是一条改变"题目难度分布"的规则。前面三十多个版本都在调"模型侧"的旋钮,答案一直在"题目侧"。

如果你也在跑自对弈,希望这篇配置清单能帮你少走点弯路。

👍 如果这篇对你有用,点个赞让我知道

配置细节建议收藏,后面第二篇会讲每个参数的血泪史

💬 评论区聊聊:你训自对弈遇到过最诡异的坑是什么?

🔗 **代码 & 全部对局记录在 Gitee:alpha zero gomoku

下一篇 :《AlphaZero 五子棋实战(二):每个参数都是血泪史------v1→v36 参数考古》

讲清楚 sim 为什么定 800、温度调度怎么来的、视觉通道为什么是 4 个、value 标签为什么从 ±1 换成 Q、开局规则怎么从"让手"一路试到"随机"------每一个配置项背后都是一串对照实验。

相关推荐
固定资产管理系统软件1 小时前
该去哪里找专业靠谱的智慧智能设备固定资产管理系统?
人工智能·python
具身AGI1 小时前
线缆绳索怎么操控,物理AI 物理推理 的新解法
人工智能
广州山泉婚姻1 小时前
列表初始化:C++11全新初始化体系
c++·人工智能
天涯浪客1 小时前
静态 → LLM → 动态:一条 6 模块流水线,把 Python 漏洞告警噪声压到 4.3%
人工智能
蜗牛互联网1 小时前
语音AI开始边听边说,改变的不只是响应速度
java·人工智能·后端·语音识别
leoZ2311 小时前
2026-09-10-静态扫描连错三次-用运行环境当裁判
前端·javascript·vue.js·人工智能·opencv·机器学习·数据挖掘
一切皆是因缘际会1 小时前
轻量化端侧部署
人工智能
FL16238631291 小时前
苹果果梗枝条识别分割数据集labelme格式712张3类别
人工智能
齐齐大魔王1 小时前
机器学习(七)
人工智能·机器学习