miércoles, 18 de abril de 2012

Redes neuronales: recolección de base de datos y entrenamiento

Como ya comentamos anteriormente, entrenar una red neuronal mediante backpropagation consiste en buscar los valores óptimos de en nuestro caso más de 14000 parámetros libres que definen el comportamiento de las neuronas de la red, para que una función asociada, conocida como función de coste, minimice su valor. Estos parámetros libres son constantes una vez fijados, y no son las variables de las funciones matemáticas implicadas. Por tanto estos parámetros habrá que buscarlos con algún criterio determinado y para un subconjunto finito de posibles valores de las variables.

Para poder entrenar la red necesitamos una base de datos de imágenes de gestos similares a las que va a utilizar el sistema final, clasificadas de forma que el algoritmo de entrenamiento conozca a qué gesto corresponde cada imagen. Para entrenar la red se comenzará con los parámetros libres ajustados completamente al azar (y con valores pequeños) y se irán pasando una a una todas las imágenes de la base de datos de entrenamiento, observando cómo clasifica la red cada imagen y si su clasificación es correcta o errónea. La función de coste será menor cuantos más aciertos tenga la red dentro del set de entrenamiento. Una vez calculada la función de coste se aplica el algoritmo de backpropagation que calcula el gradiente de algo que tiene que ver con el error cometido al clasificar las imágenes, y conocido este gradiente calcula un nuevo set de parámetros libres mediante métodos numéricos que traten de minimizar el error cometido y la función de coste. El proceso vuelve a repetirse con los nuevos parámetros y se continúa iterando hasta un número de veces fijado por el usuario. Cada vez el coste se va reduciendo y la red va aprendiendo a clasificar mejor los gestos de su set de entrenamiento. Esto puede dar lugar a un fenómeno conocido como "overfitting" en que la red queda entrenada de tal forma que reconoce a la perfección la mayoría de las imágenes de su base de datos de entrenamiento, pero no funciona bien ante nuevas imágenes que nunca había visto antes. Por ello la función de coste también penaliza en cierta medida que los parámetros tomen valores propensos a provocar overfitting, y se debe valuar el comportamiento de la red con nuevos gestos desconocidos para determinar el número óptimo de ciclos de entrenamiento y otros parámetros hasta que el sistema funcione de forma aceptable, mostrando un buen comportamiento tanto con los gestos de entrenamiento como con nuevos gestos.

Para entrenar nuestra red nos hemos propuesto obtener una base de datos de unas 10000-15000 imágenes de unas 10 manos distintas. Como estas imágenes deben ser idénticas a las que el sistema va a recibir una vez sea autónomo, es el PIC32 el encargado de capturar las imágenes y enviarselas al ordenador donde se almacenarán. Para simplificar la tarea de la captura de imágenes hemos realizado un pequeño sketch en lenguaje Processing (un lenguaje que utiliza java como base y está optimizado para trabajar con imágenes). Este sketch toma los datos de la imágen que el PIC32 envía por puerto serie y los transforma en una imágen png, que guarda en un directorio determinado según el gesto al que corresponda, lo cual indica el usuario mediante un menú de control.

[se añadiran imagenes ilustrativas]

El asistente de cámara elige en el menú el gesto que va a grabar e indica al usuario que haga el gesto. Una vez la mano se vea estable en la pantalla, el asistente de cámara pulsará el botón de grabación, momento en el cual se empiezan a guardar las imágenes enviadas por el PIC. Durante el tiempo que dure la captura, que va a unos 15-20 fotogramas por segundo limitada por la velocidad de acceso al disco a la hora de guardar imágenes, el usuario deberá mover ligeramente la mano sin dejar de hacer el gesto, para obtener muchas imágenes distintas.
En sesiones de unos 5 minutos somos capaces de obtener algo más de 1000 imágenes para la base de datos de entrenamiento. Actualmente disponemos de unas 14000 imágenes, de las cuales solo 6000 son válidas, pues tuvimos que cambiar el alfabeto de gestos y descartar las imágenes capturadas con el alfabeto anterior.

Una vez capturadas las imágenes, un script de Matlab recorre la estructura de directorios y extrae todas las imágenes que encuentra, convirtiéndolas a una gran matriz de 576 columnas (una por pixel) y tantas filas como imágenes haya, y otra matriz de una columna y el mismo número de filas que contiene, para cada imagen, el número de gesto al que corresponde.

Cabe destacar un problema que tuvimos debido a que cuando Matlab pasa una matriz a un vector lo hace columna a columna, es decir, dada una matriz
A=[1 2 3
4 5 6]
El comando A(:) de matlab lo transformaría en [1 4 2 5 3 6]. En el PIC32 las imágenes se capturan fila a fila y se guardan como un array unidimensional fila a fila ([1 2 3 4 5 6]). Por tanto nuestra primera prueba de la red neuronal en el PIC32 resultó un fracaso, ya que al no darnos cuenta del detalle anterior la red neuronal se había entrenado en realidad para reconocer las imágenes que captura el PIC rotadas 90 grados (traspuestas). El problema se arregla simplemente trasponiendo la matriz que representa cada imágen antes de transformarla en un vector en Matlab.

No hay comentarios:

Publicar un comentario