将 StackingClassifier 与 train/test split 而不是 CV 一起使用

Using StackingClassifier with train/test split instead of CV

我最近一直在试验 StackingClassifiers,通常它与交叉验证一起使用(默认值:K-fold,num-folds = 5)。是这样写的:

from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, RandomizedSearchCV, KFold

X, 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 折交叉验证作为训练堆叠分类器的一种方式确实非常慢。理想情况下,我想使用 80% 的 training 数据用于训练组件模型,而其他 20% 使用训练 final_estimator。根据 docs,您可以使用产生训练测试拆分的迭代器作为 cv(交叉验证)的输入(这很奇怪,因为它不再是 CV) .所以我想两部分问题

另外一个注意事项。在使用 nsplits=1 的 ShuffleSplit 用户指南中查看潜在的 CV 选项似乎是一个不错的选择,我试过了。

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

在 sklearn 的 Stacked Classifier 页面上,它指出“... estimators_ 适合整个 X 而 final_estimator_ 使用 cross-validated 使用 cross_val_predict.

的基础估计量的预测

我认为如果您想使用基于 80%-20% 的传统 trainig-testing 方法,您应该在 StackedClassifier 之外进行。主要原因是要使过程与根据上面记录的说明使用堆叠分类器的方式保持一致。

我已经这样做了,我的管道/设置描述如下。我不介意对每个分类器执行 training-testing 的额外时间,因为 StackedClassifier 对最终分类器的处理效率更高:

  1. 运行 个单独的分类器(KNN、决策树、随机森林、朴素贝叶斯等),拆分率为 70%-30% / 80%-20%。找到最好的参数化。
  2. 设置 StackedClassifier,其中每个分类器都符合您用整个数据确定的最佳参数(在此阶段没有拆分)
  3. 检查并验证最终分类器相对于单个分类器性能的结果。

我认为花费额外的时间是不可避免的,因为您要引入一个额外的步骤来为您的各个分类器拆分数据。对于您的最终分类器 CV 阶段,即使您进行拆分,最终模型输入也应 运行 对整个数据进行处理,以实现单个分类器和最终分类器的最大效率。

您可以获得的最快加速是 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 param only accepts “分区”或“分区程序”(正如他们所说的“根据定义”)。它们是 KFold()StratifiedKFold,但不是 ShuffleSplittrain_test_split

分区器:

n =5
x = 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]

Non-partitioners:

n =5
x = 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]