sklearn:用户定义的时间序列数据交叉验证
Posted
技术标签:
【中文标题】sklearn:用户定义的时间序列数据交叉验证【英文标题】:sklearn: User defined cross validation for time series data 【发布时间】:2016-02-28 22:17:56 【问题描述】:我正在尝试解决机器学习问题。我有一个带有 time-series 元素的特定数据集。对于这个问题,我使用了著名的 python 库 - sklearn
。这个库中有很多交叉验证迭代器。还有几个迭代器用于自己定义交叉验证。问题是我真的不知道如何为时间序列定义简单的交叉验证。这是我想要得到的一个很好的例子:
假设我们有几个时期(年),我们想将我们的数据集分成几个块,如下所示:
data = [1, 2, 3, 4, 5, 6, 7]
train: [1] test: [2] (or test: [2, 3, 4, 5, 6, 7])
train: [1, 2] test: [3] (or test: [3, 4, 5, 6, 7])
train: [1, 2, 3] test: [4] (or test: [4, 5, 6, 7])
...
train: [1, 2, 3, 4, 5, 6] test: [7]
我真的不明白如何使用 sklearn 工具创建这种交叉验证。可能我应该像这样使用sklearn.cross_validation
中的PredefinedSplit
:
train_fraction = 0.8
train_size = int(train_fraction * X_train.shape[0])
validation_size = X_train.shape[0] - train_size
cv_split = cross_validation.PredefinedSplit(test_fold=[-1] * train_size + [1] * validation_size)
结果:
train: [1, 2, 3, 4, 5] test: [6, 7]
但还是不如之前的数据拆分好
【问题讨论】:
你的数据集中有哪些变量?为什么使用时间序列进行拆分很重要,为什么不随机拆分? 您可以在不使用 scikit-learn 的情况下生成拆分,如下所示:cv_split = [(data[:i], data[i:]) for i in range(1, len(data))]
。你怎么看?
@maxymoo,不使用时间序列数据随机拆分的原因是时间可能很重要(不仅仅是您确定的其他功能),但“在野外”您永远无法训练您的模型来自未来的数据。因此,在测试您的模型时,您应该采取类似的行为,而不是使用测试日期之后的数据进行训练。
@DanOneață 很抱歉,我没有在问题中提及这一点,但在创建 PredifinedSplit
之后,我将其放入需要交叉验证生成器或可迭代生成火车的 RFECV
/test 分裂。所以我可能可以用 sklearn 工具解决问题
@Demyanov 但是,如果我们将data
视为数据的索引,那么我上面定义的cv_split
是一个产生训练/测试拆分的可迭代对象。
【参考方案1】:
您可以在不使用sklearn
的情况下获得所需的交叉验证拆分。这是一个例子
import numpy as np
from sklearn.svm import SVR
from sklearn.feature_selection import RFECV
# Generate some data.
N = 10
X_train = np.random.randn(N, 3)
y_train = np.random.randn(N)
# Define the splits.
idxs = np.arange(N)
cv_splits = [(idxs[:i], idxs[i:]) for i in range(1, N)]
# Create the RFE object and compute a cross-validated score.
svr = SVR(kernel="linear")
rfecv = RFECV(estimator=svr, step=1, cv=cv_splits)
rfecv.fit(X_train, y_train)
【讨论】:
这不会在向前开窗时为每个观察创建一个单独的拆分吗?如果我想减少这个值,我应该在范围内使用step
参数使其以更大的“块”上升吗?
@dreyco676 没错。只需使用大于一的step
参数,例如cv_splits = [(idxs[:i], idxs[i:]) for i in range(1, N, 2)]
只是为了确定:StratifiedKFold 被抛在了后面,对吧?
@paulochf 你指的是StratifiedKFold
的导入吗?你是对的,那是未使用的——我将从代码 sn-p 中删除它。【参考方案2】:
同时这已添加到库中:http://scikit-learn.org/stable/modules/cross_validation.html#time-series-split
文档中的示例:
>>> from sklearn.model_selection import TimeSeriesSplit
>>> X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
>>> y = np.array([1, 2, 3, 4, 5, 6])
>>> tscv = TimeSeriesSplit(n_splits=3)
>>> print(tscv)
TimeSeriesSplit(n_splits=3)
>>> for train, test in tscv.split(X):
... print("%s %s" % (train, test))
[0 1 2] [3]
[0 1 2 3] [4]
[0 1 2 3 4] [5]
【讨论】:
以上是关于sklearn:用户定义的时间序列数据交叉验证的主要内容,如果未能解决你的问题,请参考以下文章