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?
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
@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