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

RandomizedSearchCV+KerasClassifier训练机制与用法解析

Keras 结合 RandomizedSearchCV 做K折交叉验证的问题解答

背景

你持有一份训练数据集,计划通过K折交叉验证训练神经网络,采用keras-sklearn接口封装模型,核心实现代码如下:

# 模型初始化
model = KerasClassifier(build_fn=get_model_, epochs=120, batch_size=32, verbose=1)
# 超参数搜索空间
params = dict({'l2':[0.1,0.3,0.5,0.8],
               'dropout_rate':[0.1,0.3,0.5,0.8],
               'batch_size':[16,32,64,128],
               'learning_rate':[0.001, 0.01, 0.05, 0.1]})

def trainer(model, X, y, folds, params, verbose=None):
    from keras.wrappers.scikit_learn import KerasClassifier
    from tensorflow.keras.optimizers import Adam
    from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
    
    v = verbose if verbose else 0
    
    clf = RandomizedSearchCV(model, 
                         param_distributions = params, 
                         n_jobs = 1, 
                         scoring="roc_auc",
                         cv = folds, 
                         verbose = v)
    grid_result = clf.fit(X, y)
    # 结果输出
    print('- '*40)
    print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
    print('- '*40)

# 启动训练
trainer(model, X_train, y_train, folds, params, verbose=1)

其中get_model_为返回已编译tf.keras模型的自定义函数。


核心运行逻辑说明

默认流程下的运行规则

你对流程的基础推测符合默认逻辑:每一组待测试的超参数组合,会执行K轮独立训练,每轮取K-1折数据作为训练集训练指定epochs轮数,训练完成后在剩余1折上计算测试得分。关于你提到的几个核心机制问题,明确如下:

  • 该流程本身不直接防控模型训练过程的过拟合:K折交叉验证的核心作用是给出超参数组合的泛化性能无偏估计,避免在固定验证集上反复调参导致的超参数层面过拟合(即参数适配验证集特殊分布、换数据效果骤降的问题),训练过程的过拟合仍需通过L2正则、Dropout、早停等机制防控。
  • 原生Keras每轮epoch结束后的验证集评估逻辑,默认在当前流程中不生效:调用clf.fit(X,y)时未传入验证集拆分规则,KerasClassifier会将传入的全部数据作为训练集跑满设定的epochs,不会自动拆分验证折做epoch级评估,自然不会输出每轮的验证折得分。
  • 回调函数支持正常传入,不存在配置冲突:初始化KerasClassifier时可直接传入callbacks参数,RandomizedSearchCV不会修改回调逻辑,回调会在每折训练过程中正常生效。如果要监测val_prc指标,需要在每折训练时手动从训练折中拆分出验证子集传入fit方法——没有验证集数据的前提下,所有val_前缀的指标都无法计算。你可以通过自定义KerasClassifier子类重写fit方法,实现每折训练时自动拆分验证集的逻辑。

具体问题解答

1. 当前RandomizedSearchCV的使用是否正确?为什么始终提示Fitting 5 folds for each of 10 candidates, totalling 50 fits

你的写法整体符合接口调用规范,出现该提示是RandomizedSearchCV的默认机制导致的:

  • 和GridSearchCV遍历所有参数组合的逻辑不同,RandomizedSearchCV默认的参数采样次数n_iter=10,即无论参数空间总共有多少种组合,默认只会随机采样10组不同的参数组合做测试。
  • 当你传入的folds为5折拆分规则时,总拟合次数就是10组参数 * 5折 = 50次,和每个参数设置多少个可选值无关。如果需要增加测试的参数组合数量,初始化RandomizedSearchCV时手动设置n_iter为目标数值即可。

2. 数据不平衡、样本量不足场景下,模型得分异常偏低、loss偏高的原因

该问题通常由以下几类原因导致:

  • 超参数搜索空间设置不合理:你设置的学习率最大值为0.1、L2正则系数最大值为0.8,这两个参数的大值选项极易导致训练异常:0.1的学习率对于绝大多数神经网络任务来说过大,很容易跨过损失最低点导致训练发散;0.8的L2惩罚强度过高,会严重限制模型参数更新,直接导致模型欠拟合。
  • 样本不平衡适配缺失:你设置的评估指标为roc_auc,在样本极度不平衡场景下,如果未设置类别权重、未做采样处理,模型会直接偏向预测多数类,导致AUC得分极低;如果编译模型时使用普通交叉熵损失,也会加剧模型对多数类的偏向。
  • 无早停机制:当前配置下模型会固定跑满120个epochs,没有验证集触发早停逻辑,要么学习率过大导致训练发散loss飙升,要么正则强度过高导致模型无法学习有效特征,都会出现loss高、得分低的现象。
  • 数据预处理缺失:神经网络对输入特征尺度敏感,如果特征未做标准化/归一化处理,会直接导致收敛速度慢、训练效果差。

3. 当前代码的完整执行流程

在不修改现有代码的前提下,程序会严格按照以下顺序执行:

  1. RandomizedSearchCV初始化完成后,从你定义的params参数空间中,随机采样10组不同的超参数组合(包含l2、dropout_rate、batch_size、learning_rate四个参数的随机取值)。
  2. 对每一组采样到的超参数组合:
    • 按照传入的folds规则,将X_train、y_train拆分为K个互斥的数据折(默认5折)。
    • 依次遍历每一折:将当前折作为验证折,剩余K-1折作为训练折;调用get_model_函数,传入当前组超参数,生成一个全新的、权重随机初始化的编译完成的Keras模型。
    • 用当前训练折数据,按照当前组参数指定的batch_size连续训练120个epochs,训练全程不做epoch级验证,仅输出训练集上的训练进度和指标。
    • 训练完成后,在当前验证折上做预测,计算roc_auc得分并记录,之后丢弃当前训练好的模型,继续处理下一折。
    • 计算K折的平均roc_auc得分,作为该组超参数的最终性能得分。
  3. 10组超参数全部完成K折验证后,选出平均roc_auc得分最高的一组作为最优参数,对应得分记录为最优得分。
  4. 搜索流程结束后,RandomizedSearchCV会自动用全部X_train、y_train数据,以最优参数重新训练一个模型,作为clf对象的最终可用模型,该重训练过程同样会跑满120个epochs,无epoch级验证。
  5. 按照代码逻辑打印最优得分和最优参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:24:20