问题描述
我最近一直在尝试StackingClassifiers,通常将它与交叉验证结合使用(默认值:K折,num-folds = 5)。这样写:
Shopify
效果很好。但是,k-fold交叉验证作为训练堆叠分类器的一种方法确实非常慢。理想情况下,我想使用80%的 training 数据来训练组件模型,而其他 20%来训练final_estimator。根据{{3}},您可以使用产生火车测试拆分的迭代器作为 cv (交叉验证)的输入(这很奇怪,因为它不再是CV)。所以我想分两个部分
- 是否可以使用StackingClassifier以这种方式工作,而它根本不使用交叉验证(CV),而是进行训练/测试拆分(主要是为了加快拟合速度)?
- 如果是这样,看起来会如何?我将设置为简历的内容是什么?
另一个说明。通过nsplits = 1在用户指南ShuffleSplit中浏览潜在的CV选项似乎是一个不错的选择,我尝试过。
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)
但不幸的是,这行不通并引发错误:
model = StackingClassifier(estimators=[
('tree',cv = ShuffleSplit(n_splits=1))
model.fit(X,y)
解决方法
在sklearn的Stacked Classifier页面上,它指出“ ... estimators_拟合在完整的X上,而 final_estimator _ 是通过使用 cross_val_predict对基本估计量进行交叉验证的预测来训练的。”
我认为,如果您想使用基于80%-20%的传统训练测试方法,则应该在StackedClassifier之外进行。主要原因是要使该过程与根据上面记录的注释使用堆叠分类器的方式保持一致。
我已经做到了,我的管道/设置的描述如下。我不介意在每个分类器上进行额外的培训测试,因为StackedClassifier对于最终分类器的处理效率更高:
- 以70%-30%/ 80%-20%的比例运行各个分类器(KNN,决策树,随机森林,朴素贝叶斯等)。找到最佳的参数化。
- 设置StackedClassifier,其中每个分类器都适合您根据整个数据确定的最佳参数(此阶段不拆分)
- 检查并验证最终分类器相对于单个分类器性能的结果。
我认为花费额外的时间是不可避免的,因为您正在引入额外的步骤来为各个分类器拆分数据。对于最终分类器的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
参数only accepts“分区”或“分区程序”(按他们的说法“按定义”)。它们是KFold()
,StratifiedKFold
,但不是ShuffleSplit
或train_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]
非分区者:
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)
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]