2016-06-18 7 views
1

Für ein großes Dataset Textklassifikationsproblem, habe ich verschiedene Klassifikatoren wie LDA, RandomForest, KNN usw. verwendet und Genauigkeitsraten von 78-85% erhalten. Multinomiale Naive Bayes mit bnlearn ergaben jedoch eine Genauigkeit von 97%. Untersucht, warum die Genauigkeit so hoch ist und das Problem scheint mit der Vorhersage in bnlearn - vielleicht habe ich die falschen Parameter verwendet.Multinomiale Naive Bayes in bnlearn, Vorhersage Klärung

Veranschaulichung mit einem Beispieldatensatz.

Long Sweet Yellow Fruit 

Yes Yes Yes Banana 

Yes Yes Yes Banana 

Yes Yes Yes Banana 

Yes Yes Yes Banana 

No Yes Yes Banana 

No Yes Yes Orange 

No Yes Yes Orange 

No Yes Yes Orange 

Yes Yes Yes Other 

No Yes No Other 

Yes Yes Yes Banana 

Yes Yes Yes Banana 

Yes No Yes Banana 

Yes No No Banana 

No No Yes Banana 

No No Yes Orange 

No No Yes Orange 

No No Yes Orange 

Yes Yes No Other 

No No No Other 

Yes Yes Yes Banana 

No Yes Yes Banana 

No Yes Yes Orange 

No Yes Yes Orange 

No Yes No Other 

Obiges ist ein Datensatz von 25 Zeilen als Datenrahmen geladen bn.X
Dies kann in eine Reihe 20 Trainingsdatensatz und 5 Zeile Testdatensatz aufgeteilt werden.

Schritt 1: Laden der Daten

Y=bn.X[,4] # Outcome column 
train=1:20 
cols=1:4 
bn.X[,cols] <- data.frame(apply(bn.X[cols], 2, as.factor)) 
trainbn.X=bn.X[train,] 
testbn.X=bn.X[-train,] 
trainbn.Y=Y[train] 
testbn.Y=Y[-train] 

Schritt 2: Klassifizierung mit bnlearn

library(bnlearn) 

NB.fit = naive.bayes(trainbn.X, "Fruit") 

# Prediction  
NB.pred=predict(NB.fit,testbn.X,prob=TRUE) 
writeLines("\n Multinomial Naive Bayes\n") 
table(NB.pred, testbn.Y) 
cat("Accuracy %:", mean(NB.pred == testbn.Y)*100) 

Schritt 3: Classification LDA Verwendung

library(MASS) 

lda.fit=lda(Fruit~.,data=trainbn.X) 

# Prediction 
lda.pred=predict(lda.fit,testbn.X) 
lda.class=lda.pred$class 
writeLines("\n LDA \n") 
table(lda.class,testbn.Y) 
cat("Accuracy %:", mean(lda.class == testbn.Y)*100) 

Sowohl bnlearn Naive Bayes und LDA geben die gleiche Vorhersage mit 80% Genauigkeit für die 5 Zeilen.

Allerdings scheint bnlearn die Ergebniswerte der Testreihen auch für die Vorhersage zu verwenden. Dies scheint der Grund zu sein, warum ich einen hohen Genauigkeitswert für das Textklassifizierungsszenario, an dem ich arbeitete, erhalten habe.

Wenn ich irgendeine der folgenden vor Vorhersage,

testbn.X$Fruit=NA 
testbn.X$Fruit="Orange" 
testbn.X[1:3,]$Fruit="Orange" 

Es gibt keine Auswirkungen auf die Ergebnisse von LDA - LDA vollständig die Ergebnis-Werte der Testdaten ignoriert, wenn zur Verfügung gestellt. Das ist ein ideales Verhalten.

Für bnlearn ist dies jedoch nicht der Fall. Während der Vorhersage wird ein Fehler für NA und alle Werte = "Orange" empfangen. Und für die 3. Datenmanipulation, liefert bnlearn Vorhersage ein völlig anderes Ergebnis

Frage: Ist die Art und Weise, die ich verwendet habe, die Vorhersagefunktion von bnlearn richtig? Sollte ich andere Parameter verwenden?

Antwort

3

Es scheint, dass die Funktion naive.bayes nicht tatsächlich ein Netzwerk passt, es definiert nur die Struktur eines naiven Bayes-Netzwerk basierend auf den gelieferten Daten. Wenn Sie eine Vorhersage außerhalb der Stichprobe durchführen möchten, müssen Sie zunächst die Netzwerkparameter mithilfe von bn.fit in einem Trainingssatz schätzen.

Die Verwirrung hier verursacht wird, weil das Verfahren entweder eine predictNetzstrukturoder ein Einbau Netzwerk als object Parameter akzeptiert. Wenn object nur eine Netzwerkstruktur ist (z. B. das von naive.bayes zurückgegebene Objekt), werden die Netzwerkparameter basierend auf data geschätzt, die an die predict-Methode übergeben wird. Als Konsequenz sind die in Ihrem Beispiel erhaltenen Vorhersagen tatsächlich Vorhersagen aus den Testdaten.Von ?naive.bayes unter dem Abschnitt Hinweis:

predict akzeptiert entweder ein bn oder ein bn.fit Objekt als erstes Argument. Für die ersteren sind die Parameter des Netzwerks auf data, dass ist die Beobachtungen, deren Klasse beschriftet die Funktion versucht, voraussagen.

Wenn jedoch ein Einbau Netzwerk als object zugeführt wird, werden die Einbaunetzwerkparameter für die Vorhersage verwendet, und die Werte der Variablen in den trainingdata zum predict Verfahren geliefert haben keinen Einfluss auf die Vorhersagen . (Aus irgendeinem Grund scheinen NA Werte für die Variable training auch bei einem angepassten Netzwerk immer noch nicht zulässig zu sein.) Sie können das angepasste Netzwerk erhalten, indem Sie bn.fit mit Ihrer Netzwerkstruktur in einem bn Objekt und training_data als bn.fit(bn, training_data) aufrufen.

Ich habe das bnlearn Paket vorher noch nicht verwendet, aber das sind die Schlussfolgerungen, die ich beim Testen und Lesen der Dokumentation erreicht habe. Hier einige Code, den ich verwendet, um das Verhalten zu testen, auf der Grundlage Ihrer Arbeit:

# training and testing data 
set.seed(1) # bnlearn uses stochastic tie-breaking 
train_idx <- 1:20 

train_fruit <- fruit[train_idx, ] 
test_fruit <- fruit[-train_idx, ] 

library(bnlearn) 

nb.net <- naive.bayes(train_fruit, "Fruit") # network structure 
nb.fit <- bn.fit(nb.net, train_fruit) # fit the network 
nb.pred <- predict(nb.fit, test_fruit) # oos prediction 

mean(nb.pred == test_fruit$Fruit) 
# [1] 0.8 

# manipulated test data 
test_fruit2 <- test_fruit 
test_fruit2[1:3, "Fruit"] <- "Orange" 

# fitted network as predict object 
nb.pred2_fit <- predict(nb.fit, test_fruit2) 
identical(nb.pred2_fit, nb.pred) 
# [1] TRUE 

# network structure as predict object 
nb.pred2_net <- predict(nb.net, test_fruit2) 
#  Warning messages: 
#  1: In check.data(data, allowed.types = discrete.data.types) : 
#  variable Sweet has levels that are not observed in the data. 
#  2: In check.data(data, allowed.types = discrete.data.types) : 
#  variable Fruit has levels that are not observed in the data. 
identical(nb.pred2_net, nb.pred) 
# [1] FALSE 

Hier ist die fruit Datensatz ich in meinem Beispielcode verwendet, lesen Sie von Ihrem Beitrag:

fruit <- read.table(header = TRUE, text = " 
Long Sweet Yellow Fruit 
Yes Yes Yes Banana 
Yes Yes Yes Banana 
Yes Yes Yes Banana 
Yes Yes Yes Banana 
No Yes Yes Banana 
No Yes Yes Orange 
No Yes Yes Orange 
No Yes Yes Orange 
Yes Yes Yes Other 
No Yes No Other 
Yes Yes Yes Banana 
Yes Yes Yes Banana 
Yes No Yes Banana 
Yes No No Banana 
No No Yes Banana 
No No Yes Orange 
No No Yes Orange 
No No Yes Orange 
Yes Yes No Other 
No No No Other 
Yes Yes Yes Banana 
No Yes Yes Banana 
No Yes Yes Orange 
No Yes Yes Orange 
No Yes No Other 
") 
+0

Dank Mikko für Eure Hilfe. Ich konnte die erwarteten Ergebnisse basierend auf Ihrer Antwort erhalten. Für mein ursprüngliches Problem sank die Genauigkeit auf 80%, was im selben Bereich liegt wie die anderen Klassifikatoren. – Siddharth

+0

@Siddharth Brilliant, froh, ich könnte helfen! –

Verwandte Themen