使用管道作为估计器的 VotingClassifier

Posted

技术标签:

【中文标题】使用管道作为估计器的 VotingClassifier【英文标题】:VotingClassifier with pipelines as estimators 【发布时间】:2020-05-10 19:39:57 【问题描述】:

我想用多个不同的模型(决策树、SVC 和 Keras 网络)构建一个 sklearn VotingClassifier 集成。它们都需要一种不同类型的数据预处理,这就是为什么我为它们每个都制作了一个管道。

# Define pipelines

# DTC pipeline
featuriser = Featuriser()
dtc = DecisionTreeClassifier()
dtc_pipe = Pipeline([('featuriser',featuriser),('dtc',dtc)])

# SVC pipeline
scaler = TimeSeriesScalerMeanVariance(kind='constant')
flattener = Flattener()
svc = SVC(C = 100, gamma = 0.001, kernel='rbf')
svc_pipe = Pipeline([('scaler', scaler),('flattener', flattener), ('svc', svc)])

# Keras pipeline
cnn = KerasClassifier(build_fn=get_model())
cnn_pipe = Pipeline([('scaler',scaler),('cnn',cnn)])

# Make an ensemble
ensemble = VotingClassifier(estimators=[('dtc', dtc_pipe), 
                                        ('svc', svc_pipe),
                                        ('cnn', cnn_pipe)], 
                            voting='hard')

FeaturiserTimeSeriesScalerMeanVarianceFlattener 类是一些定制的转换器,它们都使用 fittransformfit_transform 方法。

当我尝试 ensemble.fit(X, y) 适合整个合奏时,我收到错误消息:

ValueError:估计器列表应该是一个分类器。

我可以理解,因为各个估计器不是专门的分类器,而是管道。有没有办法让它继续工作?

【问题讨论】:

dtc_pipe 真的是Pipeline Ups,抱歉有错误,我已修复。然而,我并没有改变任何东西。我仍然遇到同样的错误 【参考方案1】:

问题在于KerasClassifier。它不提供在_validate_estimator 中签入的_estimator_type

不是使用管道的问题。 Pipeline 将此信息作为属性提供。见here。

因此,快速修复是设置_estimator_type='classifier'

一个可重现的例子:

# Define pipelines
from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import MinMaxScaler, Normalizer
from sklearn.ensemble import VotingClassifier
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.datasets import make_classification
from keras.layers import Dense
from keras.models import Sequential

X, y = make_classification()

# DTC pipeline
featuriser = MinMaxScaler()
dtc = DecisionTreeClassifier()
dtc_pipe = Pipeline([('featuriser', featuriser), ('dtc', dtc)])

# SVC pipeline
scaler = Normalizer()
svc = SVC(C=100, gamma=0.001, kernel='rbf')
svc_pipe = Pipeline(
    [('scaler', scaler), ('svc', svc)])

# Keras pipeline
def get_model():
    # create model
    model = Sequential()
    model.add(Dense(10, input_dim=20, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model


cnn = KerasClassifier(build_fn=get_model)
cnn._estimator_type = "classifier"
cnn_pipe = Pipeline([('scaler', scaler), ('cnn', cnn)])


# Make an ensemble
ensemble = VotingClassifier(estimators=[('dtc', dtc_pipe), 
                                        ('svc', svc_pipe),
                                        ('cnn', cnn_pipe)], 
                            voting='hard')

ensemble.fit(X, y)

【讨论】:

以上是关于使用管道作为估计器的 VotingClassifier的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 scikit learn 中使用管道对象的最终估计器的属性?

为啥使用 1 个估计器的 adaboost 比简单的决策树更快?

API - Sklearn三大模型 - Transformer、Estimator、Pipeline

算法链与管道(下):通用的管道接口

是否有用于运行多个分类器的 Python 管道函数?

迭代器的应用,管道流筛选