Redes Neuronales en Python RNA
En un momento verdaderamente de ocio e improductividad de mi vida traduje una RNA que estaba implementada por Jeff Heaton en java a JavaSrcipt para un curso que dictaba en la consultora Everis de dicho lenguaje. La verdad me tenían medio cansado, con la pregunta ¿que se puede hacer en JS?. 😉
Hoy hablando con un amigo dije por que no hacerlo en python y mejor aun con un ejemplo mínimo y que no sea el maldito XOR para ver como se usa la RNA.
Bueno vasta de historia. Haremos un OCR que detecte números dibujados con el Mouse en una imagen jpg.
Entrenaremos la RNA con las siguientes 5 imágenes de 50×50 pixeles por número (http://picasaweb.google.com/arturoeanton/Pyrna). Y pediremos que nos entregue su representación en binario para facilitar la codificación de la salida.
#!/usr/bin/env python #Archivo: pyOcr.py import Image import pyrna def procImgRGB(arch): im=Image.open(arch) procesado=[] xsize,ysize=im.size matrixImg = map(lambda a:map(lambda a:[],range(50)),range(50)) a = "" for x in range(0,xsize): for y in range(0,ysize): matrixImg[x][y]= im.getpixel((x,y)) resp=[] for rangoX in [(0,10),(10,20),(20,30),(30,40),(40,50)]: for rangoY in [(0,10),(10,20),(20,30),(30,40),(40,50)]: manchado = 0 for x in range(rangoX[0],rangoX[1]): for y in range(rangoY[0],rangoY[1]): r,g,b=matrixImg[x][y] if ((r+g+b)/3) < 50: manchado += 1 if manchado > 0: resp.append(1) else: resp.append(0) return resp respuestas =[ [0.00,0.00,0.00,0.00],#0 [0.00,0.00,0.00,1.00],#1 [0.00,0.00,1.00,0.00],#2 [0.00,0.00,1.00,1.00],#3 [0.00,1.00,0.00,0.00],#4 [0.00,1.00,0.00,1.00],#5 [0.00,1.00,1.00,0.00],#6 [0.00,1.00,1.00,1.00],#7 [1.00,0.00,0.00,0.00],#8 [1.00,0.00,0.00,1.00] #9 ] print "Procesando ..." entrada =[] salidaIdeal = [] for i in range(10): for img in range(1,6): print "Procesando ./"+str(i)+"/"+str(img)+".jpg ...", entrada.append(procImgRGB("./"+str(i)+"/"+str(img)+".jpg")) salidaIdeal.append(respuestas[i]) print "ok Respuesta esparada :",respuestas[i] network = pyrna.classNetwork(25, 5 ,4,0.01,0.9) print "Entrenando ..." error = 10 i =0 while error > 0.25: for j in range(len(entrada)): network.computeOutputs(entrada[j]) network.calcError(salidaIdeal[j]) network.learn() error = network.getError(len(entrada)) i +=1 if i % 1000 == 0: print "Error: ",error,"%" i=0 print "Error: ",error,"%" print "recalulo Img..." for i in range(10): for img in range(1,6): a = "./"+str(i)+"/"+str(img)+".jpg" print a," ->", respDada = [] for r in network.computeOutputs(procImgRGB(a)): respDada.append(round(r)) print round(r), print (respDada == respuestas[i]) print "Que aprendiste?" img = 7 for i in range(10): a = "./"+str(i)+"/"+str(img)+".jpg" print a," ->", respDada = [] for r in network.computeOutputs(procImgRGB(a)): respDada.append(round(r)) print round(r), print (respDada == respuestas[i])
- Definimos la función procImgRGB que es una función recibe el nombre de una imagen y la separa en 25 cuadrados y nos dice que cuadrado esta manchado o no.
- Definimos el vector respuestas con las respuestas esperadas. y armamos los pares (entrada – respuesta) en los vectores entrada y salidaIdeal.
- Instanciamos una red con las 25 entradas posibles y 5 neuronas ocultas y 4 de salida. También le definimos el rate y el momentum.
- La entrenamos hasta que el error global de la RNA sea 0.25
- Imprimimos el resultado con las entradas propuestas.
- Y por ultimo vemos que aprendió mediante la imagen 7.jpg de cada numero.
Para ver la salida de este script aca esta el link http://www.binsd.com.ar/pyrna/salida.txt
Links:
- El pyrna.py que es la traducción de las redes en java de Jeff Heaton que le conté arriba esta en http://www.binsd.com.ar/pyrna/pyrna.rar, aca adentro esta tambien el ejemplito de arriba.
- El modulo que utilizo para imágenes la pueden bajar del sitio http://www.pythonware.com/products/pil/
- Link teorico: http://electronica.com.mx/neural/
- Link teorico: http://es.wikipedia.org/wiki/Red_neuronal_artificial (infaltable la wiki jejej)
- Link de Jeff Heaton: http://www.jeffheaton.com/
Como siempre espero que les guste 😉