我有一个包含文字和标签的pandas数据框,我尝试使用scikit-learn CountVectorizer
,TfidfTransformer
和MultinomialNB
来预测标签。这是数据框的样子:
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其中anforandetext
和parti
是相关列。
答案 0 :(得分:2)
你得到这么大的差异的原因是因为平滑。如果您查看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会对Multinomial Naive Bayes的计算产生巨大影响。通过在这些数字上加1,您可以完全改变其分类比例,从而使您的估算陷入困境。我假设你对Multinomial Naive Bayes的工作方式有一个很好的了解。如果没有,那么肯定会看到这个video。视频和我的回答足以了解这里出了什么问题。
您应该在TF-IDF情况下使用较小的alpha
值,或者在对原始计数进行平滑后构建TF-IDF权重。另请注意,请使用交叉验证来获得任何准确度估算值。通过在训练数据样本上测试模型,您的准确度数字将极具偏差。我建议使用交叉验证或单独的保留集来评估您的模型。
希望有所帮助。