Scikit-learn时间序列数据的交叉验证自定义拆分

15

我想使用scikit-learn的GridSearchCV确定随机森林模型的一些超参数。我的数据是时间相关的,看起来像这样:

import pandas as pd

train = pd.DataFrame({'date': pd.DatetimeIndex(['2012-1-1', '2012-9-30', '2013-4-3', '2014-8-16', '2015-3-20', '2015-6-30']), 
'feature1': [1.2, 3.3, 2.7, 4.0, 8.2, 6.5],
'feature2': [4, 4, 10, 3, 10, 9],
'target': [1,2,1,3,2,2]})

>>> train
        date  feature1  feature2  target
0 2012-01-01       1.2         4       1
1 2012-09-30       3.3         4       2
2 2013-04-03       2.7        10       1
3 2014-08-16       4.0         3       3
4 2015-03-20       8.2        10       2
5 2015-06-30       6.5         9       2

我该如何实现以下的交叉验证折叠技术?

train:(2012, 2013) - test:(2014)
train:(2013, 2014) - test:(2015)

也就是说,我想使用两年的历史观测数据来训练模型,并在随后的一年测试其准确性。

3个回答

22

您只需要传递包含划分的可迭代对象给GridSearchCV。此划分应具有以下格式:

[
 (split1_train_idxs, split1_test_idxs),
 (split2_train_idxs, split2_test_idxs),
 (split3_train_idxs, split3_test_idxs),
 ...
]

要获取idxs,您可以像这样操作:

groups = df.groupby(df.date.dt.year).groups
# {2012: [0, 1], 2013: [2], 2014: [3], 2015: [4, 5]}
sorted_groups = [value for (key, value) in sorted(groups.items())] 
# [[0, 1], [2], [3], [4, 5]]

cv = [(sorted_groups[i] + sorted_groups[i+1], sorted_groups[i+2])
      for i in range(len(sorted_groups)-2)]

这看起来像这样:

[([0, 1, 2], [3]),  # idxs of first split as (train, test) tuple
 ([2, 3], [4, 5])]  # idxs of second split as (train, test) tuple

然后你可以这样做:

GridSearchCV(estimator, param_grid, cv=cv, ...)

10

TimeSeriesSplit 函数也在 sklearn 中提供,用于将时间序列数据(即具有固定时间间隔的数据)划分为训练/测试集。需要注意的是,与标准交叉验证方法不同的是,连续的训练集是之前训练集的超集,即在每个划分中,测试索引必须比之前更高,因此交叉验证器中的洗牌是不合适的。


6
有标准的 sklearn 方法来解决这个问题,使用GroupShuffleSplit。官方文档如下所示: 提供随机的训练/测试索引,以根据第三方提供的组拆分数据。此组信息可以用作将样本编码为整数的任意特定领域分层的方法。 例如,这些分组可以是样本收集的年份,从而允许针对基于时间的拆分进行交叉验证。 非常方便适用于您的用例。以下是它的样子:
cv = GroupShuffleSplit().split(X, y, groups)

然后像之前一样将其传递给GridSearchCV

GridSearchCV(estimator, param_grid, cv=cv, ...)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接