Вычисление ближайшего совпадения с парой среднее/стандартное отклонение с помощью LibSVM

Я новичок в SVM и пытаюсь использовать интерфейс Python для libsvm для классификации выборки, содержащей среднее значение и стандартное отклонение. Однако я получаю бессмысленные результаты.

Эта задача не подходит для SVM или я использую libsvm по ошибке? Ниже приведен простой скрипт Python, который я использую для тестирования:

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

Домен кажется довольно простым. Я ожидаю, что если он обучен знать, что среднее значение 2,5 означает метку 1, то, когда он увидит среднее значение 2,4, он должен вернуть метку 1 как наиболее вероятную классификацию. Однако каждое ядро ​​имеет точность 0%. Почему это?

Пара замечаний: есть ли способ скрыть все подробные выходные данные обучения, выдаваемые libsvm, в терминале? Я искал документы и код libsvm, но не могу найти способ отключить это.

Кроме того, я хотел использовать простые строки в качестве ключей в моем разреженном наборе данных (например, {'mean': 2.5, 'stddev': 3.5}). К сожалению, libsvm поддерживает только целые числа. Я попытался использовать длинное целочисленное представление строки (например, 'mean' == 1109110110971110), но libsvm, кажется, обрезает их до обычных 32-битных целых чисел. Единственный обходной путь, который я вижу, - это поддерживать отдельный файл «ключа», который сопоставляет каждую строку с целым числом («среднее» = 0, «stddev» = 1). Но очевидно, что это будет больно, так как мне придется поддерживать и сохранять второй файл вместе с сериализованным классификатором. Кто-нибудь видит более простой способ?


person Cerin    schedule 02.04.2010    source источник
comment
Кажется, ваш код работает, если вы удалите оценку вероятности (т. е. удалите вероятность = 1, измените pred_probability на просто прогнозирование и удалите pred_probability).   -  person dmcer    schedule 02.04.2010
comment
@dmcer, гениально. И наоборот, кажется, что я могу сохранить оценки вероятности, пока у меня есть по крайней мере две выборки для каждой метки. Странно, что это не сработает только для одного образца на этикетку. Если вы опубликуете свой комментарий как ответ, я отмечу его как принятый ответ.   -  person Cerin    schedule 03.04.2010


Ответы (2)


Проблема, по-видимому, возникает из-за объединения многоклассового прогноза с оценками вероятности.

Если вы настроите свой код так, чтобы он не оценивал вероятность, он действительно работает, например:

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

С этим изменением я получаю:

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

Прогнозирование с оценками вероятности работает, если вы удваиваете данные в обучающем наборе (т. е. дважды включаете каждую точку данных). Однако я так и не смог найти способ параметризации модели, чтобы многоклассовое предсказание с вероятностями работало только с исходными четырьмя тренировочными точками.

person dmcer    schedule 03.04.2010

Если вас интересует другой способ сделать это, вы можете сделать следующее. Этот способ теоретически более разумен, но не так прост.

Упоминая среднее и стандартное, создается впечатление, что вы ссылаетесь на данные, которые, как вы предполагаете, каким-то образом распределяются. Например, данные, которые вы наблюдаете, распределены по Гауссу. Затем вы можете использовать Symmetrised Kullback-Leibler_divergence в качестве меры расстояния между этими распределениями. . Затем вы можете использовать что-то вроде k-ближайшего соседа для классификации.

Для двух плотностей вероятности p и q у вас есть KL (p, q) = 0, только если p и q одинаковы. Однако KL не симметричен, поэтому для правильной меры расстояния вы можете использовать

расстояние(p1, p2) = KL(p1, p2) + KL(p1, p2)

Для гауссов KL(p1, p2) = {(µ1 - µ2)^2 + σ1^2 - σ2^2} / (2.σ2^2) + ln(σ2/σ1). (Я украл это из здесь, где вы также можете найти отклонение: )

Короче говоря:

Учитывая обучающий набор D кортежей (среднее, стандартное, класс) и новую пару p = (среднее, стандартное), найдите такое q в D, для которого расстояние (d, p) минимально, и верните этот класс.

Мне кажется, что подход SVM с несколькими ядрами лучше, поскольку способ классификации не так уж произволен.

person bayer    schedule 02.04.2010
comment
Спасибо. Я подумал, что, вероятно, есть что-то лучше, чем SVM для нормального/гауссовского распределения. Однако я также намереваюсь включить эти гауссовые функции в другие произвольные функции, поэтому использование k-nn с использованием специальной меры расстояния было бы неуместным. - person Cerin; 03.04.2010
comment
На самом деле есть способы узнать такие меры расстояния из меток классов. Может быть, вы хотите ознакомиться с работой Сэма Ровейса по анализу компонентов окружения. - person bayer; 06.04.2010