日期:2026-07-13 范围:当前工作区中的 Python 训练链路、OpenRA 桥接、训练日志与路线图 原则:先保证实验定义、配置和指标可信,再扩大模型或迁移桥接协议
The P0 code corrections identified in this review have now been applied, with unit-level regression coverage. No new long training run has been used to claim a policy-quality improvement yet.
- PPO receives an explicit frozen BC teacher loaded from the complete
warmstart_pretrain.pth; teacher/student KL uses the same action mask and only decision steps. The trainer logs the checkpoint SHA-256 and mean KL. - A single environment configuration is used for warm-start, single-process, and vector workers. Workers return and validate a semantic config hash.
- Goal reward is potential-based, production snapshots distinguish
Donecompletion from cancellation, and reward diagnostics expose both fields. - Time-limit truncation bootstraps from the terminal observation; the invalid decomposed value auxiliary loss is disabled by default.
- Asset reward is now named/documented as gross production. Per-actor discounts no longer scale unrelated gains from the same step.
Validation completed: Python compilation, PowerShell parser validation, the
9-test regression suite, bridge-source equality, and OpenRA.Game build all
pass. The only build diagnostic is project-level StyleCop SA0001 for disabled
XML-comment analysis.
The sections below retain the pre-fix evidence and acceptance rationale. A
minimal independent evaluator now exists at scripts/evaluate_policy.py; it
uses run_metadata.json and reports fixed seed/goal matrices. The next required
action is to run it on a newly corrected checkpoint, not to compare another raw
training-reward curve.
OpenRA-Bot 已经打通以下完整链路:
- OpenRA 引擎内状态提取与动作下发
- Gymnasium 环境、entity observation、macro action
- BC warm-start、PPO、action mask、best checkpoint
- headless renderer 与
SubprocVecEnv - goal conditioning 与 reward component 日志
这些工程能力是项目当前最重要的资产。
但现阶段的主要瓶颈不是网络规模,也不能简单归因于 PPO 超参数、encoder freezing 或 mean pooling。代码核对显示,若干实验 plumbing 和 reward accounting 问题足以改变训练任务或指标含义。因此以下历史结论暂时只能视为待复验假设:
- “Teacher-KL 使策略达到 0.53”
- “Goal conditioning 带来 5 倍策略提升”
- “4-env reward 下降源于多状态梯度稀释”
- “PPO 无法超过 BC 的根因是 encoder 冻结”
下一阶段应先完成 correctness、独立评估和可复现实验,再决定是否升级 Transformer、V-trace 或 gRPC。
当前流程是:
- BC 模型保存到
warmstart_pretrain.pth。 - student 根据
load_bc_action_head选择性加载权重。 PPOAgent.train()再deepcopy(self.model)生成 teacher。
当使用推荐的 --no-load-bc-action-head 时,teacher 的 action head 仍是 student 的随机初始化 head。因此当前实现更接近“初始策略正则化”,而不是 BC expert regularization。
此外:
- BC 训练的 trainable prefixes 不包含
policy_head.gate_action_type。 - student 加载 BC 权重时也不加载该 gate。
- teacher-KL 直接使用未 mask 的 logits,没有与采样时的合法动作分布对齐。
- 独立构建并加载完整 BC teacher,不从 student 复制。
- teacher 与 student 架构完全一致,策略关键参数必须严格加载。
- teacher/student KL 使用相同的
action_typemask。 - KL 只在真正的 decision step 上计算。
- 如果保留当前 snapshot regularization,应明确命名为
initial_policy_kl,不要称为 teacher-KL。
验收:训练启动时记录 teacher checkpoint hash,并验证 teacher action head 与 BC checkpoint 完全一致。
scripts/train_rl.py 创建 EnvFactory 时没有传递至少以下参数:
goal_conditioninggoal_aligned_weightadd_opponentbot_type
这意味着命令行虽然指定了 goal/opponent,worker 实际运行的可能是另一项任务。Goal warm-start 使用 34 维 scalar,而无 goal worker 使用 28 维 scalar,还会导致部分 encoder 权重因为 shape 不一致而跳过。
修复要求:用单一 EnvConfig 创建 warm-start env、single env 和所有 workers;worker 启动后返回配置 hash、observation space 和 action space,由主进程做一致性断言。
当前 GoalLibrary.goal_reward() 返回当前 composition progress,环境每一步都把该绝对值加入 reward。达到相同状态后继续等待,也会重复获得相同奖励。
因此不同 goal_aligned_weight 的 raw reward 不在同一量纲上,不能用 0.08 → 0.40 推导“策略提升 5 倍”。已有日志中,goal run 的总分大部分直接来自 goal_aligned,其 asset component 未必高于 no-goal run。
建议:
- 训练 shaping 使用进度增量,或 potential-based shaping:
gamma * Phi(s_next) - Phi(s)。 - goal completion、time-to-goal 作为评估指标,而不是每步 living reward。
- 横向比较统一使用不随训练 reward 权重变化的评估指标。
_extract_production_items() 会过滤 Done=True 的 item;_diff_production_events() 随后把从 active 集合消失的 item 解释为 cancel。因此一个从 99% 进入 Done 的项目会产生约 0.99 个 weighted cancel。
修复要求:显式区分 started / progressed / completed / canceled / placed / rejected。短期可比较当前 Done items 和新 actor;更可靠的方案是由 C# bridge 返回生产及订单执行事件。
当前 tracker 奖励所有新出现的己方 actor,但不扣除己方损失或出售,因此它衡量的是 gross production,而不是 net worth growth。加入对手后,这会鼓励高损耗补产而不直接惩罚战损。
应根据用途选择并准确命名:
gross_production_valuenet_asset_deltaarmy_value_alivetrade_efficiency = enemy_loss_value - own_loss_value
建筑折扣也应按新 actor 类型逐项计算,不能用“本步是否新建 proc/powr”去缩放本步所有新增资产。
- 环境当前始终返回
terminated=False。 - enemy 因 fog 离开可见范围时,可能被 kill tracker 误判为死亡。
- macro action 只有生产,没有主动进攻、侦察、撤退或防守动作。
- Python 默认 bot type 为
rulebased,但 RA 内置类型是rush/normal/turtle/naval。
在这些问题解决前,--add-opponent 不能被视为完整对战训练。
ActorCritic 总是返回 asset/goal/prod/other heads,PPOAgent.train() 也会把 decomp_loss 加入总 loss。
当前 component targets 存在以下问题:
- reward components 只保存在 rollout 外部列表,没有跟随 Buffer sequence indices。
- minibatch shuffle 后,target 与 observation/action sequence 不再对齐。
- 多环境 append 顺序是 time-major,训练 reshape 却按 sequence/env/time 使用。
- cancel、idle cash、power deficit 等日志记录的是正 magnitude,合并 target 时没有恢复负号。
- head 预测 immediate component,而不是对应的 discounted/GAE return。
短期应禁用并删除该 auxiliary loss,只保留单 value head。长期若重新实现,reward components 必须作为 transition 数据存入 Buffer,并为每个分量计算正确 return。
训练把 terminated or truncated 合并成 done,并在 GAE 中把后续 value 设为零。当前绝大多数 episode 是时间截断而非自然终局,这会给 critic 带来系统性负偏差。
修复:分别存储 terminated 和 truncated;时间截断使用 terminal observation 的 value 做 bootstrap,真正胜负/灭亡才切断 return。
标准 PPO 通常在整个 rollout batch 上归一化 advantage。按 worker 单独归一化会消除 worker 之间有意义的回报差异,尤其当每个 worker 只覆盖一条或少量轨迹时。
建议恢复 global normalization 为默认,把 per-env normalization 作为有明确对照的消融项。
当前 macro mode 已经把问题化简为 noop + 17 produce types。其余五个 head 被 mask 到单一 index,logprob、entropy 和梯度均为零。
改成 gymnasium.spaces.Discrete(18)是合理的工程清理,可以:
- 删除无意义的 dummy masks 和 head storage。
- 简化 Buffer、采样、日志和部署代码。
- 避免 macro 行为与 MultiDiscrete 接口不一致。
但它不是新的学习能力突破。当前模型中五个 dummy heads 约占总参数的 16%,而不是 60%。建议保留独立的 MacroPolicy,不要为了短期 macro 训练删除未来 full/autoregressive action 的设计空间。
历史上曾用 freeze encoder 保护 BC 特征,但当前 fresh warm-start 会使用 feed-forward student,且 train_best.ps1 默认传入 --no-freeze-encoder。
冻结权重也不意味着 activation 是静态的;模型仍会随输入状态变化。真正问题是 frozen representation 不能针对 RL objective 调整。
是否冻结应作为消融项:
- BC encoder frozen
- 全量 fine-tune
- encoder 小学习率 / gradual unfreeze
SimpleEntityEncoder 的 mean pooling 对顺序不敏感,这是 set encoder 的合理属性;问题在于它不能显式建模实体关系,并可能丢失 cardinality。
Count-aware scalar 是有价值的全局统计,不应在启用 Transformer 后立即删除。后续建议按成本递增比较:
- mean pooling + explicit counts(当前基线)
- DeepSets:sum/mean/max 多池化
- learned attention pooling
- Entity Transformer + pooling
Transformer 当前只存在于 PLAN 的设计伪代码中,仓库尚无可启用实现。实体是无序集合,不应直接给 actor slot 加普通序列 positional encoding;可以使用坐标、owner、type embedding 和关系 bias。
当前 best checkpoint 根据训练 rollout 的单步平均 shaping reward 保存。这会同时受到 goal 分布、episode 阶段和 reward 权重影响,不能充当稳定的模型选择指标。
每次实验应保存:
- 完整配置、seed、Git SHA、OpenRA DLL hash
- observation/action/reward schema version
- optimizer、RNG、update 和 teacher checkpoint
- 每个 worker 的实际配置 hash
独立 evaluator 应固定地图、阵营、spawn、goal 和 opponent,至少运行多个 seed,记录:
- episode return(统一评估 reward)
- goal completion 与 time-to-goal
- gross/net asset、army value、harvester/building composition
- accepted/executed/rejected action rate
- queue utilization、idle cash、power deficit
- 对战时的 win rate、trade efficiency、survival time
BC 的验收不能只看训练集 100% accuracy,应报告 held-out accuracy、每类 precision/recall 和 decision-step accuracy。
当前瓶颈来自 C# 每次调用重建状态、重复反射、扫描 actor/resource 和计算 placement,而不是 pythonnet 函数调用本身。
短期优先级:
- 为
GetState()、placement、mask、IPC 分段计时。 - 缓存稳定的 Type/MethodInfo/FieldInfo。
- 只在有 Done building 时计算对应 placement cells。
- 缓存静态地图/资源信息,或返回 delta。
- 批量 feasibility check。
- 合并
SendActions + Step + GetState的调用边界。
当前 OpenRA.Game/PythonAPI.cs 与 OpenRA.Bot/utils/PythonAPI.cs 行为不一致,Null platform 也未纳入标准 solution/build 流程。需要:
- 只保留一个权威 bridge 源,或提供自动同步与 hash 检查。
- 将
OpenRA.Platforms.Null纳入可重复构建。 - 在 CI 中从干净 checkout 构建并运行 integration smoke test。
- 不再静默吞掉关键 reflection/action 错误。
建议逐步拆分,而不是先进行大规模目录迁移:
envs/rewards.py:reward state 与 componentsenvs/action_spaces.py:macro/full action 与 masksagent/ppo.py:PPO traineragent/rule_based.py:teacherbridge/:统一 EngineBridge 接口与实现evaluation/:独立模型评估
先增加测试,再移动文件,避免重构期间无法区分行为变化和路径错误。
- 修复真实 BC teacher 与 masked teacher-KL。
- 统一 single/vector env config。
- 修复 completion/cancel、goal delta reward 和 asset 命名。
- 禁用错误的 decomposed critic loss。
- 修复 terminated/truncated bootstrap。
- 固定 bot type 与 PythonAPI source of truth。
- 建立 synthetic unit tests 和单环境/多环境 integration tests。
- 固定 seeds 和 evaluation protocol。
- 使用 invariant metrics 选择 best checkpoint。
- 重跑旧结论对应的最小消融,不直接开始长跑。
建议矩阵:
- BC init + PPO,无 KL
- current initial-policy KL
- true BC teacher-KL
- goal observation only
- goal + potential shaping
- single env vs 4 env(相同 transition budget)
- global vs per-env advantage normalization
- 合法的固定弱 bot。
- game outcome 与 win/loss reward。
attack_move / defend / scout / retreat / rally等 macro actions。- 先验证能稳定击败弱 bot,再进入 self-play。
- DeepSets/attention/Transformer 消融。
- profile 驱动的 bridge 优化。
- 只有当进程隔离、远程部署或大规模并行成为实际瓶颈时,再启动 gRPC ADR 和原型。
在继续 100–400 update 长跑前,至少满足:
- 所有 worker 配置与主配置 hash 一致。
- teacher action head hash 与 BC checkpoint 一致。
- 相同状态不重复获得 goal progress reward。
- 正常生产完成不产生 cancel penalty。
- 时间截断正确 bootstrap。
- action accepted/executed rate 可观测。
- 单/多环境使用相同任务和相同 transition budget 可比较。
- 至少多个 seed 的独立评估结果优于 scripted baseline,而不只是在训练 shaping reward 上更高。
完成这些门槛后,模型扩容和算法迁移才有可靠的实验基础。