python - 使用朴素贝叶斯对很长的文本进行分类时,避免得到无意义的值(例如 -0.0)
问题描述
我已经实现了多项式朴素贝叶斯分类器的相当有效的实现,它就像一个魅力。math domain error
直到分类器遇到非常长的消息(大约 10k 个单词),其中预测结果是无意义的(例如 -0.0),并且在使用 Python 的math.log
函数时我得到了一个。我使用 log 的原因是,当使用非常小的浮点数时,如果将它们相乘会得到非常小的浮点数,并且 log 有助于避免导致预测失败的无限小数。
一些上下文
我正在使用没有任何矢量化的词袋方法(如 TF-IDF,因为我无法弄清楚如何正确实现它并平衡 0 出现的词。对此的片段也将不胜感激;))我正在使用频率计数和拉普拉斯加法平滑(基本上每个频率计数加 1,所以它永远不会为 0)。
我可以直接退出日志,但这意味着在如此长的消息的情况下,引擎无论如何都无法正确检测到它们,所以这不是重点。
解决方案
如果应用log-sum-exp
,则朴素贝叶斯中没有乘法,只有加法,因此不太可能出现下溢。如果你使用平滑(正如你所说的那样),你永远不会得到未定义的行为log
。
这个 stats stackexchange 答案描述了基础数学。对于参考实现,我有一个我的片段MultinomialNaiveBayes
(类似于 sklearnsklearn.naive_bayes.MultinomialNB
并具有类似的 API):
import numpy as np
import scipy
class MultinomialNaiveBayes:
def __init__(self, alpha: float = 1.0):
self.alpha = alpha
def fit(self, X, y):
# Calculate priors from data
self.log_priors_ = np.log(np.bincount(y) / y.shape[0])
# Get indices where data belongs to separate class, creating a slicing mask.
class_indices = np.array(
np.ma.make_mask([y == current for current in range(len(self.log_priors_))])
)
# Divide dataset based on class indices
class_datasets = np.array([X[indices] for indices in class_indices])
# Calculate how often each class occurs and add alpha smoothing.
# Reshape into [n_classes, features]
classes_metrics = (
np.array([dataset.sum(axis=0) for dataset in class_datasets]).reshape(
len(self.log_priors_), -1
)
+ self.alpha
)
# Calculate log likelihoods
self.log_likelihoods_ = np.log(
classes_metrics / classes_metrics.sum(axis=1)[:, np.newaxis]
)
return self
def predict(self, X):
# Return most likely class
return np.argmax(
scipy.sparse.csr_matrix.dot(X, self.log_likelihoods_.T) + self.log_priors_,
axis=1,
)
顺便提一句。-0.0
是完全一样的0.0
,是感性的价值。
推荐阅读
- node.js - ibm-cos-sdk 在 node.js 中永远不会返回
- android - RecyclerView not scrolling with firebase
- input - 角 5 输入输出
- c# - C# 动态方法 - 具有“对象”返回类型的字段获取器
- python - Keras:如何实现 LSTM 的目标复制?
- vba - 如何根据单元格值删除文件?
- angular - Karma/Jasmine:无法使用 detectChanges() 检测到 @Input 属性的更改
- c# - 如果使用 MemoryStream,从 ZipArchiveEntry 读取会导致异常和 MemoryLeak
- python - 如何从这个 BeautifulSoup 中提取数字?
- java - 在命名查询 where 子句中使用子查询