Naive Bayes sur les variables continues

8

Veuillez me permettre de poser une question de base. Je comprends la mécanique des Naive Bayes pour les variables discrètes, et peux refaire les calculs "à la main". (code de HouseVotes84 tout le chemin ci-dessous).

Cependant - j'ai du mal à voir comment la mécanique fonctionne pour les variables continues (exemple de code ci-dessous). Comment le package calcule-t-il les probabilités conditionnelles [, 1]et [, 2]dans le tableau ci-dessous? Comme toute valeur X individuelle est unique, crée-t-elle une plage autour de chaque point et calcule-t-elle les fréquences relatives dans ces plages (par exemple, si le point est +0,311, évalue-t-elle l'incidence des taches bleues et oranges dans, par exemple, une plage de 0,1 et +0,5?) Cela pourrait être une question fondamentale - excuses si c'est le cas.

Table

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

Code

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)
Wouter
la source

Réponses:

5

Du package R (e1071) et de la fonction naiveBayes que vous utilisez:

Le classificateur Bayes naïf standard (au moins cette implémentation) suppose l'indépendance des variables prédictives et la distribution gaussienne (compte tenu de la classe cible) des prédicteurs métriques. Pour les attributs avec des valeurs manquantes, les entrées de tableau correspondantes sont omises pour la prédiction.

Il est assez standard pour les variables continues dans un Bayes naïf qu'une distribution normale soit considérée pour ces variables et une moyenne et un écart-type peuvent ensuite être calculés, puis en utilisant des calculs de table z standard, les probabilités peuvent être estimées pour chacune de vos variables continues à faire le classificateur naïf de Bayes. Je pensais qu'il était possible de changer l'hypothèse de distribution dans ce package, mais apparemment je me trompe.

Il existe un autre package R (klaR) où vous pouvez changer le noyau de densité. (la fonction est NaiveBayes). De l'emballage:

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

usekernel

si VRAI, une estimation de densité du noyau (densité) est utilisée pour l'estimation de la dénstité. Si FAUX, une densité normale est estimée.

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

Il y a peu de temps, je travaillais sur un projet pour lequel j'avais besoin de calculer un classificateur bayésien naïf (à partir de zéro). J'ai commencé dans R, mais une fois le processus terminé, j'ai déplacé le code vers Python. Voici mon code avec lequel j'ai commencé. Ne vous attendez pas à ce qu'il soit poli. Pour la plupart, j'ai suivi l'exemple de Wikipedia ( https://en.wikipedia.org/wiki/Naive_Bayes_classifier#Examples ).

Les étapes sont simples:

  1. calculer les probabilités a priori qui sont la proportion des classes

  2. Pour vos données continues, supposez une distribution normale et calculez la moyenne et l'écart type.

  3. Pour classer les observations, prenez la nouvelle entrée x, calculez d' dnorm(x, mu, sigma)où viennent mu et sigma à l'étape 2.

  4. Résumé du journal (apriori) + log (dnorm (...)).

À ce stade, log(dnorm(...))doit contenir deux valeurs de journal (dans mon exemple). La probabilité d'appartenir à la classe 0 et la probabilité d'appartenir à la classe 1. C'est ce qu'Eric Peterson fait valoir dans son deuxième paragraphe.

  1. Calculer les probabilités postérieures

J'ai également comparé mes résultats à la bibliothèque R e1071. Mes résultats de probabilité ne correspondent pas aux leurs pour ce cas simple , bien que la classification le fasse. Dans leur predict.naiveBayesfonction, ils ont quelque chose comme log(apriori) + apply(log(sapply(...compute dnorm code here...)), 1, sum)qui renvoie log(apriori) + log(1) = log(apriori)ce qui est une erreur, donc leur classification est uniquement basée sur les probabilités a priori (en fait, ils utilisent les comptes et non les probabilités).

Quoi qu'il en soit, j'espère que cela vous aidera (et quiconque) à voir ce qui se cache sous le capot, car cela n'était pas clair pour moi non plus.

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
Jon
la source