domingo, 5 de diciembre de 2010

Nuevo modelo para la red neuronal: Taller de C++

En los anteriores talleres hemos visto que para simular las neuronas creamos una clase o función, en esta ocasión con una sola clase simularemos toda la red, de modo que podemos facilmente definir cuantos elementos de entrada, salida y en la capa oculta queremos.
La ventaja esta en el tiempo de ejecución del entrenamiento de la red: si fuera una sola clase para neurona, en casos en los que sean necesarias 20 o mas neuronas el tiempo de entrenamiento seria enorme.
Por motivos de espacio no pongo todo el código fuente en este post, pero podéis obtenerlo desde mi repositorio en http://github.com/Sauruxum/Sauruxum/ .
Para los que no son prácticos con este tipo de servicios, he subido los archivos en http://www.mediafire.com/?9q6sa7rxv27exsm ( Actualizado )

El código  fuente de la red es red.cpp y red.h. Como podréis ver, definimos las salidas de la red con una variable y la entrada a cada elemento es la misma que la salida de los elementos de la capa anterior, a la cual se les aplica o no la función de transferencia ( yo en este caso he decidido de usar exclusivamente la función sigmoidal )

En esta situación es útil crear una matriz para contener ordenadamente los datos de ingreso a cada elemento y tener en la misma variable un identificador de donde proviene el mismo dato.
Para crear una matriz, de modo que sea variable ( de cursos básicos de lenguaje C sabemos que cuando declaramos un vector o matriz estos no pueden cambiar la cantidad de elementos que contienen ) la cual es miembro de la clase red. La función es create_array:

//Crear una matriz de valores "double"
double **create_array( int Row, int Col )
{
    double **array = new double*[Row];
    for ( int i = 0; i < Row; i++ )
        array[i] = new double[Col];
    return array;
}

Este es un método con el cual podemos declarar matrices dinamias ( sin intención de "reinventar la rueda" esta función podéis encontrarlo en textos básicos de C ) y estas matrices se deben declarar para cada capa de la red neuronal.  Otra cosa es que el bias lo declaramos junto a todas las entradas, pero como hemos dicho, se le da un peso sinaptico aleatorio y entrada siempre 1.
Con esta función se deben crear algunas variables, como las que contendrán los pesos sinapticos, el valor del delta ( para actualizar los pesos sinapticos ).
Como dijimos necesitamos un generador de números aleatorios, pero como sabemos los números aleatorios de la librería estándar "no son tan aleatorios", en caso que el entrenamiento falle, nos encontraremos con que el entrenamiento siempre fallara, por lo tanto necesitamos cambiar la semilla para generar números aleatorios siempre distintos por cada ejecución del programa.
Cada parte del entrenamiento de la red la he dividido en funciones simples, y en la definición de las funciones miembros las he ordenado en orden cronológico de uso durante la ejecución.
Tambien se hace necesario guardar los datos del entrenamiento en un archivo para posteriormente recuperarlos, sin embargo la parte para recuperar los datos de una red ya entrenada esta en el código fuente muestras.h

Como nota final para este post dejo un par de comentarios personales:
  • Creo que aunque si mis habitos de programacion son malos, el código fuente esta ampliamente comentado, facilitando la comprension
  • El código es libre y podéis redistribuirlo o modificarlo. En el código vienen algunos ejemplos del uso de la red para los que quieren examinarlo.