2013-08-06 12 views
7

Sto cercando di insegnare il mio algoritmo SVM utilizzando i dati dei clic e la conversione da parte di persone che vedono i banner. Il problema principale è che i clic sono circa lo 0,2% di tutti i dati, quindi c'è una grande sproporzione al suo interno. Quando utilizzo SVM semplice in fase di test, prevedo sempre solo la classe "view" e mai "click" o "conversion". In media dà il 99,8% di risposte giuste (a causa della sproporzione), ma dà una previsione giusta dello 0% se si controllano quelle "clic" o "conversione". Come si può regolare l'algoritmo SVM (o selezionarne un altro) per tenere conto della sproporzione?Come dovrei insegnare l'algoritmo di apprendimento automatico usando i dati con grande sproporzione di classi? (SVM)

+0

è up-campionamento della classe di minoranza un'opzione? –

+0

Puoi dire di più su cosa intendi con up-sampling? – rvnikita

+0

possibile duplicato di [regressione logistica sklearn con classi sbilanciate] (http://stackoverflow.com/questions/14863125/sklearn-logistic-regression-with-unbalanced-classes) –

risposta

24

L'approccio più semplice qui è quello di utilizzare il cosiddetto "schema di ponderazione della classe": nella classica formulazione SVM esiste un parametro C utilizzato per controllare il conteggio delle miss classificazioni. Può essere modificato nei parametri C1 e C2 utilizzati rispettivamente per le classi 1 e 2. La scelta più comune di C1 e C2 per un dato C è di mettere

C1 = C/n1 
C2 = C/n2 

dove n1 e n2 sono rispettivamente formati di classe 1 e 2. Quindi "punisci" l'SVM per classificare la classe meno frequente molto più difficile di quella missclassification più comune.

Molte librerie esistenti (come libSVM) supportano questo meccanismo con i parametri di classe_weight.

Esempio utilizzando pitone e sklearn

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() 

In particolare, in sklearn si può semplicemente attivare il coefficiente automatico impostando class_weight='auto'.

Visualization of above code from sklearn documentation

+0

Grazie mille, è quello che sto cercando. Vorrei avere 15 punti per votare questa risposta :) – rvnikita

+0

Sono abbastanza sicuro che tu possa ancora controllare l'opzione "accetta risposta" :) – lejlot

1

Questo documento descrive una varietà di tecniche. Un semplice (ma molto male metodo per SVM) è solo replicando la classe di minoranza (s) fino ad avere un equilibrio:

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

+0

Solo per completezza - la replica della classe di minoranza dovrebbe ** mai ** essere usata in SVM. È equivalente all'utilizzo di pesi di classe, mentre nello stesso tempo è completamente inefficiente in termini di tempi di addestramento (e di test). – lejlot

+0

Ho modificato la mia risposta originale per riflettere il commento di lejlot. – denson