关于在cross_val_score中使用TimeSeriesSplit时CV参数传递正确性的问询
时间序列交叉验证的参数传递问题解答
1. 当前CV参数传递方式不正确
你现在用cv=time_split.split(scaled_train)的写法是错误的,cross_val_score的cv参数直接传入TimeSeriesSplit对象即可,它会自动调用拆分器的split方法处理输入的特征数据,不需要手动生成拆分索引。
2. 拆分对象的选择:既不能用input_data,也不该直接用scaled_train
- 绝对不能用
split(input_data):你已经将数据拆分为训练集和测试集,交叉验证只能在训练集内部执行,触碰测试集属于数据泄露,会导致模型评估结果失真。 - 不能直接用
scaled_train:你当前的写法是先对整个训练集做归一化,再进行交叉验证,这会让每个验证折的缩放用到了整个训练集的统计量(均值、方差),属于提前泄露了验证集的信息,评估结果不准确。
3. 正确做法:用Pipeline封装预处理+模型,避免数据泄露
时间序列交叉验证的核心是每个折内独立完成预处理,用Pipeline把缩放操作和模型绑定,让每个交叉验证折都单独拟合scaler,再训练模型。
修正后的代码如下:
from sklearn.pipeline import Pipeline def fit_model1(data: pd.DataFrame): df = data scores_fit_model1 = [] for sizes in test_sizes: # 划分训练/测试集(shuffle=False保证时间序列顺序不被打乱) input_data = df.drop('next_count', axis=1) output_data = df[['next_count']] X_train, X_test, y_train, y_test = train_test_split(input_data, output_data, test_size=sizes, random_state=0, shuffle=False) # 构建管道:先执行归一化,再训练线性回归模型 pipeline = Pipeline([ ('scaler', MinMaxScaler()), ('lr', LinearRegression()) ]) # 初始化时间序列拆分器 time_split = TimeSeriesSplit(n_splits=10) # 交叉验证:直接传入管道、原始训练集特征和标签,cv参数传入拆分器对象 r2_scores = cross_val_score(pipeline, X_train, y_train.values.ravel(), cv=time_split, scoring='r2', n_jobs=1) scores_fit_model1.append(r2_scores.mean()) # 可选:用整个训练集拟合管道,对测试集进行预测 pipeline.fit(X_train, y_train.values.ravel()) predictions = pipeline.predict(X_test) return scores_fit_model1
关键说明
- Pipeline解决了数据泄露问题:每个交叉验证折都会单独拟合scaler,仅用当前训练折的数据计算缩放统计量,完全符合时间序列的时序要求。
- 直接传TimeSeriesSplit对象给cv:
cross_val_score会自动遍历拆分器生成的训练/验证索引对,不需要手动调用split方法。 - 用原始X_train而非缩放后的数据:因为缩放操作已封装到管道中,传入原始数据才能保证每个折的预处理独立执行。
内容的提问来源于stack exchange,提问作者user14738548
相关产品推荐
相关产品推荐

