使用Keras Tuner时遇TensorFlow错误:迭代器图与数据集创建图不一致
Keras Tuner搭配TensorFlow Dataset时的图不匹配错误解决
问题描述
使用Keras Tuner进行超参数调优,以TensorFlow BatchDataset作为输入时,触发以下错误:
ValueError: The graph of the iterator is different from the graph the dataset: Tensor("PrefetchDataset:0", shape=(), dtype=variant) was created in. If you are using the Estimator API, make sure that no part of the dataset returned by the "input_fn" function is defined outside the "input_fn" function. Otherwise, make sure that the dataset is created in the same graph as the iterator.
错误触发于tuner.search(train_data, epochs=100, shuffle=False, validation_data=val_data)行,且不使用Keras Tuner时,相同模型与数据集可正常运行。
原代码
batch_size = 5 train_data = keras.utils.timeseries_dataset_from_array( x_train_scaled, y_train_scaled, 1, batch_size=batch_size, shuffle=False ) val_data = keras.utils.timeseries_dataset_from_array( x_val_scaled, y_val_scaled, 1, batch_size=batch_size, shuffle=False ) test_data = keras.utils.timeseries_dataset_from_array( x_test_scaled, y_test_scaled, 1, batch_size=batch_size, shuffle=False ) # design network def build_model(hp): model = keras.Sequential() model.add(keras.layers.LSTM(hp.Choice('units', [8, 16]), activation='relu', return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2]))) model.add(keras.layers.LSTM(hp.Choice('units', [8, 16]), activation='relu', return_sequences=True)) model.add(keras.layers.LSTM(hp.Choice('units', [8, 16]), activation='relu')) model.add(keras.layers.Dense(1)) model.compile(loss='mae', optimizer='adam') return model tuner = keras_tuner.RandomSearch( build_model, objective='val_loss', max_trials=100) tuner.search(train_data, epochs=100, shuffle=False, validation_data=val_data) best_model = tuner.get_best_models()[0]
错误原因
TensorFlow的图上下文不一致导致:全局上下文创建的Dataset对象,与Keras Tuner每个trial中构建模型/迭代器的新图上下文不匹配,引发迭代器与数据集的图冲突。
解决方案
方案一:将Dataset转换为Numpy数组
把BatchDataset转换为numpy数组,Keras Tuner对numpy数组的处理不存在图上下文问题:
import numpy as np # 转换训练集 x_train_list = [] y_train_list = [] for x_batch, y_batch in train_data: x_train_list.append(x_batch.numpy()) y_train_list.append(y_batch.numpy()) x_train_final = np.concatenate(x_train_list, axis=0) y_train_final = np.concatenate(y_train_list, axis=0) # 转换验证集 x_val_list = [] y_val_list = [] for x_batch, y_batch in val_data: x_val_list.append(x_batch.numpy()) y_val_list.append(y_batch.numpy()) x_val_final = np.concatenate(x_val_list, axis=0) y_val_final = np.concatenate(y_val_list, axis=0) # 执行超参搜索 tuner.search(x_train_final, y_train_final, epochs=100, shuffle=False, validation_data=(x_val_final, y_val_final))
方案二:在搜索时动态创建Dataset
将数据集的创建逻辑封装为函数,在tuner.search时调用函数生成Dataset,保证数据集与迭代器处于同一图上下文:
def create_train_dataset(): return keras.utils.timeseries_dataset_from_array( x_train_scaled, y_train_scaled, sequence_length=1, batch_size=batch_size, shuffle=False ) def create_val_dataset(): return keras.utils.timeseries_dataset_from_array( x_val_scaled, y_val_scaled, sequence_length=1, batch_size=batch_size, shuffle=False ) # 执行超参搜索 tuner.search(create_train_dataset(), epochs=100, shuffle=False, validation_data=create_val_dataset())
方案三:禁用即时执行(不推荐)
通过禁用TensorFlow的即时执行,强制使用静态图模式,避免图上下文冲突:
import tensorflow as tf tf.compat.v1.disable_eager_execution() # 后续原代码保持不变...
此方法可能影响其他依赖即时执行的代码逻辑,仅作为备选方案。
内容的提问来源于stack exchange,提问作者Meno
相关产品推荐
相关产品推荐

