2015-02-13 3 views
3

Я пытаюсь вычислить функцию принятия решения SVC-классификатора MANUALLY (в отличие от использования встроенного метода) с использованием библиотеки python SKLearn.Вычисление функции решения SVM вручную

Я пробовал несколько методов, однако, я могу только когда-либо получить ручной расчет, чтобы соответствовать, когда я не масштаб мои данные.

z - это тестовая данность (она была масштабирована), и я думаю, что другие переменные говорят сами за себя (также я использую ядро ​​rbf, если это не очевидно из кода).

Вот методы, которые я пробовал: метод

1 Цикличность:

dec_func = 0 
for j in range(np.shape(sup_vecs)[0]): 

    norm2 = np.linalg.norm(sup_vecs[j, :] - z)**2 
    dec_func = dec_func + dual_coefs[0, j] * np.exp(-gamma*norm2) 

dec_func += intercept 

2 Векторизованного Метод

diff = sup_vecs - z 
norm2 = np.sum(np.sqrt(diff*diff), 1)**2 
dec_func = dual_coefs.dot(np.exp(-gamma_params*norm2)) + intercept 

Однако, ни один из них никогда не возвращает то же значение, decision_function. Я думаю, что это может быть связано с изменением моих ценностей или, скорее, с чем-то глупым, что я уже смотрел!

Любая помощь будет оценена по достоинству.

+0

Вы пробовали с '' kernel = precomputed'' и передавали в ядре, которое вы сами вычислили? –

+0

@AndreasMueller, я использовал ядро ​​rbf «с полки», содержащееся в классе SVC, с C = 1000 и гамма = 0,01. После обучения я вызываю 'clf.decision_function (z)' и получаю значение, однако это значение никогда не совпадает с значением, которое я создаю, когда я выполняю вычисление вручную, как показано выше ... Мне интересно, если что-то не так с моя математика или есть ошибка в libsvm? – user1182556

+0

Да, мне тоже интересно, и я хотел бы получить подтверждение об этом. Я предлагал использовать предварительно вычислимое ядро, так как это обеспечило бы то, что вычисление ядра внутри libsvm будет таким же, как и то, которое вы делаете. Кто-то сообщал о подобной проблеме ранее, и я боюсь, что где-то там был введен знак. –

ответ

1

Так что после немного большего количества копания и царапин на голове, я понял это.

Как я уже упоминал выше, z - это тестовая данность, которая была масштабирована. Для масштабирования мне пришлось извлечь .mean_ и .std_ атрибуты из объекта preprocessing.StandardScaler() (после вызова .fit() на мои данные обучения, конечно).

Я использовал этот масштаб z в качестве ввода как для моих ручных вычислений, так и для встроенной функции. Однако встроенная функция была частью конвейера, который уже имел StandardScaler в качестве своего первого «трубопровода» в конвейере, и в результате z получал масштабирование дважды! Следовательно, когда я удалил масштабирование из моего конвейера, руководство ответит «согласовано» на ответ встроенной функции.

Я говорю «сопоставлен» в кавычках, так как я нашел, что мне всегда приходилось переворачивать знак моих ручных вычислений в соответствии со встроенной версией. В настоящее время я понятия не имею, почему это так.

В заключение я не понял, как работают трубопроводы.

Для тех, кто заинтересован, вот финальные версии моих ручных методов:

diff = sup_vecs - z_scaled 
# Looping Method 
dec_func_loop = 0 
for j in range(np.shape(sup_vecs)[0]): 
    norm2 = np.linalg.norm(diff[j,:]) 
    dec_func_loop = dec_func_loop + dual_coefs[j] * np.exp(-gamma*(norm2**2)) 

dec_func_loop = -1 * (dec_func_loop - intercept) 

# Vectorized method 
norm2 = np.array([np.linalg.norm(diff[n, :]) for n in range(np.shape(sup_vecs)[0])]) 
dec_func_vec = -1 * (dual_coefs.dot(np.exp(-gamma*(norm2**2))) - intercept) 

Добавление

Для тех, кто заинтересован в реализации ручного метода для мультиклассируют SVC, следующая ссылка help: https://stackoverflow.com/a/27752709/1182556

+1

Знак перевернут, потому что 'sklearn' поддерживает все типы целей (например, строки) и внутренне отображает их в порядке возрастания. Это означает, что меньшее значение (в случае двоичной классификации), например 'y = 0' или' y = -1', будет сопоставлено с классом '+ 1', а большее, например' y = 1', - ' Класс. Это, по существу, переворачивает знак двойственных коэффициентов. Это также является причиной того, что перехват имеет недостаток в документации. –

+1

Обратите внимание, что это считалось [ошибкой] (https://github.com/scikit-learn/scikit-learn/pull/4326), поэтому ваш код будет разбит на sklearn 0.16+. Исправление ввело тест проверки работоспособности, поэтому вы можете найти код для воспроизведения 'decision_function'. В принципе, знаки 'dual_coef_' и' intercept_' были инвертированы. –