Ich versuche, eine SVM aus Trainingsdaten zu erstellen, bei denen eine Gruppe mehr als die andere vertreten ist. Die Gruppen werden jedoch in den endgültigen Testdaten zu gleichen Teilen vertreten sein. Daher möchte ich den class.weights
Parameter der e1071
R-Paket-Schnittstelle verwenden libsvm
, um den Einfluss der beiden Gruppen auf die Trainingsdaten auszugleichen.
Da ich nicht genau wusste, wie diese Gewichte angegeben werden sollten, habe ich einen kleinen Test durchgeführt:
- Generieren Sie einige Nulldaten (zufällige Merkmale; Verhältnis 2: 1 zwischen Gruppenbezeichnungen)
- Passen Sie ein SVM mit dem
class.weights
Parametersatz an. - Sagen Sie eine Reihe neuer Null-Datensätze voraus und sehen Sie sich die Klassenproportionen an.
- Wiederholen Sie den gesamten Prozess mehrmals für verschiedene Null-Trainingssätze.
Hier ist der R-Code, den ich verwende:
nullSVM <- function(n.var, n.obs) {
# Simulate null training data
vars = matrix(rnorm(n.var*n.obs), nrow=n.obs)
labels = rep(c('a', 'a', 'b'), length.out=n.obs)
data = data.frame(group=labels, vars)
# Fit SVM
fit = svm(group ~ ., data=data, class.weights=c(a=0.5, b=1))
# Calculate the average fraction of 'a' we would predict from null test data
mean(replicate(50, table(predict(fit, data.frame(matrix(rnorm(n.var*n.obs), nrow=n.obs))))[1])) / n.obs
}
library(e1071)
set.seed(12345)
mean(replicate(50, nullSVM(50, 300)))
Von dieser ganzen Sache habe ich eine Ausgabe von ~ 0,5 erwartet, aber das habe ich nicht bekommen:
> mean(replicate(50, nullSVM(50, 300)))
[1] 0.6429987
Die class.weights
Paramter arbeiten, eine Art , wie das untere ich Gewicht a
, desto niedriger ist es in dieser Simulation dargestellt wird (und wenn ich weglassen class.weights
es nahe 1 zurückgibt) ... aber ich verstehe nicht , warum nur Gewichte von 1: 2 ( für Trainingsdaten, die 2: 1 sind) bringt mich nicht ganz auf 50%.
Wenn ich SVMs falsch verstehe, kann jemand diesen Punkt erklären? (oder einige refs schicken?)
Kann mir jemand sagen, wie ich den class.weights
Parameter richtig verwenden soll, wenn ich es falsch mache ?
Könnte es möglicherweise ein Fehler sein? (Ich denke nicht, da ich diese Software und die zugrunde liegende libsvm recht ausgereift verstehe)
quelle
Antworten:
Ich denke, es kann von den Werten von C und der Anzahl der Muster abhängen, die Sie haben. Die SVM versucht, die maximale Margin-Diskriminante zu finden. Wenn Sie also nur wenige Daten haben, kann es sein, dass die SVM die Lösung mit der harten Margin findet, ohne dass einer der Lagrange-Multiplikatoren seine Obergrenze erreicht (in diesem Fall das Verhältnis der Strafen für jeden Klasse ist im Wesentlichen irrelevant, da die Slack-Valiables klein oder null sind. Versuchen Sie, die Anzahl der Trainingsmuster zu erhöhen, und prüfen Sie, ob dies einen Effekt hat (da dies die Wahrscheinlichkeit verringert, dass die Hard-Margin-Lösung innerhalb der Box-Beschränkungen gefunden wird). .
Noch wichtiger ist, dass die optimalen Werte von C datenabhängig sind. Sie können sie nicht einfach auf bestimmte Werte einstellen, sondern sie optimieren, indem Sie den ausgelassenen Fehler oder eine bestimmte Verallgemeinerungsgrenze minimieren. Bei unausgeglichenen Klassen können Sie das Verhältnis der Werte für jede Klasse festlegen und die durchschnittliche Strafe für alle Muster optimieren.
quelle
caret
Paket oder die eingebautetune()
Funktion zur Optimierung von Modellparametern. Daher gefällt mir besonders Ihre zweite Idee, wie Sie in der Praxis damit umgehen können, indem Sie das Resampling-Schema an die Minoritätsklasse anpassen. Sehr geschätzt.beim trainieren von svm finden sie unterstützungsvektoren, um eine unterscheidungsgrenze zu bilden, und wenn es genug unterstützungsvektoren für alle klassendaten gibt, wäre dies kein problem. Bei der Ergebnisgenauigkeit des Testsets sollten Sie die Datenmenge für alle Klassen in der realen Welt berücksichtigen. Um echte Ergebnisse zu erzielen, sollten Sie die Daten so manipulieren, dass sie ordnungsgemäß in die reale Situation eingehen.
quelle