Spark MLlib的朴素贝叶斯

时间:2016-07-08 06:23:32

标签: java apache-spark apache-spark-mllib naivebayes

我有一个带有这种结构的小文件'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个元素的训练集获得相同的结果,10 1:1形式的350(1/3)和其余的20 1:2(2/3),我仍然得到相同的结果向量1的预测20.0。

我做错了什么?

2 个答案:

答案 0 :(得分:2)

在Spark Naive Bayes实现的source code中,您可以找到已实现的算法链接:

  
      
  1. Multinomial NB可以处理各种离散数据。例如,通过将文档转换为TF-IDF向量,它可以是   用于文档分类。
  2.   
  3. Bernoulli NB将每个向量设为0-1向量。
  4.         

    输入要素值必须为非负值。

在你的情况下,Spark使用Multinomial NB(这是默认的),所以让我们深入研究算法。

Naive Bayes通常用于文档分类,让我将您的案例解释为文档分类案例:

  1. 我们说这些课程是tentwenty
  2. 假设输入令牌(在这种情况下只有一个)是Spark
  3. 因此,对于您的第一行数据,它将是:Spark
    对于第二个和第三个,它们将是:Spark Spark

    正如我从Multinomial NB链接中所理解的那样,算法可以在这个等式中进行总结:
    Equation

    其中:
    P(Ci):属于类i的测试数据的条件概率 nf:词汇表中的术语数
    Sij:类i和术语j 的术语频率之和 Si:第i类的术语频率之和
    λ: lambda,平滑值
    v:输入测试向量
    ndci:类i中的行数据
    nd:行数据的总数
    nc:类的数量



    您的案件发生了什么

    在您的行数据中,只有一个令牌(或只有一个输入要素),这意味着等式中的 nf等于1
    所以: Sij = Si

    这将使向量的乘数:
    ln(Sij+λ) - ln(Si+nf*λ) = ln(Si+λ)-ln(Si+λ) = 0

    因此,现在的等式是:
    New Equation

    这意味着结果不再依赖于输入向量!

    现在,拥有最多行数据的类赢得了分类。

    这就是为什么你的预测结果是20而不是10。



    最后

    要避免这种情况,请尝试使用线性回归,解析树,随机森林,GBT等。

答案 1 :(得分:1)

Naive Bayes模型将针对所有3条记录进行培训。你的假设

  

如果我正确理解贝叶斯,(1)的标签应为10(概率为1!)

这里错了 正确的概率将是

P(10|1) = P(1|10) * P(10)/P(1)

根据定义,但由于添加剂平滑,该配方可能会发生变化。我不确定那是什么配方。但似乎由于加性平滑,P(20 | 1)的概率大于P(10 | 1)。因此,你得到了结果。

使用大量的训练数据会更有意义。