训练对抗性智能体的同学,大概率都撞上过这样一堵墙:最新一版策略在内部对练里胜率已经压倒性领先,可一旦丢给一个没见过的新打法,立刻被打回原形。更迷惑的是,如果让智能体只跟自己的当前版本对打,它常常不是越练越强,而是在两三种打法之间反复横跳,怎么都跳不出来。ICML 2019 上有一篇论文,专门盯着这类现象做文章,标题是《Open-ended Learning in Symmetric Zero-sum Games》,翻译过来就是"对称零和博弈中的开放式学习"。
论文的观点非常直接:在对称零和博弈里,如果把训练目标定成"击败当前对手",算法再先进也迟早走进死胡同;可持续的学习应该把目标从"赢过对手"换成"不断发现新策略",让训练过程本身永远不终结。这个想法听起来有点哲学,但论文确实给出了完整的数学框架、算法设计和实验验证。我会从动机、方法、实验到复现,一层层拆开讲。如果你在做多智能体强化学习、对抗训练或者博弈论相关方向,这篇内容应该能帮你省下不少自己啃论文的时间。
1. 从"转圈不进步"说起:对抗任务为什么需要开放学习
1.1 目标函数会漂移的任务,不能按常规套路训
传统强化学习是目标驱动的。走迷宫、抓取物体、控制机械臂,这些任务的奖励函数是固定的,智能体把数值优化到顶就算完工。但对抗性任务不一样:你的对手也在改变,于是"最优策略"的定义随时在漂移。拿最简单的石头剪刀布来说,面对一个爱出石头的人,出布就是最优;面对一个爱出布的人,同样的动作马上变成送分。固定目标、固定策略的评价体系在对抗场景里天然失效。
1.2 开放学习在等一个干净的实验场
"开放学习"这个概念,说的是智能体不在某个固定任务上终止,而是在一个足够丰富的技能空间里持续发现新的行为模式。它不算新词,几十年前就有类似提法,但长期缺少一个能把话说清楚的实验载体。对抗任务天生适合开放学习,因为对手是不确定性的来源,如果对手足够多样,你的学习就永远有下一站。但一上来就研究真实对抗游戏,又很难分辨观察到的现象到底来自算法本身的机制,还是来自具体环境的偶然性。
1.3 零和加对称,把问题削到最简
论文精妙的地方是选了一个最小模型:对称零和博弈。零和意味着双方收益相加为零,我赢你就输;对称意味着两个玩家的策略空间和规则完全一致,不分先手后手、不分攻击防御。石头剪刀布、黑白棋这类游戏都可以近似放进来。模型足够简单,于是"开放式学习"能不能成立的疑问,就被逼到了一个可以严格定义、可以复现、可以做理论分析的最小环境里。如果连这么简单的环境都解释不了开放学习的机制,那复杂场景更没有底气扯什么开放性。
1.4 博弈论给开放学习提供的度量语言
博弈论在这里的价值不只是营造氛围,而是提供了一整套精确的度量工具。策略、收益、纳什均衡、可剥削度,每一个概念都能对应到一个可计算的指标。"发现新策略"可以定义为:找到了一个当前种群中不存在、且能至少击败某些旧策略的新行为。"学习永不停止"可以定义为:随着训练推进,策略种群的规模持续增长。没有这些度量化定义,开放学习就只能停留在口号层面。这也是这篇论文在方法论上立得住的重要原因。
2. 自我博弈的瓶颈:循环、遗忘与策略塌缩
2.1 自我博弈是个好起点,但不是终点
多智能体训练最常见的起步做法是自我博弈:让智能体与自己的当前版本或历史版本对战,用对抗结果更新策略。这个思路绕开了人工数据标注,并且在很多游戏场景里效果不错。它的底层逻辑是"对手越强,我也越强",但这句话只对了一半。另一个不能被忽视的机制是:对手在变强这件事本身,也会把你的策略往特定方向推,而这个方向可能是一个圆环。
2.2 一个最小反例:石头剪刀布上的策略循环
把石头剪刀布想成一个概率策略空间,每个策略是一个三元组(p石头, p剪刀, p布)。假设两个玩家都用梯度上升更新,当前对手如果偏石头,你会把概率压向布;布的概率上去了,对手下一轮就会把概率压向剪刀;你为了应对剪刀又去增大石头比例。结果就是策略向量在三角形里转圈,永远停不下来,学习曲线表现为胜率波浪式起伏。
收益函数可以写作期望形式:双方同时出拳,你的期望收益等于"你对石头他出剪刀的概率、你对剪刀他出布的概率、你对布他出石头的概率"这三项加起来,再减去对称的负项。对固定的对手分布 q 来说,这个函数是 p 的线性函数,所以梯度上升本质上就是在单纯形上朝着"最克制当前 q"的方向走。而 RPS 里三个纯策略的克制关系恰好首尾相连,于是轨迹绕圈。这是非传递性博弈的结构病,不是实现 bug。
2.3 遗忘比想象中严重:新版本可能正好被老版本克制
自我博弈只针对当前版本训练,策略一旦飘到新区域,旧技能迅速被冲掉。更微妙的坑是:因为有循环结构,新策略可能在某个环节克制了许多近期版本,而自己却被更早的某个策略压制。于是你保留的"最新版"只是一个链条上的局部节点,抵御不了从链条另一侧来的攻击。如果把所有历史版本都留着当对手池,又会出现新问题:学习器很容易同时去拟合一堆彼此矛盾的最优应对,最后学出个四不像。
2.4 策略塌缩:种群规模很大,成分却一模一样
如果训练目标太窄,吸引域会把学习器拉进一个很紧的局部区域。种群里看起来有几十个版本,行为分布却彼此高度重叠,一旦某个外部策略抓住了这个区域的软肋,整个种群会一起崩溃。我在复现时对这点体会最深:多样性在对抗训练里不是可选项,而是保命项。没有多样性压力的种群,本质上就是把一个失败策略复制了几十遍,只是换个标签骗自己。
3. 把目标从"赢"改成"前所未有":种群与多样性设计
3.1 让策略库自己生长
论文的解法核心非常朴素:放弃只维护一条"最强策略",而是维护一个策略种群。所有历史版本中,只要在对抗上有一技之长、行为上又有足够差异,就把它们留下来。训练学习器时,对手不再是自己的当前快照,而是从整个种群里构造的混合对手。这样一来,策略的每一步更新都必须面对多样的挑战,而不是在单一对手身上过拟合。
3.2 新颖度:怎么判断一个策略算"新"
光有种群还不够。如果学习器反复面对同样的对手分布,它很容易收敛到同一个最优应对,种群里最后都会长成亲戚。论文里强调了多样性信号的作用:定义一个行为距离函数,衡量两个策略在对局中的表现是否可区分。简单做法是把策略映射成行为特征向量,再算向量距离;也可以直接看收益矩阵的行差异。新颖度定义为新策略与种群中所有成员的最小距离。小于阈值的视为已知,大于阈值的才谈得上"发现"。
3.3 把"对抗"和"探索"放进同一个目标函数
训练目标是两部分的加权和:一部分是平均对抗收益,衡量策略能不能打;另一部分是新颖度奖励,衡量策略是不是前所未有。表达式可以写成 J(π) = E_μ[u(π, μ)] + λ · d_min(π, P)。这个式子的精妙之处在于,它把两个经常互相打架的诉求放进了一个统一的尺度。λ 很小,算法退化成普通的种群自博弈,照样循环;λ 太大,智能体会变成纯粹的行为探索者,谁都打不过。实验和实际调试里最耗时间的部分,往往就是找这个 λ。
3.4 为什么会"永远学不完":非传递性结构是关键
这样设计不等于开放式学习自动成立。真正的谜团是:种群为什么不会在某一天饱和?答案藏在非传递性策略结构里。石头剪刀布之所以循环,是因为策略空间里永远存在"克制一部分旧策略、同时被另一部分旧策略克制"的区域。在非传递性空间的假设下,无论当前种群覆盖了多大面积,总有办法找到一个新策略——它能在某些对决中取得优势,又在另一些对决中落入劣势。于是新行为不断被采样出来,种群边界不断外扩。论文的理论贡献之一,就是把开放式学习能不能继续,和策略空间的拓扑与传递性结构直接挂钩。这层因果解释,比单纯堆实验数据要深刻得多。
4. 训练闭环怎么搭:主循环、种群管理与工程实现
4.1 主循环伪代码
把整个训练流程落到代码层面,其实框架比想象中简洁。下面是我复现时整理的核心伪代码:
# 种群 P 初始只含一个随机策略 p0 P = [p0] learner = p0 for step in range(MAX_STEPS): # 1. 从种群构造对手分布 opponents = sample_opponents(P, k=8) # 2. 与对手们对抗,用梯度法更新 learner for opp in opponents: batch = rollouts(learner, opp) learner = policy_gradient_update(batch) # 3. 周期性评估并决定是否入库 if step % EVAL_INTERVAL == 0: scores = evaluate(learner, P) novelty = min_distance(learner, P) if scores.mean() > WIN_THRESHOLD and novelty > NOVELTY_THRESHOLD: P.append(learner) prune_P() # 淘汰被支配且无新颖性的策略4.2 对手分布不能乱采
采样方式影响很大。如果均匀采样,学习器会把大量梯度花在处理最弱策略上;如果只采样最强的,又容易复现单一对手过拟合。我的经验是按能力加权采样,再保留一小部分均匀采样比例,保证偶尔能碰上冷门打法。论文里对应的设计一般是一个可调节的权重参数,默认按对抗胜率做 softmax 权重。这一步做得好,训练曲线会平滑很多。
4.3 种群管理:进和出都要有规则
策略入库的条件至少有两个:一是平均战绩达到阈值,保证它真的是"打得赢"的;二是新颖度超过阈值,保证它不是已有策略的微小变体。淘汰策略也不能只看支配关系——一个新策略支配了某个旧策略,不代表旧策略没有保留价值,它可能在其他方向上依然克制一大批行为。
淘汰准则应该综合"近期被新策略击败的频率"和"与周围策略的行为重复度"来定。这个设计直接决定了种群会不会无限膨胀,或者提前僵死。作者在论文里给的理论保证依赖于"种群中存在一条未被覆盖的策略链",所以淘汰逻辑做得太激进,理论前提就被自己破坏了。这也解释了为什么很多复现版本会失败:不是算法不对,是策略库管理砍得太粗暴。
4.4 工程实现上的几个注意点
评估开销是最大的工程瓶颈。种群里 50 个策略,learner 要与每个策略分别打多场,算下来相当可观。我的处理方式是把评估丢到并行 worker 上,每个 worker 专职负责一个对手对,最后汇总一个胜率矩阵。这套架构在小规模博弈里非常稳,扩展到大策略空间时,还需要配合优先级采样来降低评估频率。另外,行为距离的计算也要提前向量化,否则每次评估都卡在距离矩阵上,十几个策略就能把速度拖掉一个数量级。
5. 什么指标能证明学习真的"开放"起来了:实验设计与结果
5.1 实验环境:从三动作到带状态的扩展版本
论文用石头剪刀布做了一个自然的扩展:经典 RPS 只有三个纯策略,策略空间是二维单纯形,太小了。扩展版本引入了多个"状态",可以理解成从只猜一次拳,变成在一个小棋盘上做多回合对抗,这样策略空间变得复杂,非传递性结构也更深。选择这类环境的原因很明显:它跨在"简单到可分析"和"复杂到有研究价值"之间。
5.2 基线方法怎么选
对比对象一般包括三类:纯自我博弈、固定对手池训练、不加多样性奖励的种群训练。还有一个相对更强的基线是类似虚构自博弈的方法,用历史最优应对混合作为对手。复现时我把同一套评估指标套在每个基线上,这样比出来的结论才公平。基线之间真正的差异点是"有没有种群"和"有没有多样性信号"两个维度,只要控制住这两点,就能拆开每个组件各自的贡献。
5.3 看哪些指标
第一,种群规模和新增独特策略数:这是"开放性"最直接的证据。第二,策略间的平均行为距离:确认扩大的是真多样而不是复读机。第三,新策略对旧种群的平均胜率:确认新发现不是瞎逛。第四,可剥削度,衡量种群整体距离纳什均衡有多远,用于判断这些策略是否在均衡覆盖上有进步。另加一个泛化指标:对训练过程中从未见过的外部对手的平均胜率。
5.4 三类关键结果
结果可以归纳成三点。一是纯自我博弈在扩展 RPS 上出现预设的循环行为,胜率曲线像正弦波,策略没有实质增长。二是有多样性奖励但种群管理不好的方法,虽然策略数量多了,但多样性曲线很快饱和,对未知策略泛化一般。三是完整方法实现了种群规模持续增长,且新增策略在行为空间里分布越来越分散;可剥削度下降并保持在低位,说明它不是靠牺牲博弈强度来换多样性。对新对手的泛化胜率,完整方法显著高于所有基线。
| 方法 | 种群规模 | 平均行为距离 | 可剥削度 | 对新对手胜率 |
|---|---|---|---|---|
| 纯自我博弈 | 固定为1 | 无意义 | 高、波动大 | 偏低 |
| 固定对手池 | 固定为1 | 无意义 | 中 | 偏低 |
| 无多样性信号的种群训练 | 缓慢增长后饱和 | 低 | 中偏高 | 中 |
| 完整方法 | 持续增长 | 持续上升 | 低位稳定 | 高 |
这张表基本还原了论文的实验逻辑:开放性不是一步到位的,每一步设计都补上了一个缺口。
6. 复现中的坑与我的调试经验
6.1 多样性权重不是拍脑袋定的
我复现时先试了 λ=0.01,结果种群增长特别慢,经常插入失败,因为新颖度没过阈值;把 λ 加到 0.5,新颖度倒是轻松达标,可新策略战绩拉胯,入库后反而污染了整个种群。最后用的是退火方案:训练初期 λ 高一些,多鼓励探索;后期 λ 降下来,保证入库成员确实是"在赢的基础上更新"。这个方案我在多个随机种子下都验证过,稳定性明显更好。
6.2 淘汰策略不能手软,也不能手快
一开始我把"只要被超过一半新策略击败"当作淘汰标准,结果把种群清得很瘦,多样性断崖式下跌。原因是单维支配关系不能代表策略库的整体价值。后来改成双指标:先看行为距离,如果一个策略已经被周围策略大量覆盖、而且近期胜率又低,才淘汰。这样既控得住规模,又不会误伤有独特价值的边缘策略。这个改动让最终种群的稳健性提升非常明显。
6.3 评估全量比抽样靠谱
刚跑的时候为了省时间,我用了抽样评估,结果种群出现"老龄化":一些该入库的好策略被漏掉,成了漏网之鱼。后来改成全量矩阵评估,虽然慢了一点,但种群质量稳定多了。在小规模博弈上,全量评估的收益远大于多出来的那点时间。规模确实大起来之后,再考虑用抽样的置信区间去替代全量也不迟。
6.4 突然崩溃的诱因与应对
最头疼的现象是 learner 在某次评估时突然从强变弱。排查下来,发现是多样性和对抗收益的梯度方向冲突太剧烈,参数一次更新跨过了一个危险区域。我加了一个最低对抗胜率的入库门槛:无论新颖度多高,战绩不达标绝不入库;同时给 λ 做平滑调度,不让探索压力突然消失。处理之后训练曲线稳定非常多。这类崩溃不会每次都触发,但一旦触发就会拖慢整体实验进度,值得提前防住。
6.5 计算资源实在不够怎么办
如果机器只有一张卡,可以把策略网络做小,用简化版 RPS 环境先把整个闭环调通,再上大环境。不要一开始就追求大种群,20 个策略左右已经能暴露出大部分问题。整个框架没有硬性分布式要求,瓶颈主要在于评估环节,把评估并行化基本就够了。我见过不少人复现失败是因为一开始就上复杂环境,结果根本分不清是环境太复杂还是算法没调对。
7. 从博弈论到实际系统:开放式学习还能用在哪儿
7.1 自动构建鲁棒性测试集
把开放式学习当作一个"策略生成器",它能在无人监督的情况下生成覆盖各种打法的策略库。这些策略可以直接用来做鲁棒性测试:新模型在库上的综合表现,比在几个手写测试用例上的表现可靠得多。这个用法对安全评测、对抗鲁棒性测试尤其实用,相当于帮你自动化地补全了人工设计对抗样本时覆盖不到的边角。
7.2 多任务与课程学习的新思路
开放式学习的逻辑也可以迁移到多任务场景:把任务集本身当成一个博弈空间,"新任务发现"和"新策略发现"可以互相促进。我最近在探索的一个多任务框架就和这个思路一致——与其手写课程序列,不如让智能体自己在任务空间里冒出下一个技能需求。当然,任务空间里的"非传递性结构"不会像 RPS 这么明显,但这套思想至少提供了一种新的算法组织方式。
7.3 还没解决的问题
种群规模膨胀是现实问题。策略多了之后,评估复杂度平方级上涨,不加控制很难扩展到复杂游戏。另外,对称零和假设帮了很大忙,但现实对抗大多不对称,怎么在不对称设定下保留开放式的保证,目前研究还不充分。连续性也是个问题:对抗收益在参数空间里可能不连续,梯度更新偶尔会跳进行为完全不同的区域,这个不稳定源到现在也没有彻底解决。
7.4 我自己的体会
把这篇论文的代码跑通之后,我对"训练一个永远在线的对抗智能体"这件事的信心提高了很多。过去总以为收敛是最好的结果,现在知道在某些场景里,持续漂移才是一种健康状态。关键是要判断漂移是在探索还是在原地兜圈子,而多样性和非传递性结构恰好给了我们做判断的抓手。
我在实际做实验时最强烈的感受是:开放学习不是让算法变得更复杂,而是逼着我们重新想清楚"训练到底什么时候该结束"。之前不少项目都在为收敛目标服务,一旦换成开放式的评价眼光,很多旧结论都要重新验证。如果你也在做对抗方向的训练,强烈建议先用一个最小的石头剪刀布复现一遍循环现象,体会一下什么叫结构性的原地踏步,再上手种群方法。那之后的很多困惑,都会自动消失。