skitkit学习中的VotingClassifier:构建和优化分类模型集合

作为执行情感分析(评论分析)这一大任务的一部分,我决定花一些时间对其单独的元素进行额外的研究-使用sklearn.ensemble模块中的VotingClassifier作为构建分类模型集合并提高最终预测质量的工具。 为什么这很重要?细微差别是什么?



通常,在解决数据分析的应用问题的过程中,哪种训练模型最不适合(不是很明显)(或一点也不明显)。 一种解决方案是根据可用数据的性质选择最流行和/或直观上合适的模型。 在这种情况下,将优化所选模型的参数(例如,通过GridSearchCV),并将其用于工作中。 当其中几个模型的结果同时参与最终结果的形成时,另一种方法可能是使用一组模型。 我马上要说的是,本文的目的不是描述使用整体模型或其构造原理的优势(可在此处找到),而是描述一种单独应用的方法,该方法使用一个特定的示例来解决问题并分析在这种解决方案中产生的细微差别。

关于全球问题的陈述如下 :手机上仅给出了100条评论作为测试样本,我们需要一个预先训练的模型来显示这100条评论中的最佳结果-即,它将确定评论是正面还是负面。 根据问题的情况,另一个困难是缺少训练样本。 为了在Beautiful Soup库的帮助下克服这一困难,成功解析了其中一个俄罗斯站点的10,000条有关手机的评价以及它们的评级。

跳过解析,数据预处理和研究其初始结构的步骤 ,我们继续进行以下操作:

  • 培训样本,由10,000个电话评论组成,每个评论都标记为二进制(正面或负面)。 标记评论的定义,评分1-3为负面,评分4-5为正面。
  • 使用Count Vectorizer,以适合训练分类器模型的形式显示数据

如何确定哪种型号最适合您? 我们无法手动迭代模型,因为 仅100条评论的测试样本会冒着巨大的风险,那就是某些模型仅更适合于该测试样本,但是如果将其用于对我们隐藏的其他样本或“战斗”,结果将低于平均水平。

为了解决此问题,Scikit-learn库具有VotingClassifier模块 ,该模块是使用多个彼此不同的机器学习模型并将它们组合为一个分类器的出色工具。 这降低了重新训练的风险,以及对任何一种特定模型的结果的错误解释。 使用以下命令导入VotingClassifier模块
from sklearn.ensemble import VotingClassifier

使用此模块时的实用细节:

1)首先也是最重要的事情是如何在从组合分类器中包含的每个模型接收到预测后,获得组合分类器的单个预测。 在VotingClassifier参数中,有一个表决参数,具有两个可能的值:“硬”和“软”。

1.1)在第一种情况下,联合分类器的最终答案将对应于大多数成员的“意见”。 例如,您的组合分类器使用来自三个不同模型的数据。 他们中有两个在特定的观察结果上预测响应为“正反馈”,第三个为“负反馈”。 因此,对于此观察,最终的预测将是“正反馈”,因为我们有2个“ for”和1个“ against”。

1.2)在第二种情况下,即 当使用投票参数的“软”值时, 每个类别都有完整的模型投票“投票”和权重,因此组合分类器的最终答案是预测概率之和的argmax。 重要! 为了能够使用这种“投票”方法,合奏中包含的每个分类器都必须支持predict_proba()方法,以获得每个类中发生概率的定量估计。 请注意,并非所有分类器模型都支持此方法,因此,在使用加权概率方法(软投票)时,可以在VotingClassifier框架内使用。

让我们看一个例子 :有三个分类器和两个分类的评论:肯定和否定。 通过predict_proba方法,每个分类器将给出一定的概率值(p),通过该值将特定的观察值分配给类别1,并因此将概率(1-p)分配给类别2。 组合分类器在收到每个模型的答案后,对获得的估计值进行加权,并给出最终获得的结果为

$$显示$$ max(w1 * p1 + w2 * p1 + w3 * p1,w1 * p2 + w2 * p2 + w3 * p3)$$显示$$

,其中w1,w2,w3是包含在集合中的分类器的权重,默认情况下具有相等的权重,而p1,p2是对它们各自属于1类或2类的评估。 还请注意,使用“软投票”时可以使用weights参数更改分类器的权重,因此模块调用应如下所示:
... = VotingClassifier(estimators=[('..', clf1), ('..', clf2), ('...', clf3)], voting='soft', weights=[*,*,*]) ,其中星号可能表示每种型号所需的重量。

2) 同时使用模块VotingClassifier和GridSearch来优化集合中包含的每个分类器的超参数的能力。

当您计划使用集成并希望优化其中包含的模型时,可以在统一分类器上使用GridSearch。 下面的代码显示了如何使用其中包含的模型(逻辑回归,朴素贝叶斯,随机梯度下降),同时又保持在统一分类器(VotingClassifier)的框架内:

 clf1 = LogisticRegression() clf2 = MultinomialNB() clf3 = SGDClassifier(max_iter=1000, loss='log') eclf = VotingClassifier(estimators=[ ('lr', clf1), ('nb', clf2),('sgd', clf3)], voting='hard') #      (hard voting), . . 1.1 <b>params = {'lr__C' : [0.5,1,1.5], 'lr__class_weight': [None,'balanced'], 'nb__alpha' : [0.1,1,2], 'sgd__penalty' : ['l2', 'l1'], 'sgd__alpha': [0.0001,0.001,0.01]} </b> #       ,  ,     grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5, scoring='accuracy', n_jobs=-1) grid = grid.fit(data_messages_vectorized, df_texts['Binary_Rate']) #    ,      5      

因此,必须设置params字典,以便在通过GridSearch访问它时,可以确定模型集合中的哪个参数引用您要优化其值的参数。

这就是您需要充分使用VotingClassifier工具来构建模型和优化模型的全部知识。 让我们看一下结果:

  print grid.best_params_ {'lr__class_weight': 'balanced', 'sgd__penalty': 'l1', 'nb__alpha': 1, 'lr__C': 1, 'sgd__alpha': 0.001} 

找到参数的最佳值,剩下的是将分类器(VotingClassifier)的工作结果与最佳参数进行比较,我们将对训练样本进行交叉验证,并将具有最佳参数的模型与包含它们的整体进行比较:

 for clf, label in zip([clf1, clf2, clf3, eclf], ['Logistic Regression', 'Naive Bayes', 'SGD', 'Ensemble_HardVoting']): scores = cross_val_score(clf, data_messages_vectorized, df_texts['Binary_Rate'], cv=3, scoring='accuracy') print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label)) 

最终结果:

准确性:0.75(±0.02)[逻辑回归]
准确度:0.79(±0.02)[朴素贝叶斯]
精度:0.79(±0.02)[SGD]
准确度:0.79(±0.02)[Ensemble_HardVoting]

如您所见,模型在训练样本中显示出一些差异(使用标准参数,这种差异更加明显)。 而且,集成的总价值(根据准确性度量)不必超过其中包含的模型的最佳价值,因为 集成是一个更稳定的模型,能够在测试集中和“战斗”中显示±类似的结果,这意味着减少了重新训练的风险,适合训练集以及其他与训练相关的问题分类器。 解决应用问题的过程中祝您好运,并感谢您的关注!

PS鉴于沙箱中的发布细节和发布规则,我无法在InClass竞赛的框架中提供指向github的链接和本文给出的分析的源代码,以及与Kaggle的链接,该框架提供了测试集和用于检查模型的工具。 我只能说,此合奏在检查了测试集之后大大超过了基线,并在排行榜上占据了应有的位置。 我希望可以在以下出版物中分享。

Source: https://habr.com/ru/post/zh-CN430280/


All Articles