资讯动态

Ghost-master实战:基于Minigo的幻影围棋Python项目全解析

发布时间:2026/10/8 19:09:51 来源:尧图企业网站定制
简介基于Minigo的幻影围棋项目Ghost-master面向围棋AI学习者和Python开发者用于实现人机、机机两种对弈模式。压缩包共18个文件总量1.47MB以14个py源码为核心覆盖棋盘表示、特征提取、对弈策略、蒙特卡洛树搜索及可视化界面等模块同时附带模型权重索引文件与说明文档便于快速运行和二次开发。目前已有926人学习下载。项目通过referee、ghost_vs_human、ghost_vs_ghost等脚本清晰区分裁判、人机对战和AI自弈流程dual_net等文件展示了Minigo神经网络结构utils、symmetries等工具则提供数据增强与通用函数支持。从零搭建这套围棋AI可深入理解MCTSCNN的混合决策机制并借助机机对弈持续优化棋力是实践深度学习与博弈算法的轻量级好素材。1. Ghost-master 幻影围棋一份能直接落地的 Minigo Python 项目Ghost-master 是一份用 Python 写好的幻影围棋项目底层走的是 DeepMind 开源的 Minigo 框架压缩包里模型权重、双头网络、蒙特卡洛树搜索和三个对战入口脚本一次配齐装好依赖就能看到 AI 在 19 路棋盘上落子。它把 AlphaGo Zero 那套“特征编码 → 策略网络 → 价值网络 → MCTS 搜索”完整折叠进了可复现的代码里比对着论文空想直观得多。适合两类人围棋爱好者想本地体验 AI 对弈AI 学习者想读懂完整决策链路。我拆完这个包最大的体会是难点不在单个算法而在几个 Python 模块之间怎么衔接所以下面按“认清结构 → 跑通对战 → 拆核心机制 → 避开坑”的顺序讲。2. 项目结构与模块职责先看懂这些 .py 文件的分工拿到压缩包解压后Ghost-master 根目录下躺着十几个 Python 文件和一个 models 目录。很多人上来就双击 ghost_vs_human.py结果各种报错原因就是没搞清楚模块边界。这个项目的文件整理成下表你会发现它其实是标准 Minigo 工程的分层围棋规则层、特征层、网络层、搜索层、界面层。文件职责go.py棋盘状态、落子合法性、提子、打劫、胜负判定coords.py棋盘坐标与落子坐标之间的转换features.py把当前局面编码成 CNN 需要的特征平面dual_net.py定义策略 价值双头卷积网络symmetries.py棋盘的旋转/翻转 8 种对称变换Ghost.pyAI 玩家主逻辑封装 MCTS 搜索Ghost1.py备用的 AI 封装入口通常搜索次数更低Referee.py对局裁判负责贴目与终局数子utils.py公共工具日志、计时、模型路径等ghost_vs_human.py人机对战入口ghost_vs_ghost.pyAI vs AI 机机博弈入口ghost_vs_randomPlayer.pyAI vs 随机落子对手用于环境自检AI_GUI.pypygame 图形界面入口models/000496第 496 步训练保存的模型权重note.txt作者留下的运行说明z_trashBin.py废弃代码不要引入主流程里头的核心链路是这样走的go.py 维护棋盘features.py 把棋盘编码成 17 通道特征图dual_net.py 推理出策略先验和胜率估计Ghost.py 拿这两个输出跑 MCTS 搜索最终选一个落子点。2.1 go.py 与 coords.py对弈规则底座go.py 是整盘棋的地基。它负责记录当前局面、判断某步是否合法、处理提子和打劫以及终局时计算地盘。Minigo 的 go.py 里核心数据结构是 Position每个 Position 快照包含棋盘状态、上一次落子、是否 pass 等信息。MCTS 每展开一个节点都要调用它所以这块的性能直接影响搜索速度。coords.py 解决的是坐标转换问题。围棋里有三种常见坐标表示GTP 协议的字母坐标如 D4、SGF 棋谱坐标、还有程序内部用的 0-18 索引。人机对战的时候用户在终端输入的是 D4 这种程序内部计算用的是数字索引中间就是 coords.py 在做翻译。你改界面或者接 GTP 协议时最先碰到的就是这里。2.2 models/000496这份模型权重到底代表什么models 目录下只有一个 000496这个编号我理解是强化学习自对弈训练到第 496 次保存的权重快照。Minigo 的做法是让当前模型和旧模型不断对弈赢到一定比例才更新所以编号越大的权重通常棋力越强、棋风也越稳。000496 在训练曲线上属于中前期特征很明显会走常见定式和基本攻防但大局观偏弱特别喜欢主动引发战斗。加载模型的逻辑一般写在 Ghost.py 顶部常见写法是定义一个 MODEL_DIR 或 LOAD_PATH 常量指向 models/000496。如果你手头有更强的新权重只需要替换这个目录再改指向就行。注意这里不是只换一个文件而是换整个目录因为 Minigo 的保存格式里除了权重本身还有图结构和训练配置。2.3 三个入口脚本人机、机机、随机验证怎么选ghost_vs_human.py 是主入口跑起来后 AI 加载模型下黑棋或者白棋用户通过命令行输入坐标。ghost_vs_ghost.py 是给两个 AI 对弈用的你可以指定不同的权重目录让它们自我博弈这是最强的验证方式——两个差不多棋力的 AI 对局结果基本能反映权重好坏。ghost_vs_randomPlayer.py 则是我建议你第一次跑通的脚本它让 AI 对一个随机落子的对手程序稳定性和环境问题一眼就能暴露出来。这三个脚本的职责划分很重要。很多人一上来就试图用 GUI 跑对局结果模型加载成功但界面崩了反而分不清是模型问题还是界面问题。我的习惯是先跑 ghost_vs_randomPlayer.py 确认推理链路通再跑 ghost_vs_human.py 体验对战最后才碰 AI_GUI.py。3. 环境搭建与启动从 pip 装依赖到人机对战跑通这一章讲实际操作。Ghost-master 是 2019 年前后那个 Minigo 时期的项目依赖栈和现在主流环境差得比较多装环境的坑比代码本身还多。核心准则是Python 版本别用太高TensorFlow 别用 2.xnumpy 别用新版。我给出的组合是 Python 3.7 TensorFlow 1.15 numpy 1.19。3.1 创建虚拟环境并安装依赖先用 conda 建一个干净的环境避免污染系统 Python。conda create -n ghost python3.7 -y conda activate ghost pip install tensorflow1.15.0 pip install numpy1.19.5 pip install pygame sgf逻辑说明conda 创建独立环境是为了把 TensorFlow 1.15 和系统里其他 Python 项目隔开这个版本非常老装错地方会引发连锁冲突。tensorflow1.15.0 是这台代码能正常 import 的前提Minigo 的 dual_net.py 里大量使用 session、placeholder 这类 TF1 专用 APITF2 默认 eager 模式会直接报错。numpy 锁在 1.19.5 是为了避开 1.24 以上版本移除 np.float / np.int 别名的问题。pygame 是 AI_GUI 要用的sgf 库用来解析棋谱和记录对局。参数说明如果装 tensorflow 时提示找不到对应版本多半是 Python 版本太高退回 3.7 即可。如果你用的是 Apple Silicon 或者比较新的 macOSpip 装不了 TF1.15 的轮子我一般直接拉镜像跑docker 里放一个 tensorflow/tensorflow:1.15.5-py3 环境再把项目挂载进去。3.2 检查并修改模型路径与核心参数解压后第一步不是直接运行而是打开 Ghost.py 或 utils.py 看一眼模型路径。常见写法是顶部定义常量我按最常见的配置写下示意# utils.py 或 Ghost.py 顶部的配置区 MODEL_DIR os.path.join(os.path.dirname(__file__), models, 000496) BOARD_SIZE 19 NUM_READOUTS 800 RESIGN_THRESHOLD -0.9逻辑说明MODEL_DIR 指向模型权重目录如果脚本用相对路径建议你改成绝对路径防止从别的目录启动时报找不到文件。BOARD_SIZE 决定 dual_net 输入形状Minigo 默认 19 路也就是特征图是 19×19。NUM_READOUTS 是 MCTS 每步搜索的模拟次数800 是 Minigo 默认值。RESIGN_THRESHOLD 是认输阈值代表胜率估计跌到多少时自动认输。参数说明如果你是第一次跑且用的是 CPU建议先把 NUM_READOUTS 降到 200不然每步要等十几秒体验很差。核显或没有 GPU 的机器上800 次搜索一步棋可能要二十秒以上。跑通全流程后再逐步调高到 400、1600 对比棋力变化。3.3 跑通人机对战环境弄好后先跑最简单的随机对手脚本验证推理链路python ghost_vs_randomPlayer.py逻辑说明这个脚本让 AI 对随机落子的对手如果能在几十手内看到 AI 正常落子并最终获胜说明模型加载、特征编码、MCTS 搜索整个链路是通的。常见的失败点是前向推理时报形状错误说到底是 BOARD_SIZE 和模型训练尺寸不一致回到 3.2 检查配置。验证通过后再跑人机对战python ghost_vs_human.py启动后终端会提示你输入落子坐标比如 D4、K10 这种。输入格式走 GTP 坐标字母从 A 到 T 跳过 I数字从 1 开始A1 对应棋盘左下角。你每落一子AI 开始思考控制台会打印它的选点和胜率估计。至于是执黑先行还是执白启动时通常有提示或者进脚本里改一个常量就行。3.4 一个值得养成的验证习惯每次改完环境或者换完模型我都习惯先跑 ghost_vs_randomPlayer.py 两局再碰正式对战。这个脚本比人机对战快很多因为随机对手的落子不需要搜索几乎瞬间响应。它能快速区分“环境有问题”和“模型棋力不行”这两种完全不同的状况避免你在一个坏环境里调一个晚上的参数。4. Minigo 核心机制拆解dual_net、features、symmetries 与 MCTS 决策链路这章把 Ghost-master 内部最关键的四个模块讲透。MCTS 对很多人是黑匣子其实拆开看就三件事拿神经网络给出的先验概率和胜率估计去搜索搜索到足够次数后按访问次数落子。理解了这个你就知道为什么有时候搜索次数越高棋力越强。4.1 dual_net.py策略与价值双头卷积网络dual_net.py 定义的是 AlphaGo Zero 论文里的双头结构输入一个 19×19×17 的特征张量共享一组残差卷积层然后分两个头输出。策略头输出 19×19361 个落子点的概率分布再加 pass 的概率价值头输出一个标量胜率估计范围取 tanh 压缩到 -1 到 1 之间。部件输入输出作用共享残差块19×19×1719×19×256提取局面特征策略头19×19×2563611 个 logits每个落子点的先验概率价值头19×19×2561 个标量当前局面胜率估计结构上有一点和普通分类网络不同落子概率要先做 mask把不合法的点已经有子的位置、打劫禁止点排除掉再 softmax。这个 mask 操作在 Ghost.py 里完成。如果你换权重后棋力异常先检查 mask 是不是生效这是最容易出玄学问题的地方。4.2 features.py17 通道特征是怎么拼出来的Minigo 的输入特征沿用了 AlphaGo Zero 论文的 17 平面设计这是整个网络输入的核心。简单说它把最近 8 步的棋盘历史全部编码进去让网络看到棋局的动态演变而不仅仅当前这一步。我按惯例写一个构造特征面的示意代码方便你理解概念def build_features(history, next_player): feats np.zeros((17, 19, 19), dtypenp.float32) for step in range(8): if step len(history): board history[-(step 1)][board] own (board next_player).astype(np.float32) opp (board (1 - next_player)).astype(np.float32) else: own np.zeros((19, 19), dtypenp.float32) opp np.zeros((19, 19), dtypenp.float32) feats[step * 2] own feats[step * 2 1] opp feats[16] next_player return feats逻辑说明history 里保存的是最近若干步的棋盘快照next_player 是当前轮到的棋手。循环从最远的快照取到最近一步每步拆成两个平面分别标记当前棋手和对手的棋子位置。第 17 个平面全部用 next_player 填充表示这步轮到谁走。这样网络看到的不只是一个静止局面还包括最近 8 步双方的动作轨迹。参数说明如果棋盘是 19 路每个平面是 19×19代码里 19 出现的地方都要和 dual_net 的输入形状一致。有些改造版把 8 步历史改成 4 步以省显存但那样棋力会明显下降不建议少于 6 步。4.3 symmetries.py8 种对称变换的作用围棋棋盘有天然对称性同一盘棋旋转 90 度、水平翻转、垂直翻转后本质上还是同一局面。symmetries.py 就是做这个变换的对 19×19 的棋盘做 8 种组合变换对应正方形二面体群。这个模块有两个用途。第一是训练数据增强。自对弈产生的同一局棋可以变换成 8 个视角分别当作独立样本喂给网络等于把数据量翻了 8 倍。第二是推理时做稳定性处理常见做法是把当前局面变换成 8 个视角分别跑一次网络推理再把 8 组策略概率逆变换回原方向取平均最后的价值取平均值。这样能明显减少单次推理的方向偏差属于能涨棋但不增加搜索代价的小技巧。4.4 Ghost.py 里的 MCTS搜索次数是核心参数MCTS 搜索封装在 Ghost.py 里决策流程按顺序是四步选择、扩展、模拟、回传。选择阶段用 UCB 公式平衡“当前最佳点”和“探索少评估的点”扩展阶段调用 dual_net 得到新节点的先验概率和胜率模拟阶段沿着叶子节点继续向下评估回传阶段把收益沿路径加回每个节点。循环重复 NUM_READOUTS 次最后按根节点的访问次数选点。很多初学的人盯着 UCB 公式看半天其实这个项目里真正影响体验的是 NUM_READOUTS 这个参数。它直接决定每步棋要重复多少次搜索循环。数值越大会越强但耗时也线性增长。我的经验是CPU 上跑 200 次已经能欺负乱下的玩家到 800 次棋风明显更稳想感受完整棋力至少 1600 次且最好有 GPU。还有一个细节值得注意MCTS 的随机性来自 Dirichlet 噪声注入这是为了让开局不走成固定的重复套路。如果你看到同一盘棋 AI 走了不同开局不要以为是 bug。5. 避坑指南五个必踩的坑与排查方法这一章写我从拆包到跑通遇到的高频问题每一条都是现场真实翻车记录。我按“现象 → 原因 → 解决”的方式记录你可以直接对照着排查。5.1 坑一TensorFlow 版本冲突import 直接失败现象运行 ghost_vs_human.py 时报错 module tensorflow has no attribute contrib或者报 placeholder 不存在、Session 不存在。终端里一长串红色 traceback看最后一行通常在 import dual_net 的位置。原因Ghost-master 是基于 TensorFlow 1.x 写的网络定义里大量使用 tf.contrib、tf.Session、tf.placeholder。装上 TF2.x 之后contrib 整个被移除Session 也被禁用旧代码完全跑不起来。解决把 Python 固定到 3.7然后 pip install tensorflow1.15.0。如果系统里已经装了 TF2先 pip uninstall tensorflow 再装。实在装不了旧版就上 Docker 的 tensorflow/tensorflow:1.15.5-py3 镜像。我还见过有人在代码开头加 tf.compat.v1.disable_v2_behavior() 硬兼容但双头网络的 contrib 部分还是救不回来不推荐新手折腾。5.2 坑二numpy 新版导致 np.float 报错现象程序跑到胜负判定或特征构造时报 AttributeError: module numpy has no attribute float。有时候是 np.int 报同样错误。原因numpy 1.24 以后把 np.float、np.int 这类别名移除了而旧项目的代码里直接写了 np.float 或者 np.float32 的位置用了 np.float。这种错误很隐蔽因为在纯 Python 里不会触发只有跑到数值计算才会炸。解决pip install numpy1.19.5。注意装完 TF1.15 之后再装 numpypip 可能会帮你把 numpy 升级到新版所以顺序最好是先装 numpy 再装 tensorflow装完检查一下 numpy.version确认没有被动更新。5.3 坑三models/000496 加载失败权重形状对不上现象程序启动时能加载模型文件但一推理就报 shape mismatch比如 361 和 362 对不上或者提示 weight 数量不匹配。原因Minigo 的策略头输出是 361 个落子点再加 1 个 pass一共 362 维。如果你下载的权重是旧版 19×19 棋盘训练出来的而代码里配置改成了 9 路或者反过来都会触发形状不匹配。另一个常见原因是加载的不是完整 checkpoint而是只拷了权重文件没拷图结构导致变量名对不上。解决确认 BOARD_SIZE19 与模型训练尺寸一致。把 models/000496 整个目录保留完整不要只搬运单个 .index 或 .data 文件。加载代码一般写在 dual_net.py 的 load 函数里用 tf.train.Saver 或 tf.keras.models.load_model 时注意看日志里变量数量是否跟你网络定义一致。5.4 坑四AI_GUI 黑屏闪退对局窗口起不来现象运行 AI_GUI.py 时窗口一闪而过或者黑屏卡住不动命令行没有明显报错。CPU 飙高但界面无响应。原因AI_GUI.py 依赖 pygame 做渲染。没装 pygame 时 import 就挂在最前面窗口直接起不来。另一个原因和 pygame 版本有关部分新版本对旧式事件循环写法不友好会卡在刷新循环。解决先 pip install pygame 确认 GUI 依赖完整。更稳的做法是先用 ghost_vs_human.py 命令行模式验证核心逻辑通再跑 GUI。如果你只是想看到最终棋谱不一定要 GUIghost_vs_ghost.py 的输出信息更完整还不会抢 CPU 资源。5.5 坑五机机对战卡死或出现无限连 pass现象跑 ghost_vs_ghost.py 时有时候看到双方连续 pass 但程序没有正常结束或者一方明明有棋可下却一直 pass最后死循环。原因Minigo 有认输阈值 RESIGN_THRESHOLD当价值网络给出的胜率估计低于阈值时 AI 会选择认输。两个 AI 实力悬殊时弱势一方可能开局没多久就持续 pass而裁判逻辑如果没有对连续 pass 的次数做上限就会挂住。解决把 RESIGN_THRESHOLD 设得更低比如 -0.999让 AI 死扛到底同时检查 Referee.py 里是否对连续 pass 有终止条件常见做法是双方连续 pass 两次即终局。在做机机对局测试时我一般还会加一个最大手数上限超过比如 800 手强制判和棋防止极端局面卡死。6. 进阶玩法机机自对弈与棋力快速验证把这套环境跑通只是开始Ghost-master 真正的价值在机机博弈上。我常用的进阶操作有两个一个是拿 ghost_vs_ghost.py 做固定参数的自对弈另一个是低搜索次数快速验证不同权重。6.1 固定参数自对弈打开 ghost_vs_ghost.py通常顶部有几个常量定义两个 AI 各自的模型目录和每步搜索次数MODEL_A models/000496 MODEL_B models/000496 NUM_READOUTS_A 400 NUM_READOUTS_B 400把两个模型目录指向不同的权重或者让 A 保持高搜索次数、B 用低搜索次数就能观察同一模型在不同搜索强度下的棋力差异。我一般会记录每局胜负、最终目差、手数三个指标做个 10 局的小比赛赢多输少的权重就是当前更能打的版本。6.2 低搜索次数 sanity check换新权重时先用 NUM_READOUTS200 跑 5 局对随机玩家确认胜率正常后再做正式自对弈。这个习惯帮我过滤掉至少三次坏权重特征很典型搜索次数低时该赢的棋赢不下来但搜索次数越高胜率越稳。如果低搜索局全胜基本说明权重没废如果低搜索就翻车省下了拿高搜索跑几十局的冤枉时间。从那以后我每次拿到新训练的棋类 AI 权重第一件事都是把搜索次数压到 200和随机玩家跑 5 局做 sanity check再慢慢往上加搜索量对比。看起来多花十分钟实际避免的是在坏权重上浪费一晚上的调参。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑