domingo, 20 de marzo de 2016

La teleología en la física moderna, y su relación con la filosofía de Philipp Mainländer

"El mundo completo, el Universo, tiene una meta: el no-ser y logra ésta mediante el continuo debilitamiento de su suma de fuerzas."
(Philipp Mainländer)

Un muy interesante (como siempre) artículo en el blog de Santiago[1]: La máquina de Von Neumann, me ha hecho reflexionar estos días sobre el hecho de cómo la física moderna (especialmente los avances en termodinámica lejos del equilibrio térmico), parecen que harán probablemente resurgir con fuerza la propuesta teleológica sobre las leyes del mundo.

Me vino a la mente cómo, de hecho, el trabajo de un físico muy actual y citado como es Arto Annila[2], con publicaciones en decenas de revistas científicas de "prestigio" y revisión por pares, viene a expresar matemáticamente y con asombrosa formalidad este hecho teleológico al que pocos parecen (o quieren) prestar atención. Arto Annila ejemplarmente relaciona el principio de mínima acción (the principle of least action), con el principio termodinámico que nos dice que un sistema se mueve de modo que minimice siempre la energía libre de Gibbs disponible (least-time consumption of free energy).

Y el hecho de que el mundo natural actúe de este modo "intencional" hacia una meta tan clara y experimental como es abolir siempre los gradientes energéticos tan pronto como sea posible utilizando todos los medios disponibles en cada momento y lugar; hace sospechar (como poco) de que quizás finalmente la marcha del universo es un orden de fines que las cosas tienden a realizar, y no una mera sucesión de causas y efectos.

En este sentido, y entrando ya en terreno filosófico, cabe mencionar que un autor de mediados del siglo XIX ya tuvo en cuenta (la previó en gran parte) toda esta teleología natural (espontánea) termodinámica que observamos en la física moderna, y le dio además un significado. Es decir; la racionalizó en una original y grandiosa cosmovisión. Pero, ¿qué significado se las apañó para encontrar en este principio natural que busca eliminar gradientes energéticos a la máxima velocidad posible? Pues bien, el autor del que os hablo fue el filósofo Philipp Mainländer, y la conclusión a la que llegó fue la siguiente:

La cuestión es que para Mainländer (el cual parte del trabajo de su admirado Schopenhauer), todo en el mundo es voluntad (teleología); desde el movimiento de una simple partícula, pasando por el movimiento que conduce al enlace químico, y alcanzando incluso nuestro complejo movimiento orgánico: por lo tanto, según él; absolutamente todo en el mundo sería voluntad, o, en otras palabras: todo sería movimiento intencionado individual. Pero, claro: ¿cuál podría ser esta supuesta (y asombrosa) intención compartida tanto por un enlace químico como por una planta o un ser humano?

Pues bien, para intentar responder a esta compleja cuestión, el filósofo se limitó primeramente a aceptar para sus disquisiciones racionales (siguiendo a Immanuel Kant) sólo aquello que podemos empíricamente observar de modo inmanente en el mundo: es decir; se basó en gran parte en la física teórica. En concreto, fundó su propuesta filosófica en la física termodinámica que por aquel entonces (mediados del siglo XIX) estaba dando sus primeros pasos, y partió por tanto su argumentar posterior en una idea que hoy es un secreto a voces (pero que él tuvo que deducir en gran manera por su propia cuenta): la cuestión de que el mundo inmanente (el Universo) se dirige hacia la muerte térmica (el cese de la existencia de lo que se llama energía libre de Gibbs, la desaparición del movimiento efectivo, la aniquilación de todo gradiente energético, etc.).

En este sentido, merece la pena mencionar que Philipp Mainländer se adelanta a su tiempo y prevé sin duda cuestiones físicas (hoy día aceptadas) de un modo extraordinario. En este sentido, postula el origen del Universo de modo muy similar a como lo hace la teoría del Big Bang, nos habla de la finitud espacial del Universo, acepta ideas evolutivas aún muy controvertidas en su época, defiende sin tapujos la postura de la abiogénesis (el origen de lo orgánico a partir de lo inorgánico), y, por supuesto; comprende y adelanta la principal consecuencia de los avances en termodinámica que tienen lugar a partir de 1850: es decir; postula con la muerte térmica a la que las leyes físicas parecen conducirnos irremediablemente según nos cuenta la física teórica actual. Por otra parte, también en política y economía fue adelantado, y abiertamente supo entrever el mundo globalizado en el que hoy día convivimos. Realmente fue un visionario, y su obra merece sin duda un reconocimiento que aún se le sigue negando.

Precisamente esta muerte térmica del Universo (que como decimos es algo empíricamente constatable), es la que correlaciona el filósofo con la muerte (la aniquilación) de cada ser (orgánico e inorgánico), junto al hecho de que estas muertes individuales (y sus vidas) contribuyen siempre como medio en gran medida a acelerar este proceso cósmico de muerte térmica (todo enlace químico espontáneo, por ejemplo; consume energía libre -esa es, de hecho, la condición necesaria para la posibilidad de su espontaneidad-; y todo enlace químico "forzado" requiere del consumo de aún más energía neta). A todo lo cual se une la cuestión de percibir que todo organismo u organización compleja la componen en el fondo billones de estos enlaces químicos individuales en constante movimiento: creación y aniquilación; lo que nos permite comprender transitivamente que en el fondo todo es siempre el mismo proceso de debilitamiento de fuerzas (consumo de energía libre), sólo que usando cada vez medios (estructuras) más elaboradas para realizar esta tarea del modo más acelerado posible en cada situación. Por lo tanto, la razón de ser de todo fenómeno en el mundo se resuelve siempre en servir como medio en esta búsqueda cósmica por la eficiencia de su auto-destrucción.

El filósofo concluye así que esta búsqueda auto-destructiva podría ser, en el fondo, el "propósito" teleológico común observado en cada ser inmanente con el que nos topamos: inorgánicos y orgánicos, simples y complejos; se trataría siempre de diferentes medios para el mismo fin: la "búsqueda" por abolir los gradientes energéticos tan pronto como sea posible (remito de nuevo al trabajo del físico Arto Annila como referencia). La vida biológica sería de este modo tratado sólo un nuevo medio con el que la naturaleza ha conseguido acelerar, aquí en la Tierra, en lo posible esta muerte térmica anunciada del Cosmos. De hecho, se constata un aumento continuo en la organización del Universo, donde los niveles "teleológicos" alcanzados por la naturaleza son cada vez mejores consumidores netos de energía libre (más eficientes). Se puede comprobar sin duda como estos modos (estos medios organizados) que la naturaleza va configurando en el tiempo, son cada vez mejores en la tarea de acelerar cada vez más (exponencialmente de hecho) este debilitamiento de la fuerza global del Universo (como diría Mainländer).

En este sentido, os dejo una interesante tabla que muestra una estimación de esta mejora natural lograda en la eficiencia neta del consumo (es decir; la densidad de consumo por fenómeno):


Energy levels
(temperature,
in: K or C)
Energy levels
(pressure, in: Atmosphere)
Power Density
Φm in: watt/kg
Our Galaxy
Almost 0 K (interstellar space) up to 3 ´ 109 K (supernovae)
Almost 0 atm. (interstellar space) up to ?? (supernovae)
.00005
Sun
15 ´ 106 K (core)
up to 6000 K (surface)
340 ´ 109 atm. (core) to almost 0 atm. (edge of outer space)
.0002
Earth
150 K (upper atmosphere) up to 7000 K (core)
Almost 0 atm. (upper atmosphere) up to 5 ´ 106 atm. (core)
.0075
Life
0 C up to 90 C
1070 atm (Marianas trench) up to 0.6 atm. (high mountains – air)
.05 (plants)
2 (animals)
15 (human brains)
Humanity
20 C up to 30 C (African savanna)
0.9 atm (African savanna)
2 (proto-humans)
–20 C up to +50 C
1 atm. down to 0.6 atm.
(high mountains)
5 (advanced gatherer-hunters)
16 (early agriculturists)
26 (advanced agriculturists)
1 atm. down to 0.8 atm. (mountains)
77 (industrial society)
230 (technological society c.1970)
1 atm. down to 0.6 atm. (high mountains)
50 (all humankind on average)
Tabla 1. Flujo energético comparado. Fuente: HOW BIG HISTORY WORKS: ENERGY FLOWS AND THE RISE AND DEMISE OF COMPLEXITY (Spier, Fred) http://www.sociostudies.org/almanac/articles/how_big_history_works_energy_flows_and_the_rise_and_demise_of_complexity/

Si finalmente el hombre (u otro ser orgánico aparecido en algún otro planeta), logra conseguir con éxito (mediante el uso de máquinas u otros seres más estables y resistentes) colonizar cada vez más y más planetas, sistemas solares, galaxias, etc.; eso supondría aligerar la muerte del Universo (el consumo de toda su energía libre y útil interna aniquilando así la posibilidad de nuevo movimiento) en varios órdenes de magnitud. ¡Y eso parece realmente ser lo que pretende la naturaleza! Esta parece ser la causa última, por ejemplo; detrás de la vehemencia con la que el hombre actúa a diario, y parece evidenciar además que: si por "la naturaleza" fuese, "ésta" lo consumiría (lo aniquilaría) todo en un solo instante. Sin embargo, según Mainländer, por algún motivo (incognoscible) el mundo no puede (y no pudo antes de empezar a ser) actuar de este modo inmediato que ansía, y no tiene (no tuvo) por lo tanto más remedio que hacer uso de medios con los que aligerar en lo posible este trabajo de destrucción paulatina: nosotros seríamos en este sentido únicamente un medio más, y un medio muy eficiente por cierto, dado el ritmo exponencial al que estamos consumiendo (destruyendo) toda la reserva de energía disponible aquí en la Tierra.

Así pues, esta sería, resumiendo mucho, la cosmovisión de Mainländer: el hecho de que el mundo natural parece que se esfuerza (teleológicamente) en su pronta auto-aniquilación: esa parece ser su única meta, y conseguirla además con la mayor eficiencia y rapidez posible sería la causa que impele el modo en que cada ser se organiza y debe moverse en el mundo. A esta cosmovisión, el filósofo añade finalmente una explicación metafísica remarcable, pero eso ya quizás sobra en este contexto que hemos tratado: no obstante, el que quiera puede leer (por fin en castellano) su principal obra: "Filosofía de la redención"[3]. Merece mucho la pena ;).

Un saludo.

Referencias.

[1] https://vonneumannmachine.wordpress.com/2016/03/17/el-inquietante-principio-de-fermat/ (La máquina de Von Neumann)
[2] http://www.helsinki.fi/~aannila/arto/ (web del físico Arto Annila, con enlaces a todas sus publicaciones).
[3] http://www.casadellibro.com/libro-filosofia-de-la-redencion/9788494150555/2277755 "Filosofía de la redención" (Philipp Mainländer), enlace a la magnífica traducción que ha realizado MANUEL PEREZ CORNEJO. 


jueves, 17 de marzo de 2016

Vivir es morir

"Los hombres se parecen a esos relojes de cuerda que andan sin saber por qué. Cada vez que se engendra un hombre y se le hace venir al mundo, se da cuerda de nuevo al reloj de la vida humana, para que repita una vez más su rancio sonsonete gastado de eterna caja de música, frase por frase, tiempo por tiempo, con variaciones apenas imperceptibles." (Schopenhauer)


"To live is to die" (Vivir es morir) es una canción instrumental compuesta por el grupo Metallica, la cual forma parte del disco "..And Justice for All" de 1988. Se trata de una composición a modo de homenaje póstumo que la banda brindó a su bajista Cliff Burton fallecido en 1986.

Este trabajo, de una enorme calidad musical, tiene una interpretación, digamos oficial, en cuanto a su significado. Esta interpretación la podéis leer por ejemplo aquí: https://es.wikipedia.org/wiki/To_Live_Is_to_Die

Sin embargo, yo os voy hacer una interpretación propia (es lo bueno que tiene la música -y la poesía-, que deja siempre la puerta abierta a que cada cual la aproveche para expresar sus propias ideas ;):

La canción, de 9 minutos de duración, sólo tiene un pequeño fragmento de voz (en el minuto 7:30), el cual es parte de una poesía que la hermana de Cliff encontró entre las cosas del músico de manera fortuita tras la muerte de éste en un accidente de tráfico. La letra dice lo siguiente:
"When a man lies, he murders some part of the world, these are the pale deaths which men miscall their lives, all this i cannot bear to witness any longer, cannot the kingdom of salvation take me home?"
que viene a traducirse en algo así como:
"Cuando un hombre miente, mata una parte del mundo, estas son las muertes pálidas a las que los hombre mal llaman "sus vidas". Ya no puedo soportar ser testigo de todo esto, ¿no puede El Reino de la Salvación llevarme a casa?"
Esta letra no es sin embargo completamente original, y se supone que Cliff utilizó en parte un fragmento de un poema previo de Stephen R. Donaldson que dice:
"These are the pale deaths
which men miscall their lives:
for all the scents of green things growing,
each breath is but an exhalation of the grave.
Bodies jerk like puppet corpses,
and hell walks laughing."
Es decir:
"Estas son las muertes pálidas
que los hombres mal llaman sus vidas:
toda la esencia en las cosas que crecen,
toda respiración no es más que una exhalación hacia la tumba.
Los cuerpos se sacuden como marionetas muertas,
mientras el infierno continúa riendo."
Yo creo que Cliff intenta con su poema hacernos ver lo desilusionado que se sentía con la vida. Me parece que intentó transmitir con esas palabras el absurdo y el sinsentido del mundo, y su angustia ante esa realidad que tan patente ya le parecía. Y en este sentido, creo que la banda logra hacer un gran tributo con el tema "To live is to die".

En este tema se pueden apreciar varias partes melódicas muy bien diferenciadas, a las cuales cada cual le pone un significado distinto, y que yo interpreto del siguiente modo:

Al inicio la introducción es muy lenta, de estilo clásico y suave, lo que simboliza en mi opinión los primeros años de vida de una persona: es decir; la dulce y despreocupada infancia. Al cabo de un minuto, sin embargo, la música se vuelve repentinamente violenta y agresiva: este momento se puede correlacionar sin duda con la llegada de la adolescencia y el comienzo de la verdadera lucha personal contra el mundo. El mundo se vuelve un entorno hostil, y nuevos y variados instintos empujan al individuo con vehemencia en la búsqueda por resolver fuertes necesidades sexuales, de poder, dominación y, por supuesto, de consumo.

Esta lucha continúa durante años con rabia y determinación, hasta que llega un momento en que se alcanza una especie de cima en la vida. En el minuto 5 de la canción se simboliza esta paz temporal que alcanza el hombre cuando finalmente logra apaciguar en parte todo este gran impulso de necesidad aparecido: el individuo sobrepasa la juventud y, con suerte, logra las principales metas que le propuso la vida: posiblemente logró ya unos estudios o trabajo, y una pareja estable. Un hogar independiente y el hecho de probablemente traer ya en camino un nuevo ser al mundo mediante un embarazo.

Poco a poco, sin embargo, el tema se vuelve más duro de nuevo: nuevos problemas y necesidades aparecen en el camino de la vida conforme nuevos instintos nos empujan ahora con más fuerza aún en la crianza de estos hijos. Unos hijos que son como extensiones de nosotros mismos, y que nos hacen padecer con el dolor y la necesidad que ellos sufren, tanto o más de lo que logra hacerlo nuestro propio dolor personal.

Finalmente, en el minuto 7:30 llega la revelación: ¿qué sentido tiene todo esto? Vemos en nuestros hijos el mismo ciclo vital que ya nosotros seguimos antes, pero no vemos otra cosa más que nueva necesidad y dolor: ¿y para qué? Al mismo tiempo aparece ya en nosotros los primeros síntomas de la vejez y la enfermedad, y esta angustia se acentúa.

La música continúa con un ritmo fuerte y agresivo, lo que implica el resto del camino de padecimiento que toda persona debe seguir a pesar de que consiga llegar en algún momento a la revelación del absurdo; incluso entonces, se ve impulsado a ayudar a sus propios hijos a continuar el sonsonete de la vida; es decir; a ayudar en la crianza de sus nietos utilizando sus últimas fuerzas. Toda esta lucha instintiva continua hasta que, en el minuto 9, la música vuelve a la suavidad y al reposo melódico: la muerte finalmente se hace evidente (se la siente cerca) y nos embauca con su oferta de Salvación: de eterno descanso. Nos seduce con la prometida redención de la lucha, con la redención vital.

Una lágrima cae por la mejilla del anciano mientras éste comprende la absurda tarea existencial que se ha visto obligado a soportar. En el minuto 9:51 la canción termina abruptamente: la muerte, como siempre, inesperadamente ha llegado. Todo terminó por fin: la persona se ha visto Salvada del infierno del instinto (como diría Mainländer, el verdadero "demonio").

domingo, 13 de marzo de 2016

Pero, ¿cómo funciona AlphaGo?

"[Las neuronas son] células de formas delicadas y elegantes, las misteriosas mariposas del alma, cuyo batir de alas quién sabe si esclarecerá algún día el secreto de la vida mental." (Ramón y Cajal)

Introducción.

El programa AlphaGo desarrollado por Google DeepMind se ha hecho famoso estos días en los medios de comunicación a partir de su enfrentamiento (y victoria) frente el campeón del mundo y noveno dan, Lee Sedol.

Como digo, todos los medios se han hecho eco de esta proeza (en concreto, conseguir un algoritmo capaz de competir en igualdad de condiciones con un gran maestro de Go), algo que se pensaba que aún tardaría 10 años más en llegar, pero pocos medios no especializados han explicado con cierto detalle cómo funciona realmente AlphaGo. Y esto es precisamente lo que pretendo con esta entrada: explicar técnicamente del modo más sencillo posible qué es lo que han hecho desde Google para conseguir este hito en inteligencia artificial,  y hacerlo además de un modo que pueda ser entendido más o menos por cualquier persona.

Durante toda esta entrada, voy a basarme en el paper que el propio equipo de DeepMind ha publicado en la revista Nature explicando su obra: "Mastering the game of Go with deep neural networks and tree search" (http://www.nature.com/nature/journal/v529/n7587/full/nature16961.html). Pero para que gente no especializada pueda entender este asunto, evidentemente tendré que simplificar en gran parte el contenido de dicho trabajo. No obstante, decir a aquellos lectores con conocimientos más avanzados de computación, que podéis acceder a dicho paper y obtener toda la información técnica completa y detallada en profundidad (si no queréis pagar, aquí tenéis un enlace gratuito al PDF oficial ofrecido por Google Scholar :P).

Precedentes de AlphaGo.

El juego de tablero del Go ha sido desde hace décadas el último gran reto de la inteligencia artificial en cuanto a intentar conseguir un nivel de juego capaz de enfrentarse a grandes maestros humanos. Tal es la complejidad combinacional del juego (¡donde una partida tiene más movimientos posibles que átomos tiene el Universo!), que ni siquiera poniendo miles de ordenadores distribuidos calculando jugadas mediante algoritmos tradicionales de "fuerza bruta" se conseguía nada (algo que sí sirvió, sin embargo, para que el DeepBlue de IBM venciera al gran maestro de ajedrez Gary Kasparov en 1996). Pero como decimos, en el Go esta estrategia digamos "tradicional" de pre-programar algunas reglas de juego e invertir luego cientos de computadores para prever y calcular las mejores jugadas no conseguían ganar ¡ni siquiera a un jugador principiante!

Nuevas técnicas de inteligencia artificial fueron, no obstante, apareciendo en los últimos años, las cuales ya introducían nuevos preceptos y estrategias: siendo de destacar la aparición en el uso de árboles de exploración Monte-Carlo -no entraré en mucho detalle sobre esta técnica denominada MCTS (Monte-Carlo Tree Search), pero tenéis mucha más información en el paper y en internet ;)-. Pues bien, usando estas nuevas técnicas ya se lograron programas comerciales capaces de jugar al nivel de un jugador amateur (con un Elo de sobre 2000), siendo en este sentido de destacar los programas Crazy Stone y Zen.

Comparación del nivel de juego entre AlphaGo, el gran maestro Fan Hui, y otros programas comerciales de Go.

Sin embargo, hasta llegada de AlphaGo en 2015, ningún programa pudo pasar de este nivel amateur de juego, y se pensaba que poder llegar a competir con un gran maestro de Go de dan (p) (con un Elo por encima de 3000), era algo que tardaría en llegar un mínimo de 10 años más...pero finalmente no ha sido así. AlphaGo venció en octubre del 2015 en un torneo al gran maestro humano Fun Hui, de dan 3p (y sobre 2800 de Elo). Y aunque ya eso supuso una revolución y un verdadero logro para la tecnología, ha sido no obstante este año, tras su fenomenal enfrentamiento con el 9p dan Lee Sedol (con un Elo por encima de 3500), cuando se ha confirmado la proeza. Una proeza con un mérito aún mayor dado el método por el que ha conseguido: habiéndose literalmente simulado el modo en que el cerebro humano piensa y aprende, para lograr así generalizar y abstraer lo suficiente la capacidad del algoritmo como para entender y comprender (igual que lo haría una persona), el valor de un movimiento únicamente a partir de la información sensible (visual) del tablero. Veamos ésto con un poco más de detalle.

Redes neuronales artificiales.

Cuando decimos que este logro se ha conseguido simulando cómo funciona el cerebro humano, me estoy refiriendo, por supuesto, a que se han utilizado profusamente redes neuronales artificiales (que no son más que una emulación computacional del modo en que se conforman las redes neuronales biológicas en el hombre -y en el resto de animales- para otorgamos nuestras capacidades cognitivas).

Estas redes se usaron concretamente para dos tareas bien diferenciadas: para seleccionar (y descartar) estrategias de juego que merecen (o no) la pena estudiar más a fondo de entre las cientos de miles de combinaciones disponibles, y para evaluar lo favorable o desfavorable que es un determinado estado del tablero. Para cada una de estas dos tareas se usaron varias subredes neuronales independientes, aunque todas compartían una estructura muy similar; tratándose de redes con una entrada (input) "visual" el cual recibe directamente los pixels del tablero en un instante dado, tras lo cual 14 capas intermedias u ocultas (hidden layers) se encargan de procesar esta información "sensible" recibida, trasladando el resultado de este procesado de información hacia una capa de salida (output). Este resultado será finalmente el utilizado por AlphaGo para discriminar lo acertado o no de una determinada estrategia de juego, y para intentar prever y entender cómo de bien le iría si finalmente se decidiese por una de ellas.

Este ha sido, por tanto; el verdadero acierto del equipo de desarrollo de Google, hacer un uso muy intensivo de redes neuronales complejas para abstraer y generalizar la estrategia de juego; y ha sido además lo que ha permitido en tan sólo dos años, aumentar el Elo del estado del arte en la IA de este juego en más de 1500 puntos: todo un rotundo éxito.

Imitando al hombre.

Sin duda, la clave detrás del poder del programa se encuentra en haberse logrado imitar computacionalmente, y con mucho acierto, el modo en que se supone que la propia mente humana procede a la hora de jugar una partida de Go; y también al imitar el modo en que procede el cerebro humano a la hora de aprender a jugar primero, y a ganar después con el tiempo maestría. Y para que se comprenda este punto con claridad, creo que lo mejor es hacer un breve símil aproximado entre el modo en que se supone que la mente de un maestro humano procede, y el modo en que AlphaGo hace lo propio:

Ilustración de una red neuronal biológica.
A la hora de jugar una partida, un jugador humano primeramente observa mediante la vista (captando los fotones reflejados por el tablero) el estado actual de juego (número de piezas en cada casilla, color de las mismas, etc,); esa información eléctrica sensible se traslada mediante el nervio óptico hacia el sistema nervioso central (SNC), donde la corteza visual primaria V1 (y posteriormente las áreas visuales corticales extra estriadas: V2, V3, V4, y V5), tratan esta información visual originaria, adecuándola y transformándola de modo que sirvan más eficazmente en los sucesivos procesamientos neuronales, los cuales tomarán como entrada esta información visual tratada (y no la original del nervio óptico). No existen aún detalles exactos y completos del modo en que este procesamiento posterior ocurre, pero sí se sabe que el hipotálamo actúa como coordinador (o controlador) de un proceso asociado recurrente e interconectado donde diferentes subredes neuronales biológicas especializadas procesan toda la información de un modo concurrente (fundamentalmente en los lóbulos temporales y parietales). Durante este procesado continuo y asociado de redes especializadas, se supone que el jugador va mentalmente seleccionando y estudiando los movimientos que considera prometedores (utilizando la memoria), y luego previendo el resultado que ese movimiento conllevaría en sucesivas jugadas, descartando así las jugadas menos favorables y profundizando en aquellas que sí se lo parecen. Este bucle mental, en gran parte inconsciente, se repite durante miles de simulaciones mentales imaginarias (descartando por el camino billones de jugadas no valoradas como prometedoras) para finalmente, tras un intervalo variable de tiempo de dicha "exploración mental", procederse a una salida (es decir; a la toma de una decisión final): "colocar la pieza en la casilla x". Esta salida se transmite posteriormente a los nervios motores de las extremidades, los cuales mueven la mano que cogen la ficha (en Go a las fichas las llaman piedras), y la sueltan en la posición x. En realidad, la neurociencia dispone de detalles mucho más concretos (aunque aún incompletos) sobre este proceso, pero para el símil que vamos a realizar, con lo dicho basta.

¿Y cómo lo hace AlphaGo? Pues de un modo asombrosamente similar. La máquina utiliza una técnica de exploración iterativa muy (muy) similar a la que realiza nuestro cerebro. En concreto, utiliza un árbol de exploración MCTS (Monte-Carlo Tree Search) para emular la "exploración mental" imaginaria que hemos visto que hace el cerebro; pero adapta dicha técnica de manera que se proceda de un modo casi idéntico a cómo explora la mente del jugador humano. El proceso completo es aproximadamente el siguiente: primero la máquina recibe los pixels con el estado actual del tablero (de modo similar a cómo la retina y el nervio óptico llevan esta misma información sensible al SNC), posteriormente esta entrada visual y sensible se convoluciona por entre varias capas intermedias de neuronas (de modo similar a cómo actúa la corteza visual en V1,V2,V3,V4 y V5). Es la salida de esta convolución la que se introduce luego en los nodos (neuronas) de entrada de las 4 subredes neuronales artificiales que se usarán en el resto del proceso (de modo parecido a cómo lo hacen ciertas subredes biológicas asociadas).

Ilustración de una red neuronal artificial.
Es decir; que una vez tratada la información visual sensible, se produce un proceso iterativo de simulación muy similar al que tiene lugar en la mente de una persona por entre diferentes subredes neuronales biológicas en los lóbulos temporales y parietales. En concreto, AlphaGo procede a evaluar y seleccionar (gracias a la actuación de dos de las 4 subredes neuronales utilizadas: value network y policy SL network) las jugadas que considera más prometedores (descartando billones de alternativas del mismo modo que hace una persona), y más tarde se dedica a investigar y profundizar en el estudio de estas jugadas percibidas como buenas candidatas gracias a otra de las subredes neuronales encargadas de realizar esta tarea con gran eficacia y precisión (fast rollout policy). Este proceso de exploración ocurre a un ritmo de miles de simulaciones "imaginarias" por segundo (un ritmo del mismo orden de magnitud que el humano), pero hay que recalcar que esta cantidad es irrisoria en comparación con las decenas de millones de "simulaciones" que utilizó, por ejemplo DeepBlue contra Kasparov. Porque es importante hacer de nuevo hincapié en que aquí el poder de la máquina no recae en explotar la potencia de cálculo en un proceso de fuerza bruta de exploración, sino en usar esta potencia en la ejecución de complejas redes neuronales capaces de abstraer, generalizar y seleccionar las mejores jugadas y estrategias de juego de entre billones de alternativas que son descartadas e ignoradas. Esto es precisamente lo que se cree que el hombre hace al jugar, y lo que ha dado al AlphaGo tanta capacidad de juego al imitarle.

Cómo realizaron el entrenamiento de las redes neuronales de AlphaGo.

Pues de una manera muy similar a cómo se supone que nuestras redes neuronales biológicas se adaptan y modulan para realizar con éxito nuevas tareas requeridas por la persona: mediante un proceso continuo y gradual de ensayo y error empírico.

Cualquier persona neuronalmente sana, posee desde que concluye su desarrollo cerebral, todas las capacidades neurológicas necesarias para poder llegar a aprender a jugar Go tras un proceso de aprendizaje el cual llegue a modular y adaptar las sinapsis de ciertas subredes de neuronas en diferentes zonas del cerebro. Es decir; que las subredes que nos permiten jugar al Go ya están ahí desde el principio, y es un proceso de ensayo y error el que va poco a poco adaptando dichas subredes para ir mejorando la calidad de nuestro juego. En pocas palabras: nuestro cerebro aprender a jugar...jugando.

AlphaGo hace lo mismo, pero a la enorme escala que permite el hecho de poderse simular millones de partidas en muy poco tiempo (mientras que una persona no puede jugar más de una centena de ellas por motivos fisiológicos). En concreto, las subredes neurológicas utilizada por la máquina se entrenaron mediante este proceso empírico jugando contra sí misma durante semanas (usando una subred denominada policy RL network). Para entender este proceso de entrenamiento con más detalle, sin embargo, es necesario disponer de ciertos conocimientos previos de computación teórica, por lo que no voy a entrar en más detalles técnicos (aunque está todo muy bien explicado en el paper publicado por Google). Baste con que nos quedemos con la idea de que la máquina aprende literalmente a jugar de un modo casi idéntico a cómo lo hace el hombre (mediante la observación de partidas que son jugadas por otras personas que saben hacerlo mejor que nosotros -policy SL network-, y mediante un proceso continuo de juego y práctica personal por el que vamos limando gradualmente por ensayo y error nuestros fallos de juego -policy RL network-).

Resultados y discusión.

Los resultados han sido maravillosos. Entrenando de este modo, la misma estructura neuronal artificial ha pasado en pocas semanas de no ser capaz de ganar ni siquiera al más penoso jugador humano, a poder vencer primero al gran maestro 2p dan Fan Hui (por 5 a 0), y luego también al campeón mundial Lee Sedol 9p dan. La (durante décadas) tan prometida inteligencia artificial parece que ahora sí está dando por fin sus primeros (y verdaderos) pasos.

Pero las aplicaciones futuras de esta revolución lograda por DeepMind no se reducen a la mera posibilidad de jugar juegos con un nivel sobrehumano; sino que abre las puertas a la aplicación de estos métodos utilizados sobre muchas otras tareas complejas que hasta ahora sólo un humano era capaz de realizar con precisión. Las posibilidades son ilimitadas, y estamos sin duda ante un hito que la historia se encargará de recordar a su debido tiempo.

Opinión personal.

Pues bien, hasta aquí ya hemos dicho lo fundamental sobre cómo funciona AlphaGo y las consecuencia y resultados de su desarrollo, pero no quiero cerrar este artículo, sin embargo; sin hacer antes un par de anotaciones muy personales y subjetivas mías, que cada cual tendrá que valorar, pero que creo sinceramente que ganan fuerza tras este experimento de Google:

Primero y fundamental, creo que este experimento demuestra que nuestra mente no es ni conforma ningún fenómeno especial o diferenciado en su esencia natural. En otras palabras: creo que este desarrollo aporta mucha más fuerza a la idea que rechaza cualquier tipo de dualismo en la capacidad cognitiva del hombre. El materialismo más reduccionista creo que saca partido ante estos hechos, y que ya poco lugar a dudas queda de que nuestra mente entera, junto a sus capacidades cognitivas, es simplemente el resultado de complejos (y masivos) cálculos ocurridos por entre las neuronas de nuestro cerebro gracias a medios eléctricos...y poco más. Ni alma, ni espíritu, ni siquiera postulados estrambóticos como la supuesta intervención cuántica propuesta por Roger Penrose parecen ya necesarios ni creíbles: únicamente la física y la química a nivel mesoscópico, junto con la dirección de movimiento impuesta por la termodinámica, parecen bastar y sobrar para dar cuenta del origen y desarrollo de nuestra conciencia y capacidades mentales. Y eso sería todo.

Por otra parte, también creo que este desarrollo supone una clara muestra del modo en que nuestras propias capacidades cognitivas pueden ser (y serán) fácilmente sobrepasadas en cualquier ámbito o tarea que nos propongamos (sin importar ya su complejidad): simplemente habremos de usar redes neuronales artificiales con la estructura adecuada para cada tarea dada, y posteriormente proceder a modular sus pesos (el equivalente a adaptar la fuerza de las sinapsis biológicas) de un modo gradual pero masivo y a gran escala (parecido a como han hecho con AlphaGo). Además, no es siquiera necesario que una persona se dedique a investigar qué estructura neuronal artificial es la adecuada para cada tarea, porque dentro de poco estoy seguro que otra rama de la computación llamada computación evolutiva se unirá con éxito a estos avances, y harán posible que incluso la estructura neuronal necesaria se seleccione de manera autónoma con esta técnica (de un modo similar a como la evolución biológica hizo lo mismo en el reino animal).

Y es que yo estoy firmemente convencido de que el uso conjunto del tipo de técnicas de aprendizaje utilizadas en AlphaGo, junto con el uso concurrente de técnicas de computación evolutiva, llevarán durante las próximas tres o cuatro (o cinco :P) décadas a la aparición final de una verdadera conciencia artificial indiferenciable de la humana: esa máquina pensará, sentirá, aprenderá, se emocionará, y actuará en cualquier ámbito como nosotros...e incluso lo hará mejor.

Es más: yo creo que ya hoy día, si un gran país del estilo de EEUU se propusiese esta meta, dedicando gran parte del esfuerzo del país en esta dirección de modo similar a cómo se hizo en el proyecto Manhattan (dando lugar a la bomba atómica), o en el programa Apolo (que llevó el hombre a la luna), igualmente creo que en no más de 10 años se podría conseguir sin duda esta conciencia artificial que os digo. De hecho, tengo "confianza" en que una posible guerra fría renovada gracias al choque entre el futurible presidente americano Donald Trump y el actual presidente ruso Vladímir Putin, lleven a que al menos uno de los dos bandos (posiblemente USA), dedique grandes esfuerzos en esta dirección guiado por intereses militares; lo cual acelere así el asunto. Evidentemente hay que tener en cuenta las posibles consecuencias secundarias de este choque entre países, pero bueno, siempre hay que intentar ver el lado positivo de las cosas (xDD). Y lo positivo sería sin duda la aparición de esta hipotética conciencia artificial 40 ó 50 años antes de lo que ocurrirá con el actual nivel de financiación en estos campos de estudio ;).

Para concluir, y aunque sé que puede parecer una afirmación exagerada, en mi opinión, este logro conseguido por Google DeepMind supone una nueva y definitiva herida a la narcisista humanidad y su gran ego:

Históricamente, la primera herida la propició Nicolás Copérnico al demostrar que la Tierra no es el centro del universo. Una segunda fue obra de Charles Darwin, al demostrar que el hombre es simplmente un animal más. La tercera fue iniciada sin duda por Sigmund Freud, al proclamar que ni siquiera somos dueños de nosotros mismos (con el descubrimiento del inconsciente), herida que fue desarrollada y ampliada más tarde por la moderna neurociencia. Finalmente, creo que se acaba de producir una nueva herida desde el terreno de la inteligencia artificial al demostrarse que cualquiera de nuestras capacidades cognitivas superiores (conscientes, inconscientes, sencillas o complejas) no es sólo que sean reproducibles, sino que incluso son mejorables. El materialismo gana la batalla, y se demuestra que el tan alabado fenómeno mental humano no es especial en ningún sentido: se constata que finalmente es sólo cuestión de poner las partículas necesarias en el lugar adecuado, y dejar que la termodinámica guíe el movimiento.

Y con esto termino :). Espero que os haya interesado el artículo.

¡Un saludo!

Principales referencias utilizadas.

"Mastering the game of Go with deep neural networks and tree search" (http://www.nature.com/nature/journal/v529/n7587/full/nature16961.html) (Google DeepMind) (2015).
https://deepmind.com/publications.html (publicaciones del equipo de desarrollo Google DeepMind).


martes, 8 de marzo de 2016

Torneo de Go: "Google DeepMind Challenge Match": Lee Sedol vs AlphaGo


A continuación tenéis un vídeo con el resultado de la primera partida de las 5 que enfrentarán, por un lado el campeón mundial de Go: Lee Sedol, y por otro AlphaGo: un computador que juega gracias a una red neuronal artificial entrenada a conciencia mediante ensayo y error por Google DeepMind (el vídeo es muy interesante y contiene comentarios de profesionales):



A partir de esta noche podremos seguir en vivo, desde el canal de youtube de DeepMind, las cinco partidas que van a enfrentar a AlphaGo (red neuronal artificial desarrollada por Google), contra Lee Sedol: campeón mundial del juego de Go.

Si el algoritmo consigue vencer a Lee Sedol, se tratará de un hito en inteligencia artificial mucho mayor que el logrado por DeepBlue (de IBM) cuando logró vencer a Kasparov jugando al ajedrez. Esto es debido a que en esta ocasión no se trata de un simple programa de ordenador usando la fuerza bruta y con unas pocas tácticas de juego pre-programadas (en el juego de Go usar la fuerza bruta para explorar las jugadas no es viable ya que la explosión combinacional es tal, ¡que hay más jugadas posibles que átomos en el Universo!). Esta vez sí estamos ante una verdadera revolución en IA: AlphaGo es una máquina (una red neuronal artificial) que ha -literalmente- aprendido a jugar de manera autónoma gracias a un proceso empírico de ensayo y error (entrenamiento) mediante el cual ha conseguido modular sus conexiones "sinápticas" de un modo muy similar al que lo hacen las personas. Este aprendizaje, para más inri, se basa principalmente en una muy sencilla premisa: imitar el modo en que nuestro cerebro biológico funciona. El resultado ha sido asombroso, y ahora sí, cada vez está más claro que se abren las puertas a la llegada de una (ya) no tan lejana conciencia artificial. Es cuestión de tiempo: como diría aquel, el futuro es ahora ;).

Estad atentos a las partidas, y sed conscientes del gran hito que supone el simple hecho de que la máquina sea capaz de enfrentarse en igualdad de condiciones con el campeón mundial (independientemente de que finalmente venza AlphaGo o no).

Si queréis un poco más de información técnica sobre este desarrollo de Google, podéis ver este otro enlace de mi blog donde ya traté este tema hace semanas.

¡Un saludo!

----------------------------------------------------------
Edito el 09/03/2016 a las 9:07h.

¡AlphaGo lo hizo! Ganó la primera partida contra Lee Sedol en un disputado encuentro (y es curioso, porque Lee presumía desde el principio en que el resultado sería un 5-0 a su favor xDD). Pero la cuestión es que, independientemente del resultado final del torneo, ya es un hito el hecho de que Google haya conseguido un programa capaz de ganar aunque sólo sea una partida de Go al campeón mundial (más aún cuando el campeón humano está fuertemente motivado por el premio de un millón de dolares que hay en juego).

Os seguiré comentando más cosas sobre las sucesivas partidas en este mismo hilo. De momento, el resultado del torneo es:

Partida 1: Lee 0 - 1 AlphaGo (Lee juega con negras)

 La segunda partida empezará mañana. Estad atentos al canal de Youtube de Google DeepMind.

----------------------------------------------------------
Edito el 10/03/2016 a las 10:27h.

¡Alphago lo hizo de nuevo! Ha ganado la segunda partida, y esta vez ya no se puede achacar la derrota de Lee Sedol a que estaba confiado y suponía que su victoria sería fácil. Con este nuevo resultado favorable a AlpgaGo se confirma y afianza la idea de que finalmente se ha conseguido una máquina capaz (gracias fundamentalmente a su red neuronal artificial), de vencer a cualquier persona en el último juego de tablero que se resistía: el Go.

El hito fundamental, sin embargo, no es el hecho en sí de esta victoria, sino de que dicha victoria sólo ha sido posible una vez que se han empleado técnicas computacionales que imitan el modo en que nuestra mente (toda nuestra capacidad cognitiva) emerge y funciona: es decir; gracias a redes neuronales. Este asombroso resultado viene a indicar que que es posible emular en máquinas comportamientos tan abstractos como los requeridos para jugar a este juego de tablero con más combinaciones de juego posibles que átomos en el Universo: AlphaGo es una máquina que aprendió a jugar de manera autónoma empíricamente (por ensayo y error), del mismo modo en que se cree que lo hacen las personas; y además, por si fuera poco, basó este entrenamiento empírico en la premisa neurológica fundamental del cerebro biológico: la neurona. Todo esto no hace sino fortalecer el postulado ya ampliamente aceptado en neurociencia de que la conciencia y la capacidad de abstracción humana es el simple resultado de un procesado de información eléctrica cerebral...y nada más.


Partida 1: Lee 0 - 1 AlphaGo (Lee juega con negras)
Partida 2: Lee 0 - 2 AlphaGo (Lee juega con blancas)

 La tercera partida empezará pasado mañana. Estad atentos al canal de Youtube de Google DeepMind.

----------------------------------------------------------
Edito el 12/03/2016 a las 10:34h.

¡Nueva victoria de AlphaGo! Esto supone que van 3 a 0 en un torneo de 5 partidas, por lo que AlphaGo acaba de vencer oficialmente al gran maestro Lee Sedol. La proeza en inteligencia artificial se acaba de confirmar, y la hemos podido seguir en directo :). 

Partida 1: Lee 0 - 1 AlphaGo (Lee juega con negras)
Partida 2: Lee 0 - 2 AlphaGo (Lee juega con blancas)
Partida 3: Lee 0 - 3 AlphaGo (Lee juega con negras)

Aún se jugarán las dos partidas restantes a la espera de ver si Lee puede ganar al menos una vez, pero como digo el torneo ya tiene un ganador: AlphaGo. Es curioso cómo se empezó el torneo presuponiendo que el resultado sería de 5 a 0 a favor del gran maestro, y que estemos ahora por el contrario a la espera de ver si este gran maestro es capaz de ganar al menos una partida contra la máquina. Evidentemente se infravaloró la capacidad de Google y sus recientes investigaciones en el campo de la inteligencia artificial. Y es que es ya un hecho que la verdadera (y tan prometida durante décadas) inteligencia artificial está, por fin, llegando.

La cuarta partida se jugará mañana. Estad atentos al canal de Youtube de Google DeepMind.

----------------------------------------------------------
Edito el 15/03/2016 a las 10:09h.

Terminó el torneo: 4 a 1 a favor de la máquina. Se confirma que la IA por fin ha conseguido superar al hombre jugando al juego más complejo que aún quedaba por batir...y esta vez todo fue gracias al uso de redes neuronales artificiales ;).

Partida 1: Lee 0 - 1 AlphaGo (Lee juega con negras)
Partida 2: Lee 0 - 2 AlphaGo (Lee juega con blancas)
Partida 3: Lee 0 - 3 AlphaGo (Lee juega con negras)
Partida 4: Lee 1 - 3 AlphaGo (Lee juega con blancas)
Partida 5: Lee 1 - 4 AlphaGo (Lee juega con negras)

Un gran (aunque aún largo) camino acaba de iniciarse en el campo de la (verdadera) inteligencia artificial.

Un saludo.

jueves, 3 de marzo de 2016

¿Cómo aprende nuestro cerebro?

"[Las neuronas son] células de formas delicadas y elegantes, las misteriosas mariposas del alma, cuyo batir de alas quién sabe si esclarecerá algún día el secreto de la vida mental." (Ramón y Cajal)

Introducción.

Este artículo es una continuación de mi entrada anterior "Las matemáticas de la mente"[2]. Vimos en ese artículo cómo era posible que un simple algoritmo de computación pudiese imitar el modo en que nuestro cerebro aprende a realizar tareas con éxito, simplemente a partir del equivalente computacional de una red neuronal.

Sin embargo, a pesar de que en dicha entrada os comentaba el caso de cómo se puede programar un algoritmo capaz de conseguir literalmente, aprender a jugar al Conecta4 (4 en raya) sin especificar (pre-programar) en ningún momento las reglas del juego; es posible que muchos notasen que aún así, todavía había que pre-procesar la entrada de la red neuronal para ofrecerle a las neuronas (nodos) de la capa de entrada (inputs) qué fichas había en cada casilla del tablero y qué casillas estaban aún libres. Este hecho podía hacer a algunos sospechar de la autonomía real de este programa para aprender de un modo no supervisado a jugar.

Por lo tanto, y con ánimo de solventar este asunto, os voy a presentar un nuevo ejemplo en esta nueva entrada para intentar reforzar así la validez de las conclusiones a las que llegamos al final del artículo "Las matemáticas de la mente"[2]. Haremos ésto mediante un nuevo experimento de aprendizaje automático mediante redes neuronales, pero esta vez; aprovechando el estado del arte teórico que nos ofrece el equipo del departamento de inteligencia artificial de Google DeepMind[4].

En concreto, he dedicado un par de semanas de mi tiempo libre en implementar un muy prometedor algoritmo de aprendizaje por refuerzo (RL según siglas en inglés). Para aquellos interesados técnicamente en el asunto, pueden leer el siguiente paper[1] del que me hecho referencia: "Asynchronous Methods for Deep Reinforcement Learning", publicado a fecha del 4 de febrero de este año 2016, en colaboración con la Universidad de Montreal.

La cuestión fundamental tratada en este paper de Google es que explica el modo en que es posible entrenar una red neuronal artificial para que realice tareas sin supervisión ni pre-programación alguna. Se trata de un proceso end-to-end, mediante el cual el algoritmo accede directamente a los píxeles de la pantalla (simulando el modo en que nosotros obtenemos la información visual desde nuestra retina), y luego convoluciona y post-procesa dicha información sensible en varias capas de nodos (neuronas) internas (simulando el modo en que nuestro cerebro procesa la información obtenida en la retina posteriormente en sucesivas partes de la corteza visual); para terminar tratando dicha información visual en nuevas capas de neuronas que darán lugar finalmente a una respuesta (una acción).

Esto implica que ya no es necesario que nosotros pre-programemos y ofrezcamos como entrada a la red neuronal el estado del entorno (que en el caso del Conecta4 era estado del tablero), sino que es la propia red neuronal la que observa visualmente el entorno (por ejemplo, el tablero), y luego procesa dicha información visual en otras zonas de la misma red de manera autónoma, hasta ofrecer finalmente como salida una determinada acción a realizar.

Y sobra decir que los chicos de Google lo han conseguido (en realidad lo que han logrado es perfeccionar una técnica ya existente en gran medida); han desarrollado un algoritmo capaz de enseñar a una red neuronal artificial a procesar toda la información sensible disponible sobre el entorno de cualquier tarea a realizar, y; conseguir de un modo totalmente autónomo (end-to-end), ¡conseguir una respuesta con habilidades bastante cercanas a las humanas!

Metodología.

En el paper[1] arriba indicado nos explican teóricamente el modo en que es posible implementar un algoritmo de aprendizaje realmente autónomo como el que estamos buscando en un intento de reforzar las conclusiones obtenidas en el anterior artículo[2]. Y lo hacen mediante una detallada explicación, y ofreciendo además un pseudocódigo de guía para el interesado en realizar algún experimento o prueba práctica de lo que proponen. En realidad se ofrecen varias alternativas y variantes de lo que en DeepMind han denominado Deep Q NetWorks, aunque yo me he decantado por utilizar la variante en principio más sencilla de implementar (aunque también es la relativamente menos eficiente). Esto es, el "Asynchronous one-step Q-learning". 

Os dejo a continuación una copia del pseudocódigo ofrecido en el paper, pero aquellos lectores no técnicos no tenéis que preocuparos, continuad adelante sin prestar más atención al mismo:




Configuración experimental.

Para poner a prueba el pseudocódigo, me decidí a aprovechar la librería para desarrollo numérico computacional que desde hace unos meses ofrece el propio Google de acceso gratuito: TensorFlow[3]. En concreto, hice uso de la interfaz Python de la librería para programar mediante esta técnica de aprendizaje por refuerzo una red neuronal artificial capaz de aprender a jugar de manera totalmente autónoma (a partir únicamente de los pixels de la pantalla del ordenador) al clásico juego del Pong (el mítico juego de Atari de la pelotita rebotando en las paredes ;)).

Revisión utilizada del mítico juego del Pong

Utilicé TensorFlow para diseñar una red neuronal artificial de 6 capas: una para recibir los inputs de la imagen del entorno (el estado del juego) en formato RGB (donde cada pixel se representa mediante un número entero que es una combinación para el tono rojo, verde y azul). Estos píxels (simulando al modo en que la retina recoge los fotones en el ojo), se pasan luego a dos capas internas (o, como se las suelen llamar: ocultas -"hidden"-) que convolucionan y pre-procesan esta información visual para facilitar su uso más tarde por parte de las otras dos capas de neuronas, que finalmente procesan la información y devuelven una acción a realizar gracias a una capa de salida (output). Y esta es la red neuronal que se entrena de manera autónoma mediante el código de RL propuesto en el paper.

Como digo, todo se programó en Python usando varios hilos (threads) como requiere el pseudocódigo (ya que este aprendizaje hace uso de un procesamiento asíncrono en paralelo del entrenamiento).

Os dejo a continuación un par de vídeos donde podréis ver gráficamente en vivo cómo se produce este proceso. En un primer vídeo podréis observar como la red neuronal al inicio no se encuentra entrenada (es decir; sus "sinapsis" no están bien balanceadas), por lo que juega a lo loco (la red neuronal es la barra azul de la izquierda) . También veréis cómo se inicia el proceso de entrenamiento en paralelo mediante ensayo y error, gracias al refuerzo que supone la recompensa de ganar una partida, o el castigo que supone perderla (algo similar a lo que nosotros experimentamos como alegría y frustración cuando nos enfrentamos al aprendizaje de una nueva tarea):


Este segundo vídeo muestra la misma red neuronal inicial una vez que sus pesos (sinapsis) han sido bien moduladas por el proceso de aprendizaje. Como se puede observar, el algoritmo ahora es capaz de obtener la imagen (pixels) de la pantalla, "objetivar" lo importante de la misma (la pelota y su posición relativa), y actuar en consecuencia para maximizar el beneficio de sus acciones (ganar partidas):


Resultados.

Los resultados son muy favorables, alcanzando el algoritmo por sí mismo tras el entrenamiento autónomo un nivel de juego muy admirable y equiparable al de una persona. Además, es importante señalar una cuestión técnica: el proceso de aprendizaje se lleva a cabo con esta novedosa técnica propuesta por Google en un simple ordenador personal, sin requerir de grandes estaciones de trabajo distribuidas, y ni siquiera de un hardware específico (como tarjetas GPU). De hecho, con un simple procesador Intel Core i5 he conseguido entrenar en menos de 24 horas lo que hasta hace poco requería de grandes estaciones de trabajo distribuidas usando la técnica conocida como "Gorila" (ver el paper[1] de referencia para más información).

Por si hay algún interesado en probar todo el tinglado, os dejo a continuación copia del código fuente Python [5] que he desarrollado:

#!/usr/bin/env python
import threading
import tensorflow as tf
import cv2
import sys
sys.path.append("Wrapped Game Code/")
import pong_fun as game # Whichever is imported "as game" will be used
import random
import numpy as np
import time

#Shared global parameters
TMAX = 5000000
T = 0
It = 10000
Iasync = 5
THREADS = 12
WISHED_SCORE = 10

GAME = 'pong' # The name of the game being played for log files
ACTIONS = 3 # Number of valid actions
GAMMA = 0.99 # Decay rate of past observations
OBSERVE = 5. # Timesteps to observe before training
EXPLORE = 400000. # Frames over which to anneal epsilon
FINAL_EPSILONS = [0.01, 0.01, 0.05] # Final values of epsilon
INITIAL_EPSILONS = [0.4, 0.3, 0.3] # Starting values of epsilon
EPSILONS = 3

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev = 0.01)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.01, shape = shape)
    return tf.Variable(initial)

def conv2d(x, W, stride):
    return tf.nn.conv2d(x, W, strides = [1, stride, stride, 1], padding = "SAME")

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = "SAME")

def createNetwork():
    # network weights
    W_conv1 = weight_variable([8, 8, 4, 32])
    b_conv1 = bias_variable([32])

    W_conv2 = weight_variable([4, 4, 32, 64])
    b_conv2 = bias_variable([64])

    W_conv3 = weight_variable([3, 3, 64, 64])
    b_conv3 = bias_variable([64])

    W_fc1 = weight_variable([256, 256])
    b_fc1 = bias_variable([256])

    W_fc2 = weight_variable([256, ACTIONS])
    b_fc2 = bias_variable([ACTIONS])

    # input layer
    s = tf.placeholder("float", [None, 80, 80, 4])

    # hidden layers
    h_conv1 = tf.nn.relu(conv2d(s, W_conv1, 4) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)

    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2, 2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)

    h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3, 1) + b_conv3)
    h_pool3 = max_pool_2x2(h_conv3)

    h_pool3_flat = tf.reshape(h_pool3, [-1, 256])

    h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, W_fc1) + b_fc1)

    # readout layer
    readout = tf.matmul(h_fc1, W_fc2) + b_fc2

    return s, readout, W_conv1, b_conv1, W_conv2, b_conv2, W_conv3, b_conv3, W_fc1, b_fc1, W_fc2, b_fc2

def copyTargetNetwork(sess):
    sess.run(copy_Otarget)

def actorLearner(num, sess, lock):
    # We use global shared O parameter vector
    # We use global shared Otarget parameter vector
    # We use global shared counter T, and TMAX constant
    global TMAX, T

    # Open up a game state to communicate with emulator
    lock.acquire()
    game_state = game.GameState()
    lock.release()

    # Initialize network gradients
    s_j_batch = []
    a_batch = []
    y_batch = []

    # Get the first state by doing nothing and preprocess the image to 80x80x4
    lock.acquire()
    x_t, r_0, terminal = game_state.frame_step([1, 0, 0])
    lock.release()
    x_t = cv2.cvtColor(cv2.resize(x_t, (80, 80)), cv2.COLOR_BGR2GRAY)
    s_t = np.stack((x_t, x_t, x_t, x_t), axis = 2)
    aux_s = s_t

    time.sleep(3*num)

    # Initialize target network weights
    copyTargetNetwork(sess)

    epsilon_index = random.randrange(EPSILONS)
    INITIAL_EPSILON = INITIAL_EPSILONS[epsilon_index]
    FINAL_EPSILON =  FINAL_EPSILONS[epsilon_index]
    epsilon = INITIAL_EPSILON

    print "THREAD ", num, "STARTING...", "EXPLORATION POLICY => INITIAL_EPSILON:", INITIAL_EPSILON, ", FINAL_EPSILON:", FINAL_EPSILON 

    # Initialize thread step counter
    t = 0
    score = 0
    while T < TMAX and score < WISHED_SCORE:

        # Choose an action epsilon greedily
        readout_t = O_readout.eval(session = sess, feed_dict = {s : [s_t]})
        a_t = np.zeros([ACTIONS])
        action_index = 0
        if random.random() <= epsilon or t <= OBSERVE:
            action_index = random.randrange(ACTIONS)
            a_t[action_index] = 1
        else:
            action_index = np.argmax(readout_t)
            a_t[action_index] = 1

        # Scale down epsilon
        if epsilon > FINAL_EPSILON and t > OBSERVE:
            epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE

        # Run the selected action and observe next state and reward
        lock.acquire()
        x_t1_col, r_t, terminal = game_state.frame_step(a_t)
        lock.release()
        x_t1 = cv2.cvtColor(cv2.resize(x_t1_col, (80, 80)), cv2.COLOR_BGR2GRAY)
        x_t1 = np.reshape(x_t1, (80, 80, 1))
        aux_s = np.delete(s_t, 0, axis = 2)
        s_t1 = np.append(aux_s, x_t1, axis = 2)

        # Accumulate gradients
        readout_j1 = Ot_readout.eval(session = sess, feed_dict = {st : [s_t1]})
        if terminal:
            y_batch.append(r_t)
        else:
            y_batch.append(r_t + GAMMA * np.max(readout_j1))

        a_batch.append(a_t)
        s_j_batch.append(s_t)

        # Update the old values
        s_t = s_t1
        T += 1
        t += 1
        score += r_t

        # Update the Otarget network
        if T % It == 0:
            copyTargetNetwork(sess)

        # Update the O network
        if t % Iasync == 0 or terminal:
            if s_j_batch:
                # Perform asynchronous update of O network
                train_O.run(session = sess, feed_dict = {
                    y : y_batch,
                    a : a_batch,
                    s : s_j_batch})

            #Clear gradients
            s_j_batch = []
            a_batch = []
            y_batch = []

        # Save progress every 5000 iterations
        if t % 5000 == 0:
            saver.save(sess, 'save_networks_asyn/' + GAME + '-dqn', global_step = t)

        # Print info
        state = ""
        if t <= OBSERVE:
            state = "observe"
        elif t > OBSERVE and t <= OBSERVE + EXPLORE:
            state = "explore"
        else:
            state = "train"

        if terminal:
            print "THREAD:", num, "/ TIME", T, "/ TIMESTEP", t, "/ STATE", state, "/ EPSILON", epsilon, "/ ACTION", action_index, "/ REWARD", r_t, "/ Q_MAX %e" % np.max(readout_t), "/ SCORE", score
            score = 0

    # Save the last state of each thread
    saver.save(sess, 'save_networks_asyn/' + GAME + '-final-' + num)


# We create the shared global networks
# O network
s, O_readout, W_conv1, b_conv1, W_conv2, b_conv2, W_conv3, b_conv3, W_fc1, b_fc1, W_fc2, b_fc2 = createNetwork()

# Training node
a = tf.placeholder("float", [None, ACTIONS])
y = tf.placeholder("float", [None])
O_readout_action = tf.reduce_sum(tf.mul(O_readout, a), reduction_indices=1)
cost_O = tf.reduce_mean(tf.square(y - O_readout_action))
train_O = tf.train.RMSPropOptimizer(0.00025, 0.95, 0.95, 0.01).minimize(cost_O)

# Otarget network
st, Ot_readout, W_conv1t, b_conv1t, W_conv2t, b_conv2t, W_conv3t, b_conv3t, W_fc1t, b_fc1t, W_fc2t, b_fc2t = createNetwork()
copy_Otarget = [W_conv1t.assign(W_conv1), b_conv1t.assign(b_conv1), W_conv2t.assign(W_conv2), b_conv2t.assign(b_conv2), W_conv3t.assign(W_conv3), b_conv3t.assign(b_conv3), W_fc1t.assign(W_fc1), b_fc1t.assign(b_fc1), W_fc2t.assign(W_fc2), b_fc2t.assign(b_fc2)]

# Initialize session and variables
sess = tf.InteractiveSession()
saver = tf.train.Saver()
sess.run(tf.initialize_all_variables())
checkpoint = tf.train.get_checkpoint_state("save_networks_asyn")
if checkpoint and checkpoint.model_checkpoint_path:
    saver.restore(sess, checkpoint.model_checkpoint_path)
    print "Successfully loaded:", checkpoint.model_checkpoint_path

if __name__ == "__main__":
    # Start n concurrent actor threads
    lock = threading.Lock()
    threads = list()
    for i in range(THREADS):
        t = threading.Thread(target=actorLearner, args=(i,sess, lock))
        threads.append(t)

    # Start all threads
    for x in threads:
        x.start()

    # Wait for all of them to finish
    for x in threads:
        x.join()

    print "ALL DONE!!"

Por cierto, que no os engañe lo reducido del código. Detrás tenemos la enorme librería TensorFlow trabajando, y también una librería para Python llamada Pygame ;).

Conclusiones y discusión.

La principal conclusión que me gustaría destacar, es la de que la inteligencia artificial está avanzando de un modo casi exponencial estos últimos años (aunque los medios apenas se hagan eco de ello). Muy en particular, el grupo de IA dentro de Google llamado DeepMind[4] tiene gran parte de culpa. Sus papers de los últimos años son espectaculares, y están rebasando constantemente el estado del arte en casi todos los ámbitos. Y, además, señalar que todos y cada uno de los hitos conseguidos en el ámbito de la IA se están logrando sin excepción al imitarse cada vez mejor (en cuanto a eficiencia y escala) el modo en que la neurociencia nos cuenta que funciona nuestro cerebro. Cuestión que nos permite reflexionar sobre lo siguiente:

Las capacidades cognitivas humanas (y del resto del reino animal) parecen ser, como vemos, producto exclusivo del procesado eléctrico por entre trillones de sinapsis en el cerebro. Esto supone que sería precisamente este procesamiento de información eléctrica entre neuronas el que lograría otorgarnos todas y cada una de nuestras capacidades, sin que exista evidencia empírica alguna de que nada más intervenga en el proceso que origina lo que se entiende por mente: englobando aquí conducta, emociones, sensaciones, etc. Esta afirmación basa su fuerza en tres hechos probados: 1º) Que la moderna neurociencia indica experimentalmente que todo apunta a que las redes neuronales biológicas se sobran para acometer la gama completa cognitiva del hombre, 2º) que no se ha observado empíricamente nada más en el cuerpo humano capaz contribuir a tales procesos, y 3º) que además, por otra parte, al emular este comportamiento neuronal biológico de un modo computacional, se observan cada vez resultados más y más parecidos a los observados en los seres vivos.

Por lo tanto, esto nos permite concluir (gracias a todo lo que ya conocemos sobre las redes neuronales biológicas y artificiales) que:
Nuestra mente, en el fondo, no es más que el fruto de una enorme calculadora digital capaz de ejecutar en paralelo cientos de trillones de operaciones por segundo: operaciones que, por cierto, se reducen a meras sumas de potenciales eléctricos.

Referencias.

[1] http://arxiv.org/pdf/1602.01783v1.pdf "Asynchronous Methods for Deep Reinforcement Learning" (Google DeepMind) (2016)
[2] http://quevidaesta2010.blogspot.com.es/2016/02/las-matematicas-de-la-mente.html
[3] https://www.tensorflow.org/ (librería de código abierto ofrecida por Google)
[4] https://deepmind.com/publications.html (web del equipo de desarrollo Google DeepMind)
[5] https://github.com/Zeta36/Asynchronous-Methods-for-Deep-Reinforcement-Learning (repositorio en GitHub donde he subido todo el código fuente completo que he implementado en Python para esta entrada)