ConvLSTM比特币价格预测模型输入输出维度异常问题排查
问题根源
1. 输入维度必须匹配的原因
你在定义模型时写死了InputLayer(input_shape=(111,32,1)),Keras静态计算图构建完成后,输入的时间步长度、特征数、通道数就被固定,再加上你用了Flatten层,该层会把输入的所有维度压平为固定长度的向量,和后续全连接层的权重维度强绑定,一旦测试输入的时间步不是111,压平后的向量维度就会和全连接层要求的维度不匹配,自然会报错。并不是所有深度学习模型都支持可变输入维度,是否支持完全取决于模型的层结构。
2. 仅返回10个预测结果的原因
你代码中的RepeatVector(5)层会把前面Flatten输出的向量重复5次,搭配后续return_sequences=True的LSTM层、TimeDistributed封装的全连接层,最终模型的输出维度固定为(样本数, 5, 1),也就是每输入一段111天的特征,只会输出未来5天的预测值。你调用了两次predict,每次返回5个结果,加起来总共就是10个,自然凑不够136个要求的预测值。
解决方法
1. 调整预测逻辑适配多步输出
你当前的模型属于「输入N天历史数据,输出未来K天预测值」的多步预测架构,要得到136个预测值,需要用滑动窗口处理测试集:每次取连续111天的测试特征作为输入,预测接下来5天的价格,之后窗口向后滑动5天,重复预测,直到拼接的预测结果覆盖全部136个待预测时段即可。
2. 可选:修改模型支持可变输入长度
如果不想固定输入的时间步长度,可以把输入层改为InputLayer(input_shape=(None,32,1)),同时删掉Flatten层,替换为全局池化层(比如GlobalAveragePooling2D)适配可变长度的输入,避免维度绑定。
3. 修复训练侧的隐藏问题
- 测试集的归一化缩放器必须用训练集拟合得到的scaler,不能单独对测试集调用
fit_transform,否则会导致训练测试数据分布不一致,预测结果完全失效。 - 你当前逐段对分割数据集调用
fit的方式会让模型遗忘之前学习到的历史特征,建议把所有分割的训练数据拼接为(样本数, 111, 32, 1)格式的批量数据集,用小批量方式训练,效果会更好。
4. 维度排查通用技巧
每次构建完模型后打印model.summary(),核对每一层的输入输出维度,就能提前发现输出步长不符合预期的问题;每次预测前核对测试输入的维度,除了batch维度之外,其余维度必须和训练输入的维度完全一致。
内容的提问来源于stack exchange,提问作者Centauri_42

