Ayudar a predecir usando () para SVM de kernlab en R?
Pregunta
Estoy tratando de utilizar el paquete R kernlab
hacer máquinas de vectores soporte (SVM). Para mi ejemplo muy sencillo, tengo dos piezas de datos de entrenamiento. A y B.
(A y B son de tipo matrix
-. Que son matrices de adyacencia para gráficos)
Así que escribí una función que toma A + B y genera una matriz kernel.
> km
[,1] [,2]
[1,] 14.33333 18.47368
[2,] 18.47368 38.96053
Ahora uso la función de kernlab
ksvm
para generar mi modelo predictivo. En este momento, sólo estoy tratando de conseguir la maldita cosa a trabajar -. No estoy preocupado por error de entrenamiento, etc.
Por lo tanto, Pregunta 1 : ¿Estoy generando mi modelo correctamente? Razonablemente?
# y are my classes. In this case, A is in class "1" and B is in class "-1"
> y
[1] 1 -1
> model2 = ksvm(km, y, type="C-svc", kernel = "matrix");
> model2
Support Vector Machine object of class "ksvm"
SV type: C-svc (classification)
parameter : cost C = 1
[1] " Kernel matrix used as input."
Number of Support Vectors : 2
Objective Function Value : -0.1224
Training error : 0
Hasta aquí todo bien. Hemos creado nuestra matriz de núcleo a medida, y luego creamos un modelo ksvm usando esa matriz. Hemos llamado a nuestros datos de entrenamiento como "1" y "-1".
Ahora predecir:
> A
[,1] [,2] [,3]
[1,] 0 1 1
[2,] 1 0 1
[3,] 0 0 0
> predict(model2, A)
Error in as.matrix(Z) : object 'Z' not found
Uh-oh. Esto está bien. Tipo de espera, de verdad. "Predecir" quiere algún tipo de vector, no una matriz.
Así que vamos a probar algunas cosas:
> predict(model2, c(1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, km)
Error in as.matrix(Z) : object 'Z' not found
Algunas de las pruebas anteriores son sin sentido, pero eso es mi punto: no importa lo que hago, simplemente no puedo conseguir predecir () para mirar mis datos y hacer una predicción. Escalares no funcionan, los vectores no funcionan. Una matriz de 2x2 no funciona, ni una matriz de 3x3.
¿Qué estoy haciendo mal aquí?
(Una vez que descubra lo ksvm quiere , entonces yo puedo asegurar que mis datos de prueba pueden ajustarse a ese formato de una manera sana / razonable / matemáticamente sonido.)
Solución
Si se piensa en cómo la máquina de vectores de soporte puede "utilizar" la matriz del núcleo, verá que realmente no se puede hacer esto en la forma en que estamos tratando (como se ha visto: -)
De hecho, me ha costado un poco con esta la primera vez que estaba usando una matriz kernlab + kernel ... casualmente, también era para los núcleos de gráficos!
De todos modos, vamos a primero se dan cuenta de que, dado que la SVM no sabe cómo calcular su función de núcleo, que tiene que tener estos valores ya calculados entre sus nuevos ejemplos (de prueba), y los ejemplos se escoge como los vectores de soporte durante la etapa de formación.
Por lo tanto, tendrá que calcular la matriz de núcleo para todos de sus ejemplos juntos. Vas a entrenar después de unos y de prueba en los demás mediante la eliminación de filas + columnas de la matriz del núcleo cuando sea apropiado. Te voy a enseñar con el código.
Podemos utilizar el código de ejemplo en la documentación ksvm
para cargar nuestro espacio de trabajo con algunos datos:
library(kernlab)
example(ksvm)
Tendrá que pulsar Intro unos pocos (2) veces con el fin de permitir que las parcelas dibujar, y dejar que el acabado ejemplo, pero ahora debería tener una matriz de núcleo en su espacio de trabajo denominado K
. Vamos a tener que recuperar el vector y
que debería utilizar para sus etiquetas (como lo ha sido pisoteado por otro código en el ejemplo):
y <- matrix(c(rep(1,60),rep(-1,60)))
Ahora, escoger un subconjunto de ejemplos a utilizar para probar
holdout <- sample(1:ncol(K), 10)
A partir de ahora, voy a:
- Crear una matriz de formación de núcleo denominado
trainK
de la matriz del núcleo original deK
. - Crear un modelo SVM de mi conjunto de entrenamiento
trainK
- Utilice los vectores de soporte se encuentran en el modelo para crear una matriz
testK
pruebas del núcleo ... esta es la parte extraña. Si nos fijamos en el código enkernlab
para ver cómo se utiliza los índices de vectores de soporte, verá por qué se está haciendo de esta manera. Podría ser posible hacer esto de otra manera, pero yo no vi ninguna documentación / ejemplos de predecir con una matriz de núcleo, por lo que estoy haciendo "por las malas" aquí. - Utilice la SVM para predecir sobre estas funciones e informar exactitud
Aquí está el código:
trainK <- as.kernelMatrix(K[-holdout,-holdout]) # 1
m <- ksvm(trainK, y[-holdout], kernel='matrix') # 2
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F]) # 3
preds <- predict(m, testK) # 4
sum(sign(preds) == sign(y[holdout])) / length(holdout) # == 1 (perfect!)
Esto debería sólo de hacerlo. Buena suerte!
Respuestas a comentar a continuación
¿qué K [-holdout, -holdout] significa? (Lo que hace el "-" significa)
Imagine que tiene un x
vector, y desea recuperar los elementos 1, 3 y 5 de la misma, que haría:
x.sub <- x[c(1,3,5)]
Si desea recuperar todo, desde x
excepto los elementos 1, 3 y 5, que haría:
x.sub <- x[-c(1,3,5)]
Así K[-holdout,-holdout]
devuelve todas las filas y columnas de K
excepto para las filas que queremos retención.
¿Cuáles son los argumentos de su as.kernelMatrix - especialmente el [, SVindex (m), la caída = F] argumento
Sí, lo inlined dos comandos en una sola:
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F])
Ahora que ha entrenado el modelo, que desea darle una nueva matriz de núcleo con sus ejemplos de prueba. K[holdout,]
le daría sólo las filas que corresponden a los ejemplos de entrenamiento en K
, y todas las columnas de K
.
SVindex(m)
le da los índices de sus vectores de soporte de su matriz original de entrenamiento - recuerde, las filas / cols han holdout
eliminado. Así que para aquellos índices de columna para ser correctos (es decir. Referenciar la columna de la correcta sv), debo eliminar primero las columnas holdout
.
De todos modos, tal vez esto es más claro:
testK <- K[holdout, -holdout]
testK <- testK[,SVindex(m), drop=FALSE]
Ahora testK
solamente tiene las filas de nuestros ejemplos de prueba y las columnas que corresponden alos vectores de soporte. testK[1,1]
tendrá el valor de la función del núcleo calculada entre el primer ejemplo de prueba, y el primer vector de apoyo. testK[1,2]
tendrá el valor de la función kernel entre su ejemplo de pruebas primero y el segundo vector de soporte, etc.
Actualización (01/30/2014) para contestar comentario de @wrahool
Ha sido un tiempo desde que he jugado con esto, así que los detalles de kernlab::ksvm
son un poco oxidado, pero en principio esto debería ser correcta :-) ... aquí va:
¿cuál es el punto de
testK <- K[holdout, -holdout]
-? ¿No quitando las columnas que corresponden al equipo de prueba
Sí. La respuesta corta es que si quieres predict
utilizando una matriz de núcleo, que tiene que suministrar la una matriz que es de la dimensión rows
por support vectors
. Para cada fila de la matriz (el nuevo ejemplo, usted quiere predecir en) los valores de las columnas son simplemente el valor de la matriz del núcleo evaluado entre ese ejemplo y el vector de apoyo.
La llamada a SVindex(m)
devuelve el índice de los vectores de soporte dadas en la dimensión de la ORIGINAL de datos de entrenamiento.
Por lo tanto, yo primero haciendo testK <- K[holdout, -holdout]
da una matriz testK
con las filas de los ejemplos que queremos predecir el, y las columnas son de los mismos ejemplos (dimensión) del modelo fue entrenado en.
Me subconjunto adicional las columnas de testK
por SVindex(m)
sólo dame las columnas, que (ahora) se corresponden con mis vectores de soporte. No lo había hecho la primera selección [, -holdout]
, los índices devueltos por SVindex(m)
pueden no corresponder a los ejemplos adecuados (a menos que todos N
de sus ejemplos de prueba son las últimas columnas N
de su matriz).
Además, ¿qué hace exactamente la caída = FALSO condición de hacer?
Es un poco de codificación defensiva para asegurar que después se realiza la operación de indexación, el objeto que se devuelve es del mismo tipo que el objeto que fue indexado.
En R, si índice sólo una dimensión de una 2D (o superior (?)) Objeto, volverá un objeto de la dimensión inferior. No quiero pasar un vector numeric
en predict
porque quiere tener una matrix
Por ejemplo
x <- matrix(rnorm(50), nrow=10)
class(x)
[1] "matrix"
dim(x)
[1] 10 5
y <- x[, 1]
class(y)
[1] "numeric"
dim(y)
NULL
Lo mismo ocurrirá con data.frame
s, etc.
Otros consejos
En primer lugar, no he utilizado kernlab mucho. Sino simplemente mirar los documentos, yo veo ejemplos de trabajo para el método predict.ksvm()
. Copiar y pegar, y omitiendo las impresiones de pantalla:
## example using the promotergene data set
data(promotergene)
## create test and training set
ind <- sample(1:dim(promotergene)[1],20)
genetrain <- promotergene[-ind, ]
genetest <- promotergene[ind, ]
## train a support vector machine
gene <- ksvm(Class~.,data=genetrain,kernel="rbfdot",\
kpar=list(sigma=0.015),C=70,cross=4,prob.model=TRUE)
## predict gene type probabilities on the test set
genetype <- predict(gene,genetest,type="probabilities")
Eso parece bastante mojigata: utilizar un muestreo aleatorio para generar una genetrain
conjunto de entrenamiento y su genetest
complemento, a continuación, ajuste a través de ksvm
y una llamada a un método predict()
mediante el ajuste, y los nuevos datos en un formato de juego. Esto es muy estándar.
Puede encontrar el símbolo de intercalación href="http://cran.r-project.org/package=caret" rel="nofollow noreferrer"> paquete por Max Kuhn útil. Proporciona un marco de evaluación y ensayo general para una variedad de métodos y paquetes de regresión, de clasificación y de aprendizaje automático, incluyendo kernlab , y contiene varias viñetas más un JSS papel .
Steve Lianoglou es correcto.
En kernlab que es un poco por cable, y cuando la predicción de que requiere la matriz de núcleo de entrada entre cada ejemplo de prueba y los vectores de soporte. Es necesario encontrar esta matriz a sí mismo.
Por ejemplo, una matriz de prueba [n x m], donde n es el número de muestras de ensayo y m es el número de vectores de soporte en el modelo aprendido (ordenados en la secuencia de SVindex (modelo)).
código Ejemplo
trmat <- as.kernelMatrix(kernels[trainidx,trainidx])
tsmat <- as.kernelMatrix(kernels[testidx,trainidx])
#training
model = ksvm(x=trmat, y=trlabels, type = "C-svc", C = 1)
#testing
thistsmat = as.kernelMatrix(tsmat[,SVindex(model)])
tsprediction = predict(model, thistsmat, type = "decision")
granos es la matriz del núcleo de entrada. trainidx y testidx son los identificadores de formación y de prueba.
Construir las etiquetas a sí mismo de los elementos de la solución. Utilice este método predictor alternativo que toma modelo ksvm (m) y los datos en el formato original de entrenamiento (d)
predict.alt <- function(m, d){
sign(d[, m@SVindex] %*% m@coef[[1]] - m@b)
}
K es un kernelMatrix
para la formación. Por el bien de la validación, si ejecuta predict.alt
en los datos de entrenamiento se dará cuenta de que el método predictor alternativo cambia los valores junto a los valores ajustados devueltos por ksvm. El predictor nativa se comporta de una manera inesperada:
aux <- data.frame(fit=kout@fitted, native=predict(kout, K), alt=predict.alt(m=kout, d=as.matrix(K)))
sample_n(aux, 10)
fit native alt
1 0 0 -1
100 1 0 1
218 1 0 1
200 1 0 1
182 1 0 1
87 0 0 -1
183 1 0 1
174 1 0 1
94 1 0 1
165 1 0 1