logo

Dot CSV

Inteligencia Artificial, Tecnología, Ciencia y Futuro! Bienvenidos a la 4ª Revolución Industrial 🚀 Inteligencia Artificial, Tecnología, Ciencia y Futuro! Bienvenidos a la 4ª Revolución Industrial 🚀

Transcribed podcasts: 213
Time transcribed: 5d 22h 50m 3s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

Este vídeo está patrocinado por la Universitat Politécnica de València.
Y en el caso de hoy vamos a hablar de Pac-Man. Pac-Man, el arcade de toda la vida, el clásico,
el bueno de Pac, paquito para los amigos, y al final un juego el que posiblemente todos
hayamos jugado en algún momento. Y que bueno, pues que no deja de ser eso, un juego. Un juego
que podemos tomar y podemos desacoplar por sus diferentes niveles de desarrollo en tres capas
muy diferenciadas. La primera de ellas podría ser la capa de modelo donde tendríamos almacenada
todas las variables internas que hacen funcionar al juego. La posición del jugador, la estructura
del mapa, pues todos los elementos que sean necesarios tener en memoria. Luego tendríamos
una capa de control que sería pues donde codificaríamos todas las lógicas internas del juego. Las
dinámicas, las físicas, cómo se relaciona un jugador con el otro, cómo sumamos puntos si comemos
una fruta. Y finalmente tenemos una capa que sería la vista, la capa de renderización, el cómo se va
a visualizar todo esto que estamos haciendo en las capas inferiores. Esta forma de desacoplar un
software seguramente a más de uno le sonará. Y es que aquí estamos siguiendo el paradigma del
modelo vista controlador, o en inglés el model view control. De esto vamos a hablar en el vídeo de
hoy pero con una diferencia. Y es que hoy realmente no venimos a hablar de cómo se estructura un
videojuego, sino de cómo podemos conseguir tener codificados cada uno de estos niveles dentro de
una red neuronal. Hoy venimos a hablar de Game Gam, un trabajo que ha publicado Nvidia y que lo
que permite es que una red neuronal pueda aprender completamente todo el motor de videojuegos que hace
funcionar a un juego como Pac-Man. Un trabajo que como veremos más adelante pues conecta directamente
con una publicación que a mí me encanta y que realmente a mí me ha servido para poder tener un
mejor entendimiento de cómo funciona todo el campo del deep learning y cómo se conectan diferentes
módulos que a priori pues parece que trabajarían de manera independiente. Y es que en realidad del
sistema de hoy se trata de la combinación de diferentes módulos basados en redes neuronales.
En este caso cada módulo se van a encargar de aprender una tarea diferente que van a permitir
que podamos implementar todo nuestro motor de videojuego. Estas tareas a resolver pues tendrán
que incluir un controlador, un renderizador y una memoria, pero claro todo neuronal. Vamos por partes.
El primer módulo que vamos a analizar es el de generación de gráficos, un módulo donde tendremos
algún tipo de arquitectura basada en redes neuronales que tomará como entrada toda la
variable interna del juego, todo el estado actual del juego y lo que tendrá que generar como salida
será lo que visualizaremos en pantalla, es decir, todos los píxeles que representarían el estado
interno del juego, un proceso conocido como renderización. Acabo de tener un flashback.
Bueno, ¿cómo conseguimos hacer esto con redes neuronales? Pues a ver, los suscriptores habituales
de este canal ya sabrán parte de la respuesta y es que ya son muchas las veces que hemos hablado de
cómo al igual que podemos tener una red neuronal que es capaz de tomar una imagen y la puede
procesar y comprimir y puede aprender cuáles son los patrones que la conforman, pues podemos
tener una arquitectura como esta invertida que para una entrada comprimida que represente,
por ejemplo, el estado interno del juego, pues puede aprender a generar una imagen que
represente visualmente esta información. Claro, el entrenar de tesero a esta red para que aprenda
a generar imágenes de pantalla puede ser un objetivo bastante complejo, sobre todo en este
caso donde esta red no actúa de manera solitaria, sino que tiene que aprender conjuntamente mientras
los otros módulos también están aprendiendo. Es decir, esto sería algo así como si yo te dijera
que tú tienes que aprender a pintar cuadros, pero que en este caso las instrucciones de lo que tienes
que pintar te las voy a dar yo codificadas en chino y que tú al mismo tiempo pues tienes que
estar aprendiendo chino y que solamente te voy a evaluar que también hablas chino a partir de la
calidad de tus cuadros, lo cual hace que todo el proceso sea bastante lioso y que la verdad que
este ejemplo sea un poquito de mierda, pero bueno, creo que se entiende. La idea aquí sería que si
tú tuvieras que hacer esto de aprender chino para aprender a pintar cuadros y evaluar tu calidad
del chino a partir del resultado de tus cuadros, obviamente este proceso sería mucho más sencillo
si tú ya de partida supieras pintar de alguna manera, no exactamente lo que se te pide, pero
al menos sepas cómo generar un cuadro. Es por eso que en esta situación pues muchas veces se intenta
dar un empujoncito al sistema haciendo efectivamente esto, dejando que la propia red aprenda a generar,
aprenda a pintar como serían estas visualizaciones. Para hacer eso hacemos lo siguiente, tomamos una
de estas redes que comprime información y tomamos otra de estas que aprenden a descomprimirlas y la
juntamos. Cuando la juntamos lo que podemos hacer es coger una imagen, dejar que la red aprenda a
comprimirla y a descomprimirla y luego comparamos si el resultado de entrada y el resultado de
salida se parece. A esta arquitectura se le conoce como autoencoder y haciendo esto por un número
alto de imágenes pues lo que conseguimos es que al final estos dos módulos aquí aprendan a hacer
su tarea, a partir de una imagen a comprimirla y a partir de esta información comprimida a volver
a generarla. Con esto ya tendríamos entrenado estos dos módulos aquí, donde este pues realmente no
nos hace falta, así que ya te llamaremos hasta luego. Pero bueno, este otro de aquí sí estará
entrenado para poder generar imágenes, así que ya lo podemos integrar en todo nuestro sistema para
así facilitar el aprendizaje de nuestro motor de videojuegos. Ojo, sabe pintar, pero todavía no
sabe cómo pintar aquello que se le pida porque todavía el sistema no sabe chino. Madre mía,
vaya ejemplo. Y como digo esto no es nuevo en el canal, de arquitecturas encoder decoder ya hemos
hablado por ejemplo en el pasado con pics to pics, del cual incluso tenéis un tutorial para saber
cómo programarlo. Hemos hablado también de esto cuando vemos aquella inteligencia artificial que
era capaz de decodificar tus pensamientos y para que vean que esto no se limita solamente a imágenes,
también hace un par de semanas comentamos esto mismo en el canal de Alvinch, cuando hablamos sobre
Jukebox, que es una inteligencia artificial capaz de generar música artificial y donde se hacía uso
de un autoencoder para codificar y decodificar diferentes canciones para que se aprendiera los
diferentes patrones que conforman una canción y luego utilizar estos patrones para ahora sí generar
nueva música. Esta sería la idea intuitiva de cómo funcionaría este módulo renderizador,
aunque es cierto que en este trabajo este módulo esta pieza pues tiene unos cuantos pasos más que
hacen que sea un poco más complejo de entender y a los cuales nos vamos a entrar en detalle en este
trabajo. Simplemente quiero que sepan que en este caso el módulo renderizador sí hace una tarea
que es muy interesante y que va a favorecer el aprendizaje del resto de módulos del sistema y
es que en este caso el sistema sabe cómo poder renderizar los elementos que son dinámicos en
pantalla, es decir que se están moviendo y se están actualizando frente a aquellos elementos
que son estáticos como por ejemplo el fondo, algo que va a ser de muchísima utilidad como digo en
el resto de fases entre ellas la fase de control que pasamos a ver ahora. Las dinámicas de un
videojuego vendrían a representar pues la dinámica de un videojuego, es decir el cómo
va a evolucionar la ejecución del sistema, el cómo vamos a ir actualizando los estados internos de
nuestro simulador, en este caso por ejemplo si yo ejecuto una acción de entrada cómo debería
de moverse el personaje hacia arriba, hacia debajo, qué movimiento es legal y cuál no,
puede Pacman atravesar un muro de mi laberinto o por ejemplo cuál es la relación entre dos
jugadores, si por ejemplo Pacman se encuentra con un fantasma tiene que perseguir Pacman al fantasma
o el fantasma tiene que perseguir a Pacman o cómo funciona este maldito juego. Bueno,
cómo conseguimos que una red neuronal aprenda a predecir cuáles son todas estas dinámicas,
pues para esto de nuevo volvemos a coger elementos que ya conocemos, en este caso queremos aprender
dinámicas, cosas que van a ir evolucionando en el tiempo, es decir que para predecir cuál será el
siguiente estado no estaría nada mal conocer la información de lo que ha ocurrido en varios
fotogramas previos, es por eso que este módulo viene implementado con una red neuronal recurrente,
en este caso con una red LSTM, que además de recibir toda la variable de entrada también
tendrá en cuenta lo que se ha analizado en periodos anteriores. ¿Y cuáles son estas variables de
entrada? Pues mira, en este caso obviamente una de las variables que tendrá que recibir este
sistema tendrá que ser las acciones dadas por el jugador, aquel botón que hayas apretado en tu
mando, aquel joystick que hayas movido a la derecha, todas estas acciones tienen que estar
registradas en un vector que le pasaremos como input a este sistema. No sólo esto, también este
sistema recibirá entrada de los otros dos módulos que tenemos en todo nuestro motor de videojuego,
por una parte recibirá como input la imagen del fotograma anterior que ha predicho el módulo de
renderización, y por otra parte también recibirá el estado interno del módulo de memoria que todavía
no hemos pasado a ver. Con esto el objetivo de este módulo será coger toda esta información y
analizarla, teniendo en cuenta también los estados anteriores, porque es una red recurrente,
y con esto predecir un resumen, sacar una conclusión de cuál es el estado actual del
juego, actualizando así su dinámica. Una información que obviamente va a ser muy relevante para
actualizar tanto el módulo de memoria como para renderizar el siguiente fotograma. Con esto ya
tendríamos dos de tres, tendríamos el módulo de renderización y el módulo de control de dinámicas,
pero ahora faltaría pasar al punto que considero yo más interesante en todo este sistema.
Y es que este último módulo es quizás el más interesante y el más novedoso de cara al canal,
ya que nunca nos hemos parado a hablar de las memorias neuronales, algo que primero nos obliga
a hablar de la importancia de tener una memoria en nuestra ejecución. Imagínate que tu tarea es
encontrar un tesoro, un tesoro para el cual yo te voy a dar exactamente todas las instrucciones
que tienes que ejecutar para poder encontrarlo. Gira por el tercer árbol, sube la montaña con
forma de flecha, abordea el lago por el flanco izquierdo, todas estas cosas. Tú te lanzarás a
resolver esta tarea y la podrás resolver en la medida de lo posible que puedas retener toda esta
información que yo te he dado, que la memorices. Pero claro, no sería mucho más sencillo el poder
resolver esta tarea si pudieras almacenar toda esta información en algún tipo de soporte de memoria
externo, el por ejemplo poder apuntar todas las instrucciones en una libreta y ya con esto poder
ir a la búsqueda del tesoro sin tener que estar ocupando espacio en tu cabeza. Con esto ya podrías
dedicar el 100% de tu carga mental a poder ejecutar las instrucciones de manera inteligente y no estar
intentando retener una información que posiblemente con el paso del tiempo, pues poco a poco se vaya
deteriorando. Pues esta misma idea se traslada al motor de videojuegos. En este caso hay aspectos
como por ejemplo la forma de laberinto en el que juega Pacman que deberían de mantenerse consistente
durante toda la partida y que por tanto pues interesa tenerlo guardados en algún tipo de
soporte de memoria en el que se pueda preservar. En caso contrario de no contar con una memoria,
pues tendría que ser de alguna manera el módulo de dinámicas o el módulo de renderización quien
tendría que contener en su cabeza, en sus parámetros, contenida toda esta información de
cómo es la forma del laberinto, produciendo posiblemente inconsistencias temporales que
hagan que el motor de videojuegos no funcione correctamente. Y ojo porque aquí no estamos
hablando de crear algún tipo de mecanismo donde cada cierto tiempo guardemos un archivo en nuestro
disco duro que se llame laberinto.data y que podamos cargar a nuestra conveniencia. No,
aquí estamos hablando de crear una simbiosis entre una memoria y una red neuronal, un mecanismo por
el cual pues todos los procesos de lectura y escritura, toda la búsqueda de posiciones en memoria,
la sacada y entrada de elementos, todo eso esté implementado con los mismos mecanismos que hacen
funcionar a una red neuronal, vectores y estructuras diferenciables. Todo esto con el objetivo de que
nuestra arquitectura al completo cuente con un sistema de memoria que no sólo pueda utilizar,
sino que también pueda aprender a utilizar. En este caso no estamos especificando un sistema
de memoria que yo como programador tenga que especificarla al sistema como lo tiene que utilizar
en cada momento, sino que en este caso le estamos facilitando la arquitectura de deep learning,
un sistema de almacenamiento que podrá utilizar en su favor para escribir o sacar información como
él quiera de cara a poder resolver su tarea, es decir, puede aprender a usar la memoria. Estos
sistemas toman el nombre de neural tutoring machine y en este caso otorgan a las redes
neuronales la capacidad de la memorización, algo que es tan fundamental en el aprendizaje de una
tarea como lo ha sido el uso de sistemas de memoria tradicionales en el campo de la computación.
Y en el caso de Pacman que se almacena en memoria? Pues bueno, recuerdas que antes te he dicho que
tenemos la capacidad de poder desacoplar los elementos dinámicos de los elementos estáticos
del juego? Pues en este caso estos elementos estáticos que no deberían ir variando en el
paso del tiempo son los que vamos a mantener almacenados en memoria, algo que en el caso de
Pacman pues principalmente es el propio laberinto del juego. Aquí cuando el usuario realiza una
acción, esto va a producir un movimiento del personaje de Pacman, haciendo que se muestre una
región u otra del mapa. Y es por eso que este vector de acciones es una de las variables de
entrada que recibe este módulo de memoria en conjunto con el output del módulo de dinámicas.
Todo esto para que en conjunto se pueda decidir a qué celda de memoria tenemos que acceder para
sacar así la región del mapa que se tendrá que visualizar en el módulo de renderización.
Lo estamos viendo todo en conjunto? Fijaros como en este caso lo único que hemos hecho ha sido
conectar distintos módulos de los cuales nosotros creemos que van a cumplir una función determinada
en la tarea de aprender el juego de Pacman. Pero bueno todavía faltaría que exista un entrenamiento
y que vayamos evaluando las diferentes tareas que este sistema tiene que cumplir. Esto se consigue
con estos módulos y también con el uso de las funciones de error adecuadas. Funciones de error
que van a ir evaluando si el aprendizaje de toda la ejecución del juego pues está realizando de
manera correcta. En este caso hay funciones muy variadas que van evaluando si los fotogramas que
se generan son realistas, si hay una consistencia temporal entre la secuencia de fotogramas que se
genera, si hay una preservación de los elementos que deberían de ser estáticos y por tanto no
deberían ir cambiando durante la ejecución del juego. Es decir un conjunto de funciones que al
final nos van a ir evaluando y delimitando el aprendizaje de nuestro juego. Y con todo esto ya
conectado tenemos a nuestro sistema, a Gengar, que es alucinante porque básicamente para su
entrenamiento lo único que necesitamos es tener a un jugador que vayamos registrando cuáles son
todas las acciones que realiza en el juego y cuál es el output que se muestra en pantalla, cuáles
son las visualizaciones de los pixeles en pantalla. Con esta información Gengar es capaz de ir
entendiendo no solamente cómo generar nuevos fotogramas o cómo condicionar esto a las acciones
que hace el jugador, sino que también va a ir aprendiendo toda la lógica interna del juego
de Pac-Man. Que Pac-Man no puede atravesar paredes en el laberinto, que coger frutas suma puntos,
que a lo mejor este punto de aquí que está más marcado te va a permitir de repente ir a perseguir
los fantasmas que se van a poner de color azul. Todo el motor de videojuegos codificado dentro
de una red neuronal. Algo que es impresionante y que no solamente está acotado al juego de Pac-Man,
sino que lo podríamos trasladar a otros tipos de juegos que también podrían ser aprendidos. Un
sistema que tiene una utilidad bastante interesante y que realmente ya exploraba un trabajo anterior
que se llama World Models. Un trabajo del cual sacan mucha inspiración en este paper y realmente
es el artículo que recomendaría todo el mundo que fuera a leer. No solamente por ser el primero que
plantea toda esta estructura de crear simuladores aprendidos en redes neuronales que conectan
diferentes módulos, sino porque también es una lectura súper sencilla de leer. Es quizás uno de
los materiales divulgativos de un trabajo científico que más trabajados he visto dentro del campo de la
inteligencia artificial. De hecho si queréis explorar más este trabajo tenéis suerte porque
justamente fue este proyecto el primero que analizamos dentro de la cien horas de Machine Learning
en los directos que estamos haciendo en Twitch y tenéis disponible en el canal secundario dos
horas donde vamos repasando y les voy explicando todo este artículo sobre World Models que a lo
mejor les podría interesar. En este caso la utilidad de estos sistemas sería la de poder
aprender automáticamente perfectos entornos de simulación donde poder entrenar de manera más
eficiente a algoritmos de aprendizaje reforzados que luego puedan ser trasladados al mundo real.
Y con esto llegamos al final del vídeo, un vídeo que ha sido un poco más tenso, ha sido más técnico,
pero bueno quería analizar este paper con ustedes porque quizás les permita tener una visión de
cómo los algoritmos, las arquitecturas más complejas que se van publicando realmente son
la concatenación de arquitecturas mucho más sencillas y que con esto pues puedan tener un
mejor entendimiento de cómo funciona todo esto. Si queréis apoyar este contenido, contenido de
inteligencia artificial Deep Learning en YouTube y en Twitch podéis acudir a mi Patreon, podéis
apoyar a través de Patreon y que así este proyecto siga creciendo y también podéis apoyarme a
través de Twitch donde ya sabéis que cada vez más voy a estar haciendo más contenido que también
les podría interesar. Por mi parte nada más, nos vemos con más inteligencia artificial en el próximo vídeo.