我开始使用 sklearn.naive_bayes.GaussianNB 进行文本分类,并且获得了很好的初步结果。我想使用分类器返回的概率作为置信度的度量,但 predict_proba()方法对于所选类始终返回“1.0”,对于所有其余类别返回“0.0”。
我知道(来自here)“......来自predict_proba的概率输出不应过于严肃”,但到了那个程度?! 分类器可能会误认为财务投资或和弦字符串,但 predict_proba()输出显示没有任何犹豫的迹象......
关于背景的一点:
- 我一直在使用 sklearn.feature_extraction.text.TfidfVectorizer 进行特征提取,而不是一开始就用 stop_words 或 min / max_df <来限制词汇量/ strong> - &gt;我的矢量非常大。
- 我一直在分层类别树上训练分类器(浅层:深度不超过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 &amp;的逻辑回归即可。它们都返回不同的概率,并且在任何方面对我的任务都更好:更准确的分类,更小的存储器和物体。更好的速度( MultinomialNB 快速闪电!)。
我现在遇到了一个新问题:返回的概率非常小 - 通常在0.004-0.012范围内。这是针对预测/获胜类别(并且分类是准确的)。
答案 0 :(得分:12)
“......来自predict_proba的概率输出不应过于严肃”
我是写这篇文章的人。关键在于朴素的贝叶斯倾向于预测几乎总是非常接近于零或非常接近于1的概率;正是你观察到的行为。逻辑回归(sklearn.linear_model.LogisticRegression
或sklearn.linear_model.SGDClassifier(loss="log")
)产生更实际的概率。
生成的GaussianNB对象非常大(~300MB),预测相当慢:一个文本大约1秒。
那是因为GaussianNB
是一个非线性模型,不支持稀疏矩阵(你已经发现了,因为你使用的是toarray
)。使用MultinomialNB
,BernoulliNB
或逻辑回归,它们在预测时间更快,也更小。他们的假设是。对于术语特征,输入也更加真实。 GaussianNB
实际上不是文本分类的好估算器。