scikit管道python中的多个分类模型

Posted

技术标签:

【中文标题】scikit管道python中的多个分类模型【英文标题】:Multiple classification models in a scikit pipeline python 【发布时间】:2018-07-08 12:37:08 【问题描述】:

我正在使用 Python 解决一些文本文档的二进制分类问题并实现 scikit-learn 库,我希望尝试不同的模型来比较和对比结果 - 主要使用 朴素贝叶斯分类器,带 K 的 SVM -折叠 CV,CV=5。鉴于后两种模型使用gridSearchCV(),我发现将所有方法组合到一个管道中存在困难。由于并发问题,我不能在单个实现期间运行多个管道,因此我需要使用一个管道来实现所有不同的模型。

这是我到现在为止的,​​

# pipeline for naive bayes
naive_bayes_pipeline = Pipeline([
    ('bow_transformer', CountVectorizer(analyzer=split_into_lemmas, stop_words='english')),
    ('tf_idf', TfidfTransformer()),
    ('classifier', MultinomialNB())
])

# accessing and using the pipelines
naive_bayes = naive_bayes_pipeline.fit(train_data['data'], train_data['gender'])

# pipeline for SVM
svm_pipeline = Pipeline([
    ('bow_transformer', CountVectorizer(analyzer=split_into_lemmas, stop_words='english')),
    ('tf_idf', TfidfTransformer()),
    ('classifier', SVC())
])

param_svm = [
  'classifier__C': [1, 10], 'classifier__kernel': ['linear'],
  'classifier__C': [1, 10], 'classifier__gamma': [0.001, 0.0001], 'classifier__kernel': ['rbf'],
]

grid_svm_skf = GridSearchCV(
    svm_pipeline,  # pipeline from above
    param_grid=param_svm,  # parameters to tune via cross validation
    refit=True,  # fit using all data, on the best detected classifier
    n_jobs=-1,  # number of cores to use for parallelization; -1 uses "all cores"
    scoring='accuracy',
    cv=StratifiedKFold(train_data['gender'], n_folds=5),  # using StratifiedKFold CV with 5 folds
)

svm_skf = grid_svm_skf.fit(train_data['data'], train_data['gender'])
predictions_svm_skf = svm_skf.predict(test_data['data'])

编辑 1: 第二个管道是唯一使用gridSearchCV() 的管道,似乎从未执行过。

编辑 2: 添加了更多代码以显示 gridSearchCV() 的使用。

【问题讨论】:

并发问题是什么意思?你的内存不足了吗?如何将每个管道(在适合之后)保存到文件中?然后加载你想要的并训练你的模型。另外,请分享您看到的任何错误消息。 您能否详细说明“由于并发问题,我不能在单个实现期间运行多个管道”,我怀疑这是X-Y problem。至少,Pipeline 可以解决哪些并发问题对我来说并不明显。 @pault 我似乎无法开始执行第二个管道,因为我已经有一个正在运行的管道。 那么,第二个管道是使用网格搜索的管道......为什么你说它似乎永远不会被执行?我认为您应该将此作为edit 扩展为您的问题,然后才能成为一长串 cmets。 @denbuttigieg,尝试通过 GridSearchCV(..., verbose=3) 并检查它输出什么... 【参考方案1】:

考虑在这里查看类似的问题:

    Compare multiple algorithms with sklearn pipeline Pipeline: Multiple classifiers?

总结一下,

这是一种优化任何分类器以及为每个分类器优化参数设置的简单方法。

创建适用于任何估算器的切换器类

from sklearn.base import BaseEstimator
class ClfSwitcher(BaseEstimator):

def __init__(
    self, 
    estimator = SGDClassifier(),
):
    """
    A Custom BaseEstimator that can switch between classifiers.
    :param estimator: sklearn object - The classifier
    """ 

    self.estimator = estimator


def fit(self, X, y=None, **kwargs):
    self.estimator.fit(X, y)
    return self


def predict(self, X, y=None):
    return self.estimator.predict(X)


def predict_proba(self, X):
    return self.estimator.predict_proba(X)


def score(self, X, y):
    return self.estimator.score(X, y)

现在您可以为 estimator 参数传入任何内容。您可以为传入的任何估算器优化任何参数,如下所示:

执行超参数优化

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import SGDClassifier
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV

pipeline = Pipeline([
    ('tfidf', TfidfVectorizer()),
    ('clf', ClfSwitcher()),
])

parameters = [
    
        'clf__estimator': [SGDClassifier()], # SVM if hinge loss / logreg if log loss
        'tfidf__max_df': (0.25, 0.5, 0.75, 1.0),
        'tfidf__stop_words': ['english', None],
        'clf__estimator__penalty': ('l2', 'elasticnet', 'l1'),
        'clf__estimator__max_iter': [50, 80],
        'clf__estimator__tol': [1e-4],
        'clf__estimator__loss': ['hinge', 'log', 'modified_huber'],
    ,
    
        'clf__estimator': [MultinomialNB()],
        'tfidf__max_df': (0.25, 0.5, 0.75, 1.0),
        'tfidf__stop_words': [None],
        'clf__estimator__alpha': (1e-2, 1e-3, 1e-1),
    ,
]

gscv = GridSearchCV(pipeline, parameters, cv=5, n_jobs=12, return_train_score=False, verbose=3)
gscv.fit(train_data, train_labels)

如何解读clf__estimator__loss

clf__estimator__loss 被解释为loss 参数,无论estimator 是什么,其中estimator = SGDClassifier() 在最上面的示例中,它本身就是clf 的一个参数,它是一个ClfSwitcher 对象。

【讨论】:

我熟悉GridSearchCV 在传统情况下只有一个估算器。当您提供带有两个估计器的参数时,您能解释一下GridSearchCV 中实际发生的情况吗?它是否会执行两次 5 倍 CV(即,一轮用于SGDClassifier,一轮用于MultinomialNB)然后对每组网格参数重复执行? 你知道是否可以提供多个数据集作为参数,以便我可以用不同的数据集拟合不同的估计器? 当然.. for dataset in datasets: gscv.fit(...) 我认为这不会起作用,因为对gscv.fit 的多次调用会破坏最后一个数据集的拟合。我希望对 fit 的每个调用都附加不同的数据集。 破坏者?每次都初始化。 gscv = GridSearchCV(); gscv.fit() 仅此而已。

以上是关于scikit管道python中的多个分类模型的主要内容,如果未能解决你的问题,请参考以下文章

python Scikit-Learn的不同分类模型

相同数据和步骤的 Scikit-learn 管道无法分类

Python:Scikit Learn MLPClassifier 放入管道时出错

有没有办法在 Python 中为具有多个分类的随机森林制作部分依赖图(使用 scikit-learn)?

Python - Scikit 找到分类变量的变量重要性

Python SciKit Learn 和 Pandas 分类数据