我最近一直在尝试使用 StackingClassifier,通常它是与交叉验证一起使用的(默认:K-fold,折数 = 5)。代码如下所示:
from sklearn.pipeline import Pipelinefrom sklearn.tree import DecisionTreeClassifierfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.datasets import load_breast_cancerfrom sklearn.model_selection import train_test_split, RandomizedSearchCV, KFoldX, y = load_breast_cancer(return_X_y=True, as_frame=True)model = StackingClassifier(estimators=[ ('tree', Pipeline([('tree', DecisionTreeClassifier(random_state=42))])), ('knn', Pipeline([('knn', KNeighborsClassifier())])), ],final_estimator = final_estimator, n_jobs = 10, passthrough = False, cv = KFold())model.fit(X, y)
这种方法运行得很好。然而,使用 k-fold 交叉验证来训练堆叠分类器确实非常慢。理想情况下,我希望使用一种方法,其中 80% 的训练数据用于训练组件模型,而另外的20%用于训练 final_estimator。根据文档,您可以使用一个生成训练-测试分割的迭代器作为cv(交叉验证)的输入(这有点奇怪,因为它不再是交叉验证)。所以我有一个两部分的问题
- 是否可以使用 StackingClassifier 以这种方式工作,即完全不使用交叉验证(CV),而是使用训练/测试分割(主要是为了加速拟合)?
- 如果可以,这会是什么样子?我应该如何设置cv的输入?
另外一点。查看用户指南中的潜在 CV 选项,ShuffleSplit 设定 nsplits=1 似乎是一个不错的选择,我尝试了一下。
model = StackingClassifier(estimators=[ ('tree', Pipeline([('tree', DecisionTreeClassifier(random_state=42))])), ('knn', Pipeline([('knn', KNeighborsClassifier())])), ],final_estimator = final_estimator, n_jobs = 10, passthrough = False, cv = ShuffleSplit(n_splits=1))model.fit(X, y)
但遗憾的是,这不起作用并抛出了一个错误:
ValueError: cross_val_predict only works for partitions
回答:
你能获得的最快加速是使用 KFold(n_splits=2)
:
model = StackingClassifier(estimators=[ ('tree', Pipeline([('tree', DecisionTreeClassifier(random_state=42))])), ('knn', Pipeline([('knn', KNeighborsClassifier())])), ],final_estimator = final_estimator, n_jobs = 10, passthrough = False, cv = KFold(n_splits=2))
cv
参数只接受“分区”或“分区器”(正如他们所说)。它们是 KFold()
、StratifiedKFold
,但不是 ShuffleSplit
或 train_test_split
。
分区器:
n =5x = range(90,100)cv = KFold(n_splits=n).split(x)for i,j in cv: print("TRAIN:",i,"TEST",j)TRAIN: [2 3 4 5 6 7 8 9] TEST [0 1]TRAIN: [0 1 4 5 6 7 8 9] TEST [2 3]TRAIN: [0 1 2 3 6 7 8 9] TEST [4 5]TRAIN: [0 1 2 3 4 5 8 9] TEST [6 7]TRAIN: [0 1 2 3 4 5 6 7] TEST [8 9]
非分区器:
n =5x = range(90,100)# cv = KFold(n_splits=n).split(x)cv = ShuffleSplit(n_splits=n, train_size=.8).split(x)for i,j in cv: print("TRAIN:",i,"TEST",j)TRAIN: [7 9 0 1 6 4 8 3] TEST [2 5]TRAIN: [3 2 7 0 8 4 6 1] TEST [5 9]TRAIN: [5 1 8 7 4 0 2 6] TEST [9 3]TRAIN: [7 1 5 8 6 9 4 0] TEST [2 3]TRAIN: [7 0 3 2 6 1 5 9] TEST [4 8]