使用Keras Tuner调优LSTM timesteps输入形状报错解决
问题根因
报错本质是传参逻辑和Keras Tuner执行流程不匹配:
- 你调用
tuner.search()时传入的build_model.scaled_train、build_model.train_label是调用瞬间的固定值,也就是初始化阶段timesteps=2时生成的形状为(4096, 2, 64)的数据,整个搜索流程启动后这份传入的数据不会自动更新。 - 你在
build_model内部虽然会根据当前trial的timesteps重新生成对应形状的数据,还把数据挂到了函数属性上,但tuner.search根本不会读取这个后续更新的属性,始终拿最开始传入的旧数据喂给每轮新构建的模型——而新模型的输入形状是和当前轮timesteps绑定的(比如timesteps=16时输入形状要求是(None,16,64)),喂进去形状为(None,2,64)的旧数据必然触发形状不匹配错误。 - 给函数挂自定义属性传递训练数据的写法本身不符合Keras Tuner的设计逻辑,数据处理流程不应该放在
build_model内部。
修复方案
把和超参数绑定的数据生成逻辑移到重写的run_trial方法中,保证每轮试验选到新的timesteps时,先生成对应形状的训练/验证数据,再传入模型训练。
修正后的核心代码如下:
# 提前保留好未做时序滑窗转换的原始基础数据DF、UF,不要提前做形状切分 def build_model(hp): timesteps = hp.Choice('timesteps', [2, 4, 8, 16], ordered=False) nosamples = 64 # 替换为你实际的特征维度值 model = keras.Sequential() model.add(keras.layers.InputLayer(input_shape=(timesteps, nosamples))) # 此处补充你原有的LSTM层、全连接层、输出层结构 # ... model.compile(optimizer="adam", loss="mse") # 替换为你实际使用的优化器、损失函数、评估指标 return model class MyTuner(keras_tuner.BayesianOptimization): def run_trial(self, trial, *args, **kwargs): hp = trial.hyperparameters # 读取当前轮试验的超参数取值 current_timesteps = hp.Choice('timesteps', [2, 4, 8, 16], ordered=False) kwargs['batch_size'] = hp.Choice('batch_size', [32, 64, 128, 256]) # 按当前timesteps生成对应形状的数据集 DFS, UFS = get_data_in_shape(DF, UF, current_timesteps) scaled_train, train_label = train_test_splitting(DFS, UFS) # 传入当前轮匹配形状的数据执行训练 return super().run_trial( trial, scaled_train, train_label, validation_split=0.2, epochs=100, callbacks=[early_stopping], **kwargs ) tuner = MyTuner( build_model, objective='val_loss', max_trials=20, overwrite=True, directory='/content/drive/MyDrive/Colab Notebooks', project_name='bo4' ) # 启动搜索时不需要提前传入固定数据集,每轮数据会在run_trial中动态生成 tuner.search()
注意事项
build_model的单一职责是根据传入的超参数对象构建、编译模型,不要在里面掺杂数据处理、数据集生成的逻辑。- 如果需要降低指标波动,不建议使用
validation_split随机拆分验证集,可以提前针对每个timesteps生成固定的验证集,在run_trial中通过validation_data参数传入,保证每轮试验的验证集分布一致。
内容的提问来源于stack exchange,提问作者Srijan
相关产品推荐
相关产品推荐

