7

我开始使用sklearn.naive_bayes.GaussianNB进行文本分类,并且得到了很好的初步结果。我想使用分类器返回的概率作为置信度的度量,但是predict_proba()方法总是为所选类返回“1.0”,而对于所有其他类返回“0.0”。

我知道(从这里)“...... predict_proba 的概率输出不要太认真”,但是到那个程度?!分类器可能会误认为finance-investingchords-strings,但predict_proba()输出没有任何犹豫的迹象......

关于上下文的一些信息:
-我一直在使用sklearn.feature_extraction.text.TfidfVectorizer进行特征提取,但首先没有使用stop_wordsmin/max_df限制词汇表——>我得到了非常大的向量。
- 我一直在分层类别树(浅层:深度不超过 3 层)上训练分类器,每个类别有 7 个文本(手动分类)。现在是flat培训:我没有考虑等级制度。

生成的GaussianNB对象非常大(~300MB),并且预测相当慢:一个文本大约 1 秒。
这有关系吗?巨大的向量是这一切的根源吗?
如何获得有意义的预测?我需要使用不同的分类器吗?

这是我正在使用的代码:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import GaussianNB
import numpy as np
from sklearn.externals import joblib

Vectorizer = TfidfVectorizer(input = 'content')
vecs = Vectorizer.fit_transform(TextsList) # ~2000 strings
joblib.dump(Vectorizer, 'Vectorizer.pkl') 
gnb = GaussianNB()
Y = np.array(TargetList) # ~2000 categories 
gnb.fit(vecs.toarray(), Y)
joblib.dump(gnb, 'Classifier.pkl') 
...

#In a different function:
Vectorizer = joblib.load('Vectorizer.pkl')
Classifier = joblib.load('Classifier.pkl')
InputList = [Text] # One string
Vec = Vectorizer.transform(InputList)
Probs = Classifier.predict_proba([Vec.toarray()[0]])[0]
MaxProb = max(Probs)
MaxProbIndex = np.where(Probs==MaxProb)[0][0]
Category = Classifier.classes_[MaxProbIndex]
result = (Category, MaxProb)  

更新:
按照下面的建议,我尝试了MultinomialNB & LogisticRegression。它们都返回不同的概率,并且在任何方面都更适合我的任务:更准确的分类、更小的内存对象和更快的速度(MultinomialNB快如闪电!)。

我现在有一个新问题:返回的概率非常小——通常在 0.004-0.012 范围内。这是针对预测/获胜类别的(并且分类是准确的)。

4

1 回答 1

13

“......不要太认真地对待 predict_proba 的概率输出”

我是写那个的人。关键是朴素贝叶斯倾向于预测几乎总是非常接近于零或非常接近于一的概率。正是您观察到的行为。逻辑回归 (sklearn.linear_model.LogisticRegressionsklearn.linear_model.SGDClassifier(loss="log")) 产生更现实的概率。

生成的 GaussianNB 对象非常大(~300MB),并且预测相当慢:一个文本大约 1 秒。

那是因为GaussianNB它是一个非线性模型并且不支持稀疏矩阵(您已经发现了,因为您使用的是toarray)。使用或逻辑回归MultinomialNBBernoulliNB它们在预测时间更快而且更小。他们的假设。对于术语特征,输入也更真实。GaussianNB确实不是文本分类的好估计器。

于 2013-08-05T16:43:35.850 回答