如何针对数组输入调整DQN模型的输出形状?
DQN猜字母游戏模型:多维输出问题解决
问题背景
作为Python机器学习新手,搭建猜字母游戏的DQN模型时遇到形状不匹配错误。相关代码、模型结构及报错如下:
模型代码
states = def build_model(): model = Sequential() model.add(Dense(30, activation='relu', input_shape=(26,41))) model.add(Dense(30, activation='relu')) model.add(Dense(26, activation='linear')) return model model = build_model() model.summary()
生成的模型结构
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_1 (Dense) (None, 26, 30) 1260 dense_2 (Dense) (None, 26, 30) 930 dense_3 (Dense) (None, 26, 26) 806 ================================================================= Total params: 2,996 Trainable params: 2,996 Non-trainable params: 0 _________________________________________________________________
报错信息
Model output "Tensor("dense_61/BiasAdd:0", shape=(None, 26, 26), dtype=float32)" has invalid shape. DQN expects a model that has one dimension for each action, in this case 26.
问题解答
1. 为什么Dense层会输出多维形状?
Keras的Dense层默认仅对输入张量的最后一个维度执行全连接运算。你的输入形状是(26,41),意味着每个样本包含26组、每组41维的特征。第一个Dense(30)会对每组41维特征单独做全连接,输出26组30维特征,形状变为(None,26,30);后续Dense层延续这个逻辑,最终输出(None,26,26)——这就是多维输出的原因。
2. 如何将输出调整为符合DQN要求的1D向量?
DQN需要输出形状为(None,26)(每个样本对应26个动作的Q值),有两种简单可行的方法:
方法一:用Flatten层展平输入
在模型最开始加入Flatten层,把(26,41)的二维特征直接展平为1维的26*41=1066维向量,后续Dense层就会输出一维结果:
from keras.models import Sequential from keras.layers import Dense, Flatten def build_model(): model = Sequential() model.add(Flatten(input_shape=(26,41))) # 展平二维输入为一维 model.add(Dense(30, activation='relu')) model.add(Dense(30, activation='relu')) model.add(Dense(26, activation='linear')) return model model = build_model() model.summary()
调整后最终输出形状为(None,26),完全符合DQN的要求。
方法二:用全局池化层压缩多余维度
如果不想直接展平输入,可以在最后一个Dense层前加入GlobalAveragePooling1D或GlobalMaxPooling1D,把26组特征压缩为一组:
from keras.models import Sequential from keras.layers import Dense, GlobalAveragePooling1D def build_model(): model = Sequential() model.add(Dense(30, activation='relu', input_shape=(26,41))) model.add(Dense(30, activation='relu')) model.add(GlobalAveragePooling1D()) # 对26组特征做平均,压缩维度 model.add(Dense(26, activation='linear')) return model model = build_model() model.summary()
这种方法会保留特征的全局统计信息,最终输出同样是(None,26)。
注意:你之前尝试的Reshape层之所以没用,是因为错误地将
(26,26)转为了(780,1),但实际上我们需要的是去掉多余的26维度,而不是调整维度顺序或拆分维度——上述两种方法才是针对性的解决方案。
内容的提问来源于stack exchange,提问作者potatopowered
相关产品推荐
相关产品推荐

