¿Cómo kernelize un perceptrón simple?

10

Los problemas de clasificación con límites no lineales no se pueden resolver con un simple perceptrón . El siguiente código R tiene fines ilustrativos y se basa en este ejemplo en Python):

nonlin <- function(x, deriv = F) {
  if (deriv) x*(1-x)
  else 1/(1+exp(-x))
}

X <- matrix(c(-3,1,
              -2,1,
              -1,1,
               0,1,
               1,1,
               2,1,
               3,1), ncol=2, byrow=T)

y <- c(0,0,1,1,1,0,0)

syn0 <- runif(2,-1,1)

for (iter in 1:100000) {
  l1 <- nonlin(X %*% syn0)
  l1_error <- y - l1
  l1_delta <- l1_error * nonlin(l1,T)
  syn0 <- syn0 + t(X) %*% l1_delta
}

print("Output After Training:")
## [1] "Output After Training:"
round(l1,3)
##       [,1]
## [1,] 0.488
## [2,] 0.468
## [3,] 0.449
## [4,] 0.429
## [5,] 0.410
## [6,] 0.391
## [7,] 0.373

Ahora, la idea de un kernel y el llamado truco del kernel es proyectar el espacio de entrada en un espacio dimensional más alto, de esta manera ( fuentes de fotos ):

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Mi pregunta
¿Cómo hago uso del truco del núcleo (p. Ej., Con un núcleo cuadrático simple) para obtener un perceptrón del núcleo , que puede resolver el problema de clasificación dado? Tenga en cuenta: esta es principalmente una pregunta conceptual, pero si también pudiera dar la modificación de código necesaria, sería genial

Lo que probé hasta ahora
probé lo siguiente, que funciona bien, pero creo que este no es el verdadero negocio porque se vuelve computacionalmente demasiado costoso para problemas más complejos (el "truco" detrás del "truco del núcleo" no es solo la idea de un kernel en sí, pero que no tiene que calcular la proyección para todas las instancias):

X <- matrix(c(-3,9,1,
              -2,4,1,
              -1,1,1,
               0,0,1,
               1,1,1,
               2,4,1,
               3,9,1), ncol=3, byrow=T)

y <- c(0,0,1,1,1,0,0)

syn0 <- runif(3,-1,1)

Divulgación completa Publiqué
esta pregunta hace una semana en SO, pero no recibió mucha atención. Sospecho que este es un lugar mejor porque es más una pregunta conceptual que una pregunta de programación.

vonjd
fuente

Respuestas:

2

XX=X,X<,>:Rp×RpRk:Rp×RpR

K(xi,xj)=exp(||xixj||22σ2)

Como se menciona en la página de Wikipedia sobre el perceptrón del núcleo , seleccionamos un subconjunto de tamaño de las entradas y usamos una combinación lineal de ellas para producir nuestra salida, M

f(x)=iMαiyiK(x,xi)

Si ha visto la máquina de vectores de soporte ( SVM ), notará el doble idéntico. Para seleccionar el subconjunto de tamaño a utilizar, optimizamos sobre , que representa si la muestra es un vector de soporte / base de nuestra solución. En la optimización de incluimos los pesos de la optimización original de perceptrón.Mαiiαiωi

En cuanto a su pregunta sobre no tener que calcular la proyección, tiene razón, su matriz de datos de entrada todavía es bidimensional. En el cálculo de la salida, reemplazamos un producto de puntos con la función del núcleo, y aquí es donde ocurre el cálculo 'implícito' en el espacio de características.X

Kellan Fluette
fuente
Gracias. ¿Podría hacer que su respuesta sea más concreta en el sentido de que indique qué líneas del código desde arriba deben modificarse de qué manera? Si no conoce R, las modificaciones pueden, por supuesto, expresarse en pseudocódigo. Entonces
gusto
La publicación a la que está vinculado en la que basó su código es, en mi opinión, una presentación deficiente de perceptrones y propagación inversa, aunque seguramente es breve. ¿Sabes cómo funciona la propagación hacia atrás y la teoría general del perceptrón?
Kellan Fluette
Bueno, hasta cierto punto, espero. ¿A qué te refieres exactamente? ¿Cómo modificaría el código anterior para usar el truco del núcleo con un núcleo cuadrático?
vonjd
¿No hay un $ \ vec {x} ^ \ intercal \ vec {x) $ en el dual lagrangiano del criterio de percepción? Ahí es específicamente donde reemplaza el producto interno con la evaluación de la función del núcleo.
Kellan Fluette