You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Keras Tuner调参时,TensorBoard提取数据遇KeyError问题求助

解决Keras Tuner回归任务中TensorBoard标量提取的KeyError问题

问题场景

用Keras Tuner对序列神经网络做回归任务超参调优,采用MSE作为损失函数,需要提取所有试验的损失、超参数、试验编号、训练轮次等数据存到文件用于后续绘图。基于官方教程搭建框架后,使用TensorBoard回调提取数据时出现KeyError: 'Key epoch_loss was not found in Reservoir',且调用ea.scalars.Keys()返回空列表,无法获取正确的标量键名。

问题原因

  1. 路径错误:Keras Tuner默认会将每个试验的日志存放在project_name指定的目录下(示例中是keras_tuner_test),而非手动指定的sample_log_directory,导致找不到日志文件,ea.scalars.Keys()返回空。
  2. 键名错误:Keras默认的训练损失标量键是loss,验证损失是val_loss,而非代码中的epoch_loss;且回归任务未配置准确率指标,代码中尝试提取的epoch_acc本身不存在。
  3. 遍历不完整:代码仅提取了execution0的数据,未覆盖executions_per_trial指定的多次执行,会丢失部分数据。

解决方案

1. 调整TensorBoard回调配置

无需手动指定log_dir,Keras Tuner会自动在项目目录下为每个试验创建独立的日志子目录,确保日志路径正确。

2. 修正数据提取逻辑

  • 使用正确的标量键名loss和val_loss
  • 移除所有准确率相关的提取代码
  • 遍历所有试验和每个试验下的所有执行

3. 提取超参数信息

从tuner.oracle.trials中获取每个试验的超参数、试验ID、最终损失等信息,和训练过程的损失数据合并。

修改后的完整代码

模型与调参部分

import numpy as np
import keras
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import layers
import keras_tuner
from sklearn.model_selection import train_test_split
from tensorboard.backend.event_processing import event_accumulator
import pandas as pd

# 生成随机回归数据
random_data = np.random.rand(100,4)
x_data = random_data[:, :-1]
y_data = random_data[:, -1:]
input_dimensions = len(x_data[0, :])

# 划分训练集和验证集
x_train, x_eval, y_train, y_eval = train_test_split(x_data, y_data, test_size=0.3, random_state=101)

# 构建超参数模型
def build_model(hp):
    model = keras.Sequential()
    # 搜索层数、每层神经元数、激活函数
    for i in range(hp.Int("num_layers", 2, 4)):
        model.add(layers.Dense(
                units=hp.Int(f"units_{i}", min_value=32, max_value=1024, step=32),
                activation=hp.Choice("activation", ["relu", "sigmoid"])))
    model.add(layers.Dense(1, activation="linear"))
    model.compile(optimizer=Adam(learning_rate=0.0005), 
                  loss='mse')

    return model

# 初始化调优器
tuner = keras_tuner.RandomSearch(
    hypermodel=build_model, 
    objective=keras_tuner.Objective('val_loss', direction="min"),  # 用验证损失更合理
    max_trials=5,
    executions_per_trial=3, 
    overwrite=True, 
    project_name="keras_tuner_test")

# 添加TensorBoard回调,无需指定log_dir,自动存在keras_tuner_test目录下
tensorboard_callback = keras.callbacks.TensorBoard()
tuner.search(x_train, y_train, epochs=3, validation_data=(x_eval, y_eval), callbacks=[tensorboard_callback])

数据提取与保存部分

def extract_trial_data(trial_id, project_dir="keras_tuner_test"):
    """提取单个试验所有执行的训练/验证损失数据"""
    trial_data = []
    # 遍历所有执行(executions_per_trial指定的次数)
    for exec_idx in range(tuner.executions_per_trial):
        log_dir = f"{project_dir}/{trial_id}/execution{exec_idx}"
        # 加载训练日志
        train_ea = event_accumulator.EventAccumulator(f"{log_dir}/train")
        train_ea.Reload()
        # 加载验证日志
        val_ea = event_accumulator.EventAccumulator(f"{log_dir}/validation")
        val_ea.Reload()
        
        # 获取训练损失序列
        train_loss = [scalar.value for scalar in train_ea.Scalars('loss')]
        # 获取验证损失序列
        val_loss = [scalar.value for scalar in val_ea.Scalars('val_loss')]
        
        # 按轮次整理数据
        for epoch in range(len(train_loss)):
            trial_data.append({
                "trial_id": trial_id,
                "execution_idx": exec_idx,
                "epoch": epoch+1,
                "train_loss": train_loss[epoch],
                "val_loss": val_loss[epoch]
            })
    return trial_data

# 提取所有试验的数据
all_data = []
for trial in tuner.oracle.trials.values():
    # 提取试验的超参数
    hyperparams = trial.hyperparameters.values
    # 提取训练过程数据
    trial_history = extract_trial_data(trial.trial_id)
    # 将超参数合并到每条记录中
    for record in trial_history:
        record.update(hyperparams)
        # 添加试验的最终损失
        record["final_val_loss"] = trial.score
        all_data.append(record)

# 转换为DataFrame并保存到CSV文件
df = pd.DataFrame(all_data)
df.to_csv("keras_tuner_trial_data.csv", index=False)
print("数据已保存到keras_tuner_trial_data.csv")

说明

  • 保存的CSV文件包含所有试验的试验ID、执行序号、训练轮次、训练损失、验证损失、所有超参数、最终验证损失,可直接用于绘图分析
  • 若需要查看日志中的所有标量键名,可在加载event_accumulator后打印train_ea.scalars.Keys(),确认可用的键

内容的提问来源于stack exchange,提问作者Tobitobitobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:30:06