miércoles, 26 de noviembre de 2008

Support Vector Machine

Support vector machine es una técnica avanzada de IA para el reconocimiento de patrones basada en funciones kernel.
Bien y eso que!, bueno, bueno vamos a ver como se hace un svm para el proceso de aprendizaje supervisado de una compuerta xor. Puesto que en internet se encuentra mucha información acerca del tema, no voy a reparar en detalles, como lo serian los optimizadores de lagrange y las funciones kernel y todo el principio matemático(matrices, derivadas, sistemas de ecuaciones, etc), ya que mi objetivo es mostar una manera rápida de construir un svm con python y sympy, sin complicados procedimientos matemáticos, claro que también se puede hacer en matlab, pero bueno no nos gustan las cajas negras y por eso no lo hacemos en matlab.

Primero vamos a derivar manualmente, respecto de a1, a2, a3, a4:
a1 + a2 + a3 + a4 + a1*a4 + a2*a4 + a3*a4 - a1*a2 - a1*a3 - a2*a3 - 9*a1^2/2 - 9*a2^2/2 - 9*a3^2/2 - 9*a4^2/2
Y luego solucionamos el sistema de ecuaciones.

No, es una broma!, para eso tenemos las rutinas proporcionadas por sympy para no quebrarnos la cabeza.

Bien veamos el codigo.

from sympy import *

xor = [[-1,-1],[-1,1],[1,-1],[1,1]]
signos = [-1,1,1,-1]
literals = var('a1 a2 a3 a4')
equis = var('x1 x2')

alfa = []
for i in range(len(xor)):
alfa.append(signos[i] * literals[i])

alfas = Matrix(alfa)

k = zeros(len(xor))
for i in range(len(xor)):
for j in range(len(xor)):
k[i,j] = (1+(Matrix(xor[j]).transpose() * Matrix(xor[i]))[0])**2

ecuation = (alfas.transpose() * k * alfas)[0] * -1/2

for i in literals:
ecuation += i

siseq = diff(ecuation, literals)

solution = solve(siseq, literals)

def kernel(list):
nlist=[]
for i in list:
nlist.append([1, i[0]**2, i[0]*i[1]*sqrt(2), i[1]**2, i[0]*sqrt(2), i[1]*sqrt(2)])
return nlist

kersol = kernel(xor)

w = Matrix([0,0,0,0,0,0])

for i in range(len(xor)):
w += signos[i]*Matrix(kersol[i]) * solution[literals[i]]

compxor = Matrix(kernel([equis])[0]).transpose() * w


#entonces compxor nos debe dar como resultado -x1*x2 y es asi como se comporta una compuerta xor, donde x1 y x2 son la entradas, mas que ovio verdad.




Aquí vemos una imagen que nos representa dos clases ya separadas, esta imagen la tome de la aplicacion en linea: http://svm.dcs.rhbnc.ac.uk/pagesnew/GPat.shtml. Espero que este siempre disponible en línea, si no ya hare mi propia aplicación para graficar los resultados de la svm.

martes, 11 de noviembre de 2008

Matematicas con python

Ok basta de palabrería vamos ha ver algunas cosas de buena programación con python, antes que nada me gustaria platicarles hacerca de mi ultimo descubrimiento, se trata de sympy.

Sympy es una librería para calculo simbolico (cas), -¿qué es eso del calculo simbólico?, -a pues es una maravilla, se trata de un muy completo ambiente que puede hacer operaciones matemáticas entre números reales y símbolos. por ejemplo se pueden hacer operaciones como 2*a+4*a=6a, -¿y bien y esto tan sencillo para que puede servir?. A pues nos habre todo un mundo de posibilidades de calculo, por que este principio no solo aplica a la aritmética, sympy puede hacer operaciones de matrices, integración simbólica, algebra lineal, entre otras operaciones tal como lo haríamos en el cuaderno que llevamos a clases, además de las bondades del lenguaje de programación python.

Para mostrar algo de las posibilidades ilimitadas de cálculo de sympy voy a mostrar parte del código de un clasificador bayesiano, que es una técnica de reconocimiento de patrones, elaborado como tarea para la asignatura de inteligencia artificial en el Itesi.


#Como primera parte aquí tenemos dos vectores con par de puntos (x,y), que nos representan dos patrones linealmente separables:
w1 = [[2, 6], [3, 4], [3, 8], [4, 6]]
w2 = [[1, -2], [3, 0], [3, -4], [5, -2]]

#Ahora procederemos ha hacer algunas operaciones algebraicas y de matrices para separar la clase w1

#nótese que en la línea de abajo se dan de alta algunas variables simbólicas
vars = var('x y')
size = len(vars)

#este es un procedimiento para a calcular la media de un vector
#hasta aquí es solo código python
def mean(vector, dim):
mean = [0,0]
for i in range(0,dim):
for j in vector:
mean[i] += j[i]
mean[i]/=len(vector)
return mean

m1 = mean(w1, size)

#lo interesante viene a continuación, se trata de la conversión entre vectores y matrices
#y sus consecuentes operaciones
def matriz_sigma_inversa(vector, mean):
array_mtx = range(0,len(vector))
sum_mtx = zeros(len(mean))
for i in array_mtx:
array_mtx[i] = Matrix(vector[i]) - Matrix(mean)
sum_mtx += (array_mtx[i] * array_mtx[i].transpose())
return (sum_mtx * 1/len(vector)).inv()

#es aquí donde se realizan las operaciones simbólicas entre números y literales "x", "y"
def matriz_vector_mean(mean, literals):
return Matrix(literals) - Matrix(mean)

#wow podria ser esto mas facil!!!
mtx_sig_w1 = matriz_sigma_inversa(w1, m1)
mtx_med_w1 = matriz_vector_mean(m1, vars)
mtx_tran_w1 = matriz_vector_mean(m1, vars).transpose()
det_w1 = mtx_sig_w1.det()

#ahora tenemos la ecuación de la clase w1, hacer esto para la clase w2
gw1 = (mtx_tran_w1 * mtx_sig_w1 * mtx_med_w1 * -1/2)[0] + (ln(det_w1)*-1/2 + ln(0.5)).evalf()

#igualamos ha cero la ecuación
bayes = gw1-gw2

#y finalmente despejamos "y", lo cual nos dará como resultado una ecuación cuadrática
#que al ser graficado nos mostrara el hiperplano que separa alas clases w1 de w2
solve(bayes, y)

Bien eso es fácil, no son muchas operaciones pero imaginemos un vector de tres dimensiones con muchos mas puntos para graficar, esto si que llevaría mucho tiempo hacer a la antigua.


Ahora veamos la grafica con gnuplot de un espacio vectorial de tres dimenciones.

Por supuesto que esto se puede hacer todo desde python, ya hablaremos de la maravilla de gnuplot en otra ocacion.
.