实现Doom(VizDoom)深度Q网络时的形状不兼容问题
解决DQN中VizDoom动作独热编码的形状不兼容问题
嘿,我之前在做VizDoom的DQN项目时也踩过类似的形状坑,让我帮你捋清楚问题所在和解决办法!
问题根源分析
你提到的形状不兼容错误,核心问题出在动作独热编码的维度不对:
- 你的原始动作已经是
[Batch_size, 3]的独热形式(比如[[True, False, False], ...]),这其实就是DQN计算Q值时需要的正确形状。 - 但你额外做了一次独热编码后,得到了
[BatchSize, 3, 3]的三维数组,这就和网络输出的Q值(通常是[BatchSize, 3])维度不匹配,自然会在逐元素相乘时报错。
具体解决方案
1. 停止对已独热的动作重复编码
你的原始动作数组已经是合法的独热编码了,不需要再做额外的独热处理。如果是从动作索引(比如0、1、2)生成独热编码,用下面的代码就能得到正确的[BatchSize, 3]形状:
# 假设actions是形状为[BatchSize]的动作索引数组(比如每个元素是0/1/2) actions_one_hot = tf.one_hot(actions, depth=3)
如果你的动作已经是布尔型的[BatchSize,3]数组,直接转成浮点型就能用:
actions_one_hot = tf.cast(your_boolean_action_array, tf.float32)
2. 正确计算选中动作的Q值
当q_values(网络输出,形状[BatchSize, 3])和actions_one_hot(形状[BatchSize, 3])维度匹配后,用下面的代码计算每个样本对应选中动作的Q值:
# 逐元素相乘后对动作维度求和,得到每个样本的单个Q值 selected_q_values = tf.reduce_sum(q_values * actions_one_hot, axis=1, keepdims=True)
这里axis=1指定对每个样本的3个动作维度求和,keepdims=True会保持结果形状为[BatchSize, 1],方便后续和目标Q值计算损失时维度对齐。
3. 排查三维数组的来源
如果你的actions_one_hot还是三维的,建议在每个处理动作的步骤后打印形状:
print(your_action_array.shape) print(processed_action.shape)
大概率是你在某个步骤对已经是独热的数组又做了一次独热编码,或者误操作增加了维度(比如用了错误的axis参数)。
总结
核心原则就是:确保动作独热编码的形状和网络输出Q值的最后一个维度一致(都是[BatchSize, 动作数量]),这样逐元素相乘和求和的操作就能顺利进行。
内容的提问来源于stack exchange,提问作者Thomas Simonini
相关产品推荐
相关产品推荐

