You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RLlib训练时打印动作分布报错求助:多智能体剪刀石头布场景

解决RLLib多智能体环境中Episode结束后打印动作分布的报错问题

你想在每个Episode结束后打印动作分布来观察智能体行为的思路是对的,但代码里有几个关键问题导致了输入形状不匹配的错误,我来帮你拆解一下:

错误原因分析

你遇到的ValueError: Input 0 of layer fc_value_1 is incompatible with the layer: expected axis -1 of input shape to have value 3 but received input with shape [1, 6],核心问题是你错误地定义了观测空间:

  • 在原RockPaperScissors多智能体环境中,每个智能体的观测空间是Discrete(3)(观测内容是对手上一轮的动作),而不是你写的Tuple((Discrete(3),Discrete(3)))。
  • 你手动创建的预处理器基于错误的观测空间,把输入处理成了6维(两个3维离散空间拼接),但训练好的模型是基于3维观测构建的,自然会出现形状不匹配。

除此之外,代码还有几个不规范/错误的地方:

  • 直接访问episode._policies是访问私有属性,RLLib推荐用公开API获取策略;
  • 手动创建预处理器没必要,应该用策略自带的预处理器来处理观测,保证和训练时的预处理逻辑一致;
  • 构造的curr_state = (0,1)不符合单个智能体的观测格式,应该是单个0-2的整数。

修正后的代码示例

下面是调整后的on_episode_end回调函数,你可以直接替换原代码:

import numpy as np
from ray.rllib.policy.sample_batch import SampleBatch

def on_episode_end(info):
    episode = info["episode"]
    # 通过智能体ID获取对应的策略(比如"player1"是使用learned策略的智能体)
    policy = episode.policy_for("player1")
    
    # 构造符合观测空间的测试状态:比如对手上一轮出了动作0(石头)
    test_obs = 0
    # 使用策略自带的预处理器处理观测,和训练时逻辑一致
    processed_obs = policy.preprocessors[SampleBatch.OBS].transform([test_obs])
    
    # 获取模型的logits输出
    logits, _ = policy.model.from_batch({SampleBatch.OBS: np.array(processed_obs)})
    # 创建分布对象
    dist = policy.dist_class(logits, policy.model)
    
    # 打印动作分布的概率、采样结果和指定动作的log概率
    print(f"动作概率分布: {dist.prob_numpy()}")
    print(f"采样动作: {dist.sample().numpy()}")
    print(f"动作0的log概率: {dist.logp([0]).numpy()}")

关键调整点说明

  • 正确获取策略:用episode.policy_for("player1")替代私有属性访问,更稳定且符合RLLib的API规范;
  • 使用策略自带的预处理器:policy.preprocessors[SampleBatch.OBS]是训练时用的预处理器,保证观测处理逻辑和训练完全一致;
  • 构造正确的观测格式:单个Discrete(3)类型的观测是0-2的整数,而不是元组;
  • 打印更直观的分布信息:新增了打印动作概率分布的代码,比只打印log概率更便于观察智能体的行为倾向。

内容的提问来源于stack exchange,提问作者Charlie Hou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:31:59