Scikit learn 如何在python中通过三个步骤定义管道:预处理、预测和后处理?

Scikit learn 如何在python中通过三个步骤定义管道:预处理、预测和后处理?,scikit-learn,pipeline,post-processing,Scikit Learn,Pipeline,Post Processing,我试图使用sklearn.pipeline.pipeline在python中定义一个管道,以执行3个步骤:预处理、预测和后处理。最终的目标是定义一个googlecloud函数,我只需通过joblib模型,就可以得到这个标签的预测标签和预测概率 我通过前两个步骤成功地定义了管道,它运行良好。但是,当我尝试包括第三步(后处理)时,我会收到错误消息。我尝试了各种方法,得到了不同的错误消息。 在下面的代码中,如果我从管道中删除('proba',FunctionTransformer(findProba(

我试图使用sklearn.pipeline.pipeline在python中定义一个管道,以执行3个步骤:预处理、预测和后处理。最终的目标是定义一个googlecloud函数,我只需通过joblib模型,就可以得到这个标签的预测标签和预测概率

我通过前两个步骤成功地定义了管道,它运行良好。但是,当我尝试包括第三步(后处理)时,我会收到错误消息。我尝试了各种方法,得到了不同的错误消息。 在下面的代码中,如果我从管道中删除
('proba',FunctionTransformer(findProba())
,一切都正常。我似乎不知道如何将后处理步骤包括到管道中

Scikit学习将管道类(请参阅)定义为:

具有最终估计器的变换管道

按顺序应用变换列表和最终估计器。管道的中间步骤必须是“变换”,也就是说,它们必须实现拟合和变换方法。最终估计器只需要实现拟合。管道中的转换器可以使用内存参数缓存

阅读这个定义,我开始怀疑是否有可能在估计器之后包含一个步骤。但是在我的例子中,我真的需要能够返回类(在我的例子中是konto)和得到该情况的概率(proba).如果在第二步之后停止,我将无法计算并返回在线预测期间的概率

我包括代码摘要,以说明我正在做什么:

from nltk import word_tokenize
from nltk.corpus import stopwords
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import numpy as np
from sklearn.model_selection import train_test_split 
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import MultinomialNB
from datetime import date
import time 

import warnings
warnings.filterwarnings('ignore')


def findProba(model,Input_Text):
    Input_Text = [Input_Text]
    Y_predicted = model.predict(Input_Text)
    Y_predict_proba = model.predict_proba(Input_Text)
    max_proba_rows = np.amax(Y_predict_proba, axis=1)*100
    round_off_proba = np.around(max_proba_rows, decimals = 1)
    d = dict()
    d['Konto'] = Y_predicted[0]
    d['proba'] = round_off_proba[0]
    return d


df_total = pd.read_csv('dataset_mars2019_trimmed_mapped.csv')
df=df_total.sample(frac=0.001, random_state=1)

X_train, X_test, y_train, y_test = train_test_split(df['Input_Data'], df['LABEL'], random_state = 0, test_size=0.25)

text_clf = Pipeline([('tfidf', TfidfVectorizer()),
                     ('clf', MultinomialNB()),
                     ('proba', FunctionTransformer(findProba()),
])

 _ = text_clf.fit(X_train, y_train)


from sklearn.externals import joblib
joblib.dump(text_clf, 'model.joblib')

sklearn.pipeline.pipeline
的语义如下:一系列变换器(即实现
fit
transform
),然后是最终预测器(即实现
fit
predict
(可选
预测概率
决策
)等)

由于所有scikit学习指标仅期望
predict
predict\u proba
输出,因此做您喜欢的事情并不简单

我认为最简单的方法是实现您自己的元估计器,它将实现您想要的:

来自sklearn.base导入BaseEstimator
类后处理器(BaseEstimator):
def u u初始值_;(自,预测器):
self.predictor=预测器
def配合(自、X、y):
自预测拟合(X,y)
def预测(自我,X):
y_pred=自预测器预测(X)
y_pred_proba=自我预测者预测概率(X)
#用这些做点什么
返回np.hstack([y\u pred,y\u pred\u proba])

非常感谢您的快速回答。但是,我对编程不是很有经验,我不确定我是否正确理解在我的情况下应该在哪里以及如何实现元估计器。您的意思是我应该替换:
text\u clf=Pipeline([('tfidf',TfidfVectorizer()),('clf',多项式nb()),('proba',FunctionTransformer(findProba()),
通过类似的方式:
text\u clf=Pipeline([('tfidf',TfidfVectorizer()),('clf',PostProcessor()),
使用您上面提到的定义的后处理器?好的,我想我现在知道了。如果我错了,请纠正我。正确的应该是:
classifier=MultinomialNB()text\u clf=Pipeline([('tfidf',tfidfvectorier()),('proba',后处理器(分类器)),]))
这是使用自定义元估计器的正确方法吗?您需要首先定义类
后处理器
,然后准确地调用您提到的代码。仅供参考,元估计器只是一个以估计器为参数的估计器。请注意,调用
分类器会更简洁。预测(X)
分类器。预测_proba(X)
并将输出存储到两个不同的数组中,而不是实现元估计器。您将能够使用当时可用的所有不同的scikit学习度量。太好了!非常感谢!它工作正常,符合我的要求。