En el año 2003 asistí en mi Universidad a un curso de Verano titulado "Inteligencia Artificial" bajo la tutela de la Escuela de Ingenieros Industriales y de Telecomunicación. He de decir, que el curso me resultó bastante aburrido, al centrarse fundamentalmente en la aplicación de ciertas técnicas de IA a la resolución de problemas prácticos de ingeniería, lo cuál en principio no despartaba gran interés en mí (admirador de Marvin Minsky y por tanto con un corte más soñador).
Me entretenía, sin embargo, durante aquellas clases, a desarrollar un pequeño juego basado en el concepto de las redes neuronales artificiales (RNA).
Las redes neuronales son sistemas de cálculo, que "imitan" la estructura del sistema nervioso de los seres vivos. Habitualmente suelen estar compuestas por una matriz de nxm nodos o neuronas. A cada una de las filas se le conoce como capa, y particularme la capa primera y la capa final como entrada y salida.
No existe, en principio, comunicación alguna entre nodos de una misma capa, pero cada nodo está conectado al resto de nodos de la capa siguiente.
La dinámica del sistema queda determinada por las funciones características de cada nodo:
- Función de inhibición: Esta función se aplica sobre los datos provenientes de los nodos de la capa anterior. Generalmente suele ser el sumatorio de las entradas, pesadas por unos valores específicos. Si esta función es positiva suele hablarse de una excitación, mientras que por el contrario si es negativa suele hablar de una inhibición.
- Función de activación: Una nueva función que se aplica sobre el resultado de la función de inhibición. En muchas ocasiones esta función no existe.
- Función de transferencia: Se aplica sobre el valor devuelto por la función de activación. Suele ser una forma de normalizar la salida, y de uso habitual es una función de tipo sigmoide (para obtener valores entre 0 y 1).
La característica principal de las redes neuronales es su capacidad para "aprender". Es lo que se conoce como "Entrenamiento" de una red neuronal. Si de forma sucesiva se le proporcionan a la red, los valores de entrada y los valores correctos de salida, ésta es capaz de modificar los pesos de su función de inhibición hasta ser capaz de implementar con bastante precisión la función específica para la que ha sido entrenada.
No voy a ir más allá en esta descripción, y tampoco voy a dar referencias, debido a la inmensa cantidad de información que hay en la red sobre este tema.
Por el contrario, retomo la historia del pequeño juego que desarrollé (y posteriormente implementé) en aquel curso de IA. La idea fue hacer una red neuronal sin las simplificaciones habituales:
- Si bien se partió de una matriz de nodos (40x40 exactamente), no existía una estructura de capas en el sentido de que la capa primera actue como entrada y la capa última como salida. Todos los nodos del borde de la matriz estaban conectados al exterior, y en cualquier momento podían recibir entradas o "impulsos" del usuario. De la misma forma los cálculos no se hacían capa a capa, sino con un bucle que barría toda la matriz en cada iteración.
- Los nodos tenían conexiones locales: sólo podían comunicarse con aquellos nodos que estuviesen contiguos. Esto limitaba el número de conexiones, pero permitía que la conexión fuese en cualquier dirección.
- Las funciones características de cada nodo lejos de ser lineales, contenían elementos altamente no lineales y acotados para impedir crecimientos desmedidos.
- El nodo adquirió cierta individualidad, al definirse la variable "calidad". El nodo constantemente buscaba maximizar esta variable, modificándose a sí mismo a través de sus funciones características para lograrlo.
- La red era cíclica. No respondía a la estructura entrada-salida sino que "pensaba" permanentemente.
Decidí llamar a este artefacto "Celebro", y a la información retenida en los nodos en cada iteración "Pensamiento". La cantidad de pensamiento generado por "Celebro" era aproximadamente de 1Mb cada 10 segundos (en mi antigua máquina, cuyas características no recuerdo muy bien).
Sin embargo, lo más divertido y fascinante de toda esto, sobrevino cuando comencé a analizar el "Pensamiento" en función de los impulsos que yo introducía en Celebro. Concretamente, llegado un momento, me interesé por introducir impulsos desmesurados en zonas pequeñas del borde (1 o 2 nodos). Pude observar cómo esos impulsos generaban una gran actividad en los nodos circundantes, y poco a poco se propagaban hasta afectar rápidamente a todo el "Celebro". Con el tiempo, sin embargo, la actividad se detenía y volvía a los niveles habituales. Probé a introducir estos impulsos de forma más o menos periódica. Observando más o menos reacciones parecidas. Pero tras suministrar varios impulsos de este tipo observé el siguiente y fascinante efecto:
Celebro comenzó a generar él solo, a través de los nodos frontera, impulsos parecidos a los que yo introducía, y que tanta actividad le reportaban.
Quise reproducir el efecto, y pude aproximadamente ver que era un comportamiento general. Si hiperestimulabas a "Celebro" de forma periódica, llegaba un momento en que aunque dejases de estimular, él sólo era capaz de generar sus estímulos.
En este momento comprendí que había creado un yonki.