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

如何获取Keras GridSearchCV所有超参数组合的全轮次训练历史

获取Keras GridSearchCV中所有超参数组合的每轮训练历史

嘿,我完全懂你想要的——不只是GridSearchCV给出的平均得分,而是每个超参数组合在每一轮epoch的完整训练/验证准确率记录对吧?默认的GridSearchCV确实不会帮你保存这些细节,但我们可以通过自定义Keras分类器包装器来实现这个需求。

下面是具体的实现步骤,一步步来:

1. 自定义KerasClassifier子类,保存训练历史

首先,我们需要创建一个继承自KerasClassifier的子类,它会在每个折叠训练时自动保存该模型的训练历史:

from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
import pandas as pd

class HistoryTrackingKerasClassifier(KerasClassifier):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.fold_histories = []  # 存储当前折叠的训练历史
    
    def fit(self, X, y, **kwargs):
        # 调用父类的fit方法,获取训练历史
        training_history = super().fit(X, y, **kwargs)
        # 将当前折叠的历史添加到列表中
        self.fold_histories.append(training_history.history)
        return training_history

2. 定义模型构建函数与参数网格

接下来,你需要定义你的Keras模型构建函数(接受超参数作为输入),以及要搜索的参数网格:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

def build_keras_model(units=64, activation='relu'):
    model = Sequential()
    model.add(Dense(units, activation=activation, input_shape=(X_train.shape[1],)))
    model.add(Dense(1, activation='sigmoid'))  # 假设是二分类任务
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    return model

# 定义要搜索的超参数网格
param_grid = {
    'units': [32, 64, 128],
    'activation': ['relu', 'tanh'],
    'epochs': [10, 20]  # 也可以把epochs作为超参数搜索
}

3. 运行GridSearchCV并收集所有历史数据

现在用我们自定义的分类器包装模型,运行网格搜索,然后从结果中提取每个超参数组合的所有折叠训练历史:

from sklearn.model_selection import GridSearchCV

# 初始化自定义分类器
model = HistoryTrackingKerasClassifier(build_fn=build_keras_model, batch_size=32, verbose=0)

# 初始化GridSearchCV,设置交叉验证折数
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=3, verbose=1)
grid_results = grid_search.fit(X_train, y_train)

# 创建字典存储所有超参数组合的历史数据
all_param_histories = {}

# 遍历每个超参数组合
for idx, params in enumerate(grid_results.cv_results_['params']):
    # 将参数转为可哈希的键(比如字符串)
    param_key = str(params)
    # 获取该参数组合对应的所有折叠的模型实例
    fold_history_list = []
    for fold_num in range(grid_search.cv):
        # 计算当前折叠的模型在cv_results_中的索引
        estimator_idx = idx * grid_search.cv + fold_num
        fold_estimator = grid_results.cv_results_['estimator'][estimator_idx]
        # 添加该折叠的训练历史
        fold_history_list.extend(fold_estimator.fold_histories)
    
    all_param_histories[param_key] = fold_history_list

4. 分析与可视化历史数据

现在all_param_histories里就保存了每个超参数组合对应的所有折叠的每轮训练历史。你可以把这些数据转换成DataFrame,方便分析或绘图:

def convert_history_to_dataframe(histories):
    df_list = []
    for fold_idx, hist in enumerate(histories):
        df = pd.DataFrame(hist)
        df['fold'] = fold_idx + 1
        df['epoch'] = df.index + 1
        df_list.append(df)
    return pd.concat(df_list, ignore_index=True)

# 示例:获取units=32, activation='relu', epochs=10的历史数据
target_params = "{'units': 32, 'activation': 'relu', 'epochs': 10}"
history_df = convert_history_to_dataframe(all_param_histories[target_params])

# 查看前5轮的数据
print(history_df.head())

# 绘制该参数组合的训练/验证准确率变化
import matplotlib.pyplot as plt

plt.figure(figsize=(10,6))
for fold in history_df['fold'].unique():
    fold_data = history_df[history_df['fold'] == fold]
    plt.plot(fold_data['epoch'], fold_data['accuracy'], label=f'Fold {fold} - Train Acc')
    plt.plot(fold_data['epoch'], fold_data['val_accuracy'], label=f'Fold {fold} - Val Acc')

plt.title('Training & Validation Accuracy per Epoch')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

注意事项

  • 这种方法会占用更多内存,因为要保存所有模型的每轮训练数据,如果你的参数组合多、epoch数大,需要注意内存限制。
  • 如果你的任务是多分类,记得修改模型的输出层和损失函数,对应的metrics也要调整(比如metrics=['categorical_accuracy'])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:36:11