OpenAI Gym复杂Dict观测空间扁平化及DQN实现问题咨询
关于DQN实现中Dict观测空间的问题
问题1:扁平化Dict观测空间的差异原因
你手动计算的513维是把每个Discrete空间当成单个离散值,但gym.spaces.utils.flatten_space默认会对Discrete类型做one-hot编码,而非直接保留离散数值,这是两者差异的核心:
elem_1是Discrete(64):扁平化后是64维的one-hot数组(每个离散值对应数组中唯一的1,其余为0)elem_2中的每个子Dict:prop_1(Discrete(100))→100维one-hotprop_2(Discrete(10))→10维one-hotprop_3到prop_8共6个Discrete(4)→每个4维,总计24维
单个子Dict扁平化长度为100+10+24=134
- 64个子Dict总长度为64×134=8576,加上elem_1的64,总长度为8640,和你看到的8801接近(可能是Tuple包装的微小差异或近似计算)
如果要得到你预期的513维数组(用离散值本身而非one-hot),需要手动遍历观测字典提取数值并拼接,不要用gym自带的flatten工具。
问题2:观测数组形式与replay函数错误
观测的numpy数组形式
原始观测是嵌套字典+元组结构:elem_1为整数,elem_2是64个字典的元组,每个字典包含8个整数。转换成数组有两种方式:
- 用gym的
flatten函数:得到one-hot编码的高维数组(长度约8640) - 手动提取离散值:拼接成1+64×8=513维的一维数值数组
replay函数错误原因及解决
你直接将嵌套字典形式的states转成numpy数组,得到的是object类型数组(每个元素是字典),而非数值型数组,这会导致reshape操作完全不匹配,出现“期望3D输入,得到(1,1)数组”的错误。
解决步骤:
统一预处理观测:在将观测存入replay buffer前,先转换成数值数组:
def preprocess_observation(obs): # 提取elem_1的数值 elem1 = np.array([obs["elem_1"]]) # 提取elem_2中所有子字典的属性值 elem2 = [] for sub_dict in obs["elem_2"]: elem2.extend([ sub_dict["prop_1"], sub_dict["prop_2"], sub_dict["prop_3"], sub_dict["prop_4"], sub_dict["prop_5"], sub_dict["prop_6"], sub_dict["prop_7"], sub_dict["prop_8"] ]) elem2 = np.array(elem2) # 拼接成一维数组 return np.concatenate([elem1, elem2])每次从环境获取
obs后,调用preprocess_observation(obs)得到513维数组,再存入replay buffer。修正replay函数:
def replay(self, replay_buffer, batch_size, model, target_model): if len(replay_buffer) < batch_size: return samples = random.sample(replay_buffer, batch_size) zipped_samples = list(zip(*samples)) states, actions, rewards, new_states, dones = zipped_samples # 此时states已是(batch_size, 513)的数值数组 states = np.array(states) # 若模型期望3D输入(如(batch_size, 1, 513)),执行reshape states = states.reshape((batch_size, 1, 513)) targets = target_model.predict(states, verbose=0) new_states = np.array(new_states) new_states = new_states.reshape((batch_size, 1, 513)) q_values = model.predict(new_states, verbose=0)匹配模型输入:确保你的Sequential模型输入层形状与预处理后的数组一致——如果输入层定义为
Input(shape=(1,513)),则reshape正确;如果是Input(shape=(513,)),则无需reshape成3D。
内容的提问来源于stack exchange,提问作者Ai_Nebula
相关产品推荐
相关产品推荐

