R e1071中的朴素贝叶斯算法存在Bug吗?

我在R社区没有任何经验,所以如果这里不是合适的论坛,请指引我去其他地方…

长话短说,我担心e1071::naiveBayes倾向于按字母顺序给出标签。

在之前的一个问题这里,我注意到e1071实现的朴素贝叶斯算法在处理数值预测变量时有一些奇怪的行为。虽然我得到了一个更合理的答案,但一些概率似乎向上偏斜了。

谁能解释一下为什么这个模拟会变成这样?我现在只能认为这是一个bug…

library(e1071)# 获取一个包含numObs行和numDistinctLabels个可能标签的数据框# 每个标签随机从字母a-z中抽取# 每个标签都有自己的数值变量分布# 这是normal(i*100, 10),i在1:numDistinctLabels之间# 因此,如果标签是t, m和q,那么t是normal(100, 10),m是normal(200, 10),依此类推# 想法是所有标签应该被预测的频率相同# 但似乎"a"会被预测得最多,"b"第二,依此类推doExperiment = function(numObs, numDistinctLabels){    possibleLabels = sample(letters, numDistinctLabels, replace=F)    someFrame = data.frame(        x=rep(NA, numObs),        label=rep(NA, numObs)    )    numObsPerLabel = numObs / numDistinctLabels    for(i in 1:length(possibleLabels)){        label = possibleLabels[i]        whichAreNA = which(is.na(someFrame$label))        whichToSet = sample(whichAreNA, numObsPerLabel, replace=F)        someFrame[whichToSet, "label"] = label        someFrame[whichToSet, "x"] = rnorm(numObsPerLabel, 100*i, 10)    }    someFrame = as.data.frame(unclass(someFrame))    fit = e1071::naiveBayes(label ~ x, someFrame)    # 阈值参数似乎不会改变这个问题...    someFrame$predictions = predict(fit, someFrame, threshold=0)    someFrame}# 给定一个带标签的数据框,返回最常被预测的标签getMostFrequentPrediction = function(labeledFrame){    names(which.max(sort(table(labeledFrame$prediction))))}# 运行几千次实验mostPredictedClasses = sapply(1:2000, function(x) getMostFrequentPrediction(doExperiment(100, 5)))# 制作最常预测标签的条形图plot(table(mostPredictedClasses))

这会生成如下图表:

enter image description here

给每个标签相同的正态分布(即均值100,标准差10)会得到:

enter image description here

关于评论中的混淆:

这可能已经超出了Stack Overflow的范围,但无论如何…虽然我期望分类结果不那么集中,但标准差的影响很大程度上平滑了概率密度函数,如果你足够多次地进行这个实验,你会观察到一两个标签实际上倾向于占主导地位(在这种情况下是红色和黑色)。

enter image description here

遗憾的是,我们无法利用所有标签的标准差相同的知识。

如果你在均值上添加一点噪声,分布会变得更加均匀,尽管仍然存在一些错误分类。

enter image description here


回答:

问题不在于naiveBayes,而在于你的getMostFrequentPrediction函数。你在有多个标签并列第一的情况下只返回一个值。由于你使用了table(),表中的计数是按字母顺序隐式排序的。所以当你获取第一个最大值时,它也会是字母顺序中“最小的”。因此,如果你多次这样做:

getMostFrequentPrediction(data.frame(predictions=sample(rep(letters[1:3], 5))))

你会总是得到”a”,尽管字母”a” “b”和”c”都出现了5次。

如果你想随机选择最常预测的类别之一,这里是另一种可能的实现方式

getMostFrequentPrediction = function(labeledFrame){    tt<-table(labeledFrame$predictions)    names(sample(tt[tt==max(tt)], 1))}

这会得到

enter image description here

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注