如何在Keras Tuner中查看每个试验的多次执行结果?
问题
我正尝试使用Keras Tuner的Hyperband算法为自编码器模型选择超参数,相关伪代码如下:
class AEHyperModel(kt.HyperModel): def __init_(self, input_shape): self.input_shape = input_shape def build(self, hp): # Input layer x = Input(shape=(input_shape,)) # Encoder layer 1 hp_units1 = hp.Choice('units1', values=[10, 15]) z = Dense(units=hp_units1, activation='relu')(x) # Encoder layer 2 hp_units2 = hp.Choice('units2', values=[3, 4]) z = Dense(units=hp_units2, activation='relu')(z) # Decoder y = Dense(units=hp_units1, activation='relu')(z) y = Dense(inputnodes,activation='linear')(y) # compile encoder autoencoder = Model(x,y) autoencoder.compile(optimizer='adam', loss='mean_squared_error') return autoencoder def fit(self, hp, autoencoder, *args, **kwargs): return autoencoder.fit(*args, batch_size=hp.Choice('batch_size', [16]), **kwargs)
超参数搜索代码如下:
tuner= kt.Hyperband(AEHyperModel(input_shape), objective='val_loss', max_epochs=100, factor=3, directory=os.path.join(softwaredir, 'AEhypertuning'), project_name='DRautoencoder2', overwrite=True, hyperband_iterations=5, executions_per_trial=5) # patient early stopping and tensorboard callback callbacks=[EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=20, restore_best_weights=True), keras.callbacks.TensorBoard('C:/whatever/tmp/tb_logs')] # Search the best hyperparameters for the model tuner.search(Xz, Xz, epochs=100, shuffle=True, validation_data=(valz, valz), callbacks=[callbacks])
我设置了executions_per_trial=5,但查看试验指标时仅显示单次执行结果:
tuner.oracle.trials['0000'].metrics.metrics['val_loss'].get_history() Out[19]: [MetricObservation(value=[0.118283973634243], step=1)] tuner.oracle.trials['0000'].metrics.metrics['val_loss'].get_statistics() Out[20]: {'min': 0.118283973634243, 'max': 0.118283973634243, 'mean': 0.118283973634243, 'median': 0.118283973634243, 'var': 0.0, 'std': 0.0}
请问如何真正实现每个试验的多次执行,并获取每次执行的结果,或至少获取均值和标准差以了解结果稳定性?
解决方法
1. 修正HyperModel的fit方法
当前fit方法直接返回单次训练结果,没有处理多次执行的逻辑,导致executions_per_trial参数失效。需要手动循环执行训练,记录每次结果并计算统计量:
import numpy as np class AEHyperModel(kt.HyperModel): def __init__(self, input_shape, inputnodes): self.input_shape = input_shape self.inputnodes = inputnodes # 补充初始化inputnodes,避免未定义错误 def build(self, hp): # Input layer x = Input(shape=(self.input_shape,)) # Encoder layer 1 hp_units1 = hp.Choice('units1', values=[10, 15]) z = Dense(units=hp_units1, activation='relu')(x) # Encoder layer 2 hp_units2 = hp.Choice('units2', values=[3, 4]) z = Dense(units=hp_units2, activation='relu')(z) # Decoder y = Dense(units=hp_units1, activation='relu')(z) y = Dense(self.inputnodes, activation='linear')(y) autoencoder = Model(x,y) autoencoder.compile(optimizer='adam', loss='mean_squared_error') return autoencoder def fit(self, hp, model, *args, **kwargs): executions = hp.get('executions_per_trial', 5) all_val_loss = [] for _ in range(executions): # 每次执行重新构建模型,保证权重初始化独立 model = self.build(hp) history = model.fit(*args, batch_size=hp.Choice('batch_size', [16]), **kwargs) # 记录最后一轮的验证损失 all_val_loss.append(history.history['val_loss'][-1]) # 返回统计指标,供Keras Tuner记录 return { 'val_loss': np.mean(all_val_loss), 'val_loss_std': np.std(all_val_loss), 'all_val_loss': all_val_loss }
2. 修正tuner.search的回调参数
你在传入回调时嵌套了一层列表[callbacks],会导致回调无法正确生效,改为直接传入列表:
tuner.search(Xz, Xz, epochs=100, shuffle=True, validation_data=(valz, valz), callbacks=callbacks) # 移除外层的[]
3. 获取多次执行的结果
修改后,可通过以下方式提取单次试验的所有执行数据:
# 获取指定试验 trial = tuner.oracle.trials['0000'] # 获取所有执行的验证损失 all_execution_loss = trial.metrics.metrics['all_val_loss'].get_history()[0].value # 获取均值和标准差 loss_mean = trial.metrics.metrics['val_loss'].get_history()[0].value[0] loss_std = trial.metrics.metrics['val_loss_std'].get_history()[0].value[0] print("所有执行的验证损失:", all_execution_loss) print("均值:", loss_mean) print("标准差:", loss_std)
关键注意事项
- 每次执行重新构建模型:确保每次训练的权重初始化不同,避免因复用权重导致结果一致。
- 补充
inputnodes初始化:原代码中Dense(inputnodes)未定义inputnodes,需在__init__中传入并存储。 - 自定义指标存储:通过返回字典的方式,将所有执行结果、均值、标准差都作为指标保存,方便后续分析稳定性。
内容的提问来源于stack exchange,提问作者YoungResearcher
相关产品推荐
相关产品推荐

