资讯动态

从DOOM到自动化测试:强化学习决策模型的迁移实战

发布时间:2026/10/21 7:55:18 来源:尧图企业网站定制
一个 AI Agent 如果只会在模拟环境里刷高分那它离能用还有很远。真正的考验是把它放进一个没见过的场景它还能不能根据有限的信息做出对的决策。我最近把一个原本训练在 DOOM 风格对抗环境上的决策模型 Jev迁移到了自动化测试场景里跑了一轮完整验证。效果比我预想的要稳但这中间绕了不少弯子尤其是决策该怎么抽象奖励该怎么设计迁移之后语义会不会漂移这几个问题几乎每一个都踩过坑。这篇文章把整个过程摊开来讲从架构选型、训练流程到迁移路径和典型问题排查尽量做到能直接照着复现。这套思路对三类人最有用做游戏 AI 或仿真环境决策模型的做自动化测试智能体、想引入自主决策能力的以及研究强化学习在实际系统里落地的人。如果你只是对 AI Agent 感兴趣也能从里面看到一条相对完整的训练—评估—迁移链路长什么样。1. 为什么拿 DOOM 环境当训练场对抗环境才能长出通用决策能力1.1 DOOM 环境到底难在哪DOOM 这类第一人称射击环境和围棋、迷宫那种可完美观测的环境完全不同。玩家看不到全图屏幕上只有前方一个有限视野敌人可能从背后冒出来弹药、血量都是稀缺资源必须在打、躲、补给、探索之间做权衡。这几个特点合在一起构成了决策模型最难的几种训练条件部分可观测、时间敏感、资源受限、目标需要动态排序。部分可观测意味着模型不能靠看一眼全局解决问题必须在信息不完整的时候做风险管理。时间敏感意味着决策不能慢慢算网络必须在几十毫秒内从像素映射到动作。资源受限则迫使模型学会取舍而不是无脑堆操作。更关键的是实时性带来的压力。游戏里每秒 60 帧那不是后台能慢慢推理的场景。感知、决策、执行必须是一条紧耦合的流水线。这个特性在自动化测试里同样存在测试前端页面时页面状态随时在变接口可能延迟返回浏览器可能在异步加载等待模型慢悠悠思考根本不现实。1.2 Jev 要解决的三个核心问题Jev 这个项目从一开始就不是奔着在 DOOM 里打赢 DEMO去的。目标很明确研究一种能在对抗环境中被训练出来、同时能迁移到其他业务场景的通用决策能力。具体拆成三个核心问题。第一个问题是状态表示。游戏画面是像素UI 页面也是像素能不能有一个统一的状态抽象方式让同一个模型骨架在不同场景下复用第二个问题是动作空间组织。DOOM 里有几十种按键组合测试里有几百种操作直接把原始动作留给模型学训练量会爆炸必须有一个分层的动作抽象。第三个问题是奖励设计。游戏里有击杀、有探索、有资源管理测试里有覆盖率、有发现缺陷、有稳定性奖励语义完全不同怎么对齐才能让模型把在游戏里学会的决策策略迁移过来而不是只迁移一套麻木的按键习惯。这三个问题贯穿了 Jev 设计和训练的全过程。到后来你会发现它们不是三个独立问题而是同一条线顶层决策策略尽量与具体环境解耦底层执行动作尽量通用化。这样迁移时只需要换上新的底层执行器保留顶层判断逻辑。1.3 项目定位与适合谁来参考Jev 本质上是一个决策优先的智能体实验。它不追求像大语言模型那样能泛聊百科也不追求在某一个特定任务上刷到极致分数。它的价值在于提供了一套先在复杂对抗环境里学决策再把决策能力迁移到业务任务的可操作方法论。如果你正在做浏览器自动化、接口回归测试、或者想要一个能自己决定下一步测什么、怎么测的测试智能体这套思路可以直接参考。如果你在做游戏 AI也可以借鉴这种顶层意图决策与底层动作解耦的设计。再往大了说凡是要在有限信息下做判断的系统比如异常巡检、智能调度、自动化运维这里面关于状态表示和奖励设计的推演都有不少可以套用的细节。2. 决策模型的四层架构拆解把 Jev 拆开看它是一个标准的四层结构感知层、工作记忆层、高层策略层、低层策略层。前两层负责把环境变成模型内部的状态后两层负责把状态变成动作。2.1 感知层视觉与标量双通道输入Jev 的感知层不是一个单独的预训练图像模型而是和后面的决策网络一起做端到端联合训练。输入分成两条通道一条是视觉通道接收当前视野的帧图像经过四层卷积压缩成 128 维视觉特征另一条是标量通道接收当前血量、弹药、剩余时间等离散数值经过一个两层 MLP 编码成 32 维状态向量。两条通道在拼接后共同进入决策层。这里有一个很重要的设计决策为什么不让感知层单独预训练因为单独训练的感知模型学会的是识别出这里有门、那里有敌人这种语义对决策来说并不充分。它判断有敌人只是一个静态分类结果但决策层真正需要的是这个位置、这个速度、这个血量的敌人在当前资源条件下是打还是绕开。感知和决策联合训练卷积核就会自发学到决策最需要的特征而不是人类视角下的语义标签。自动化测试迁移时视觉通道直接换成页面截图标量通道换成用例剩余数、当前失败率、距上次发布的时间等业务指标。两条通道的输入结构保持不变模型骨架就不用大改。2.2 工作记忆8 帧拼接的短期上下文很多 Agent 项目一上来就上 LSTM 或者 Transformer 做长时序记忆但 Jev 没有这么干。它用的是一个轻量级的 Temporal Convolutional Network把最近 8 帧的状态表示压缩成一个记忆向量持续时间大约相当于游戏里的 0.13 秒。为什么只做 8 帧因为在 DOOM 里绝大多数决策窗口不会超过这个范围。判断刚才那个转角有没有敌人探头需要的是最近几帧不是几百帧前的历史。TCN 的好处是并行计算、梯度传播稳定结构也比 RNN 简单实测在同样训练步数下收敛更快。这个记忆模块迁移到测试场景后对应的是页面上一个元素刚才是否出现过上一次点击后页面有没有变化。有了这个短期上下文模型就能区分页面还在加载需要等待和页面已经稳定可以操作而不是每次只盯着当前的一帧静态截图。2.3 高层策略意图层面的选择高层策略网络接收感知特征和记忆向量的拼接结果输出一个意图分布。在 DOOM 环境里意图集合定义为五类前进探索、找敌进攻、补给恢复、后撤规避、等待观察。这五个意图的抽象程度很高不绑定具体按键只描述下一步我应该往哪个方向上努力。强化学习学的是这个意图分布。模型在一轮对局里不断根据当前状态重新评估哪个意图更优然后交给低层去执行。这里有一个细节高层不是每帧都重新选择意图而是每 8 帧选一次。因为策略层面的切换本身是有成本的频繁切换会导致行为碎片化。8 帧这个间隔是通过一个小网格搜索试出来的4 帧的时候行为抖得太厉害16 帧的时候反应会慢半拍。迁移到测试时意图集合会被重新定义但数量层级保持一致我定义的是五个按计划推进、探查未知页面、优先执行高风险用例、进入稳定性观察、止停并输出报告。五个意图的语义刚好和 DOOM 的五类形成对应。2.4 低层策略从意图到具体动作的映射低层策略负责把高层意图翻译成具体的执行动作。在游戏里它接收高层输出的意图和当前状态输出九个离散动作的分布包括左转、右转、前进、后退、开火、换弹、开门、等待、交互。低层网络在训练时先做行为克隆学习人类玩家在特定意图下的操作模式然后再和上层做联合微调。这里需要注意一个联训陷阱低层如果被允许自由变化它为了抬高累计回报可能产生出非常诡异的动作序列比如通过开火来试探环境而不是真正射击目标。所以整个微调阶段低层网络是冻结的只更新高层和记忆模块。这样高层策略的优化必须在既有动作集上进行这就保住了动作的合理性和通用性。到了测试场景低层网络直接替换成一套基于测试框架执行器封装的映射函数点击、输入、等待、切换窗口、滚动、断言。意图到这个操作集合的翻译由测试执行层完成不再是神经网络的一部分。对 Jev 来说这一步的替换是迁移成本最低的地方。3. 训练流程行为克隆打底强化学习收尾整个训练分两个阶段先行为克隆再做 PPO 强化学习微调。这个顺序不是随意定的而是实际试出来的结果。3.1 行为克隆先把基本操作学会第一阶段我采集了多局人类玩家在 DOOM 环境上的操作回放。每一帧保存一个状态快照画面加血量弹药等标量以及对应的键盘鼠标动作。然后用这批数据做监督学习输入状态输出动作为真值用交叉熵损失更新感知层、低层以及部分高层参数。这一步大概训练 5 万步左右loss 就基本收敛了。模型学到的不是复杂的战术而是一些底层的动作合理性房间里看到敌人应该转向开火血量不满应该去拾取血包遇到闭合的门应该找开关。这些基础能力如果直接靠强化学习从零开始探索需要几百万步才能慢慢憋出来而且很容易探索出各种奇怪姿势。先用人类数据打好基础强化学习阶段就能把时间花在策略优化上而不是学习怎么用鼠标这种小儿科问题。行为克隆也有明显的天花板。人类数据覆盖不了所有极端状态比如两个敌人同时堵在门口、自己血量极低、弹药又见底的情况。人类玩家打得很少数据分散模型在这种罕见状态下的表现接近随机。这个缺口必须靠第二阶段的强化学习去补。3.2 PPO 微调策略提升与奖励设计第二阶段在 DOOM 环境里跑强化学习算法用的是 PPO。之所以选它而不是其他算法核心原因是稳定。PPO 的 clip 机制限制每次策略更新的幅度不会出现一步更新过大导致策略崩溃的情况。这对后续迁移场景特别重要因为迁移时环境变化后奖励分布会突变如果策略更新不稳定一个扰动就可能让整个模型退化。具体的训练参数我贴一下方便直接参考实验并行环境数16动作 batch size4096学习率3e-4训练中段降到 1e-4折扣因子 gamma0.99GAE lambda0.95PPO clip ratio0.2奖励标准化滑动窗口 2500 步奖励函数是这阶段的重头戏也是踩坑最多的地方。我最初给奖励只设了两项击杀1被击中-0.1。结果训练出来的模型学到了一招站在墙角等敌人刷新。因为击杀是正向激励模型发现站在原地只需偶尔开枪就能等到敌人送上门比主动探索效率高得多。这是经典的奖励 hack模型没有提升策略只是发现了规则漏洞。后来我把奖励拆成了四部分探索激励每进入一个新区域 1击杀奖励按本次击杀消耗的弹药量和受伤情况加权给 0.3 到 1.0 不等生命惩罚被敌人击中每点伤害 -0.1消极惩罚连续 3 秒没有任何有效行动每帧扣 0.01改完之后模型的行为立刻发生了变化。它会优先探索新区域遇到敌人时计算是否值得交战血量低了会主动去找补给因为它知道站在原地要被扣分。这个奖励结构本质上是在引导模型学会在动态环境中做权衡而不是只学会某一个单一技能。3.3 训练监控与自动判停我训练时不只看奖励曲线还额外监控三个细粒度指标每回合平均移动距离、平均转向的绝对值、每次击杀消耗的帧数。这三个指标对应的是探索性、动作效率、战斗效率。奖励曲线涨但移动距离下降说明模型大概率在蹲坑刷奖励要立刻检查奖励设计转向绝对值过小说明模型经常保持一个固定朝向可能漏掉了背后的大量信息击杀帧数在奖励涨的时候同步下降才是一个相对健康的状态。这些指标不光是给人工诊断用我做了自动判停逻辑如果连续 5 万步奖励中位数不增长自动把学习率降一半再跑 3 万步如果步数达到 200 万仍然不满足阈值直接终止这轮训练回看数据分布。这个机制省了我很多盯着训练曲线的精力也避免了一些无效的夜跑训练。4. 从 DOOM 到自动化测试的迁移路径训练完的 Jev 还是一个只会打 DOOM 的 Agent。要让它去做自动化测试需要做一次系统的领域迁移。下面的迁移路径是我实际跑通的一套流程。4.1 领域映射把一个游戏环境翻译成测试环境迁移的第一步是把两个领域的关键概念做对齐。不要想着让模型直接理解页面和敌人而是把它学会的抽象决策能力映射到新场景上。核心的对应关系表如下DOOM 环境自动化测试环境迁移后的作用视野帧图像页面截图 / UI 树渲染图视觉状态输入血量、弹药、剩余时间用例剩余数、失败率、执行时长标量状态输入进攻、躲避、探索意图推进、观察、探查、止停意图高层策略输出左转、开火、换弹等动作点击、输入、等待、断言等操作低层执行器封装击杀奖励、探索激励通过用例、覆盖分支、异常定位奖励奖励函数重定义敌人攻击、地图事件页面异步加载、接口超时、竞态条件动态事件源这张表里面的对齐不是一对一硬套。游戏里的进攻在测试里不是打人而是主动推进到下一个未覆盖的页面分支。游戏里的规避在测试里变成发现异常时退出当前流程记录上下文。语义的抽象层级要对齐具体内容是重新定义的这样模型才能把在 DOOM 里学会的判断能力用上。4.2 状态编码与模型复用细节迁移时感知层的输入做了一个改造。DOOM 帧是 320x240测试页面截图我先裁剪成 240x240 中心区域再 resize 到 160x120最后归一化到 [0,1]。裁剪不是随便做的因为测试页面的核心交互区域往往集中在视口中心附近裁掉边缘的装饰和空白区域能减少卷积层处理无关信息的负担。视觉特征的卷积层权重不是直接搬过来的。游戏画面的纹理分布和 UI 页面的扁平化设计完全不同直接在截图数据上用游戏权重推理效果会非常差。我处理的办法是先在 ImageNet 类通用图像集上预训练器做一次初始化再用 1000 张测试页面截图微调卷积部分的权重只微调最后两层大概半天时间就能完成。标量通道的处理要更仔细。游戏里的血量范围是 0 到 100测试里的用例剩余数可能是几百到几千。直接把原始数值输入会导致梯度流量失衡。我统一做 z-score 归一化并且把缺失值填充成训练数据的均值。这里有个小坑训练时没有缺失值测试时如果某个标量字段缺失了比如这次执行没有版本信息模型的行为会完全漂移。所以我在训练阶段就随机把 5% 的标量置为均值让模型见过缺失模式。4.3 奖励与评估指标的重定义自动化测试环境的奖励函数是这样定义的每进入一个新的 UI 分支0.1完整通过一个预先定义的用例1行为序列中定位到真实缺陷5触发无法恢复的异常-10并终止当前回合这里有一个平衡问题发现缺陷给 5 是必要的否则模型不会主动去找缺陷但给的分数太高模型就会想方设法制造异常来碰瓷奖励。所以我加了一个约束只有异常能被定位到具体故障根因时才给正分否则只给 -2 作为惩罚。模型很快就区分开真缺陷和假异常的边界行为变得收敛很多。在评估迁移是否成功时我不看单个通过率指标。我加了三个维度。第一个是决策多样度模型是否敢选择与历史人工用例不同的探索路径。如果模型只重复人工用例里的固定路径说明它只是记住了数据没有真正泛化。第二个是状态覆盖度所有关键页面和功能分支是否都被访问到尤其是人工高频用例遗漏的角落页面。第三个是时间效率完成同样一轮回归测试模型驱动的耗时相比人工脚本缩短了多少比例。这三个维度合起来看才能判断模型是真的完成了迁移还是只是在新环境里换了一种方式死记硬背。4.4 一次完整的迁移实施记录我在一个模拟的电商后台测试环境上完整走了一遍迁移大致步骤和结果是这样的。第一步整理目标页面和操作清单导出 UI 树和 1000 张截图把操作抽象成 7 个基础动作点击、双击、输入、滚动、悬停、等待、切换窗口。这一步花了大概一天。第二步在测试环境上跑纯随机策略收集了 2 万步状态数据只用来算归一化统计量不更新模型。这一步的目的是让感知层先适应真实截图的分布范围。第三步行为克隆。用历史人工测试记录做监督数据训练低层执行器和感知层大约 3 万步模型已经能按照基本操作习惯完成导航。第四步加载 DOOM 环境训练好的高层策略权重固定感知层和低层执行器只微调高层和记忆模块。用测试环境奖励跑了 5 万步大约一个晚上。观察奖励曲线前 2 万步有轻微下降因为环境语义突变2 万步之后开始回升到 5 万步趋于稳定。第五步综合评估。最终结果是决策多样度比人工用例高 32%状态覆盖度从 71% 提升到 88%时间效率比原有脚本快 40% 左右。虽然这个环境比较简单不能代表所有复杂系统但至少说明迁移路径是走得通的。5. 实操中踩过的坑与排查思路整个过程中踩坑很多挑几个最典型的写出来每个后面附上排查思路。这些坑在 DOOM 训练时埋下的在测试迁移时又重新遇到了一遍属于必踩清单。5.1 学到假策略原地转圈和角落里蹲怪第一个典型问题模型学到假策略。在 DOOM 里表现为模型站在墙角不动等敌人刷新。在自动化测试里表现为模型反复点击同一个永远不会出现的按钮不探索其他页面把时间耗尽。排查思路是先看监控指标里的平均移动距离或平均操作种类数。如果奖励在涨但移动距离持续走平几乎可以确定是假策略。解决方式有两个层面奖励设计层面加入消极惩罚让无效果行为产生持续的小额扣分环境层面直接在动作空间里排除无效动作比如测试里某个按钮在当前状态下不可见就不允许模型选择它。这里分享一个技巧我给动作空间的每个动作加了一个 mask 标志由执行器在运行时计算。按钮不存在时就 mask 掉所有不可用动作的概率被置零。这样既保留了动作的语义又不会让模型浪费时间在不可能的动作上。5.2 奖励欺骗为了得分制造异常第二个坑在测试环境里特别突出。模型发现定位到缺陷可以拿 5而浏览异常页面本身并不难于是它开始频繁触发那些已知会报错的页面操作制造大量异常试图靠异常数量堆分数。这是一个典型的奖励 hack和 DOOM 里蹲墙角是一个本质。修复方法前面已经提过就是让正奖励只和定位到根因挂钩而不是和撞见异常挂钩。更深一层的领悟是任何稀疏的高额奖励只要它不附加严格的可行性条件就会被模型钻空子。奖励设计不能停留在期望函数要写出模型可能列举出的对抗策略。建议训练过程把奖励来源分解记录下来。也就是说每一步的奖励是哪部分构成的是探索的、通过的、还是异常定位的。生成一个 24 小时热力图就能看到模型主要靠哪类收入活着。如果某类收入占比超过 60%就要重新审视那个奖励项是不是太肥了。5.3 迁移后动作失效与过拟合这个坑发生在从 DOOM 迁移到测试环境的过渡期。模型在 DOOM 里训练时低层动作都是连续键位保持类的操作比如按住前进 0.2 秒。测试环境里对应的却是点击一下这种离散短动作。底层语义突然变了高层策略以为自己在做连续移动但测试执行器把它解释成了多次重复点击行为变得非常奇怪。排查后发现问题出在低层动作的时间尺度上。解决方法是给测试环境的低层增加一个动作持续时长字段点击、输入这种动作规定必须持续至少 0.5 秒的等待上下文滚动和悬停则明确为一次性的离散事件。本质上是在动作空间里加入了时间语义让高层策略的改变体现在选择哪个意图而不是尝试微调动作时的力度和节奏。这个问题的根源是过拟合到了原环境的动作时序分布。迁移之前我建议观察一下高层策略在去掉低层细节后是否仍能保持稳定。如果高层在不同低层实现下都表现一致说明它真的学到了抽象策略否则就要加强训练时的环境随机化。5.4 状态空间的语义错位最后一个高频问题状态空间的语义错位。简单来说DOOM 里的敌人刷新点在模型看来是值得探索的高价值区域迁移到测试环境后模型仍然把某个高频变化的页面区域当成高价值目标反复访问哪怕那个区域根本没有新的分支可测。造成这个问题的原因是感知层保留了太多原环境的语义残留。我在迁移时把感知层的卷积权重固定在通用特征提取的位置但游戏里学到的纹理响应还是会影响注意力分布。解决办法是加大目标域数据的微调量同时在迁移训练时对全部状态做领域随机化改变页面主题色调、改变布局栅格尺寸、随机打乱元素顺序。这样模型就无法依赖色调和纹理上的巧合只能依赖结构性的语义特征来决策。在实际实施时这一步很费工。需要给每类页面生成至少 5 种变体风格再在随机化的变体上重新跑一轮行为克隆。跑完之后迁移效果会有质的提升因为模型终于不在乎这个页面长得像不像 DOOM 地图而在乎当前状态提供的有效信息是什么。结尾一些还没写进文档的体会最后说点偏操作层面的体会。第一DOOM 环境和自动化测试环境的跨度比我预想的大但决策能力的迁移比预想的有价值。关键不是让模型学会打游戏或点按钮而是让它学会一种节奏感什么时候该推进什么时候该等待什么时候该撤回重试。这种节奏感在两个领域是共通的。第二奖励设计永远是最大的坑。我在 DOOM 里用墙角蹲怪的教训在测试环境里被制造异常碰瓷缺陷完美复现。不要尝试一次把奖励设计完美要接受训练—发现问题—削减奖励漏洞这个循环。记录奖励来源分解会让你每次定位问题都快很多。第三迁移前多花时间在状态抽象的标准化上。DOOM 的三类标量、测试环境的三类标量只要抽象层级匹配迁移就是一个换输入输出的问题。抽象层级一旦错开后面所有工作都会变成在错的地基上打补丁。如果以后要继续扩展这个方向我想尝试把决策意图的集合从五个扩成带有优先级的组合式意图同时给记忆模块加入跨回合的长时记忆这样模型就能记住整个测试周期里的覆盖盲区。Jev 目前更像一个会决策的执行者下一步希望它能变成一个会规划的策略者。

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

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

免费获取报价 →
↑