Scikitklearns TfidfTransformer 让我的管道只预测一个标签

Posted

技术标签:

【中文标题】Scikitklearns TfidfTransformer 让我的管道只预测一个标签【英文标题】:Scikitklearns TfidfTransformer makes my pipeline predict just one label 【发布时间】:2016-10-20 20:07:40 【问题描述】:

我有一个包含文本和标签的 pandas 数据框,我正在尝试使用 scikit-learn 的 CountVectorizerTfidfTransformerMultinomialNB 预测标签。数据框如下所示:

                                                text party
0  Herr ålderspresident! Att vara talman i Sverig...     S
1  Herr ålderspresident! Ärade ledamöter av Sveri...     M
2  Herr ålderspresident! Som företrädare för Alli...     M
3  Val av andre vice talman Herr ålderspresident!...    SD
4  Herr ålderspresident! Vänsterpartiet vill utny...     V

当我使用上面提到的三个估计器构建管道时,我的预测准确度只有约 35%,但当我删除 TfidfTransformer 时,准确度会提高到更合理的约 75% 准确度。

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()), # problematic row
                     ('clf', MultinomialNB()),
                   ])

text_clf = text_clf.fit(df.text.values, df.party.values)

test = df.sample(500, random_state=42)
docs_test = test.text.values
predicted = text_clf.predict(docs_test)
np.mean(predicted == test.party.values)
# Out: either 0.35 or 0.75 depending on whether I comment out the problematic row above

当我得到 0.35 并检查 predicted 时,我发现它几乎只包含一个标签 ('S')。这是原始数据集中最常见的标签,但这不应该影响预测,对吧?关于我为什么会得到这些奇怪结果的任何想法?

编辑:Link to data,其中anforandetextparti 是相关列。

【问题讨论】:

为什么要在用于训练模型的相同数据上进行测试?这是机器学习中的一大禁忌。不过,这可能无关紧要,但您应该使用交叉验证来获得准确度估计。 【参考方案1】:

之所以有如此大的差异是因为平滑。如果您查看MultinomialNB class 的文档,请查看alpha 参数。其默认值为1.0。这意味着它默认实现 Plus One 平滑。加上一个平滑是一种非常常见的技术,用于相对频率估计来解释看不见的数据。在 Plus One 平滑中,我们将 1 添加到所有原始计数中,以解决看不见的术语和文档术语矩阵的稀疏性。

但是,当您最终使用 TF-IDF 权重时,您得到的数字非常小,而且大多介于 0 到 1 之间。为了说明,如果我使用您的数据并仅将其转换为 TF-IDF 权重,则为我获得的 TF-IDF 权重的小快照。

  (0, 80914)    0.0698184481033
  (0, 80552)    0.0304609466459
  (0, 80288)    0.0301759343786
  (0, 80224)    0.103630302925
  (0, 80204)    0.0437500703747
  (0, 80192)    0.0808649191625

您可以看到这些数字非常小,将它们加 1 以进行平滑处理将对多项朴素贝叶斯的计算产生巨大影响。通过在这些数字上加 1,您可以完全改变它们的分类规模,因此您的估计会混乱。我假设,您对多项式朴素贝叶斯的工作原理有一个很好的了解。如果没有,那么一定要看到这个video。视频和我的回答足以理解这里出了什么问题。

您应该在 TF-IDF 情况下使用较小的 alpha 值,或者您应该在对原始计数进行平滑后构建 TF-IDF 权重。另外,请使用交叉验证来获得任何准确度估计。通过在训练数据样本上测试模型,您的准确度数字将非常有偏差。我建议使用交叉验证或单独的保留集来评估您的模型。

希望对您有所帮助。

【讨论】:

很好的答案。谢谢!

以上是关于Scikitklearns TfidfTransformer 让我的管道只预测一个标签的主要内容,如果未能解决你的问题,请参考以下文章