如何在scikit-learn中使用TimeSeriesSplit和GridSearchCV对象来调整模型?

38
我已经搜索过sklearn文档中的TimeSeriesSplit交叉验证文档,但是我没有找到一个可用的示例。
我正在使用sklearn版本0.19。
这是我的设置。
import xgboost as xgb
from sklearn.model_selection import TimeSeriesSplit
from sklearn.grid_search import GridSearchCV
import numpy as np
X = np.array([[4, 5, 6, 1, 0, 2], [3.1, 3.5, 1.0, 2.1, 8.3, 1.1]]).T
y = np.array([1, 6, 7, 1, 2, 3])
tscv = TimeSeriesSplit(n_splits=2)
for train, test in tscv.split(X):
    print(train, test)

提供:

[0 1] [2 3]
[0 1 2 3] [4 5]

如果我尝试:

model = xgb.XGBRegressor()
param_search = {'max_depth' : [3, 5]}

my_cv = TimeSeriesSplit(n_splits=2).split(X)
gsearch = GridSearchCV(estimator=model, cv=my_cv,
                        param_grid=param_search)
gsearch.fit(X, y)

错误信息为: TypeError: object of type 'generator' has no len()

问题出在: GridSearchCV 尝试调用 len(cv), 但是 my_cv 是一个没有长度的迭代器。然而,关于GridSearchCV的文档表明我可以使用

int、交叉验证生成器或可迭代对象,可选参数

我尝试使用 TimeSeriesSplit 而没有使用 .split(X), 但还是不行。

我确定我正在忽略一些简单的东西,谢谢!


1
尝试使用 my_cv = [(train,test) for train, test in TimeSeriesSplit(n_splits=2).split(X)] - Vivek Kumar
那个可行,谢谢!但这个函数不应该使用迭代器吗?当观测数量很大时(如果折叠数很大,情况会更糟),如果可能的话,最好不要在内存中保存这些大数组。 - cd98
1
是的,应该这样做。您应该在scikit-learn的github页面上发布一个问题。 - Vivek Kumar
1个回答

57

问题出在我使用的是sklearn.grid_search中的GridSearchCV,而该版本已经被弃用。改为从sklearn.model_selection导入GridSearchCV即可解决问题:

import xgboost as xgb
from sklearn.model_selection import TimeSeriesSplit, GridSearchCV
import numpy as np
X = np.array([[4, 5, 6, 1, 0, 2], [3.1, 3.5, 1.0, 2.1, 8.3, 1.1]]).T
y = np.array([1, 6, 7, 1, 2, 3])

model = xgb.XGBRegressor()
param_search = {'max_depth' : [3, 5]}

tscv = TimeSeriesSplit(n_splits=2)
gsearch = GridSearchCV(estimator=model, cv=tscv,
                        param_grid=param_search)
gsearch.fit(X, y)

提供:

GridSearchCV(cv=<generator object TimeSeriesSplit.split at 0x11ab4abf8>,
       error_score='raise',
       estimator=XGBRegressor(base_score=0.5, colsample_bylevel=1, colsample_bytree=1, gamma=0,
       learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='reg:linear', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1),
       fit_params=None, iid=True, n_jobs=1,
       param_grid={'max_depth': [3, 5]}, pre_dispatch='2*n_jobs',
       refit=True, return_train_score=True, scoring=None, verbose=0)

6
也许我做错了什么,但在当前的实现中,似乎应该将这一行:my_cv = TimeSeriesSplit(n_splits=2).split(X) 更正为 my_cv = TimeSeriesSplit(n_splits=2)。否则它会抛出一个错误。 - Odisseo

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