Je suis nouveau dans les SVM et j'essaie d'utiliser l'interface Python pour libsvm pour classer un échantillon contenant une moyenne et stddev. Cependant, je reçois des résultats absurdes.Calcul de la correspondance la plus proche à la paire moyenne/Stddev avec LibSVM
Cette tâche est-elle inappropriée pour les SVM ou y a-t-il une erreur dans mon utilisation de libsvm? Voici le script Python simple que j'utilise pour tester:
#!/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))
Le domaine semble assez simple. Je m'attendais à ce que, s'il est entraîné à connaître une moyenne de 2,5 signifie label 1, alors quand il voit une moyenne de 2.4, il devrait retourner l'étiquette 1 comme classification la plus probable. Cependant, chaque noyau a une précision de 0%. Pourquoi est-ce? Un couple de notes secondaires, est-il un moyen de cacher toutes les sorties de formation verbeux déversés par libsvm dans le terminal? J'ai recherché les docs et le code de libsvm, mais je ne trouve aucun moyen de désactiver cela.
En outre, j'avais voulu utiliser des chaînes simples comme clés dans mon jeu de données épars (par exemple {'mean': 2.5, 'stddev': 3.5}). Malheureusement, libsvm ne supporte que les entiers. J'ai essayé d'utiliser la représentation en entier long de la chaîne (par exemple 'mean' == 1109110110971110), mais libsvm semble les tronquer en entiers normaux de 32 bits. La seule solution de contournement que je vois est de conserver un fichier "clé" distinct qui mappe chaque chaîne à un entier ("mean" = 0, "stddev" = 1). Mais évidemment, ça va être pénible car je vais devoir maintenir et maintenir un second fichier avec le classificateur sérialisé. Est-ce que quelqu'un voit un moyen plus facile?
Votre code semble fonctionner, si vous supprimez l'estimation de probabilité (c'est-à-dire, supprimez "probabilité = 1", changez la valeur de predict_probability pour la prédire, et supprimez pred_probability). – dmcer
@dmcer, brillant. Inversement, il semble que je puisse conserver les estimations de probabilité tant que j'ai au moins deux échantillons pour chaque étiquette. Étrange, cela ne fonctionnerait pas pour un seul échantillon par étiquette. Si vous postez votre commentaire comme réponse, je le marquerai comme la réponse acceptée. – Cerin