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

如何将自定义拆分的DataFrame作为训练集与验证集传入GridSearchCV?

自定义时间拆分验证集的GridSearchCV参数调优问题

问题背景

我是一名刚涉足机器学习领域的程序员,现有2010-2019年的数据,需对梯度提升回归(GradientBoostingRegressor)模型进行参数调优,计划采用60%数据训练、20%验证、20%测试的方案。根据研究需求,我已按时间维度拆分出:train_df(2010-2014年)、evaluate_df(2015-2017年)、test_df(2018-2019年)。期望用train_df训练模型,evaluate_df作为验证集调参,最终用最优模型在test_df上测试。

我的代码如下:

p_test3 = {'learning_rate':[0.1,0.05,0.01,0.005], 'n_estimators':[500,750,1000,1250,1500]}

tuning = GridSearchCV(estimator =GradientBoostingRegressor( min_samples_split=2, min_samples_leaf=1, subsample=1,max_features='sqrt', random_state=10), 
            param_grid = p_test3, scoring='r2',n_jobs=-1, cv=evaluate_df)
tuning.fit(train_df[[col1]],train_df['col2'])
tuning.cv_results_, tuning.best_params_, tuning.best_score_

运行后出现报错:

ValueError: too many values to unpack (expected 2)

错误原因

GridSearchCV的cv参数不支持直接传入DataFrame。该参数的合法输入包括:

  • 整数(表示K折交叉验证的折数)
  • 交叉验证生成器/迭代器
  • PredefinedSplit对象
  • 包含(train_idx, val_idx)索引对的列表

直接传入evaluate_df会导致内部解析时无法正确拆分成训练/验证索引对,因此抛出too many values to unpack错误。

解决方案

针对固定时间拆分的验证集需求,有两种可行实现方式:

方式1:使用PredefinedSplit

将训练集和验证集合并后,通过标记区分训练/验证样本,再传入PredefinedSplit对象:

import numpy as np
import pandas as pd
from sklearn.model_selection import GridSearchCV, PredefinedSplit
from sklearn.ensemble import GradientBoostingRegressor

# 合并训练集与验证集的特征和目标变量
X = pd.concat([train_df[[col1]], evaluate_df[[col1]]], axis=0)
y = pd.concat([train_df['col2'], evaluate_df['col2']], axis=0)

# 生成拆分标记:-1表示属于训练集,0表示属于验证集
test_fold = np.concatenate([
    np.full(len(train_df), -1),
    np.full(len(evaluate_df), 0)
])
ps = PredefinedSplit(test_fold)

# 定义参数网格
p_test3 = {'learning_rate':[0.1,0.05,0.01,0.005], 'n_estimators':[500,750,1000,1250,1500]}

# 初始化GridSearchCV,传入PredefinedSplit作为cv参数
tuning = GridSearchCV(
    estimator=GradientBoostingRegressor(
        min_samples_split=2,
        min_samples_leaf=1,
        subsample=1,
        max_features='sqrt',
        random_state=10
    ),
    param_grid=p_test3,
    scoring='r2',
    n_jobs=-1,
    cv=ps
)

# 拟合数据
tuning.fit(X, y)

# 查看调参结果
print("交叉验证结果:", tuning.cv_results_)
print("最优参数:", tuning.best_params_)
print("最优R2分数:", tuning.best_score_)

方式2:手动构建索引对

直接定义训练集和验证集的索引列表,组成(train_idx, val_idx)的元组传入cv参数:

import pandas as pd
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import GradientBoostingRegressor

# 合并训练集与验证集
X = pd.concat([train_df[[col1]], evaluate_df[[col1]]], axis=0)
y = pd.concat([train_df['col2'], evaluate_df['col2']], axis=0)

# 手动生成训练/验证索引
train_indices = list(range(len(train_df)))
val_indices = list(range(len(train_df), len(train_df) + len(evaluate_df)))
cv_splits = [(train_indices, val_indices)]

# 初始化GridSearchCV
tuning = GridSearchCV(
    estimator=GradientBoostingRegressor(
        min_samples_split=2,
        min_samples_leaf=1,
        subsample=1,
        max_features='sqrt',
        random_state=10
    ),
    param_grid=p_test3,
    scoring='r2',
    n_jobs=-1,
    cv=cv_splits
)

# 拟合数据并查看结果
tuning.fit(X, y)
print(tuning.best_params_, tuning.best_score_)

后续测试

调参完成后,使用最优模型在test_df上测试:

best_model = tuning.best_estimator_
test_r2 = best_model.score(test_df[[col1]], test_df['col2'])
print("测试集R2分数:", test_r2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:05:55