大模型下的深度强化学习的多智能体渗透测试(11)
PenGym 单智能体 izumi 当日进展报告:success distillation 压出 tiny-small deterministic 成功策略,并迁移到 tiny-hard BC solved 基线
一、这篇文章要说明什么
上一篇记录结束时,项目已经推进到一个新的关键位置:
- 当前主线已经固定为
646/192,即obs_dim=646、action_dim=192; - unified demo dataset 与 BC 训练链路已经打通;
- BC 到 MaskablePPO 的 warm-start 工程链路已经打通;
tiny-small的问题已经从“接口不通 / 数据不足”推进到更具体的策略提取问题;- 修复 repeat guard 后,stochastic policy 已经能偶尔成功,但 deterministic argmax 仍然不稳定;
- 继续普通 PPO 训练、继续简单 root bonus、继续无控制采样都没有形成稳定 deterministic 成功策略。
本阶段的核心目标不再是继续盲目堆训练步数,而是做一件更聚焦的事:
把 stochastic 已经走出来的成功轨迹蒸馏回 BC,使 deterministic policy 稳定复现成功路径。
今天的真实结果可以概括为八点:
- 已完成
tiny-small的 low-cost stochastic success trace collection,收集到 2 条真实成功轨迹。 - 已将 stochastic success traces 合并进 multidemo dataset,形成 successdistill dataset。
- 已训练出
tiny-smallsuccessdistill BC checkpoint,并在 deterministic eval 下达到10/10成功。 - 已确认普通 PPO warm-start 会破坏 BC actor,使策略从
10/10退化到0/10。 - 已新增 actor-freeze / value-only PPO 路线,并解决 SB3 optimizer state 参数组不一致的加载问题。
- 已验证 actor-freeze PPO 在
tiny-small上 deterministic 达到10/10,并把平均步数从 BC 的 16 步进一步压到 12 步。 - 已将同一套 unified demo + BC 路线迁移到
tiny-hard,构造出第一个 tiny-hard unified dataset。 - 已训练并验证
tiny-hardBC deterministic 达到10/10,说明tiny-hard也已获得可复现的 BC solved baseline。
因此,本阶段的最重要结论是:
tiny-small已经不再只是 stochastic 偶发成功,而是通过 success distillation 压成了 deterministic 成功策略;并且 actor-freeze PPO 可以在不破坏 BC actor 的前提下保留甚至优化这条策略。与此同时,tiny-hard也已经通过最小 expert demo + BC 训练达到 deterministic10/10成功。
二、为什么不继续普通 PPO,而是转向 success distillation
在本阶段开始时,tiny-small 的核心现象已经很明确:
- guard bug 修复后,
e_http@(3,1)已经可以执行; - 50k 与 100k 训练都能看到 stochastic 成功;
- 但 deterministic argmax 长期无法稳定选择正确动作;
- 特别是在
(4,0)附近,策略会在e_ssh与e_ftp之间产生错误偏好。
100k 的 logit 诊断进一步说明:
1 | 50k: e_ftp - e_ssh = -1.78 |
也就是说,继续训练不但没有把 e_ftp@(4,0) 拉成 argmax,反而让 e_ssh 的优势更强。
随后尝试了 root transition bonus,希望通过更强的 ROOT 奖励把 e_ftp@(4,0) 拉起来。但 rootbonus_20k 训练中出现了一个关键现象:
1 | ROOT_BONUS never fired |
这说明奖励虽然实现了,但策略在训练过程中并没有稳定走到能触发该奖励的位置。因此继续调 root bonus 并不是低成本优先解。
于是本阶段转向了更直接的办法:
1 | stochastic success rollout |
这条路线的核心判断是:
既然 stochastic policy 已经能走出成功路径,就不要继续让 PPO 随机漂移,而是直接把成功轨迹蒸馏成监督数据,强行让 deterministic policy 学会这些状态下的正确动作。
三、低成本收集 tiny-small stochastic 成功轨迹
为了避免此前 Claude 长时间后台采集导致成本失控,本阶段把采集目标改成低成本版本:
1 | target_successes = 2 |
最终使用模型:
1 | prototype/models/maskable_ppo_tiny_small_bc_multidemo_guardfix_rootbonus_20k.zip |
收集结果为:
1 | n_episodes_run = 9 |
输出数据集:
1 | prototype/models/tiny_small_stochastic_success_traces.npz |
两条成功轨迹都包含关键动作:
1 | e_ftp@(4,0) |
其中一条典型成功轨迹为:
1 | service_scan@(1,0) |
这一步非常关键,因为它证明:
成功路径不是人工幻想出来的,而是当前 policy 在真实 stochastic rollout 中实际走出来的成功 episode。
四、合并 successdistill dataset 并训练 tiny-small BC
随后将原有 multidemo dataset 与 stochastic success traces 合并。
原始 multidemo dataset:
1 | prototype/models/demo_tiny_small_unified_multidemo_dataset.npz |
新增 stochastic success traces:
1 | prototype/models/tiny_small_stochastic_success_traces.npz |
合并后 successdistill dataset:
1 | prototype/models/demo_tiny_small_unified_successdistill_dataset.npz |
随后训练 successdistill BC:
1 | prototype/models/bc_unified_tiny_small_successdistill_300e.pt |
训练结果:
1 | obs shape = (113, 646) |
这里 acc 没有达到 1.0,但这不是坏事。原因是 successdistill dataset 中包含多条不同轨迹和不同状态分支,不再是单轨迹重复记忆。
真正关键的是 deterministic rollout 结果。
五、tiny-small successdistill BC 达到 deterministic 10/10
使用 eval_bc_unified.py 对 successdistill BC checkpoint 做 deterministic eval,结果为:
1 | Aggregate: |
稳定复现的 16 步成功路径为:
1 | service_scan@(1,0) |
这一步是本阶段第一个真正的成功里程碑:
tiny-small已经可以被 successdistill BC deterministic 稳定解决。
对应 checkpoint:
1 | prototype/models/bc_unified_tiny_small_successdistill_300e.pt |
建议固化副本:
1 | prototype/models/bc_unified_tiny_small_successdistill_SOLVED_10of10.pt |
六、普通 PPO warm-start 会破坏 BC actor
在 BC deterministic 10/10 后,尝试将该 BC checkpoint 接回普通 MaskablePPO warm-start。
训练命令使用:
1 | BC_CHECKPOINT=prototype/models/bc_unified_tiny_small_successdistill_300e.pt |
训练本身可以完成,日志中也显示:
1 | entropy_loss: around -2.02 -> -1.53 |
但 deterministic eval 结果严重退化:
1 | PPO deterministic: |
典型失败轨迹表现为:
1 | os_scan@(1,0) |
这说明普通 PPO fine-tune 把 BC actor 中已经学到的成功路径冲坏了。
因此,本阶段明确得到一个结论:
successdistill BC 已经解决
tiny-small,但普通 PPO actor 更新会破坏它,不能继续使用无约束 PPO warm-start。
七、actor-freeze / value-only PPO 路线打通
为了解决“PPO 破坏 BC actor”的问题,本阶段新增了 actor-freeze PPO 路线。
新增脚本:
1 | prototype/rl/train_maskable_ppo_tiny_small_bc_actorfreeze.py |
核心思路是:
- 加载 successdistill BC checkpoint;
- 将 BC actor/action 权重迁移到 MaskablePPO;
- 冻结 actor / policy_net / action_net;
- 只训练 value branch;
- 避免 PPO 在早期直接破坏已成功的 BC policy。
训练结果显示:
1 | approx_kl ≈ 2e-08 |
这说明 actor 基本没有被改动,主要是 value branch 在更新。
中途还遇到一个 SB3 optimizer state 问题:
1 | ValueError: loaded state dict contains a parameter group that doesn't match the size of optimizer's group |
原因是 actor-freeze 训练时 optimizer 只包含 value branch 参数,而 SB3 load 时会重建完整 PPO optimizer,导致 parameter group size mismatch。
后续修复方式为:
- 保存前重建 optimizer,使其覆盖全部 policy 参数;
- eval 加载时加入 fallback,必要时丢弃
policy.optimizer并恢复 policy 权重。
修改文件:
1 | prototype/rl/train_maskable_ppo_tiny_small_bc_actorfreeze.py |
八、actor-freeze PPO 在 tiny-small 上达到 10/10,并压到 12 步
使用 actor-freeze PPO 模型:
1 | prototype/models/maskable_ppo_tiny_small_successdistill_actorfreeze_20k.zip |
deterministic eval 结果为:
1 | Aggregate: |
相比 BC baseline:
1 | BC successdistill: |
这说明 actor-freeze / value-only PPO 不仅保住了 BC policy,还压出了更短路径。
典型 12 步轨迹为:
1 | os_scan@(1,0) |
stochastic eval 结果为:
1 | success_rate = 6/10 = 60.0% |
当前目标是 deterministic solved,因此 stochastic 结果只作为参考。
本阶段第二个关键结论是:
普通 PPO 会破坏 BC actor,但 actor-freeze / value-only PPO 可以把 BC actor 安全封装进 PPO,并进一步压缩成功路径。
建议固化模型:
1 | prototype/models/maskable_ppo_tiny_small_successdistill_actorfreeze_SOLVED_10of10_12steps.zip |
九、迁移到 tiny-hard:先做最小 unified demo + BC
在 tiny-small 已经获得两个 solved baseline 后,继续把同样路线迁移到 tiny-hard。
本阶段没有直接跑 PPO,也没有直接采集 stochastic success,而是先做最小闭环:
1 | tiny-hard demo JSON |
首先新增 tiny-hard demo:
1 | prototype/models/demo_tiny_hard_candidate.json |
动作路径为:
1 | host1-0: |
实际构建 dataset 时观察到一个细节:
1 | PrivilegeEscalation_Tomcat@(1,0) failed |
但整条 episode 仍然成功完成,最终通过 e_ftp@(3,0) 获得 ROOT。
构建结果:
1 | prototype/models/demo_tiny_hard_unified_dataset.npz |
inspect 结果:
1 | observations shape : (15, 646) |
这里曾经因为 --out 参数传了 .npz,builder 又自动追加 .npz,导致文件名变成:
1 | demo_tiny_hard_unified_dataset.npz.npz |
后续已改名整理为:
1 | demo_tiny_hard_unified_dataset.npz |
十、tiny-hard BC 训练与 deterministic eval 成功
使用 tiny-hard unified dataset 训练 BC:
1 | prototype/models/bc_unified_tiny_hard_candidate_300e.pt |
训练结果:
1 | obs shape = (15, 646) |
随后做 deterministic eval,最开始 eval_bc_unified.py 仍然输出 tiny-small 专用字段:
1 | reached_(4,0) |
这对 tiny-hard 没意义,因为 tiny-hard 的目标是:
1 | (3,0), e_ftp@(3,0) |
因此对 eval_bc_unified.py 做了最小修改:
- 当
--scenario包含tiny-hard时,target host 自动设为(3,0); - 其他场景仍保留原先
(4,0)统计; - 不改变模型加载、wrapper 或评估逻辑。
修改后 tiny-hard BC deterministic eval 结果为:
1 | Aggregate: |
这说明:
tiny-hard也已经通过最小 expert demo + BC 路线得到 deterministic solved baseline。
建议固化模型:
1 | prototype/models/bc_unified_tiny_hard_SOLVED_10of10_15steps.pt |
十一、当前模型与数据资产整理
截至本阶段,关键资产如下。
1. tiny-small 数据集
1 | prototype/models/demo_tiny_small_unified_multidemo_dataset.npz |
2. tiny-small BC baseline
1 | prototype/models/bc_unified_tiny_small_successdistill_300e.pt |
建议固化:
1 | prototype/models/bc_unified_tiny_small_successdistill_SOLVED_10of10.pt |
结果:
1 | success_rate = 10/10 |
3. tiny-small actor-freeze PPO baseline
1 | prototype/models/maskable_ppo_tiny_small_successdistill_actorfreeze_20k.zip |
建议固化:
1 | prototype/models/maskable_ppo_tiny_small_successdistill_actorfreeze_SOLVED_10of10_12steps.zip |
结果:
1 | success_rate = 10/10 |
4. tiny-hard 数据集
1 | prototype/models/demo_tiny_hard_candidate.json |
5. tiny-hard BC baseline
1 | prototype/models/bc_unified_tiny_hard_candidate_300e.pt |
建议固化:
1 | prototype/models/bc_unified_tiny_hard_SOLVED_10of10_15steps.pt |
结果:
1 | success_rate = 10/10 |
十二、当前阶段的关键技术结论
1. success distillation 是 tiny-small 的有效解法
普通 PPO 继续训练没有把 stochastic success 压成 deterministic success。
相反,低成本收集真实 stochastic 成功轨迹,再蒸馏进 BC,直接得到 deterministic 10/10。
这说明在当前问题上:
1 | successful trajectory distillation > blind PPO fine-tuning |
2. 普通 PPO 会破坏已成功的 BC actor
即使 BC deterministic 已经 10/10,普通 PPO warm-start 20k 仍然把策略冲坏到 0/10。
原因不是 BC 不会,而是 PPO actor update 在当前 reward/mask/trajectory distribution 下会让策略偏离成功路径。
3. actor-freeze / value-only 是当前更安全的 PPO 接法
actor-freeze PPO 的结果说明:
- actor 保持 BC 成功策略;
- value branch 可以继续学习;
- deterministic 成功率不下降;
- 路径还能从 16 步压到 12 步。
因此后续如果要把 BC 接回 PPO,应优先考虑:
1 | actor freeze |
不应继续直接 PPO 更新 actor。
4. tiny-hard 并不是不可解,只是此前纯 DRL adaptation 没打出来
此前 tiny-hard 在 20k adaptation 下失败,但现在通过最小 expert demo + BC 训练已经 deterministic 10/10。
这说明 tiny-hard 的核心难点并不是环境不可达,而是当前纯 PPO adaptation 在有限步数与有限探索下未能稳定找到正确路径。
5. 当前主线仍应保持 646/192
本阶段所有成功结果都建立在:
1 | obs_dim = 646 |
因此短期内不要切回 1368/420,否则所有 dataset、BC checkpoint、PPO checkpoint 都需要重新对齐。
十三、当前不应该继续做什么
当前阶段不建议继续:
- 继续普通 PPO warm-start;
- 对
tiny-small继续无约束 50k / 100k / 200k 训练; - 继续重复采集大量 stochastic traces;
- 继续调 root bonus 作为主修复线;
- 在
tiny-small已 solved 后继续微调同一个场景; - 切换到
1368/420v2 主线; - 上 Transformer 或完整 DAgger;
- 让 Claude 执行长时间训练或后台轮询。
尤其要避免再次出现:
1 | 收 10 条成功轨迹 / max 100 episodes / 后台轮询 |
这种高成本、低可控的任务模式。
十四、下一阶段建议
下一阶段应分成两条低风险线。
1. 固化 solved baselines
先把当前已经成功的模型复制成明确命名:
1 | cp prototype/models/bc_unified_tiny_small_successdistill_300e.pt \ |
这些文件应该作为当前阶段的可复现实验资产保留。
2. 继续推进 tiny-hard actor-freeze PPO,但不要普通 PPO
tiny-hard 现在已经有 BC solved baseline,下一步可以仿照 tiny-small:
1 | tiny-hard BC solved |
但必须遵守:
- 不直接普通 PPO 更新 actor;
- 先 actor-freeze / value-only;
- eval 成功后再考虑小步解冻;
- 如果 actor-freeze 退化,先查 wrapper 和 freeze,不继续训练。
3. 后续再考虑跨 tiny-family 的策略抽象
当前 tiny-small 与 tiny-hard 都已经能通过 BC solved。后续更有价值的问题不是继续单点调参,而是研究:
- 是否能从
tiny-small的 successdistill 数据迁移到tiny-hard; - 是否能统一 tiny family 的 demo schema;
- 是否能让一个 BC / PPO policy 覆盖多个 tiny scenarios;
- 是否能结合 LLM 做高层任务分解,而不是底层 step-level override。
十五、今天最终阶段结论
本阶段的核心突破是:
tiny-small已经从 stochastic 偶发成功推进到 deterministic solved,并进一步通过 actor-freeze PPO 得到更短路径;tiny-hard也已经通过最小 unified demo + BC 达到 deterministic solved。
当前最重要的两个结果是:
1 | tiny-small actor-freeze PPO: |
这说明当前 646/192 unified cross-family 主线已经不仅能跑通 medium/small/tiny 的接口,也已经开始能通过 imitation + safe PPO warmup 解决原本纯 PPO adaptation 失败的 tiny-family 难点。
下一阶段应停止在已 solved 的 tiny-small 上继续消耗训练预算,转而把 actor-freeze PPO 安全迁移到 tiny-hard,并逐步研究 tiny family 内的统一策略与高层规划问题。
