通常堆叠算法使用 K 折交叉验证技术来预测用于 2 级预测的 oof 验证。
对于时间序列数据(比如股票走势预测),不能使用 K 折交叉验证,而时间序列验证(在 sklearn lib 上建议的一种)适合评估模型性能。在这种情况下,第一个折叠不应进行预测,最后一个折叠不应进行任何训练。我们如何对时间序列数据使用堆叠算法交叉验证技术?
通常堆叠算法使用 K 折交叉验证技术来预测用于 2 级预测的 oof 验证。
对于时间序列数据(比如股票走势预测),不能使用 K 折交叉验证,而时间序列验证(在 sklearn lib 上建议的一种)适合评估模型性能。在这种情况下,第一个折叠不应进行预测,最后一个折叠不应进行任何训练。我们如何对时间序列数据使用堆叠算法交叉验证技术?
时间序列算法假设数据点是有序的。传统的 K-Fold不能用于时间序列,因为它没有考虑数据点出现的顺序。验证时间序列算法的一种方法是使用基于时间的拆分。
下面的两张图显示了 K-Fold 和基于时间的拆分之间的差异。从它们中,可以观察到以下特征。
K-Fold 总是所有数据点。
时基拆分使用所有数据点的一小部分。
K-Fold 让测试集是任何数据点。
时基拆分只允许测试集比训练集具有更高的索引。
K-Fold 将使用第一个数据点进行测试,最后一个数据点进行训练。
Time Base Splitting永远不会使用第一个数据点进行测试,也永远不会使用最后一个数据点进行训练。
Scikit-learn 有一个名为TimeSeriesSplit的算法实现。
查看他们的文档,您会发现以下示例:
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=5)
for train_index, test_index in tscv.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
>> TRAIN: [0] TEST: [1]
>> TRAIN: [0 1] TEST: [2]
>> TRAIN: [0 1 2] TEST: [3]
>> TRAIN: [0 1 2 3] TEST: [4]
>> TRAIN: [0 1 2 3 4] TEST: [5]
sklearn 的标准TimeSeriesSplit
无法使用,StackingRegressor
因为在后台StackingRegressor
使用cross_val_predict
。这将导致如下错误:
cross_val_predict 仅适用于分区
要使用时间序列和 sklearn 模型进行堆叠,您只需编写这几行代码......
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import TimeSeriesSplit
# generate dummy data
X = np.random.uniform(0,1, (1000,10))
y = np.random.uniform(0,1, (1000,))
# initialize two models to be stacked
rf = RandomForestRegressor()
gb = GradientBoostingRegressor()
# generate cross-val-prediction with rf and gb using TimeSeriesSplit
cross_val_predict = np.row_stack([
np.column_stack([
rf.fit(X[id_train], y[id_train]).predict(X[id_test]),
gb.fit(X[id_train], y[id_train]).predict(X[id_test]),
y[id_test] # we add in the last position the corresponding fold labels
])
for id_train,id_test in TimeSeriesSplit(n_splits=3).split(X)
]) # (test_size*n_splits, n_models_to_stack+1)
# final fit rf and gb with all the available data
rf.fit(X,y)
gb.fit(X,y)
# fit a linear stacking on cross_val_predict
stacking = LinearRegression()
stacking.fit(cross_val_predict[:,:-1], cross_val_predict[:,-1])
# how generate predictions on new unseen data
X_new = np.random.uniform(0,1, (30,10))
pred = stacking.predict(
np.column_stack([
rf.predict(X_new),
gb.predict(X_new)
])
)