我有一个带有这种结构的小文件'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。
我做错了什么?
答案 0 :(得分:2)
在Spark Naive Bayes实现的source code中,您可以找到已实现的算法链接:
- Multinomial NB可以处理各种离散数据。例如,通过将文档转换为TF-IDF向量,它可以是 用于文档分类。
- Bernoulli NB将每个向量设为0-1向量。
醇>输入要素值必须为非负值。
在你的情况下,Spark使用Multinomial NB(这是默认的),所以让我们深入研究算法。
Naive Bayes通常用于文档分类,让我将您的案例解释为文档分类案例:
ten
和twenty
Spark
因此,对于您的第一行数据,它将是:Spark
对于第二个和第三个,它们将是:Spark Spark
正如我从Multinomial NB链接中所理解的那样,算法可以在这个等式中进行总结:
其中:
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
这意味着结果不再依赖于输入向量!
现在,拥有最多行数据的类赢得了分类。
这就是为什么你的预测结果是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)。因此,你得到了结果。
使用大量的训练数据会更有意义。