Spark MLlib 中的朴素贝叶斯
Posted
技术标签:
【中文标题】Spark MLlib 中的朴素贝叶斯【英文标题】:Naive Bayes in Spark MLlib 【发布时间】:2016-11-10 15:19:53 【问题描述】:我有一个具有这种结构的小文件“naivebayestest.txt”
10 1:1
20 1:2
20 1:2
我试图根据这些数据对向量 (1) 进行分类。如果我正确理解贝叶斯,(1)的标签应该是 10(概率为 1!)。 Spark MLlib 中的程序:
String path = "/usr/local/spark/data/mllib/bayestest.txt";
JavaRDD<LabeledPoint> training = MLUtils.loadLibSVMFile(jsc.sc(), path).toJavaRDD();
final NaiveBayesModel model = NaiveBayes.train(training.rdd());
Vector v = Vectors.dense(1);
double prediccion = model.predict(v);
System.out.println("Vector: "+v+" prediction: "+prediccion);
显示Vector: [1.0] prediction: 20.0
我使用 1050 个元素的训练集获得了相同的结果,其中 350 个 (1/3) 的形式为 10 1:1
,其余为 20 1:2
(2/3),我仍然得到相同的向量预测 20.0 1.
我做错了什么?
【问题讨论】:
【参考方案1】:在 Spark Naive Bayes 实现的source code 中,您可以找到实现的算法的链接:
Multinomial NB 可以处理各种离散数据。例如,通过将文档转换为 TF-IDF 向量,可以 用于文档分类。 Bernoulli NB 将每个向量设为 0-1 向量。
输入的特征值必须是非负的。
在你的例子中,Spark 使用 Multinomial NB(这是默认的),所以让我们深入研究一下算法。
朴素贝叶斯常用于文档分类,我把你的案例解释为文档分类案例:
-
假设课程是
ten
和twenty
假设输入令牌(在这种情况下只有一个)是Spark
所以对于您的第一行数据,它将是:Spark
对于第二个和第三个,他们将是:Spark Spark
正如我从 Multinomial NB 链接中了解到的那样,该算法可以总结为以下等式:
地点: P(Ci) : 属于 i 类的测试数据的条件概率 nf : 词汇表中的词条数 Sij : 类 i 和词条 j 的词频总和 Si : 第 i 类的词频总和 λ:λ,平滑值 v : 输入测试向量 ndci : i 类中的行数据数 nd : 行数据总数 nc : 类数 你的情况发生了什么
在您的行数据中,只有一个标记(或只有一个输入特征),这意味着等式中的 nf
等于 1
所以:Sij = Si
这将使向量的乘数:ln(Sij+λ) - ln(Si+nf*λ) = ln(Si+λ)-ln(Si+λ) = 0
因此,现在的等式是:
这意味着结果不再依赖于输入向量!
现在是拥有最多行数据的类赢得分类。
这就是为什么您的预测结果是 20 而不是 10。 到底
为避免这种情况,请尝试使用线性回归、决策树、随机森林、GBT 等。
【讨论】:
【参考方案2】:Naive Bayes
模型将针对所有 3 条记录进行训练。你的假设
如果我正确理解贝叶斯,则 (1) 的标签应该是 10(概率为 1!)
这里错了 正确的概率是
P(10|1) = P(1|10) * P(10)/P(1)
根据定义,但由于附加平滑,此公式可能会发生变化。我不确定那是什么公式。但似乎由于加法平滑,概率 P(20|1) 大于 P(10|1)。因此,您会得到这样的结果。
如果有大量的训练数据,它会更有意义。
【讨论】:
你是对的,但是 p(1|10)*p(10)/p(1) = (1*1/3 )/ (1/3) = 1 我尝试过使用更大的训练集(1050 个元素),结果相同。无论如何感谢您的帮助以上是关于Spark MLlib 中的朴素贝叶斯的主要内容,如果未能解决你的问题,请参考以下文章
贝叶斯朴素贝叶斯及调用spark官网 mllib NavieBayes示例
为啥朴素贝叶斯不能像逻辑回归一样在 Spark MLlib 管道中工作?
Spark MLlib 源码学习---朴素贝叶斯模型(Naive Bayes)