Skip to content

Latest commit

 

History

History
338 lines (222 loc) · 15 KB

note.md

File metadata and controls

338 lines (222 loc) · 15 KB

OpenRA-Bot 结构与实验有效性审查

日期:2026-07-13 范围:当前工作区中的 Python 训练链路、OpenRA 桥接、训练日志与路线图 原则:先保证实验定义、配置和指标可信,再扩大模型或迁移桥接协议


Correctness-gate implementation status (2026-07-13)

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 Done completion 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.

1. 结论

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。


2. P0:实验 plumbing 与 teacher 定义

2.1 当前 Teacher-KL 不是完整 BC teacher

当前流程是:

  1. BC 模型保存到 warmstart_pretrain.pth。
  2. student 根据 load_bc_action_head 选择性加载权重。
  3. 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,没有与采样时的合法动作分布对齐。

2.2 修复要求

  • 独立构建并加载完整 BC teacher,不从 student 复制。
  • teacher 与 student 架构完全一致,策略关键参数必须严格加载。
  • teacher/student KL 使用相同的 action_type mask。
  • KL 只在真正的 decision step 上计算。
  • 如果保留当前 snapshot regularization,应明确命名为 initial_policy_kl,不要称为 teacher-KL。

验收:训练启动时记录 teacher checkpoint hash,并验证 teacher action head 与 BC checkpoint 完全一致。

2.3 多环境没有继承完整配置

scripts/train_rl.py 创建 EnvFactory 时没有传递至少以下参数:

  • goal_conditioning
  • goal_aligned_weight
  • add_opponent
  • bot_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,由主进程做一致性断言。


3. P0:Reward 与事件统计正确性

3.1 Goal reward 反复奖励绝对进度

当前 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 权重变化的评估指标。

3.2 正常生产完成被计为取消

_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 返回生产及订单执行事件。

3.3 Asset reward 不是净资产增长

当前 tracker 奖励所有新出现的己方 actor,但不扣除己方损失或出售,因此它衡量的是 gross production,而不是 net worth growth。加入对手后,这会鼓励高损耗补产而不直接惩罚战损。

应根据用途选择并准确命名:

  • gross_production_value
  • net_asset_delta
  • army_value_alive
  • trade_efficiency = enemy_loss_value - own_loss_value

建筑折扣也应按新 actor 类型逐项计算,不能用“本步是否新建 proc/powr”去缩放本步所有新增资产。

3.4 Combat/terminal 尚未形成闭环

  • 环境当前始终返回 terminated=False。
  • enemy 因 fog 离开可见范围时,可能被 kill tracker 误判为死亡。
  • macro action 只有生产,没有主动进攻、侦察、撤退或防守动作。
  • Python 默认 bot type 为 rulebased,但 RA 内置类型是 rush/normal/turtle/naval。

在这些问题解决前,--add-opponent 不能被视为完整对战训练。


4. P0:PPO 与 critic 实现

4.1 Multi-value heads 不是死代码,而是错误地处于激活状态

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。

4.2 truncated 被当成真正 terminal

训练把 terminated or truncated 合并成 done,并在 GAE 中把后续 value 设为零。当前绝大多数 episode 是时间截断而非自然终局,这会给 critic 带来系统性负偏差。

修复:分别存储 terminated 和 truncated;时间截断使用 terminal observation 的 value 做 bootstrap,真正胜负/灭亡才切断 return。

4.3 Per-env advantage normalization 不应默认视为修复

标准 PPO 通常在整个 rollout batch 上归一化 advantage。按 worker 单独归一化会消除 worker 之间有意义的回报差异,尤其当每个 worker 只覆盖一条或少量轨迹时。

建议恢复 global normalization 为默认,把 per-env normalization 作为有明确对照的消融项。


5. P1:动作与模型架构收口

5.1 Macro mode 应使用真正的 Discrete policy

当前 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 的设计空间。

5.2 Encoder freezing 不是当前 P0

历史上曾用 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

5.3 Mean pooling 的真实限制

SimpleEntityEncoder 的 mean pooling 对顺序不敏感,这是 set encoder 的合理属性;问题在于它不能显式建模实体关系,并可能丢失 cardinality。

Count-aware scalar 是有价值的全局统计,不应在启用 Transformer 后立即删除。后续建议按成本递增比较:

  1. mean pooling + explicit counts(当前基线)
  2. DeepSets:sum/mean/max 多池化
  3. learned attention pooling
  4. Entity Transformer + pooling

Transformer 当前只存在于 PLAN 的设计伪代码中,仓库尚无可启用实现。实体是无序集合,不应直接给 actor slot 加普通序列 positional encoding;可以使用坐标、owner、type embedding 和关系 bias。


6. P1:评估与复现体系

当前 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。


7. P2:Bridge 与工程组织

7.1 先优化状态提取,不先迁移协议

当前瓶颈来自 C# 每次调用重建状态、重复反射、扫描 actor/resource 和计算 placement,而不是 pythonnet 函数调用本身。

短期优先级:

  1. 为 GetState()、placement、mask、IPC 分段计时。
  2. 缓存稳定的 Type/MethodInfo/FieldInfo。
  3. 只在有 Done building 时计算对应 placement cells。
  4. 缓存静态地图/资源信息,或返回 delta。
  5. 批量 feasibility check。
  6. 合并 SendActions + Step + GetState 的调用边界。

7.2 建立唯一 source of truth

当前 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 错误。

7.3 代码拆分

建议逐步拆分,而不是先进行大规模目录迁移:

  • envs/rewards.py:reward state 与 components
  • envs/action_spaces.py:macro/full action 与 masks
  • agent/ppo.py:PPO trainer
  • agent/rule_based.py:teacher
  • bridge/:统一 EngineBridge 接口与实现
  • evaluation/:独立模型评估

先增加测试,再移动文件,避免重构期间无法区分行为变化和路径错误。


8. 修订后的执行路线

阶段 A:Correctness(最高优先级)

  • 修复真实 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。

阶段 B:可信评估

  • 固定 seeds 和 evaluation protocol。
  • 使用 invariant metrics 选择 best checkpoint。
  • 重跑旧结论对应的最小消融,不直接开始长跑。

建议矩阵:

  1. BC init + PPO,无 KL
  2. current initial-policy KL
  3. true BC teacher-KL
  4. goal observation only
  5. goal + potential shaping
  6. single env vs 4 env(相同 transition budget)
  7. global vs per-env advantage normalization

阶段 C:对战闭环

  • 合法的固定弱 bot。
  • game outcome 与 win/loss reward。
  • attack_move / defend / scout / retreat / rally 等 macro actions。
  • 先验证能稳定击败弱 bot,再进入 self-play。

阶段 D:模型与吞吐升级

  • DeepSets/attention/Transformer 消融。
  • profile 驱动的 bridge 优化。
  • 只有当进程隔离、远程部署或大规模并行成为实际瓶颈时,再启动 gRPC ADR 和原型。

9. 验收门槛

在继续 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 上更高。

完成这些门槛后,模型扩容和算法迁移才有可靠的实验基础。