连续变量上的朴素贝叶斯

机器算法验证 r 朴素贝叶斯 贝叶斯
2022-03-14 22:03:08

请允许我问一个基本问题。我了解离散变量的朴素贝叶斯机制,并且可以“手动”重做计算。(HouseVotes84 代码如下)。

但是 - 我正在努力了解连续变量的机制是如何工作的(下面的示例代码)。包如何计算条件概率[, 1][, 2]在下表中?由于任何单个 X 值都是唯一的,它是否会在每个点周围创建一个范围,并计算这些范围内的相对频率(例如,如果该点为 +0.311,它是否评估蓝色和橙色点在例如 0.1 和+0.5?)这可能是基本问题-如果是,请道歉。

桌子

A-priori probabilities:
Y
  blue orange 
   0.5    0.5 

Conditional probabilities:
        values
Y              [,1]      [,2]
  blue   0.08703793 0.9238799
  orange 1.33486433 0.9988389

代码

blue=rep("blue",50); orange=rep("orange",50); colour=c(blue,orange); values1=rnorm(50,0,1); values2=rnorm(50,1,1); values=c(values1,values2)
df=data.frame(colour,values)

(model <- naiveBayes(colour ~ ., data = df))
(predict(model, df[1:10,]))
(predict(model, df[1:10,], type = "raw"))
(pred <- predict(model, df))
table(pred, df$colour)

## Categorical data only:
library(e1071)
data(HouseVotes84, package = "mlbench")
HouseVotes84=HouseVotes84[,1:3]
(model <- naiveBayes(Class ~ ., data = HouseVotes84))
(predict(model, HouseVotes84[1:10,]))
(predict(model, HouseVotes84[1:10,], type = "raw"))
(pred <- predict(model, HouseVotes84))
table(pred, HouseVotes84$Class)
2个回答

来自 R 包 (e1071) 和您正在使用的函数 naiveBayes:

标准的朴素贝叶斯分类器(至少这个实现)假设预测变量的独立性,以及度量预测变量的高斯分布(给定目标类)。对于具有缺失值的属性,相应的表条目被省略以进行预测。

对于朴素贝叶斯中的连续变量来说,这是非常标准的,即为这些变量考虑正态分布,然后可以计算平均值和标准差,然后使用一些标准的 z 表计算可以估计每个连续变量的概率朴素贝叶斯分类器。我认为可以改变这个包中的分布假设,但显然我错了。

还有另一个 R 包 (klaR),您可以在其中更改密度内核。(功能是 NaiveBayes)。从包装:

NaiveBayes(x, grouping, prior, usekernel = FALSE, fL = 0, ...)

用户内核

如果为 TRUE,则使用核密度估计(密度)进行密度估计。如果为 FALSE,则估计正常密度。

density(x, bw = "nrd0", adjust = 1,
        kernel = c("gaussian", "epanechnikov", "rectangular",
                   "triangular", "biweight",
                   "cosine", "optcosine")

不久前我正在做一个项目,我需要计算一个朴素贝叶斯分类器(从头开始)。我从 R 开始,但是一旦我完成了这个过程,我就将代码移到了 Python。这是我开始的代码。不要指望它会被抛光。在大多数情况下,我遵循 Wikipedia 的示例(https://en.wikipedia.org/wiki/Naive_Bayes_classifier#Examples)。

步骤很简单:

  1. 计算先验概率,即类的比例

  2. 对于您的连续数据,假设一个正态分布并计算平均值和标准差。

  3. 要对观察结果进行分类,请使用新输入x,计算dnorm(x, mu, sigma)mu 和 sigma 来自步骤 2 的位置。

  4. 总结 log(apriori) + log(dnorm(...))。

此时,log(dnorm(...))应该包含两个对数值(在我的示例中)。他们属于第 0 类的概率和属于第 1 类的概率。这是 Eric Peterson 在他的第二段中提出的观点。

  1. 计算后验概率

我还将我的结果与 R 库 e1071 进行了比较。对于这个简单的案例,我的概率结果与他们的结果不一致,尽管分类确实如此。在他们的predict.naiveBayes功能中,他们有类似log(apriori) + apply(log(sapply(...compute dnorm code here...)), 1, sum)which 返回log(apriori) + log(1) = log(apriori)哪个是错误的东西,所以他们的分类完全基于先验概率(实际上,他们使用计数而不是概率)。

无论如何,我希望这可以帮助您(和其他任何人)了解引擎盖下的内容,因为我也不清楚。

n=30 ## samples
set.seed(123)
x = c(rnorm(n/2, 10, 2), rnorm(n/2, 0, 2))
y = as.factor(c(rep(0, 20), rep(1, 10)))
y


#library(e1071)
#nb = naiveBayes(x, y, laplace = 0)
#nb

#nb_predictions = predict(nb, x[1], type='raw')
#nb_predictions



library(dplyr)

nbc <- function(x, y){
  df <- as.data.frame(cbind(x,y))
  a_priori <- table(y) #/length(y)

  cond_probs <- df %>% group_by(y) %>% summarise(means = mean(x), var = sd(x))

  print("A Priori Probabilities")
  print(a_priori/sum(a_priori))

  print("conditional probabilities \n")
  print(cond_probs)

  return(list(apriori = a_priori, tables = cond_probs))
}



predict_nbc <- function(model, new_x){
  apriori = as.matrix(model$apriori)
  a = log(apriori/sum(apriori))
  msd = as.matrix(model$tables)[,c(2,3)] ## creates 3 columsn; first is junk
  probs = sapply(new_x, function(v) dnorm(x = v, mean = msd[,1], sd = msd[,2]))
  b = log(probs)
  #L = a + b ## works for 1 new obs
  L = apply(X = b, MARGIN = 2, FUN = function(v) a + v)

  results <- apply(X = L, MARGIN = 2, function(x){
                   sapply(x, function(lp){ 1/sum(exp(x - lp)) }) ## numerically stable
  })
  return(results)
}



fit = nbc(x,y)

fit ## my naive bayes classifier model

myres = predict_nbc(fit, new_x = x[1:4])
myres