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

如何在Python中拆分含多日交易记录的时间序列用于机器学习交叉验证?

按日期分组的时间序列交叉验证实现

因为你的数据是按天聚合多条记录,直接用TimeSeriesSplit会把同一天的记录拆到训练和验证集里,这不符合时间序列的核心逻辑——训练集必须完全早于验证集。所以解决的核心是按日期维度拆分,再映射回原数据集的对应记录。

方法1:手动实现日期拆分

先提取所有唯一日期并按时间排序,再按需求划分训练/验证的日期区间,最后筛选对应的数据。

示例代码:

import pandas as pd

# 假设你的数据集是df,包含'date'列和其他特征、标签
df = pd.read_csv('your_transaction_data.csv')
df['date'] = pd.to_datetime(df['date'])

# 提取并排序唯一日期
unique_dates = df['date'].dt.date.unique()
unique_dates.sort()

# 定义交叉验证折数,比如5折
n_splits = 5
split_size = len(unique_dates) // n_splits

# 生成每一组训练/验证的日期区间
for i in range(n_splits):
    # 训练集日期:从起始到第(i+1)*split_size天
    train_dates = unique_dates[: (i+1)*split_size]
    # 验证集日期:下一个split_size天,最后一折取剩余所有日期
    val_dates = unique_dates[(i+1)*split_size : (i+2)*split_size] if (i+2)*split_size <= len(unique_dates) else unique_dates[(i+1)*split_size:]
    
    # 映射回原数据集
    train_df = df[df['date'].dt.date.isin(train_dates)]
    val_df = df[df['date'].dt.date.isin(val_dates)]
    
    # 这里插入你的模型训练逻辑
    print(f"第{i+1}折:训练集日期范围{train_dates[0]}至{train_dates[-1]},验证集日期范围{val_dates[0]}至{val_dates[-1]}")
    print(f"训练集样本数:{len(train_df)},验证集样本数:{len(val_df)}")

方法2:自定义sklearn兼容的交叉验证器

如果要和sklearn的cross_val_score等API配合使用,可以继承BaseCrossValidator实现自定义拆分逻辑,让代码更贴合sklearn生态:

from sklearn.model_selection import BaseCrossValidator
import pandas as pd

class DateBasedTimeSeriesSplit(BaseCrossValidator):
    def __init__(self, n_splits=5):
        self.n_splits = n_splits
        
    def get_n_splits(self, X=None, y=None, groups=None):
        return self.n_splits
    
    def split(self, X, y=None, groups=None):
        # 假设X是包含'date'列的DataFrame
        unique_dates = X['date'].dt.date.unique()
        unique_dates.sort()
        split_size = len(unique_dates) // self.n_splits
        
        for i in range(self.n_splits):
            val_start_idx = (i+1)*split_size
            val_end_idx = val_start_idx + split_size if (val_start_idx + split_size) <= len(unique_dates) else len(unique_dates)
            
            # 训练集取所有早于验证集的日期
            train_dates = unique_dates[:val_start_idx]
            val_dates = unique_dates[val_start_idx:val_end_idx]
            
            # 获取训练和验证集的行索引
            train_indices = X[X['date'].dt.date.isin(train_dates)].index
            val_indices = X[X['date'].dt.date.isin(val_dates)].index
            
            yield train_indices, val_indices

# 使用示例
df = pd.read_csv('your_transaction_data.csv')
df['date'] = pd.to_datetime(df['date'])

X = df.drop('target', axis=1)
y = df['target']

cv = DateBasedTimeSeriesSplit(n_splits=5)
for train_idx, val_idx in cv.split(X, y):
    X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
    y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
    
    # 模型训练逻辑
    print(f"训练集样本数:{len(X_train)},验证集样本数:{len(X_val)}")

注意事项

  • 必须确保date列是datetime格式,否则无法正确按日期筛选
  • 如果需要滚动验证(训练集每次累加之前所有日期,验证集固定窗口),只需调整train_dates为unique_dates[:val_start_idx]即可
  • 最后一折的验证集如果日期数量不足split_size,直接取剩余所有日期即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 13:55:17