6

Soy nuevo en SVMs, y estoy tratando de usar la interfaz de Python a libsvm para clasificar una muestra que contiene una media y stddev. Sin embargo, estoy obteniendo resultados sin sentido.Calculando la coincidencia más cercana a Mean/Stddev Pair con LibSVM

¿Es esta tarea inapropiada para SVM o hay un error en mi uso de libsvm? Debajo está el script simple de Python que estoy usando para probar:

#!/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)) 

El dominio parece bastante simple. Supongo que si está capacitado para saber que una media de 2.5 significa etiqueta 1, cuando vea una media de 2.4, debería devolver la etiqueta 1 como la clasificación más probable. Sin embargo, cada kernel tiene una precisión del 0%. ¿Por qué es esto?

Un par de notas al margen, ¿hay alguna manera de ocultar toda la salida de entrenamiento detallado que arroja libsvm en el terminal? He buscado los documentos y el código de libsvm, pero no encuentro ninguna forma de desactivarlo.

Además, quería utilizar cadenas simples como las claves en mi conjunto de datos dispersos (por ejemplo, {'mean': 2.5, 'stddev': 3.5}). Desafortunadamente, libsvm solo admite enteros. Intenté usar la representación entera larga de la cadena (por ejemplo, 'mean' == 1109110110971110), pero libsvm parece truncar estos a enteros normales de 32 bits. La única solución que veo es mantener un archivo de "clave" separado que asigne cada cadena a un entero ('mean' = 0, 'stddev' = 1). Pero obviamente eso será un problema, ya que tendré que mantener y mantener un segundo archivo junto con el clasificador serializado. ¿Alguien ve una manera más fácil?

+0

Parece que su código funciona, si elimina la estimación de probabilidad (es decir, elimina "probabilidad = 1", cambie predic_probability para predecir y elimine pred_probability). – dmcer

+0

@dmcer, Brilliant. Por el contrario, parece que puedo mantener las estimaciones de probabilidad siempre que tenga al menos dos muestras para cada etiqueta. Extraño, no funcionaría para una sola muestra por etiqueta. Si publica su comentario como respuesta, lo marcaré como la respuesta aceptada. – Cerin

Respuesta

5

El problema parece provenir de la combinación de la predicción multiclase con las estimaciones de probabilidad.

Si configura su código para no hacer estimaciones de probabilidad, realmente funciona, p.:

<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 este cambio, me sale:

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

Predicción con las estimaciones de probabilidad funciona, si se duplica los datos en el conjunto de entrenamiento (es decir, incluyen cada punto de datos dos veces) . Sin embargo, no pude encontrar de todos modos para parametrizar el modelo para que la predicción multiclase con probabilidades funcione solo con los cuatro puntos de entrenamiento originales.

3

Si le interesa una forma diferente de hacerlo, puede hacer lo siguiente. De esta manera, teóricamente es más sólida, aunque no tan directa.

Al mencionar mean y std, parece como si se refiriera a datos que supone que se distribuirán de alguna manera. Por ejemplo, los datos que usted observa son distribuidos por Gauss. Luego puede usar el Symmetrised Kullback-Leibler_divergence como una medida de distancia entre esas distribuciones. A continuación, puede usar algo como k-nearest neighbour para clasificar.

Para dos densidades de probabilidad p y q, tiene KL (p, q) = 0 solo si p y q son iguales. Sin embargo, KL no es simétrico - por lo que con el fin de tener una medida de la distancia adecuada, puede utilizar

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

Para gaussianas , KL (p1, p2) = {(μ1 - μ2)^2 + σ1^2 - σ2^2}/(2.σ2^2) + ln (σ2/σ1). (Robé que desde here, donde también se puede encontrar una desviación :)

Larga historia corta:

Dado un conjunto de entrenamiento D de la media, std, clase) tuplas (y un nuevo p = (media, std) pair, encuentra que q en D para el cual la distancia (d, p) es mínima y devuelve esa clase.

Para mí, eso se siente mejor como el enfoque SVM con varios núcleos, ya que la forma de clasificar no es tan arbitraria.

+0

Gracias. Pensé que probablemente había algo mejor que un SVM para distribuciones normales/gaussianas. Sin embargo, también tengo la intención de incluir estas características de guassian con otras características arbitrarias, por lo que k-nn utilizando una medida de distancia especializada no sería apropiado. – Cerin

+0

En realidad, hay maneras de aprender tales medidas de distancia de las etiquetas de clase. Tal vez quieras ver el trabajo de Sam Roweis en el Análisis de componentes del vecindario. – bayer

Cuestiones relacionadas