Naive Bayes über kontinuierliche Variablen

8

Bitte erlauben Sie mir, eine grundlegende Frage zu stellen. Ich verstehe die Mechanik von Naive Bayes für diskrete Variablen und kann die Berechnungen "von Hand" wiederholen. (Code von HouseVotes84 ganz unten).

Ich habe jedoch Schwierigkeiten zu sehen, wie die Mechanik für kontinuierliche Variablen funktioniert (Beispielcode siehe unten). Wie berechnet das Paket die bedingten Wahrscheinlichkeiten [, 1]und [, 2]in der folgenden Tabelle? Da jeder einzelne X-Wert eindeutig ist, erstellt er einen Bereich um jeden Punkt und berechnet die relativen Häufigkeiten innerhalb dieser Bereiche (z. B. wenn der Punkt +0,311 ist, bewertet er das Auftreten von blauen und orangefarbenen Punkten in z. B. einem Bereich von 0,1 und +0,5?) Dies könnte eine grundlegende Frage sein - entschuldigen Sie sich, wenn ja.

Tabelle

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
quelle

Antworten:

5

Aus dem R-Paket (e1071) und der von Ihnen verwendeten Funktion naiveBayes:

Der standardmäßige naive Bayes-Klassifikator (zumindest diese Implementierung) setzt die Unabhängigkeit der Prädiktorvariablen und die Gaußsche Verteilung (unter Berücksichtigung der Zielklasse) der metrischen Prädiktoren voraus . Bei Attributen mit fehlenden Werten werden die entsprechenden Tabelleneinträge zur Vorhersage weggelassen.

Es ist ziemlich normal für kontinuierliche Variablen in einem naiven Bayes, dass eine Normalverteilung für diese Variablen berücksichtigt wird und dann ein Mittelwert und eine Standardabweichung berechnet werden können und dann unter Verwendung einiger Standard-Z-Tabellen-Berechnungswahrscheinlichkeiten für jede Ihrer kontinuierlichen Variablen geschätzt werden kann der naive Bayes-Klassifikator. Ich dachte, dass es möglich ist, die Verteilungsannahme in diesem Paket zu ändern, aber anscheinend irre ich mich.

Es gibt ein weiteres R-Paket (klaR), in dem Sie den Dichtekern ändern können. (Die Funktion ist NaiveBayes). Aus dem Paket:

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

usekernel

Wenn TRUE, wird eine Kernel-Dichteschätzung (Dichte) für die Dichte-Schätzung verwendet. Wenn FALSE, wird eine normale Dichte geschätzt.

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

Ich habe vor nicht allzu langer Zeit an einem Projekt gearbeitet, für das ich einen naiven Bayes-Klassifikator (von Grund auf neu) berechnen musste. Ich habe in R angefangen, aber als ich den Prozess beendet hatte, habe ich den Code nach Python verschoben. Hier ist mein Code, mit dem ich begonnen habe. Erwarten Sie nicht, dass es poliert wird. Zum größten Teil folgte ich dem Beispiel von Wikipedia ( https://en.wikipedia.org/wiki/Naive_Bayes_classifier#Examples ).

Die Schritte sind einfach:

  1. Berechnen Sie die a priori Wahrscheinlichkeiten, die den Anteil der Klassen ausmachen

  2. Nehmen Sie für Ihre kontinuierlichen Daten eine Normalverteilung an und berechnen Sie den Mittelwert und die Standardabweichung.

  3. Um Beobachtungen zu klassifizieren, nehmen Sie die neue Eingabe xund berechnen Sie, dnorm(x, mu, sigma)woher mu und sigma aus Schritt 2 stammen.

  4. Fassen Sie log (apriori) + log (dnorm (...)) zusammen.

Zu diesem Zeitpunkt log(dnorm(...))sollte zwei Protokollwerte enthalten (in meinem Beispiel). Die Wahrscheinlichkeit, dass sie zur Klasse 0 gehören, und die Wahrscheinlichkeit, dass sie zur Klasse 1 gehören. Dies ist der Punkt, den Eric Peterson in seinem zweiten Absatz hervorhebt.

  1. Berechnen Sie die posterioren Wahrscheinlichkeiten

Ich habe meine Ergebnisse auch mit der R-Bibliothek e1071 verglichen. Meine Wahrscheinlichkeitsergebnisse stimmen in diesem einfachen Fall nicht mit denen überein , obwohl die Klassifizierung dies tut. In ihrer predict.naiveBayesFunktion haben sie so etwas wie log(apriori) + apply(log(sapply(...compute dnorm code here...)), 1, sum)die Rückgabe, log(apriori) + log(1) = log(apriori)was ein Fehler ist, so dass ihre Klassifizierung ausschließlich auf den a priori-Wahrscheinlichkeiten basiert (tatsächlich verwenden sie Zählungen, nicht die Wahrscheinlichkeiten).

Wie auch immer, ich hoffe, dies hilft Ihnen (und allen anderen) zu sehen, was sich unter der Haube befindet, da es mir auch nicht klar war.

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
quelle