我想训练一个LogisticRegression
和一个RandomForestClassifier
,并使用GaussianNB
结合它们的得分:
from sklearn.datasets import make_classificationfrom sklearn.linear_model import LogisticRegressionfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.naive_bayes import GaussianNBX, y = make_classification(n_samples=1000, n_features=4, n_informative=2, n_redundant=0, random_state=0, shuffle=False)logit = LogisticRegression(random_state=0)logit.fit(X, y)randf = RandomForestClassifier(n_estimators=100, max_depth=2, random_state=0)randf.fit(X, y)X1 = np.transpose([logit.predict_proba(X)[:,0], randf.predict_proba(X)[:,0]])nb = GaussianNB()nb.fit(X1, y)
我如何使用Pipeline来实现这个目标,以便我可以将其传递给cross_validate
和GridSearchCV
?
附注:我想我可以定义自己的类来实现fit
和predict_proba
方法,但我认为应该有标准的方法来做这件事…
回答:
不,没有sklearn内置的功能可以让你在不编写一些自定义代码的情况下实现你想要的功能。你可以通过使用FeatureUnion
来并行化代码的某些部分,并使用Pipeline
来序列化整个任务,但你需要编写自定义的变换器,这些变换器可以将predict_proba
的输出转发到transform
方法中。
类似这样的代码:
from sklearn.datasets import make_classificationfrom sklearn.linear_model import LogisticRegressionfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.naive_bayes import GaussianNBfrom sklearn.base import BaseEstimator, TransformerMixinfrom sklearn.pipeline import Pipeline, FeatureUnionX, y = make_classification(n_samples=1000, n_features=4, n_informative=2, n_redundant=0, random_state=0, shuffle=False)# 这是自定义变换器,将# predict_proba()转换为pipeline友好的transform()class PredictProbaTransformer(BaseEstimator, TransformerMixin): def __init__(self, clf=None): self.clf = clf def fit(self, X, y): if self.clf is not None: self.clf.fit(X, y) return self def transform(self, X): if self.clf is not None: # 删除第二列但保持2d形状 # 因为FeatureUnion需要这样 return self.clf.predict_proba(X)[:,[0]] return X # 这个方法对于pipeline的正确工作很重要 def fit_transform(self, X, y): return self.fit(X, y).transform(X)logit = LogisticRegression(random_state=0)randf = RandomForestClassifier(n_estimators=100, max_depth=2, random_state=0)pipe = Pipeline([ ('stack',FeatureUnion([ ('logit', PredictProbaTransformer(logit)), ('randf', PredictProbaTransformer(randf)), #你可以像上面一样添加更多的分类器和自定义包装器 ])), ('nb',GaussianNB())])pipe.fit(X, y)
现在你可以简单地调用pipe.predict()
,所有的事情都会被正确处理。
关于FeatureUnion的更多信息,你可以查看我在这里对类似问题的另一个回答: