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