大模型下的深度强化学习的多智能体渗透测试(5)
PenGym 单智能体 izumi 当日进展报告:reward2 主线保留,reward3 未胜出,长训收益有限,研究重点正式转向泛化接口
一、这篇文章要说明什么
这份记录只描述今天真实完成的事情,不把尚未完成的泛化接口、LLM 接入、多智能体协作写成已经做完。
今天最重要的结果可以概括为六点:
- 已确认当前单智能体学习型
izumi的主 baseline 仍应保留为MaskablePPO + reward2 + base_200k。 - 已完成
reward3分支训练与评测,但当前结果并没有超过reward2,因此不作为主线。 - 已尝试在
base_200k基础上继续训练,但在当前单局 deterministic eval 口径下,没有观察到比200k更明显的提升,因此暂不继续把精力放在长训上。 - 已尝试直接做跨场景泛化评测,但发现现有实现并不具备直接跨场景 zero-shot 的条件,核心阻塞是 observation / action space 不统一。
- 已通过阅读
PenGymEnv、NASimEnv、Observation、HostVector等实现,定位出当前泛化问题并不在 PPO 算法本身,而在状态表示与动作空间的场景绑定。 - 已明确下一阶段的实际工程目标:先做 medium family 的 unified observation adapter,在不更换 PPO 的前提下,为后续泛化训练和测试打底。
二、今天的主线目标
今天原本围绕两个方向推进:
- 一条线是继续验证
reward2与reward3,确认 reward 设计是否还能带来收益。 - 另一条线是评估是否应该继续在
base_200k基础上做更长训练,或者把研究重点转向泛化。
经过今天的实际训练、评测与源码排查,结论已经比较清楚:
reward2 继续保留,reward3 先停;长训暂时降级;泛化正式上升为下一阶段主问题。
三、今天具体做了什么
1. 梳理并确认当前主 baseline
首先重新对齐了当前主线模型的实际状态:
- 当前已训练得到的主模型是
base_200k - 奖励主线是
reward2 - 当前 agent 仍然是基于
MaskablePPO的单智能体izumi
这一步的意义在于防止后续实验线继续混乱。因为如果 baseline 本身没有锁定,后续无论是 reward 改造、长训还是泛化,最后都会失去比较基准。
因此,今天先做的不是盲目继续训,而是先把“当前哪个是主版本”这件事说清楚:
主 baseline =
MaskablePPO + reward2 + base_200k
2. 完成 reward3 分支训练与评测
今天继续沿着“是否通过奖励函数设计提升渗透 agent 表现”这条线做了 reward3 分支。
reward3 的改动方向主要是:
- 更强调真实推进(例如新主机发现、权限提升)
- 更强调对无效扫描、无收益 exploit、显式错误的惩罚
- 试图减少策略在无意义动作上的循环
从工程上,reward3 分支已经跑通:
- 训练能正常启动
- 模型能正常保存
- 评测也能完整跑通
但真正关键的是结果,而不是“能跑”。
在当前单局评测口径下:
reward2:total_reward = 155.0,steps = 23reward3:total_reward = 153.0,steps = 25
这说明 reward3 并没有在当前评测下打赢 reward2。二者都成功完成任务,但 reward3:
- 总回报略低
- 步数略多
- 没有体现出明确的行为改善优势
所以,今天对 reward3 的结论不是“失败到完全不可用”,而是:
reward3 是一个有效实验分支,但目前不优于 reward2,不作为主线保留。
3. 验证长训收益,但未观察到明显增益
在确定 reward3 没有打赢之后,进一步尝试了继续长训的方向。
这里的核心问题并不是“训练有没有跑”,而是:
在当前评测口径下,继续训练后是否真的带来了更强表现。
实际结果是:
- 已完成从
base_200k继续训练的实验 - 产生了新的 continuation checkpoint
- 但在当前 deterministic 单局 eval 上,没有看到比
200kbaseline 更明显的改进
这说明一件事:
至少在当前评测方式下,继续堆训练步数没有立刻转化为可见的策略收益。
因此,今天没有再把时间继续压在“再训、更久地训”上,而是做了一个更重要的判断:
当前阶段真正的瓶颈很可能不是训练步数,而是表示空间与泛化条件本身。
4. 尝试直接做跨场景泛化,发现结构性阻塞
随后,开始把 attention 从 reward 和长训转向泛化。
最先尝试的是直接把当前 base_200k + reward2 拿去做跨场景 zero-shot evaluation。
第一组测试选的是与训练场景同属于 medium family 的:
medium-multi-site(训练主场景)medium-single-sitemedium
在对 medium-single-site 做直接评测时,立即触发了关键报错:
- 模型期望 observation shape 是
(476,) - 但新场景给出的 observation shape 是
(561,)
也就是说,问题不是“策略差”,而是:
当前模型根本没有资格直接跨场景推理,因为输入维度已经不匹配。
这一步非常关键,因为它把“泛化难题”从模糊的性能问题,变成了明确的工程与表示问题。
今天因此得出的一个重要科研结论是:
当前
izumi + MaskablePPO实现仍然依赖固定 observation/action space,不能直接支持不同 NASim/PenGym 场景之间的 zero-shot 迁移。
5. 系统排查 PenGym / NASim 源码,定位阻塞位置
为了搞清楚为什么一换场景 observation 就变,今天没有停留在“报错现象”,而是继续往实现里追。
排查路径包括:
pengym/envs/environment.pynasim/envs/environment.pynasim/envs/observation.pynasim/envs/host_vector.py
通过这一轮源码阅读,今天已经定位出几个关键事实。
(1)PenGymEnv 本身并不决定 observation shape
PenGymEnv 只是对 NASimEnv 做了一层包装,它真正做的主要是:
- 继承
NASimEnv - 初始化
PenGymNetwork - 初始化
PenGymState
说明 observation 的真正生成逻辑并不在这层薄包装里。
(2)NASimEnv 直接把 observation 变成固定长度 flatten 向量
NASimEnv 在初始化时:
- 先
reset()生成last_obs - 再用
last_obs.shape_flat()决定 observation space 的形状 - 在
step()/reset()时把 observation 通过numpy_flat()压平给 PPO
这说明当前 PPO 接收到的输入不是结构化对象,而是一个已经被 flatten 的固定长度向量。
(3)Observation 本质上是二维张量再 flatten
Observation 的结构是:
- 若干个 host row
- 最后一行 auxiliary row(success / permission_error / connection_error / undefined_error 等)
最后通过 flatten() 变成一维 observation。
这意味着不同场景 observation 长度变化的根源,来自:
- host row 数量
- 每个 host row 的宽度
(4)HostVector 说明了 host row 的组成规则
HostVector 给出了一台主机对应那一行 observation 的字段组成:
- subnet one-hot
- host address one-hot
- compromised / reachable / discovered / value / discovery_value / access
- os one-hot
- services one-hot
- processes one-hot
而每行宽度的公式也被明确写出来了:
#subnets + max_hosts_in_subnet + 6 + #OS + #services + #processes
所以当前 observation 的场景绑定问题,不是随机产生的,而是因为:
- 地址空间编码长度会随场景拓扑变化
- action space 也会随 scenario 变化
这一步带来的真正收获是:
当前泛化问题已经被定位到表示层,而不是 PPO 算法本身。
6. 确认 medium family 是第一阶段泛化改造的最佳目标
今天还进一步对 medium family 做了结构信息对比,打印了:
address_space_boundssubnetsosservicesprocesses
结果很重要:
medium-multi-sitemedium-single-sitemedium
这三个场景在:
osservicesprocesses
这三个部分上完全一致。
真正不同的是:
- subnet 数量
- host slot 数量
- 地址编码方式
这意味着第一阶段泛化改造可以不碰 small / tiny,先集中做 medium family。
这是今天最正向的发现之一。因为它说明:
至少在 medium family 内,做统一 observation 接口是有现实工程可行性的。
7. 明确了 medium-family unified observation adapter 的方向
在上面这些排查基础上,今天已经把下一阶段泛化接口的大方向初步定下来了。
medium family 的 unified observation schema,计划先按下面这个 canonical 结构来做:
- max subnet slots = 7
- max host slots per subnet = 16
- 标量字段 = 6
- os = 1
- services = 5
- processes = 3
对应每一行固定宽度:
7 + 16 + 6 + 1 + 5 + 3 = 38
再结合当前 medium family 的 observation row 结构,计划把第一版统一接口做成:
17 rows × 38 cols- flatten 后是
646维输入
这个设计意味着:
后续不需要先换 PPO,只需要先做统一 observation adapter,再在统一接口上重新训练 PPO。
这也就是明天继续推进时的起点。
四、今天做对了什么
今天最重要的正向进展,不是“又训练出一个更高分模型”,而是把问题看清了。
1. 没有在 reward3 上继续死磕
reward3 没赢就是没赢。今天没有为了“非要让 reward3 有价值”而继续硬凹,这一点是对的。
这让主线保持清楚:
- reward2 保留
- reward3 存档
- 不继续在错误方向上消耗时间
2. 没有继续盲目堆长训
在 200k continuation 没打出明显增益后,今天没有简单粗暴地继续加码训练步数,而是转向追问:
- 为什么长训没收益?
- 真正的瓶颈在哪?
最终发现真正阻塞泛化的是 observation/action 空间问题,这比继续长训更有价值。
3. 没停留在“报错现象”,而是追到源码层
今天最有科研价值的一点,是没有把
Unexpected observation shape
当成一个“换个参数也许就好了”的小问题,而是直接追到了:
- PenGymEnv
- NASimEnv
- Observation
- HostVector
这一步把泛化问题定位成了一个清晰的系统设计问题。
4. 已经把下一阶段的第一目标缩小到 medium family
今天没有试图一口气解决:
- medium
- small
- tiny
- 不同 action_n
- 不同 obs_shape
而是把问题缩小到最有希望先打通的 medium family。
这让明天开始的工作会更聚焦,也更容易产出阶段性结果。
五、今天的问题与不足
今天当然也有一些明确的问题,需要记下来。
1. 对“长训命名 / 训练步数语义”的表述一度混乱
今天在讨论 200k、400k、continuation 训练时,对“当前这次 learn 跑了多少步”和“checkpoint 所代表的总训练量”一度存在表述混乱。
虽然最后已经把事情说清,但这个问题说明:
后续实验命名、checkpoint 命名、日志解释必须统一,不然很容易把训练语义和实验结论搅乱。
2. 现在还没有真正开始泛化训练
今天只是把泛化问题定位清楚,并确定 medium-family adapter 的目标方向,
但还没有真正写出 unified observation wrapper,更没有在新接口上重新训练 PPO。
所以现在还不能说“已经做出泛化 agent”,只能说:
已经完成了泛化问题的结构定位与方案收敛。
3. 当前评测口径仍然比较单薄
今天关于 reward2 / reward3、200k / continuation 的判断,依然主要基于:
- deterministic
- 单局或极少量局数
- 当前已有 eval 脚本
这意味着后面即使进入统一接口训练后,也必须尽快补足更规范的多 episode、多 seed 评测方式。
六、今天停在哪
今天最终停在了一个比较清楚的位置:
- reward2 继续作为主 baseline
- reward3 归档为未胜出的实验分支
- 长训暂时不是研究重点
- 泛化正式成为下一阶段主线
- 泛化的第一阶段目标锁定为 medium family
- 下一步不是继续测,而是先做 unified observation adapter
也就是说,今天的暂停点不是“卡住不知道怎么做”,而是:
已经明确下一步该改哪一层,只是还没开始写 adapter 代码。
七、明天开始时的第一件事
明天继续时,不再回头重复 reward、长训、是否继续堆步数这些讨论,直接从这里接:
第一目标
实现一个 medium-family unified observation adapter wrapper。
它要解决的问题
把:
medium-multi-sitemedium-single-sitemedium
当前各自不同长度的 flatten observation,统一映射成固定的 646 维输入。
这样做的意义
一旦这层统一接口打通,后面就可以在不更换 PPO 的前提下,真正开始做:
- medium family 内部的泛化训练
- medium family 内部的 held-out 场景测试
这才是下一阶段最实在的工作。
八、今天的结论
今天没有拿到一个“分数暴涨”的新模型,但拿到了一条更重要的结论链:
- reward3 没有超过 reward2,因此主线继续保留 reward2;
- 继续长训在当前口径下没有打出明显提升,因此长训不是当前主问题;
- 真正限制 agent 跨场景迁移的不是 PPO 本身,而是 observation / action space 被场景绑定;
- medium family 具备先做统一 observation 接口的条件,因此泛化的第一阶段方向已经确定。
所以,今天的价值不在于“又多训了一轮”,而在于:
已经把研究主线从 reward/长训试错,推进到了“统一表示空间下的泛化训练”这个更核心的问题上。
这也是明天最应该继续做的地方。
