Предварительно вычисленные ядра с LibSVM в Python - PullRequest
9 голосов
/ 19 марта 2010

Я искал в сети ~ 3 часа, но пока не нашел решения. Я хочу дать предварительно вычисленное ядро ​​libsvm и классифицировать набор данных, но:

  • Как мне сгенерировать предварительно вычисленное ядро? (например, какое базовое предварительно вычисленное ядро ​​для данных радужной оболочки ?)

  • В документации libsvm указано, что:

    Для предварительно вычисленных ядер первый элемент каждого экземпляра должен быть ID. Например,

            samples = [[1, 0, 0, 0, 0], [2, 0, 1, 0, 1], [3, 0, 0, 1, 1], [4, 0, 1, 1, 2]]
            problem = svm_problem(labels, samples)
            param = svm_parameter(kernel_type=PRECOMPUTED)
    

Что такое идентификатор? Там нет никаких подробностей об этом. Могу ли я назначить идентификаторы последовательно?

Любая помощь libsvm и пример предварительно вычисленных ядер действительно приветствуются.

Ответы [ 4 ]

16 голосов
/ 19 марта 2010

Прежде всего , немного информации о ядрах и SVM ...

Если вы хотите предварительно вычислить ядро ​​для n векторов (любого измерения), вам нужно вычислить функцию ядра между каждой парой примеров. Функция ядра берет два вектора и дает скаляр, поэтому вы можете думать о предварительно вычисленном ядре как о nxn матрице скаляров. Обычно ее называют матрицей ядра или иногда матрицей Грама.

Существует много разных ядер, самое простое - линейное ядро ​​(также известное как скалярное произведение):

sum(x_i * y_i) for i in [1..N] where (x_1,...,x_N) (y_1,..,y_N) are vectors

Во-вторых , пытаясь ответить на вашу проблему ...

Документация по предварительно вычисленным ядрам в libsvm на самом деле довольно хорошая ...

Assume the original training data has three four-feature instances 
and testing data has one instance:

15  1:1 2:1 3:1 4:1
45      2:3     4:3
25          3:1
15  1:1     3:1

If the linear kernel is used, we have the following 
new training/testing sets:

15  0:1 1:4 2:6  3:1
45  0:2 1:6 2:18 3:0 
25  0:3 1:1 2:0  3:1

15  0:? 1:2 2:0  3:1

Каждый вектор во втором примере - это строка в матрице ядра. Значение в индексе ноль является значением идентификатора, и это, кажется, просто последовательный счет. Значение по индексу 1 первого вектора является значением функции ядра первого вектора из первого примера с самим собой (т. Е. (1x1)+(1x1)+(1x1)+(1x1) = 4), второе - значением функции ядра первого вектора со вторым ( т.е. (1x3)+(1x3)=6). Это следует так же для остальной части примера. Вы можете видеть, что матрица ядра является симметричной, как и должно быть, потому что K (x, y) = K (y, x).

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

6 голосов
/ 16 декабря 2010

scikit-learn скрывает большинство деталей libsvm при работе с собственными ядрами. Вы можете либо просто передать произвольную функцию в качестве вашего ядра, и она вычислит матрицу грамм для вас, либо передать предварительно вычисленную матрицу Грама ядра.

Для первого синтаксис:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel=my_kernel)

где my_kernel - ваша функция ядра, а затем вы можете вызвать clf.fit (X, y), и она вычислит матрицу ядра для вас. Во втором случае синтаксис:

   >>> from scikits.learn import svm
   >>> clf = svm.SVC(kernel="precomputed")

И когда вы вызываете clf.fit (X, y), X должен быть матрицей k (X, X), где k - ваше ядро. Смотрите также этот пример для более подробной информации:

http://scikit -learn.org / стабильный / auto_examples / SVM / plot_custom_kernel.html

4 голосов
/ 14 сентября 2010

Вот простой векторный входной файл ядра с двумя категориями 3, который работает правильно. Я объясню части (хотя вы также должны увидеть ответ StompChicken):

1 0:1 1:10 2:12 3:21<br> 2 0:2 1:12 2:19 3:30<br> 1 0:3 1:21 2:30 3:130<br>

Первое число в каждой строке соответствует категории, к которой оно относится. Следующая запись в каждой строке имеет вид 0: n и должна быть последовательной, то есть
0: 1 при первой записи
0: 2 при второй записи
0: 3 при третьем входе

Возможная причина этого заключается в том, что libsvm возвращает значения alpha_i, которые идут с вашими векторами в выходном файле, но для предварительно вычисленных ядер векторы не отображаются (что может быть действительно огромным), а индекс 0: n, который идет с этим вектор показан, чтобы сделать ваш вывод легче сопоставить с вашим вводом. Тем более что выходные данные не в том порядке, в котором вы их поместили, они сгруппированы по категории . Таким образом, при чтении входного файла очень полезно иметь возможность сопоставлять выходные данные libsvm с вашими собственными входными данными, чтобы иметь эти значения 0: n. Здесь вы можете увидеть вывод

svm_type c_svc
предварительно вычисленный тип ядра
nr_class 2
всего_св 3
ро -1,53951
этикетка 1 2
nr_sv 2 1
SV
0,4126650675419768 0: 1
0.03174528241667363 0: 3
-0,4444103499586504 0: 2

важно отметить, что с предварительно вычисленными ядрами вы не можете опускать нулевые записи, как вы можете со всеми другими ядрами. Они должны быть явно включены.

3 голосов
/ 11 сентября 2010

Я полагаю, что связывание libSVM с помощью scikit-learn на python должно решить эту проблему.

Дополнительную информацию смотрите в документации по http://scikit -learn.sourceforge.net / modules / svm.html # kernel-functions .

...