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

如何解决GridSearchCV与自定义Keras模型的兼容报错问题?

如何让GridSearchCV与Keras自定义模型协作?

问题背景

尝试用GridSearchCV优化基于Keras构建的自定义模型超参数,现有代码及报错如下:

模型定义函数

def build_nn_model(n, hyperparameters, loss, metrics, opt):
    model = keras.Sequential([
    keras.layers.Dense(hyperparameters[0], activation=hyperparameters[1], # number of outputs to next layer
                           input_shape=[n]),  # number of features
    keras.layers.Dense(hyperparameters[2], activation=hyperparameters[3]),
    keras.layers.Dense(hyperparameters[4], activation=hyperparameters[5]),

    keras.layers.Dense(1) # 1 output (redshift)
    ])

    model.compile(loss=loss,
                  optimizer = opt,
            metrics = metrics)
    return model

网格搜索代码

optimizer = ['SGD', 'RMSprop', 'Adagrad', 'Adadelta', 'Adam', 'Adamax', 'Nadam']
epochs = [10, 50, 100]

param_grid = dict(epochs=epochs, optimizer=optimizer)
grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring='accuracy', n_jobs=-1, refit='boolean')
grid_result = grid.fit(X_train, y_train)

报错信息

TypeError: Cannot clone object '<keras.engine.sequential.Sequential object at 0x0000028B8C50C0D0>' (type <class 'keras.engine.sequential.Sequential'>): it does not seem to be a scikit-learn estimator as it does not implement a 'get_params' method.

解决方案

核心问题是Keras原生模型不兼容Scikit-learn的estimator接口,需要用Keras提供的包装器将模型转换为Scikit-learn兼容格式,同时调整参数传递方式。

1. 导入Keras包装器

因为你的模型是回归任务(输出连续值redshift),使用KerasRegressor:

from keras.wrappers.scikit_learn import KerasRegressor

2. 修改模型构建函数

将超参数拆分为独立参数,便于GridSearchCV直接传递不同组合:

def build_nn_model(n, dense1_units=64, dense1_act='relu', 
                   dense2_units=32, dense2_act='relu', 
                   dense3_units=16, dense3_act='relu',
                   optimizer='adam', loss='mse', metrics=['mae']):
    model = keras.Sequential([
        keras.layers.Dense(dense1_units, activation=dense1_act, input_shape=[n]),
        keras.layers.Dense(dense2_units, activation=dense2_act),
        keras.layers.Dense(dense3_units, activation=dense3_act),
        keras.layers.Dense(1)  # 回归任务输出1个连续值
    ])
    model.compile(loss=loss, optimizer=optimizer, metrics=metrics)
    return model

3. 初始化兼容Scikit-learn的estimator

# n为输入特征数量,替换为你的数据集特征数(比如X_train.shape[1])
estimator = KerasRegressor(build_fn=build_nn_model, n=X_train.shape[1], verbose=0)

4. 定义完整参数网格

包含所有需要搜索的超参数:

param_grid = {
    'epochs': [10, 50, 100],
    'optimizer': ['SGD', 'RMSprop', 'Adagrad', 'Adadelta', 'Adam', 'Adamax', 'Nadam'],
    'dense1_units': [32, 64, 128],
    'dense1_act': ['relu', 'tanh'],
    'dense2_units': [16, 32, 64],
    'dense2_act': ['relu', 'tanh']
}

5. 执行网格搜索

注意回归任务要使用回归类评分指标(如neg_mean_squared_error),而非分类用的accuracy:

grid = GridSearchCV(estimator=estimator, param_grid=param_grid, 
                    scoring='neg_mean_squared_error', n_jobs=-1, refit=True)
grid_result = grid.fit(X_train, y_train)

查看最佳结果

print(f"最佳得分: {grid_result.best_score_}")
print(f"最佳参数组合: {grid_result.best_params_}")

关键注意点

  • 回归任务用KerasRegressor,分类任务用KerasClassifier,需匹配对应评分指标。
  • 模型构建函数的参数名必须与param_grid中的键完全一致,才能让GridSearchCV正确传递参数。
  • 无需搜索的参数可在构建函数中设置默认值,不用加入param_grid。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:16:22