引言:为什么我们需要专门的多智能体环境库?
在单智能体强化学习中,我们有Gym、Atari等成熟的环境库,但当转向多智能体系统时,问题复杂度呈指数级增长。想象一下:每个智能体都有独立的观察空间、动作空间,需要处理通信、协调、竞争等各种交互模式,还要应对非平稳性、信用分配等特有挑战。在这种情况下,一个专门为多智能体设计的环境库变得至关重要。
PettingZoo应运而生,它是Gym的多智能体扩展,由Farama基金会(原Gym的维护者)开发。与传统的多智能体环境相比,PettingZoo提供了标准化的API、丰富的环境集合、以及与Gym完全兼容的接口,让多智能体强化学习的研究和开发变得更加便捷。
本文将带你从零开始搭建PettingZoo环境,深入剖析经典的simple_adversary环境,并探索多智能体交互的核心机制。
第一章:PettingZoo环境搭建全攻略
1.1 环境要求与安装准备
在开始安装之前,我们需要确保系统满足以下基本要求:
- Python 3.7及以上版本
- pip包管理器(推荐使用最新版)
- 可选但建议:虚拟环境(venv或conda)
bash
# 创建并激活虚拟环境(以conda为例)
conda create -n pettingzoo_env python=3.8
conda activate pettingzoo_env
# 或者使用venv
python -m venv pettingzoo_env
source pettingzoo_env/bin/activate # Linux/Mac
# 或 .\pettingzoo_env\Scripts\activate # Windows
1.2 安装PettingZoo及依赖
PettingZoo的安装可以根据需求选择不同模块:
bash
# 基础安装(仅包含经典环境)
pip install pettingzoo
# 完整安装(推荐,包含所有环境)
pip install "pettingzoo[all]"
# 如果安装速度慢,可以使用国内镜像
pip install "pettingzoo[all]" -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2.1 安装问题排查
安装过程中可能遇到的问题及解决方案:
- 依赖冲突问题:
bash
# 尝试使用conda安装部分依赖
conda install numpy scipy matplotlib
pip install "pettingzoo[all]" --no-deps
- 特定环境依赖:
bash
# 如果只需要特定类型的环境
pip install pettingzoo[atari] # Atari多智能体环境
pip install pettingzoo[classic] # 经典游戏环境
pip install pettingzoo[mpe] # 多粒子环境(simple_adversary在此)
pip install pettingzoo[sisl] # 社交推理环境
- 版本兼容性问题:
python
# 在代码中检查版本
import pettingzoo
print(f"PettingZoo版本: {pettingzoo.__version__}")
1.3 验证安装
创建一个简单的验证脚本:
python
# verify_installation.py
import pettingzoo
from pettingzoo.mpe import simple_adversary_v3
# 测试环境能否正常创建
try:
env = simple_adversary_v3.env(render_mode="human")
print("✓ PettingZoo安装成功!")
print(f"✓ 可用智能体: {env.possible_agents}")
env.close()
except Exception as e:
print(f"✗ 安装出现问题: {e}")
第二章:PettingZoo核心概念与API详解
2.1 多智能体环境的基本结构
PettingZoo环境与单智能体Gym环境的主要区别体现在以下几个方面:
| 维度 | Gym(单智能体) | PettingZoo(多智能体) |
|---|---|---|
| 环境创建 | env = gym.make('EnvName') |
env = parallel_env() |
| 重置 | obs = env.reset() |
observations = env.reset() |
| 步进 | obs, reward, done, info = env.step(action) |
observations, rewards, dones, infos = env.step(actions) |
| 终止判断 | 单个done布尔值 |
字典dones['agent_name'] |
2.2 PettingZoo的三种执行模式
PettingZoo支持三种环境执行模式,满足不同的开发需求:
2.2.1 AEC(Agent Environment Cycle)模式
传统的循环模式,智能体依次行动。这种模式适合回合制游戏。
python
from pettingzoo.mpe import simple_adversary_v3
# 创建AEC环境
env = simple_adversary_v3.env(render_mode="human")
# 初始化环境
env.reset()
# AEC循环
for agent in env.agent_iter():
observation, reward, termination, truncation, info = env.last()
if termination or truncation:
action = None
else:
# 这里插入智能体的策略
action = env.action_space(agent).sample() # 随机动作
env.step(action)
# 如果需要渲染
env.render()
env.close()
2.2.2 并行(Parallel)模式
所有智能体同时行动,适合实时环境。这是更现代、更高效的接口。
python
from pettingzoo.mpe import simple_adversary_v3
# 创建并行环境
parallel_env = simple_adversary_v3.parallel_env(render_mode="human")
# 初始化
observations = parallel_env.reset()
# 并行循环
while parallel_env.agents:
# 收集所有智能体的动作
actions = {}
for agent, obs in observations.items():
# 这里插入每个智能体的策略
actions[agent] = parallel_env.action_space(agent).sample()
# 并行执行一步
observations, rewards, terminations, truncations, infos = parallel_env.step(actions)
# 渲染
parallel_env.render()
parallel_env.close()
2.2.3 包装器(Wrapper)系统
PettingZoo提供了丰富的包装器,可以轻松修改环境行为:
python
from pettingzoo.utils import wrappers
from pettingzoo.mpe import simple_adversary_v3
# 使用包装器链
def make_env(render_mode=None):
env = simple_adversary_v3.parallel_env(render_mode=render_mode)
# 添加包装器
env = wrappers.AssertOutOfBoundsWrapper(env)
env = wrappers.OrderEnforcingWrapper(env)
env = wrappers.CaptureStdoutWrapper(env)
env = wrappers.ClipOutOfBoundsWrapper(env)
return env
# 现在可以使用包装后的环境
env = make_env(render_mode="human")
2.3 关键API详解
2.3.1 智能体管理
python
# 获取所有智能体
agents = env.agents # 列表形式
print(f"当前活跃智能体: {agents}")
# 获取可能的智能体
possible_agents = env.possible_agents
print(f"环境中所有可能的智能体: {possible_agents}")
# 智能体迭代器
for agent_name in env.agent_iter(max_iter=1000):
# 处理每个智能体
pass
2.3.2 观察与动作空间
python
# 获取智能体的观察空间
for agent in env.possible_agents:
obs_space = env.observation_space(agent)
print(f"{agent}的观察空间: {obs_space}")
print(f"观察空间形状: {obs_space.shape}")
print(f"观察空间类型: {obs_space.dtype}")
# 获取智能体的动作空间
for agent in env.possible_agents:
action_space = env.action_space(agent)
print(f"{agent}的动作空间: {action_space}")
# 离散动作空间
if hasattr(action_space, 'n'):
print(f"离散动作数量: {action_space.n}")
# 连续动作空间
if hasattr(action_space, 'shape'):
print(f"连续动作维度: {action_space.shape}")
print(f"动作范围: [{action_space.low}, {action_space.high}]")
2.3.3 奖励与终止条件
python
# 在循环中处理奖励和终止
rewards = env.rewards # 当前奖励字典
dones = env.terminations # 终止字典
truncations = env.truncations # 截断字典(超过最大步数)
# 检查是否所有智能体都终止了
all_done = all(env.terminations.values()) or all(env.truncations.values())
第三章:simple_adversary环境深度解析
3.1 环境背景与问题设定
simple_adversary是MPE(Multi-Particle Environment)中的一个经典环境,它模拟了一个部分可观察的追逃游戏。在这个环境中:
- 场景:一个二维连续空间
- 智能体 :
- 1个对手(adversary):无法直接看到地标位置
- 2个合作智能体(agents):可以看到所有地标位置
- 地标:3个地标,其中1个是目标(绿色),2个是干扰项(红色)
- 目标 :
- 对手:找出并移动到目标地标
- 合作智能体:帮助对手找到目标地标,同时避免对手发现哪个是目标
3.2 环境状态与观察空间
3.2.1 完整状态空间
环境的完整状态包含:
- 所有智能体的位置(x, y坐标)
- 所有地标的位置(x, y坐标)
- 目标地标的索引(哪个地标是目标)
3.2.2 部分可观察性设计
每个智能体只能看到部分信息:
python
# 观察空间结构(以合作智能体为例)
def get_observation(self, agent_idx):
"""获取智能体的部分观察"""
observation = []
# 1. 自身位置
observation.append(self.agent_positions[agent_idx])
# 2. 所有地标的位置
observation.extend(self.landmark_positions)
# 3. 其他智能体的相对位置
for other_idx in range(self.num_agents):
if other_idx != agent_idx:
relative_pos = (self.agent_positions[other_idx] -
self.agent_positions[agent_idx])
observation.append(relative_pos)
# 合作智能体额外知道目标地标
if agent_idx > 0: # 合作智能体(索引1和2)
# 目标地标的one-hot编码
target_one_hot = [0] * self.num_landmarks
target_one_hot[self.target_landmark] = 1
observation.extend(target_one_hot)
return np.concatenate(observation)
3.3 动作空间设计
simple_adversary采用连续动作空间:
python
# 每个智能体的动作是二维连续向量
action_dim = 2 # x方向力和y方向力
# 动作范围通常为[-1, 1],表示力的大小和方向
action = [force_x, force_y] # 每个分量在-1到1之间
# 物理更新
new_velocity = old_velocity * damping + action * max_force
new_position = old_position + new_velocity * delta_time
3.4 奖励函数设计
奖励函数是多智能体环境设计的核心,体现了智能体间的交互关系:
python
class SimpleAdversaryReward:
def __init__(self):
self.target_penalty = -10 # 对手选择错误目标的惩罚
self.collision_penalty = -1 # 碰撞惩罚
self.distance_weight = -0.1 # 距离权重
def compute_rewards(self, agent_positions, landmark_positions, target_idx):
rewards = {}
# 对手的奖励(索引0)
adversary_pos = agent_positions[0]
# 计算对手到所有地标的距离
distances = []
for landmark_pos in landmark_positions:
dist = np.linalg.norm(adversary_pos - landmark_pos)
distances.append(dist)
# 找到对手最近的地标
closest_landmark = np.argmin(distances)
if closest_landmark == target_idx:
# 对手找到了目标地标
rewards['adversary_0'] = 10
else:
# 对手选择了错误的地标
rewards['adversary_0'] = self.target_penalty
# 合作智能体的奖励(索引1和2)
for i in range(1, len(agent_positions)):
agent_pos = agent_positions[i]
# 合作智能体的目标是让对手找到正确目标
# 同时自己不要离地标太近(避免泄露信息)
total_distance = 0
for landmark_pos in landmark_positions:
dist = np.linalg.norm(agent_pos - landmark_pos)
total_distance += dist
# 合作智能体的奖励是负的距离和(鼓励远离地标)
rewards[f'agent_{i}'] = self.distance_weight * total_distance
# 如果合作智能体碰撞了地标,额外惩罚
if min([np.linalg.norm(agent_pos - lm) for lm in landmark_positions]) < 0.1:
rewards[f'agent_{i}'] += self.collision_penalty
return rewards
3.5 环境动态与智能体交互
智能体间的交互形成了有趣的博弈动态:
- 对手的困境:无法直接知道目标,需要观察合作智能体的行为来推断
- 合作智能体的困境:需要帮助对手,但不能太明显地暴露目标
- 信息传递的微妙平衡:合作智能体需要在"帮助"和"欺骗"之间找到平衡点
第四章:实战代码:观察与分析多智能体交互
4.1 基础交互观察
让我们创建一个完整的观察脚本,可视化智能体间的交互:
python
# simple_adversary_observer.py
import numpy as np
from pettingzoo.mpe import simple_adversary_v3
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class SimpleAdversaryObserver:
def __init__(self, render_mode="human", max_cycles=100):
self.env = simple_adversary_v3.env(render_mode=render_mode,
max_cycles=max_cycles)
self.fig, self.ax = plt.subplots(figsize=(10, 8))
self.data_records = {
'positions': [],
'rewards': [],
'actions': [],
'distances_to_target': []
}
def run_episode(self, policy_fn=None):
"""运行一个完整的回合并记录数据"""
observations = self.env.reset()
# 初始化记录
episode_positions = {agent: [] for agent in self.env.possible_agents}
episode_rewards = {agent: [] for agent in self.env.possible_agents}
episode_actions = {agent: [] for agent in self.env.possible_agents}
while self.env.agents:
current_agent = self.env.agent_selection
# 获取当前观察和奖励
obs, reward, termination, truncation, _ = self.env.last()
# 记录数据
if hasattr(self.env, 'world'):
# 记录位置
for i, agent_name in enumerate(self.env.possible_agents):
pos = self.env.world.agents[i].state.p_pos
episode_positions[agent_name].append(pos.copy())
# 记录到目标的距离
target_pos = self.env.world.landmarks[self.env.world.target_idx].state.p_pos
distances = {}
for agent_name in self.env.possible_agents:
agent_idx = int(agent_name.split('_')[-1])
agent_pos = self.env.world.agents[agent_idx].state.p_pos
dist = np.linalg.norm(agent_pos - target_pos)
distances[agent_name] = dist
# 选择动作
if termination or truncation:
action = None
else:
if policy_fn is not None:
action = policy_fn(current_agent, obs)
else:
# 随机策略
action = self.env.action_space(current_agent).sample()
# 记录动作
episode_actions[current_agent].append(action)
# 执行一步
self.env.step(action)
# 记录奖励
for agent in self.env.possible_agents:
if agent in self.env.rewards:
episode_rewards[agent].append(self.env.rewards[agent])
else:
episode_rewards[agent].append(0)
# 保存回合数据
self.data_records['positions'].append(episode_positions)
self.data_records['rewards'].append(episode_rewards)
self.data_records['actions'].append(episode_actions)
self.env.close()
return episode_rewards
def visualize_trajectories(self, episode_idx=0):
"""可视化智能体的运动轨迹"""
if len(self.data_records['positions']) <= episode_idx:
print("没有找到指定的回合数据")
return
positions = self.data_records['positions'][episode_idx]
self.ax.clear()
self.ax.set_xlim(-1.5, 1.5)
self.ax.set_ylim(-1.5, 1.5)
self.ax.set_aspect('equal')
self.ax.grid(True, alpha=0.3)
# 定义颜色和标记
colors = {'adversary_0': 'red', 'agent_1': 'blue', 'agent_2': 'green'}
markers = {'adversary_0': 'o', 'agent_1': 's', 'agent_2': '^'}
# 绘制轨迹
for agent_name, traj in positions.items():
traj = np.array(traj)
self.ax.plot(traj[:, 0], traj[:, 1],
color=colors[agent_name],
alpha=0.5,
label=f'{agent_name}轨迹')
# 绘制起点和终点
self.ax.scatter(traj[0, 0], traj[0, 1],
color=colors[agent_name],
marker=markers[agent_name],
s=100,
label=f'{agent_name}起点')
self.ax.scatter(traj[-1, 0], traj[-1, 1],
color=colors[agent_name],
marker=markers[agent_name],
s=200,
edgecolors='black',
label=f'{agent_name}终点')
self.ax.legend()
self.ax.set_title('Simple Adversary - 智能体运动轨迹')
self.ax.set_xlabel('X坐标')
self.ax.set_ylabel('Y坐标')
plt.tight_layout()
plt.show()
def plot_rewards_over_time(self, episode_idx=0):
"""绘制奖励随时间的变化"""
rewards = self.data_records['rewards'][episode_idx]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for idx, (agent_name, agent_rewards) in enumerate(rewards.items()):
axes[idx].plot(range(len(agent_rewards)), agent_rewards,
linewidth=2, marker='o', markersize=4)
axes[idx].set_title(f'{agent_name}的奖励')
axes[idx].set_xlabel('时间步')
axes[idx].set_ylabel('奖励')
axes[idx].grid(True, alpha=0.3)
# 计算累计奖励
cumulative_rewards = np.cumsum(agent_rewards)
axes[idx].plot(range(len(agent_rewards)), cumulative_rewards,
'r--', linewidth=1.5, label='累计奖励')
axes[idx].legend()
plt.tight_layout()
plt.show()
def analyze_interaction_patterns(self, episode_idx=0):
"""分析智能体间的交互模式"""
positions = self.data_records['positions'][episode_idx]
actions = self.data_records['actions'][episode_idx]
# 计算智能体间的距离
agents = list(positions.keys())
num_steps = min(len(pos_list) for pos_list in positions.values())
distances = {}
for i in range(len(agents)):
for j in range(i+1, len(agents)):
key = f"{agents[i]}_vs_{agents[j]}"
distances[key] = []
for step in range(num_steps):
if (step < len(positions[agents[i]]) and
step < len(positions[agents[j]])):
pos_i = np.array(positions[agents[i]][step])
pos_j = np.array(positions[agents[j]][step])
dist = np.linalg.norm(pos_i - pos_j)
distances[key].append(dist)
# 绘制距离变化
fig, axes = plt.subplots(2, 1, figsize=(12, 8))
# 距离图
for key, dist_list in distances.items():
axes[0].plot(range(len(dist_list)), dist_list,
linewidth=2, label=key)
axes[0].set_title('智能体间距离变化')
axes[0].set_xlabel('时间步')
axes[0].set_ylabel('距离')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 动作统计
for idx, (agent_name, agent_actions) in enumerate(actions.items()):
if agent_actions and all(a is not None for a in agent_actions):
actions_array = np.array(agent_actions)
axes[1].plot(range(len(actions_array)),
np.linalg.norm(actions_array, axis=1),
label=f'{agent_name}动作幅度')
axes[1].set_title('智能体动作幅度')
axes[1].set_xlabel('时间步')
axes[1].set_ylabel('动作幅度')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 使用观察器
if __name__ == "__main__":
observer = SimpleAdversaryObserver(render_mode="rgb_array", max_cycles=50)
print("运行10个回合并收集数据...")
for episode in range(10):
rewards = observer.run_episode()
total_rewards = {agent: sum(rewards[agent]) for agent in rewards}
print(f"回合 {episode}: {total_rewards}")
print("\n可视化分析...")
observer.visualize_trajectories(episode_idx=0)
observer.plot_rewards_over_time(episode_idx=0)
observer.analyze_interaction_patterns(episode_idx=0)
4.2 交互模式分析
通过运行上面的观察器,我们可以发现几种典型的交互模式:
4.2.1 合作智能体的策略分析
python
def analyze_cooperative_strategies(positions, actions):
"""分析合作智能体的策略"""
strategies = {
'distracting': 0, # 分散注意力策略
'guiding': 0, # 引导策略
'stationary': 0, # 静止策略
'random': 0 # 随机策略
}
# 分析合作智能体的运动模式
for agent_name in ['agent_1', 'agent_2']:
agent_positions = np.array(positions[agent_name])
# 计算移动距离
total_movement = np.sum(np.linalg.norm(
np.diff(agent_positions, axis=0), axis=1))
# 计算与地标的平均距离
# 这里假设我们有地标位置信息
# 根据移动模式分类策略
if total_movement < 0.5:
strategies['stationary'] += 1
elif total_movement > 3.0:
strategies['random'] += 1
else:
# 需要更多上下文判断是distracting还是guiding
pass
return strategies
4.2.2 对手的推理过程
对手的决策过程可以建模为一个贝叶斯推理问题:
python
class AdversaryBeliefModel:
def __init__(self, num_landmarks=3):
# 初始信念:每个地标是目标的概率相等
self.belief = np.ones(num_landmarks) / num_landmarks
def update_belief(self, observations, cooperative_agents_positions):
"""根据观察更新信念"""
# 观察合作智能体的行为
# 如果他们经常靠近某个地标,那个地标可能不是目标
# 如果他们避开某个地标,那个地标可能是目标
# 简化的更新规则
for landmark_idx in range(len(self.belief)):
# 计算合作智能体与该地标的平均距离
avg_distance = 0
for agent_pos in cooperative_agents_positions:
# 假设我们有地标位置
# distance = compute_distance(agent_pos, landmark_pos)
# avg_distance += distance
pass
# 如果合作智能体离地标远,增加该地标是目标的概率
# 如果离得近,减少概率
# 贝叶斯更新
likelihood = self.compute_likelihood(landmark_idx, avg_distance)
self.belief[landmark_idx] *= likelihood
# 归一化
self.belief /= np.sum(self.belief)
def get_target_guess(self):
"""返回最可能的目标地标"""
return np.argmax(self.belief)
4.3 高级分析:通信模式推断
即使在没有显式通信的环境中,智能体也会通过行为进行隐式通信:
python
class ImplicitCommunicationAnalyzer:
def __init__(self):
self.communication_signals = []
def analyze_position_based_signaling(self, positions):
"""分析基于位置的信号传递"""
signals = []
# 分析合作智能体与地标的位置关系
for step in range(len(positions['agent_1'])):
signal_at_step = {}
# 计算每个合作智能体与各地标的距离
for agent_name in ['agent_1', 'agent_2']:
agent_pos = positions[agent_name][step]
# 假设我们有地标位置
# distances_to_landmarks = compute_distances(agent_pos, landmark_positions)
# 信号:智能体是否在"守护"某个地标
# 守护定义为:智能体在地标附近,且面向其他方向
# 信号:智能体是否在"引诱"对手到某个地标
# 引诱定义为:智能体在地标和对手之间,且朝向对手
signal_at_step[agent_name] = self.extract_signal(agent_pos)
signals.append(signal_at_step)
return signals
def extract_signal(self, agent_position_history):
"""从位置历史中提取信号"""
signals = []
if len(agent_position_history) < 3:
return signals
# 分析移动模式
recent_positions = agent_position_history[-3:]
velocities = np.diff(recent_positions, axis=0)
# 检测周期性运动(可能表示"守护"行为)
if self.is_periodic(velocities):
signals.append('guarding')
# 检测直线加速(可能表示"引导"行为)
if self.is_accelerating_towards(velocities):
signals.append('guiding')
# 检测随机游走(可能表示"迷惑"行为)
if self.is_random_walk(velocities):
signals.append('confusing')
return signals
第五章:从观察到算法开发
5.1 为simple_adversary设计基础算法
基于我们对环境的理解,可以设计一个简单的启发式算法:
python
class HeuristicPolicy:
def __init__(self, agent_name):
self.agent_name = agent_name
self.strategy = self.determine_strategy(agent_name)
def determine_strategy(self, agent_name):
"""根据智能体角色确定策略"""
if 'adversary' in agent_name:
return 'bayesian_inference'
else:
return 'cooperative_deception'
def get_action(self, observation, env_info=None):
"""根据策略选择动作"""
if self.strategy == 'bayesian_inference':
return self.adversary_policy(observation, env_info)
else:
return self.cooperative_policy(observation, env_info)
def adversary_policy(self, observation, env_info):
"""对手策略:贝叶斯推理+探索"""
# 提取观察中的信息
self_pos = observation[:2]
# 如果有其他智能体的相对位置信息
if len(observation) > 8: # 假设观测包含足够信息
other_agents_relative = observation[8:12] # 示例索引
# 简单启发式:向合作智能体远离的地标移动
action = self.simple_heuristic(other_agents_relative)
else:
# 随机探索
action = np.random.uniform(-1, 1, 2)
return action
def cooperative_policy(self, observation, env_info):
"""合作智能体策略:微妙的信息隐藏"""
# 目标:既不明显暴露目标,又给对手足够线索
# 策略1:偶尔靠近非目标地标
# 策略2:保持一定的运动但不过度
# 策略3:观察对手行为并相应调整
# 简单的实现:适度随机运动
action = np.random.uniform(-0.5, 0.5, 2)
return action
5.2 集成到训练框架
将我们的策略集成到标准训练循环中:
python
def train_with_heuristic(num_episodes=1000):
"""使用启发式策略训练"""
env = simple_adversary_v3.parallel_env(max_cycles=50)
# 初始化策略
policies = {}
for agent_name in env.possible_agents:
policies[agent_name] = HeuristicPolicy(agent_name)
# 训练循环
episode_rewards = {agent: [] for agent in env.possible_agents}
for episode in range(num_episodes):
observations, infos = env.reset()
episode_reward = {agent: 0 for agent in env.possible_agents}
while env.agents:
# 收集动作
actions = {}
for agent_name, obs in observations.items():
actions[agent_name] = policies[agent_name].get_action(obs)
# 环境步进
observations, rewards, terminations, truncations, infos = env.step(actions)
# 累计奖励
for agent_name, reward in rewards.items():
episode_reward[agent_name] += reward
# 记录回合奖励
for agent_name in env.possible_agents:
episode_rewards[agent_name].append(episode_reward.get(agent_name, 0))
# 每100回合输出进度
if episode % 100 == 0:
avg_rewards = {
agent: np.mean(episode_rewards[agent][-100:])
for agent in env.possible_agents
}
print(f"回合 {episode}: 平均奖励 {avg_rewards}")
env.close()
return episode_rewards
第六章:扩展与进阶
6.1 PettingZoo中的其他有趣环境
除了simple_adversary,PettingZoo还提供了许多其他环境:
- simple_spread:合作导航,智能体需要覆盖所有目标点
- simple_tag:追逃游戏,有捕食者和猎物
- simple_world_comm:带有显式通信的环境
- pistonball:多智能体Atari风格游戏
- knights_archers_zombies:塔防风格合作游戏
6.2 多智能体算法实现建议
要在PettingZoo环境中实现先进的多智能体算法:
- MADDPG:集中训练,分散执行
- QMIX:值分解方法
- COMA:反事实多智能体策略梯度
- MAPPO:多智能体近端策略优化
6.3 性能优化技巧
python
# 1. 向量化环境(支持并行采样)
from pettingzoo.utils import parallel_to_aec
from supersuit import vectorize_aec_env_v0
# 2. 使用SupSuit进行预处理
import supersuit as ss
env = simple_adversary_v3.parallel_env()
env = ss.pettingzoo_env_to_vec_env_v1(env)
env = ss.concat_vec_envs_v1(env, 8) # 8个并行环境
# 3. 高效的数据收集
from pettingzoo.utils import RandomReferenceWrapper
# 4. 自定义环境(如果需要更复杂的行为)
from pettingzoo.utils import BaseParallelWrapper
class CustomAdversaryEnv(BaseParallelWrapper):
def __init__(self, env):
super().__init__(env)
# 添加自定义逻辑
总结与展望
通过本文的探索,我们完成了从PettingZoo环境安装到simple_adversary环境深度分析的全过程。我们看到了多智能体系统中复杂的交互模式、部分可观察性带来的挑战,以及智能体间微妙的博弈关系。
关键收获:
- PettingZoo提供了一个标准化的多智能体环境接口
- simple_adversary展示了混合动机环境中的复杂交互
- 部分可观察性是多智能体系统的核心特征
- 智能体间的隐式通信可以通过行为分析来理解
下一步:
- 尝试实现先进的多智能体算法(如MADDPG、QMIX)
- 探索PettingZoo中的其他环境
- 设计自己的多智能体环境
- 研究通信在MARL中的作用
多智能体强化学习是一个充满挑战和机遇的领域,PettingZoo为我们提供了一个极佳的起点。通过深入理解环境动态和智能体交互,我们可以设计出更智能、更高效的算法,最终实现真正的群体智能。