我在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))
这会生成如下图表:
给每个标签相同的正态分布(即均值100,标准差10)会得到:
关于评论中的混淆:
这可能已经超出了Stack Overflow的范围,但无论如何…虽然我期望分类结果不那么集中,但标准差的影响很大程度上平滑了概率密度函数,如果你足够多次地进行这个实验,你会观察到一两个标签实际上倾向于占主导地位(在这种情况下是红色和黑色)。
遗憾的是,我们无法利用所有标签的标准差相同的知识。
如果你在均值上添加一点噪声,分布会变得更加均匀,尽管仍然存在一些错误分类。
回答:
问题不在于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))}
这会得到