强化学习算法基准测试:6种算法在多智能体环境中的表现实测
强化学习作为机器学习领域的重要分支,通过智能体与环境的交互来学习最优决策策略。在单智能体环境中,智能体面临的是相对静态的环境动态,而多智能体环境则引入了更为复杂的交互机制和竞争关系,这为强化学习算法的设计和评估带来了全新的挑战。
现实世界中的许多决策问题涉及多个智能体的同时参与,如游戏对战、市场竞争和协作任务等。在这些场景中,每个智能体的行为不仅影响自身的收益,还会直接改变其他智能体所面临的环境动态。这种相互依赖关系使得传统的单智能体学习方法面临非平稳性、探索-利用权衡复杂化等新挑战。
本文构建了多智能体强化学习的系统性评估框架,选择井字棋和连珠四子这两个具有代表性的双人博弈游戏作为基准测试环境。通过引入模型动物园策略和自我对战机制,研究探索了各种表格方法在动态对抗环境中的学习能力和收敛特性。
实验结果揭示了表格方法在不同复杂度游戏中的显著性能差异:在状态空间相对较小的井字棋中,Q-learning和同策略蒙特卡洛方法表现优异;而在状态空间指数级增长的连珠四子游戏中,所有表格方法均未能产生有效策略。这一发现不仅验证了理论分析的正确性,更为后续转向函数逼近技术提供了强有力的实证支撑。
本文建立了多智能体强化学习的标准化评估流程,系统比较了各种表格方法在竞争环境中的性能表现,并通过实证分析明确了表格方法的适用边界,为深入理解强化学习算法的可扩展性问题提供了重要参考。
GridWorld环境下的算法实现与性能分析
本节将系统回顾所采用的强化学习方法,以及在单智能体游戏环境(特别是不同规模的GridWorld环境)中观察到的性能表现。
蒙特卡洛方法的原理与实现
蒙特卡洛方法作为无模型学习方法,通过采样完整回合来基于经验回报估计价值函数。这种方法在概念上具有简洁性和高度可解释性特征,动作评估完全基于实际执行结果。然而,该方法对回合终止的依赖性以及采样回报的高方差特性可能对学习效率产生负面影响。
研究中实现了同策略MC控制方法,该方法通过改进用于数据生成的策略(如ε-贪心策略)来优化性能。同时实现了异策略MC控制方法,该方法使用重要性采样技术纠正分布差异,从而学习与数据生成策略不同的贪心策略。
实验结果表明,同策略MC方法在GridWorld环境中表现出人意料的优异性能。这一现象可能归因于其简洁无偏的算法特性。此外,研究采用的中间奖励设计有效引导模型向目标状态收敛,从而缓解了MC方法仅收集稀疏奖励且需在完整回合后更新的固有局限性。
时序差分方法的理论基础与算法实现
时序差分方法通过基于自举机制的估计更新,在动态规划和蒙特卡洛方法之间建立了有效的桥梁。该方法通过结合观察奖励与估计的未来回报,实现从不完整回合中的学习。与蒙特卡洛方法的显著区别在于,TD方法在每个时间步后即可执行更新,从而具备更高的数据效率和在线学习适应性。
研究实现了四种关键的TD方法:Sarsa作为同策略方法,基于实际执行的动作进行价值更新;Q-learning作为异策略方法,利用下一状态中的贪心动作进行更新;Expected SARSA通过在当前策略下对所有可能后续动作进行期望计算来更新价值;Double Q-learning通过解耦动作选择与价值评估过程来有效缓解过估计问题。
基准测试结果显示,TD方法在选定任务中表现符合预期,其中Q-learning和Sarsa展现了相对优异的性能。然而,由于实验过程中涉及的方差因素,难以得出确定性的性能排序结论。
TD-n方法的扩展机制与性能分析
TD-n方法通过将多个未来时间步信息纳入更新过程,实现了对单步TD方法的有效扩展。这种机制在偏差与方差之间建立了灵活的权衡关系:增加步数能够捕获更长期的决策后果,但同时会引入更多的不确定性。
实验中采用了Sarsa-n方法,将传统Sarsa算法推广到n步回报计算。同时实现了n步树备份方法,这是一种更具通用性的异策略方法,通过备份期望值而非单一样本来进行价值更新。
实验结果显示,n步树备份方法实际上是所有测试方法中性能最优的。这一结果可能源于该方法成功结合了异策略方法的优势与同策略方法的稳定性特征。相比之下,Sarsa-n在所有方法中表现相对较差,这可能是由于在单次更新中结合多个时间步信息引入了额外的偏差和方差。
Dyna-Q的模型学习机制
规划方法通过构建环境模型来模拟经验并提升样本利用效率。Dyna-Q方法将无模型学习与基于模型的更新机制相结合:在每个真实交互步骤后,利用学习得到的状态转移和奖励模型执行多次模拟更新。
该方法的核心思想包括两个关键组件:从实际交互数据中学习环境的状态转移模型;利用学习得到的模型生成额外的学习更新步骤(规划阶段)。
基准测试结果表明,Dyna-Q的性能与经典TD方法基本持平。虽然理论上模型学习应当带来性能提升,但实验中未观察到显著改善,具体原因有待进一步分析。
多智能体强化学习问题的理论基础
多智能体强化学习问题与单智能体环境存在根本性差异,主要体现在其他智能体的存在引入了新的复杂性挑战。这类问题面临两个核心理论问题:其他智能体的控制机制设计,以及多智能体决策相互依赖情况下的学习机制构建。
针对第二个问题,常见的解决方案是从学习智能体的角度将所有其他智能体视为环境的组成部分。这种处理方式将学习设置简化为相对熟悉的单智能体框架。而第一个问题关于其他智能体的实际控制机制则提供了多种设计选择空间。
双智能体游戏的状态转移建模
考虑一个双人游戏场景,其中包含以下决策序列:玩家1(绿色)从初始状态s₀开始,执行动作a₀并获得奖励r₁;随后玩家2(蓝色)从状态s₁开始行动,执行动作a₁并获得奖励r₂。
这一场景的关键问题在于:玩家1无法在状态s₁中执行动作,且其初始获得的奖励r₁可能失去意义,特别是当玩家2的后续行动显著改变游戏结果时。因此,从玩家1的角度而言,真正重要的是从其位置观察到的r₂。例如,若r₂ = +1表示玩家2获胜,则玩家1的真实奖励应为-1,表示其失败状态。
为解决这一建模问题,研究从玩家1的视角将状态转移建模为:(s₀, a₀) → s₂,对应奖励为r = -r₂。在这种建模方式下,玩家2被视为环境的组成部分,其行为效应被整合到玩家1的状态转移和奖励动态机制中。
对手控制的模型策略
回到第一个核心问题:在训练特定智能体(如玩家1)的过程中,如何设计玩家2的控制机制?一种直接的方法是为玩家2预设固定策略,这实质上将问题简化为单智能体强化学习场景。然而这种方法可能导致过拟合现象或产生脆弱的决策策略。
研究采用了更具动态性的模型动物园方法,该方法维护多样化的对手策略集合。具体实现机制包括:选择待训练的策略(如Q-Learning、蒙特卡洛等算法);确定该策略的学习起始位置;从模型动物园中采样对手策略进行对战;定期更新动物园内容,包括保存当前策略的快照、评估动物园中所有策略的性能表现,以及仅保留表现最优的前k个模型以维持质量和多样性。
这种机制随时间推移创建了自我改进的学习课程:智能体持续面对更强大、更多样化的对手挑战,有效避免了对任何单一策略的过拟合问题。
多智能体强化学习评估框架的构建
为实现多智能体强化学习的系统性实验,研究采用了PettingZoo库[2],该库为多智能体环境提供了标准化的编程接口。本研究专注于两个经典的双人对战游戏:井字棋和连珠四子游戏。
状态转移跟踪机制的实现
研究维护了一个字典结构state_dict,用于存储每个玩家最近观察到的状态以及其执行的动作。参照前述双人游戏示例,这相当于为玩家1存储状态-动作对(s₀, a₀)。
当某玩家再次轮到行动时,系统查询上一步行动的结果(如r₂),并利用该信息构建状态转移:(s₀, a₀) → r₂(从玩家1的视角)。这种设计使得多智能体交互可以表示为一系列环境转移序列,每个转移都会更新相应玩家的学习模型。
强化学习方法的统一接口设计
为实现对多种算法的清晰支持,研究将所有强化学习智能体重构为基类RLMethod的子类。该基类定义了标准化的方法接口:act(state, step, mask)方法在给定状态下基于当前策略返回动作选择(用于回合生成);update(episode, step)方法基于经验数据更新内部参数(如Q表结构)。
这种模块化架构设计便于灵活集成不同算法(如Q-Learning、蒙特卡洛、Sarsa等),并在相同实验条件下进行性能比较分析。
PettingZoo环境的关键API方法
研究依赖PettingZoo环境提供的几个核心函数接口:env.agent_selection用于标识当前应执行动作的智能体;env.last()方法返回当前状态、最近观察到的奖励以及终止状态信息;env.rewards提供包含所有智能体最终奖励的字典结构(游戏结束后可访问)。
这些方法构成了实现训练循环和管理智能体间交互的核心基础。基于上述设计理念,研究实现了完整的训练框架,代码实现遵循前述逻辑并保持了良好的可读性:
def train_multi_player( env: MultiPlayerEnv, methods: list[MethodWithStats], zoo: list[MethodWithStats], max_steps: int = 100, zoo_update_interval: int = 500, zoo_size: int = 50, plot_interval: int | None = None,
) -> None: """在多智能体环境中训练强化学习方法(当前支持双人游戏)。 Args: env: 训练环境实例 methods: 待训练方法列表 zoo: 初始对手策略集合 max_steps: 最大训练步数 """ # 用于性能可视化:记录每种方法在不同训练步数下的(step, win_ratio)数据对 win_ratios: list[list[tuple[int, float]]] = [[] for method in methods] for step in range(max_steps): env.env.reset() # 随机选择待更新方法和起始位置 method_idx = random.randint(0, len(methods) - 1) player_pos = random.randint(0, 1) # 从模型动物园中随机选择对手 opponent_idx = random.randint(0, len(zoo) - 1) opponent = zoo[opponent_idx] methods[method_idx].update_pick() zoo[opponent_idx].update_pick() state_dict = {} done = False episode = [] while not done: agent = env.env.agent_selection # type: ignore ( observation, reward, termination, truncation, _, ) = env.env.last() # type: ignore done = termination or truncation if done: action = None # 游戏结束,更新双方智能体的最终结果 methods[method_idx].update_result( env.get_game_result( env.env.rewards[env.players[player_pos]] # type: ignore ) ) zoo[opponent_idx].update_result( env.get_game_result( env.env.rewards[env.players[1 - player_pos]] # type: ignore ) ) else: mask = observation["action_mask"] state = env.obs_to_state(observation["observation"], player_pos) if agent == env.players[player_pos]: action = methods[method_idx].method.act(state, step, mask) else: action = opponent.method.act(state, step, mask) state_dict[agent] = (state, action, mask) env.env.step(action) _, reward, _, _, _ = env.env.last() # type: ignore if ( env.env.agent_selection == env.players[player_pos] # type: ignore and env.env.agent_selection in state_dict # type: ignore ): s, a, mask = state_dict[env.players[player_pos]] observation_new = env.env.observe( # type: ignore env.players[player_pos] ) episode.append(ReplayItem(s, a, reward, mask)) methods[method_idx].method.update(episode, step) episode.append( ReplayItem( env.obs_to_state( observation_new["observation"], player_pos ), # type: ignore -1, 0, [], ) ) methods[method_idx].method.finalize(episode, step) if plot_interval and step % plot_interval == 0 and step > 0: for idx, method in enumerate(methods): win_ratios[idx].append((step, method.get_win_ratio())) plt.clf() for idx, method in enumerate(methods): x = [epoch for epoch, _ in win_ratios[idx]] y = [win_ratio for _, win_ratio in win_ratios[idx]] plt.plot(x, y, label=method.method.get_name()) plt.legend() plt.savefig("wins.png") log_methods(methods, step) for method in methods: method.method.save_weights() if step % zoo_update_interval == 0: zoo.append(methods[method_idx].clone()) zoo = sorted(zoo, key=lambda x: -x.get_win_ratio()) zoo = zoo[:zoo_size] env.env.close()
多智能体环境下表格方法的基准测试与性能分析
本节将详细分析所有介绍算法在多智能体设置下的性能表现。性能评估通过跟踪整个训练过程中每种方法的统计数据(胜利、平局、失败次数)来实现。
需要注意的是,由于各方法之间存在相互对战关系,单纯的胜率指标并不能完全反映性能差异。例如,若所有方法随时间推移均有相似程度的改进,则胜率可能保持相对平衡,尽管方法本身已获得显著提升。
为解决这一评估问题,研究在智能体池中引入了随机策略方法,该方法始终执行随机动作选择。通过测量各方法相对于随机策略的性能差异,可以有效估计其绝对性能水平。此外,在训练完成后,研究还提供了用户与训练智能体进行交互式对战的功能模块。
井字棋游戏的实验结果与分析
实验首先在井字棋这一相对简单的游戏环境中进行测试。井字棋的游戏规则广为人知,其目标是在3×3网格中率先形成三个连续的标记(行、列或对角线)。理论上,采用最优策略的双方对战必然导致平局结果。
下图展示了所有方法在100,000个训练步骤中的胜率变化趋势:
训练循环同时以表格形式输出相同的统计信息:
基于实验结果,可将不同方法按性能表现分为以下层次:
顶层性能组:Q-learning与同策略蒙特卡洛方法
这两种方法表现出最优性能,均达到超过77%的胜率且失败率较低。其优异表现体现了两个互补的算法优势:同策略蒙特卡洛方法受益于完整回合回报估计机制,这种机制在相对较短的回合制游戏中表现尤为有效;Q-learning作为异策略方法,能够在探索性行为训练过程中有效学习贪心策略,使其对自我对战过程中的动态变化具有良好的鲁棒性。
值得注意的是,同策略方法在GridWorld等单智能体环境中同样表现优异,而Q-learning在这些问题中也位居前列,这表明了这些方法的一般性优势。
中层性能组:Dyna-Q、Sarsa-n与Sarsa方法
这一组方法表现尚可,但相比Q-learning等顶层方法存在明显的性能差距。这种差异在GridWorld基准测试中并未显现,其原因可能与同策略方法的固有局限性相关。同策略方法通过使用相同策略进行数据生成和学习更新,这种机制在静态环境中效果良好。然而在当前设置中,对手策略持续演化导致环境本质上处于非平稳状态,状态转移动态随时间发生变化。
与Q-learning等异策略方法不同,后者能够学习最优策略而不受行为策略影响,同策略方法与其生成的数据分布存在紧密耦合关系。这种特性使得它们在环境持续变化的情况下表现更加脆弱。在自我对战等动态设置中,同策略学习器相比异策略对应方法可能面临泛化困难、收敛速度较慢或稳定于次优策略等问题。
Dyna-Q可能面临相似的相关问题,因为该方法额外学习环境模型,而模型学习同样假设环境的平稳性特征。
较低性能组:Expected Sarsa、异策略蒙特卡洛与Double Q-learning
异策略蒙特卡洛方法在单智能体设置中已表现出学习困难。Expected Sarsa的问题可能与Sarsa和n步树备份方法类似,因为它采用期望更新机制。Double Q-learning的相对较差表现令人意外,但经过深入分析可以得出以下解释:Double Q-learning旨在缓解过度自信和价值过估计问题,这种修正机制通常有益于学习过程,但在某些情况下可能过度保守,导致利用不足的问题,特别是在当前测试环境中。Double Q-learning的保守特性可能使其难以果断地偏向最优动作,因为在噪声价值估计环境中,利用略优选项的收益并不明确。该方法可能倾向于"安全行事"而非积极寻找最优策略。此外,由于其更新机制更加谨慎以防止过估计,其适应速度可能低于Q-learning。后者积极利用最有希望的价值估计,即使其中一些可能过于乐观,而这种特性在策略快速演化的双人游戏中可能带来优势。
底层性能组:n步树备份方法
这一结果尤为令人意外,因为该算法在GridWorld基准测试中表现最优。这种性能差异可能与前述非平稳环境问题相关。n步树备份算法以及Expected Sarsa都需要计算动作概率分布(甚至多层动作的概率分布)。为实现这一计算,算法必须假设状态-动作分布的某种稳定性,即假设环境的平稳性。然而,如此显著的性能下降仍然令人困惑。
人机对战验证与方法局限性分析
对于此类游戏,人机对战是检验算法性能的重要标准。尽管井字棋规则极其简单且理论上总是可以避免失败,但实际对战中,由于注意力不够集中,研究者确实在与这些训练方法的对战中败北数次。因此可以认为,测试方法在游戏技能方面通过了基本验证。
然而,需要对实验结果保持谨慎态度。井字棋是一个极其简单的游戏,人类能够快速掌握至少保证平局的策略。而研究中的强化学习方法未能发现这种解决方案(或者顶层与底层方法间的性能差异过大)。这是否应当引起对未来发展的担忧——如此大量的计算资源仅获得如此有限的解决方案?
答案是否定的。当前研究在根本上受到表格解决方法的固有限制。正如前文所述,这些方法将每个状态-动作对的价值信息存储在独立的表格条目中,意味着每个状态-动作对都是独特且不同的,需要在观察到确切组合时进行明确更新,算法无法实现泛化学习。
对于井字棋,理论上最多存在3^9(约20,000)种不同的棋盘配置,尽管其中一些在实际游戏中无法达到。由于这种有限的状态空间规模,研究能够通过若干方法勉强解决该问题。然而,下一个实验将证明,对于更大规模的问题,表格方法完全不可行,必须转向函数逼近技术。
连珠四子游戏的实验结果与复杂性分析
接下来的实验转向连珠四子游戏。在该游戏中,双方玩家轮流在游戏场中投放棋子,目标是形成四个相同颜色棋子的连续排列(行、列或对角线)。
以下展示与前节相同形式的实验结果:
实验观察显示,经过100,000个训练步骤后,没有任何方法表现显著优于随机策略。尽管如此,仍可给出一些性能排序:正面表现方面,Q-learning和同策略蒙特卡洛方法相对较优,与井字棋实验结果类似,这些方法位于性能排行榜的前端;负面表现方面,n步树备份和异策略蒙特卡洛方法再次位列最低性能层次。
当然,可以通过延长训练时间、改进奖励设计、调整超参数等方式继续优化性能。然而在采取这些措施之前,有必要深入分析问题的本质复杂性。
在连珠四子游戏中,每个位置可以处于三种状态之一:空位、玩家1占据或玩家2占据。因此,理论上最多存在342种不同的游戏状态,这个数字约为1020或100万万万万(即100万亿万)种不同状态,尽管并非所有状态在实际游戏中都可达到。这显然是一个难以想象的巨大数字。
更重要的是,这仅仅是一个相对简单的玩具问题。其他实际应用问题自然具有更大的状态空间。例如,考虑从摄像头图像学习控制机械臂的任务,可能的图像数量超过宇宙中原子的总数。因此,完全不可能使用表格解决方法来处理这类大规模问题,函数逼近技术成为绝对必要的选择。恰好,这正是本系列研究的下一个重要议题。
总结
本文研究构建了多智能体强化学习的系统性评估框架,通过井字棋和连珠四子两个经典博弈环境,深入分析了表格方法在竞争性学习场景中的性能表现和适用边界。
井字棋环境的成功验证了研究框架的有效性:Q-learning和同策略蒙特卡洛方法达到超过77%的胜率,展现了异策略学习在非平稳环境中的适应优势。相比之下,连珠四子游戏中所有表格方法的失败清晰地揭示了泛化能力缺失的根本局限性。
面对10^20量级的状态空间,表格方法的独立存储机制导致其无法从部分经验中学习有用模式,这一发现为理解强化学习可扩展性问题提供了重要洞察。
后续研究将重点探索价值函数逼近、深度神经网络等可扩展解决方案,这些技术能够从有限的交互经验中提取通用模式,并有效应用于未见过的状态配置。当这些先进工具建立完善后,研究将重新审视当前基准测试环境,预期将观察到显著的性能提升。
本文不仅为多智能体强化学习领域贡献了标准化的评估方法论,更重要的是通过对比实验明确了从表格方法向函数逼近技术演进的必然性,为该领域的理论发展和实际应用奠定了坚实基础。
https://avoid.overfit.cn/post/a1b5e09228344eafa89914172f1b4a17
作者:Oliver S