6

Sono nuovo di SVM e sto cercando di utilizzare l'interfaccia Python su libsvm per classificare un campione contenente una media e uno stddev. Tuttavia, sto ottenendo risultati senza senso.Calcolo della corrispondenza più vicina a media/coppia di stddev con LibSVM

Questa attività è inappropriata per SVM o c'è un errore nel mio utilizzo di libsvm? Di seguito è riportato il semplice script Python che sto utilizzando per testare:

#!/usr/bin/env python 
# Simple classifier test. 
# Adapted from the svm_test.py file included in the standard libsvm distribution. 
from collections import defaultdict 
from svm import * 
# Define our sparse data formatted training and testing sets. 
labels = [1,2,3,4] 
train = [ # key: 0=mean, 1=stddev 
    {0:2.5,1:3.5}, 
    {0:5,1:1.2}, 
    {0:7,1:3.3}, 
    {0:10.3,1:0.3}, 
] 
problem = svm_problem(labels, train) 
test = [ 
    ({0:3, 1:3.11},1), 
    ({0:7.3,1:3.1},3), 
    ({0:7,1:3.3},3), 
    ({0:9.8,1:0.5},4), 
] 

# Test classifiers. 
kernels = [LINEAR, POLY, RBF] 
kname = ['linear','polynomial','rbf'] 
correct = defaultdict(int) 
for kn,kt in zip(kname,kernels): 
    print kt 
    param = svm_parameter(kernel_type = kt, C=10, probability = 1) 
    model = svm_model(problem, param) 
    for test_sample,correct_label in test: 
     pred_label, pred_probability = model.predict_probability(test_sample) 
     correct[kn] += pred_label == correct_label 

# Show results. 
print '-'*80 
print 'Accuracy:' 
for kn,correct_count in correct.iteritems(): 
    print '\t',kn, '%.6f (%i of %i)' % (correct_count/float(len(test)), correct_count, len(test)) 

Il dominio sembra abbastanza semplice. Mi aspetto che se è addestrato a conoscere una media di 2,5 significa etichetta 1, quindi quando vede una media di 2,4, dovrebbe restituire l'etichetta 1 come la classificazione più probabile. Tuttavia, ogni kernel ha una precisione dello 0%. Perchè è questo?

Un paio di note a margine, c'è un modo per nascondere tutto il prolisso output di addestramento scaricato da libsvm nel terminale? Ho cercato i documenti e il codice di libsvm, ma non riesco a trovare alcun modo per disattivarlo.

Inoltre, avrei voluto utilizzare stringhe semplici come chiavi nel mio set di dati sparsi (ad es. {'Mean': 2.5, 'stddev': 3.5}). Sfortunatamente, libsvm supporta solo interi. Ho provato ad usare la rappresentazione intera a lungo della stringa (ad esempio 'mean' == 1109110110971110), ma libsvm sembra troncare questi valori ai normali numeri interi a 32 bit. L'unica soluzione che vedo è mantenere un file "chiave" separato che associa ogni stringa a un intero ('mean' = 0, 'stddev' = 1). Ma ovviamente questo sarà un problema dal momento che dovrò mantenere e mantenere un secondo file insieme al classificatore serializzato. Qualcuno vede un modo più semplice?

+0

Il codice sembra funzionare, se si rimuove la stima di probabilità (ad esempio, eliminare "probabilità = 1", modificare predict_probability per prevedere e eliminare pred_probability). – dmcer

+0

@dmcer, brillante. Viceversa, sembra che possa mantenere le stime di probabilità a condizione che abbia almeno due campioni per ciascuna etichetta. Strano che non avrebbe funzionato per un solo campione per etichetta. Se pubblichi il tuo commento come risposta, la contrassegnerò come risposta accettata. – Cerin

risposta

5

Il problema sembra derivare dalla combinazione della previsione multiclasse con le stime di probabilità.

Se si configura il codice per non effettuare stime di probabilità, in realtà funziona, ad es.:

<snip> 
# Test classifiers. 
kernels = [LINEAR, POLY, RBF] 
kname = ['linear','polynomial','rbf'] 
correct = defaultdict(int) 
for kn,kt in zip(kname,kernels): 
    print kt 
    param = svm_parameter(kernel_type = kt, C=10) # Here -> rm probability = 1 
    model = svm_model(problem, param) 
    for test_sample,correct_label in test: 
     # Here -> change predict_probability to just predict 
     pred_label = model.predict(test_sample) 
     correct[kn] += pred_label == correct_label 
</snip> 

Con questa modifica, ottengo:

-------------------------------------------------------------------------------- 
Accuracy: 
     polynomial 1.000000 (4 of 4) 
     rbf 1.000000 (4 of 4) 
     linear 1.000000 (4 of 4) 

Predizione con stime di probabilità funziona, se si raddoppia il backup dei dati del training set (ad esempio, includono ogni dato punto due volte) . Tuttavia, non sono riuscito a trovare il parametro per parametrizzare il modello in modo che la previsione multicanale con probabilità funzionasse solo con i quattro punti di allenamento originali.

3

Se sei interessato a un modo diverso di farlo, puoi fare quanto segue. In questo modo è teoricamente più valido, ma non così semplice.

Accennando a mean e std, sembra che si faccia riferimento a dati che si presume vengano distribuiti in qualche modo. Ad esempio, i dati che osservate sono distribuiti gaussiani. È quindi possibile utilizzare Symmetrised Kullback-Leibler_divergence come misura di distanza tra tali distribuzioni. È quindi possibile utilizzare qualcosa come k-nearest neighbour per classificare.

Per due densità di probabilità p e q, si ha KL (p, q) = 0 solo se p e q sono uguali. Tuttavia, KL non è simmetrica - così al fine di avere una misura giusta distanza, è possibile utilizzare

distanza (P1, P2) = KL (p1, p2) + KL (P1, P2)

Per gaussiane , KL (p1, p2) = {(μ1 - μ2)^2 + σ1^2 - σ2^2}/(2.σ2^2) + ln (σ2/σ1). (Ho rubato che dal here, dove è possibile trovare anche una deviazione :)

Per farla breve:

Dato un training set D di (media, std, classe) tuple e un nuovo p = (media, std) pair, trova q in D per cui la distanza (d, p) è minima e restituisce quella classe.

Per me è meglio come l'approccio SVM con diversi kernel, poiché il modo di classificare non è così arbitrario.

+0

Grazie. Ho pensato che probabilmente c'era qualcosa di meglio di un SVM per le distribuzioni normali/gaussiane. Tuttavia, intendo anche includere queste caratteristiche guassiane con altre caratteristiche arbitrarie, quindi k-nn utilizzando una misura di distanza specializzata non sarebbe appropriato. – Cerin

+0

Esistono effettivamente modi per apprendere tali misure di distanza dalle etichette delle classi. Forse vuoi fare il checkout del lavoro di Sam Roweis su Neighborhood Component Analysis. – bayer