2010-03-19 19 views
7

He estado buscando en la red durante ~ 3 horas pero no he podido encontrar una solución todavía. Quiero dar un núcleo precomputed a libSVM y clasificar un conjunto de datos, pero:Kernels precalculados con LibSVM en Python

  • ¿Cómo puedo generar un kernel precomputed? (Por ejemplo, ¿cuál es el núcleo básico para precomputed Iris data?)

  • En la documentación libsvm, se afirma que:

    Para los núcleos de cálculo previo, el primer elemento de cada instancia debe ser el ID. Por ejemplo,

     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) 
    

¿Qué es un ID? No hay más detalles sobre eso. ¿Puedo asignar identificaciones secuencialmente?

Cualquier ayuda de libsvm y un ejemplo de núcleos precalculados realmente apreciados.

Respuesta

14

En primer lugar, algunos antecedentes de los granos y las MSV ...

Si desea pre-calcular un núcleo para n vectores (de cualquier dimensión), lo que hay que hacer es calcular la función del núcleo entre cada par de ejemplos. La función kernel toma dos vectores y da un escalar, por lo que puede pensar en un kernel precalculado como una matriz de escalares nxn. Por lo general, se lo denomina matriz del kernel o, a veces, matriz de Gram.

Hay muchos núcleos diferentes, el más simple es el núcleo lineal (también conocido como el producto escalar):

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

En segundo lugar, tratando de responder a su problema ...

La documentación sobre núcleos precalculados en libsvm es bastante buena ...

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 

Cada vector aquí en el segundo ejemplo es una fila en la matriz del kernel. El valor en el índice cero es el valor de ID y simplemente parece ser un conteo secuencial. El valor en el índice 1 del primer vector es el valor de la función kernel del primer vector del primer ejemplo consigo mismo (es decir, (1x1)+(1x1)+(1x1)+(1x1) = 4), el segundo es el valor de la función kernel del primer vector con el segundo (es decir, (1x3)+(1x3)=6) Sigue así por el resto del ejemplo. Puede ver que la matriz del kernel es simétrica, como debería ser, porque K (x, y) = K (y, x).

Vale la pena señalar que el primer conjunto de vectores se representa en un formato disperso (es decir, los valores faltantes son cero), pero la matriz del kernel no es ni debe ser escasa. No sé por qué es así, parece ser una cosa de libsvm.

+0

¡La respuesta más útil! – JXITC

2

Aquí hay un archivo de entrada de kernel personalizado de dos categorías 3 que funciona correctamente.Voy a explicar las partes (aunque también se debe ver la respuesta de StompChicken):

1 0:1 1:10 2:12 3:21
2 0:2 1:12 2:19 3:30
1 0:3 1:21 2:30 3:130

El primer número en cada línea es qué categoría pertenece. la siguiente entrada en cada línea es de la forma 0: n y debe ser secuencial, es decir,
0: 1 en la primera entrada
0: 2 en segunda entrada
0: 3 en la entrada thrid

Una posible razón para esto es que libsvm devuelve los valores alpha_i que acompañan a tus vectores en el archivo de salida, pero para los núcleos precalculados no se muestran los vectores (lo que podría ser realmente grande) en vez del índice 0: n que iba con ese vector. para hacer que su salida sea más fácil de hacer coincidir con su entrada. Especialmente dado que la salida es , no en el mismo orden en que los coloca, se agrupa por categoría. Por lo tanto, es muy útil para ti leer el archivo de entrada para poder hacer coincidir las salidas de libsvm con tus propias entradas para tener esos valores 0: n. Aquí se puede ver la salida

svm_type c_svc
kernel_type precalculadas
nr_class 2
total_sv 3
rho -1,53951
etiqueta 1 2
nr_sv 2 1
SV
,4126650675419768 0: 1
0.03174528241667363 0: 3
-0.4444103499586504 0: 2

Es importante para tener en cuenta que con los núcleos precalculados no se puede omitir las entradas cero como se puede con todos los demás núcleos. Deben ser incluidos explícitamente.

5

scikit-learn oculta la mayoría de los detalles de libsvm cuando se manejan kernels personalizados. Puedes simplemente pasar una función arbitraria como tu kernel y calculará la matriz de gram para ti o pasará la matriz de Gram precalculada del kernel.

Para el primero, la sintaxis es:

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

donde my_kernel es su función de núcleo, y luego se puede llamar clf.fit (x, y) y se calculará la matriz kernel. En el segundo caso, la sintaxis es:

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

Y cuando se llama clf.fit (x, y), X debe ser la matriz K (X, X), donde k es el núcleo. Vea también este ejemplo para más detalles:

http://scikit-learn.org/stable/auto_examples/svm/plot_custom_kernel.html

Cuestiones relacionadas