2013-08-06 8 views
7

Ich versuche, meinen SVM-Algorithmus mit Daten von Klicks und Conversion von Leuten, die die Banner sehen, zu unterrichten. Das Hauptproblem ist, dass die Klicks etwa 0,2% aller Daten ausmachen, also ist es ein großes Missverhältnis. Wenn ich einfache SVM in der Testphase benutze, wird immer nur die Klasse "view" vorhergesagt und niemals "click" oder "conversion". Im Durchschnitt gibt es 99,8% richtige Antworten (wegen Unverhältnismäßigkeit), aber es gibt 0% richtige Vorhersage, wenn Sie "Klick" oder "Umwandlung" überprüfen. Wie können Sie den SVM-Algorithmus abstimmen (oder einen anderen auswählen), um das Missverhältnis zu berücksichtigen?Wie soll ich den maschinellen Lernalgorithmus unter Verwendung von Daten mit großen Unverhältnismäßigkeiten von Klassen unterrichten? (SVM)

+0

Ist Upsampling der Minderheit Klasse eine Option? –

+0

Können Sie mehr darüber erfahren, was Sie mit Up-Sampling meinen? – rvnikita

+0

mögliches Duplikat von [sklearn logistische Regression mit unausgeglichenen Klassen] (http://stackoverflow.com/questions/14863125/sklearn-logistic-regression-with-unbalanced-classes) –

Antwort

24

Der einfachste Ansatz ist hier so verwenden „Klasse Gewichtungsschema“ genannt - in der klassischen Formulierung SVM ein C Parameter verwendet, um die missclassification Zahl zu steuern. Es kann in C1 und C2 Parameter für Klasse 1 und 2 jeweils geändert werden. Die häufigste Wahl von C1 und C2 für ein gegebenes C ist

C1 = C/n1 
C2 = C/n2 

zu setzen, wo n1 und n2 Größen von Klasse 1 bzw. 2. Sie "bestrafen" SVM für das Fehlklassifizieren der weniger häufigen Klasse viel schwieriger als für die Fehlklassifikation am häufigsten.

Viele vorhandene Bibliotheken (wie libSVM) unterstützen diesen Mechanismus mit Parametern class_weight.

Beispiel Python und sklearn mit

print __doc__ 

import numpy as np 
import pylab as pl 
from sklearn import svm 

# we create 40 separable points 
rng = np.random.RandomState(0) 
n_samples_1 = 1000 
n_samples_2 = 100 
X = np.r_[1.5 * rng.randn(n_samples_1, 2), 
      0.5 * rng.randn(n_samples_2, 2) + [2, 2]] 
y = [0] * (n_samples_1) + [1] * (n_samples_2) 

# fit the model and get the separating hyperplane 
clf = svm.SVC(kernel='linear', C=1.0) 
clf.fit(X, y) 

w = clf.coef_[0] 
a = -w[0]/w[1] 
xx = np.linspace(-5, 5) 
yy = a * xx - clf.intercept_[0]/w[1] 


# get the separating hyperplane using weighted classes 
wclf = svm.SVC(kernel='linear', class_weight={1: 10}) 
wclf.fit(X, y) 

ww = wclf.coef_[0] 
wa = -ww[0]/ww[1] 
wyy = wa * xx - wclf.intercept_[0]/ww[1] 

# plot separating hyperplanes and samples 
h0 = pl.plot(xx, yy, 'k-', label='no weights') 
h1 = pl.plot(xx, wyy, 'k--', label='with weights') 
pl.scatter(X[:, 0], X[:, 1], c=y, cmap=pl.cm.Paired) 
pl.legend() 

pl.axis('tight') 
pl.show() 

Insbesondere in sklearn Sie können einfach auf die automatische Gewichtung drehen durch class_weight='auto' Einstellung.

Visualization of above code from sklearn documentation

+0

Vielen Dank, es ist, was ich suche. Ich wünschte, ich hätte 15 Punkte für diese Antwort :) – rvnikita

+0

Ich bin mir ziemlich sicher, dass Sie immer noch die Option "Antwort annehmen" aktivieren können. – lejlot

1

Dieses Papier beschreibt eine Vielzahl von Techniken. Eine einfache (aber sehr schlechte Methode für SVM) repliziert nur die Minderheit der Klasse (n), bis ein Gleichgewicht haben:

http://www.ele.uri.edu/faculty/he/PDFfiles/ImbalancedLearning.pdf

+0

Nur der Vollständigkeit halber - replizierende Minderheitsklasse sollte ** niemals ** in SVM verwendet werden. Es ist äquivalent zur Verwendung von Klassengewichten, während es gleichzeitig hinsichtlich der Trainings- (und Test-) Zeiten völlig ineffizient ist. – lejlot

+0

Ich habe meine ursprüngliche Antwort bearbeitet, um den Kommentar von lejlot zu reflektieren. – denson