我在使用sklearn中的StackingClassifier时,希望组件模型可以是自定义分类器。为此,我尝试用一些虚拟代码进行测试,其中自定义分类器与已有的模型(在这个例子中是KNN)完全相同。然而,这抛出了一个错误,我不确定为什么会这样,正在寻找帮助。这可能是一个相当明显的问题(我刚开始尝试编写自定义分类器和使用ClassifierMixin),但我似乎找不到我遗漏了什么:
代码 — 没有我的自定义类时的基准示例(可运行):
from sklearn.ensemble import StackingClassifierfrom sklearn.pipeline import Pipelinefrom sklearn.tree import DecisionTreeClassifierfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.datasets import load_breast_cancerX, 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())])), ])model.fit(X, y)
代码 — 使用我的自定义类(不可运行):
class MyOwnClassifier(ClassifierMixin): def __init__(self,classifier): self.classifier = classifier def fit(self, X, y): self.classifier.fit(X,y) return self def predict(self, X): return self.classifier.predict(X) def predict_proba(self, X): return self.classifier.predict_proba(X)model = StackingClassifier(estimators=[ ('tree', Pipeline([('tree', DecisionTreeClassifier(random_state=42))])), ('knn', Pipeline([('knn', MyOwnClassifier(KNeighborsClassifier()))])), ])model.fit(X, y)
返回的错误是
AttributeError: 'MyOwnClassifier' object has no attribute 'classes_'
让我感到困惑的是,在这个回答中,一个身份转换可以作为管道的一部分,我无法想象那个对象有’classes_‘属性。
回答:
你的代码有三个问题:
-
StackingClassifier
期望在拟合的分类器上有一个名为classes_
的属性,这在错误消息中已经明确指出。链接的示例中有这个属性,而你的没有。你可以运行dir(MyOwnClassifier(KNeighborsClassifier()).fit(X,y))
来检查这一点。 -
你的类定义中缺少
BaseEstimator
(你可以不使用它,但它的存在会使事情变得更简单) -
你代码中的
Pipelines
是多余的杂乱,它们对于调试你的代码来说不是必需的,只会使调试变得复杂。
一旦你修正了这些问题,你就有了可运行的代码:
from sklearn.ensemble import StackingClassifierfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.datasets import load_breast_cancerfrom sklearn.base import ClassifierMixin, BaseEstimatorX, y = load_breast_cancer(return_X_y=True, as_frame=True)class MyOwnClassifier(ClassifierMixin, BaseEstimator): def __init__(self,classifier): self.classifier = classifier def fit(self, X, y): self.classifier.fit(X,y) self.classes_ = self.classifier.classes_ return self def predict(self, X): return self.classifier.predict(X) def predict_proba(self, X): return self.classifier.predict_proba(X)model = StackingClassifier(estimators=[ ('tree', DecisionTreeClassifier(random_state=42)), ('knn', MyOwnClassifier(KNeighborsClassifier()))])model.fit(X,y)StackingClassifier(estimators=[('tree', DecisionTreeClassifier(random_state=42)), ('knn', MyOwnClassifier(classifier=KNeighborsClassifier()))])