Introducción a Deep Q-Learning: juguemos a Doom

Este artículo es parte del curso de aprendizaje de refuerzo profundo con Tensorflow? ️. Consulta el plan de estudios aquí.

La última vez, aprendimos sobre Q-Learning: un algoritmo que produce una tabla Q que un agente usa para encontrar la mejor acción a tomar en un estado.

Pero como veremos, producir y actualizar una Q-table puede volverse ineficaz en entornos de grandes espacios estatales.

Este artículo es la tercera parte de una serie de publicaciones de blog sobre el aprendizaje por refuerzo profundo. Para obtener más información y recursos, consulte el programa del curso.

Hoy crearemos una red neuronal Deep Q. En lugar de utilizar una tabla Q, implementaremos una red neuronal que toma un estado y aproxima los valores Q para cada acción en función de ese estado.

¡Gracias a este modelo, podremos crear un agente que aprenda a jugar a Doom!

En este artículo aprenderá:

  • ¿Qué es Deep Q-Learning (DQL)?
  • ¿Cuáles son las mejores estrategias para usar con DQL?
  • Cómo manejar el problema de la limitación temporal
  • Por qué usamos la reproducción de experiencia
  • ¿Cuáles son las matemáticas detrás de DQL?
  • Cómo implementarlo en Tensorflow

Añadiendo 'Deep' a Q-Learning

En el último artículo creamos un agente que juega a Frozen Lake gracias al algoritmo Q-learning.

Implementamos la función Q-learning para crear y actualizar una Q-table. Piense en esto como una "hoja de trucos" para ayudarnos a encontrar la recompensa futura máxima esperada de una acción, dado un estado actual. Esta fue una buena estrategia; sin embargo, no es escalable.

Imagínese lo que vamos a hacer hoy. Crearemos un agente que aprende a jugar a Doom. Doom es un gran entorno con un espacio de estados gigantesco (millones de estados diferentes). Crear y actualizar una Q-table para ese entorno no sería eficaz en absoluto.

La mejor idea en este caso es crear una red neuronal que aproximará, dado un estado, los diferentes valores Q para cada acción.

¿Cómo funciona Deep Q-Learning?

Esta será la arquitectura de nuestro Deep Q Learning:

Esto puede parecer complejo, pero explicaré la arquitectura paso a paso.

Nuestra red neuronal Deep Q toma una pila de cuatro fotogramas como entrada. Estos pasan a través de su red y generan un vector de valores Q para cada acción posible en el estado dado. Necesitamos tomar el mayor valor Q de este vector para encontrar nuestra mejor acción.

Al principio, el agente lo hace realmente mal. Pero con el tiempo, comienza a asociar marcos (estados) con las mejores acciones para realizar.

Pieza de preprocesamiento

El preprocesamiento es un paso importante. Queremos reducir la complejidad de nuestros estados para reducir el tiempo de cálculo necesario para la formación.

Primero, podemos aplicar una escala de grises a cada uno de nuestros estados. El color no aporta información importante (en nuestro caso, solo necesitamos encontrar al enemigo y matarlo, y no necesitamos color para encontrarlo). Este es un ahorro importante, ya que reducimos nuestros canales de tres colores (RGB) a 1 (escala de grises).

Luego, recortamos el marco. En nuestro ejemplo, ver el techo no es realmente útil.

Luego reducimos el tamaño del marco y apilamos cuatro subcuadros juntos.

El problema de la limitación temporal

Arthur Juliani da una explicación asombrosa sobre este tema en su artículo. Tiene una idea inteligente: usar redes neuronales LSTM para manejar el problema.

Sin embargo, creo que es mejor que los principiantes usen marcos apilados.

La primera pregunta que puede hacer es ¿por qué apilamos marcos juntos?

Apilamos marcos porque nos ayuda a manejar el problema de la limitación temporal.

Tomemos un ejemplo, en el juego de Pong. Cuando vea este marco:

¿Puedes decirme adónde va la pelota?

No, ¡porque un fotograma no es suficiente para tener una sensación de movimiento!

Pero, ¿y si agrego tres marcos más? Aquí puedes ver que la pelota va hacia la derecha.

Eso es lo mismo para nuestro agente de Doom. Si le damos solo un cuadro a la vez, no tiene idea de movimiento. ¿Y cómo puede tomar una decisión correcta si no puede determinar dónde y qué tan rápido se mueven los objetos?

Usar redes de convolución

Los fotogramas son procesados ​​por tres capas de convolución. Estas capas le permiten aprovechar las relaciones espaciales en las imágenes. Pero también, debido a que los marcos se apilan juntos, puede aprovechar algunas propiedades espaciales en esos marcos.

Si no está familiarizado con la convolución, lea este excelente artículo intuitivo de Adam Geitgey.

Cada capa de convolución utilizará ELU como función de activación. Se ha demostrado que ELU es una buena función de activación para capas de convolución.

Usamos una capa completamente conectada con la función de activación ELU y una capa de salida (una capa completamente conectada con una función de activación lineal) que produce la estimación del valor Q para cada acción.

Reproducción de experiencias: hacer un uso más eficiente de la experiencia observada

La repetición de experiencias nos ayudará a manejar dos cosas:

  • Evite olvidar experiencias anteriores.
  • Reduce correlations between experiences.

I will explain these two concepts.

This part and the illustrations were inspired by the great explanation in the Deep Q Learning chapter in the Deep Learning Foundations Nanodegree by Udacity.

Avoid forgetting previous experiences

We have a big problem: the variability of the weights, because there is high correlation between actions and states.

Remember in the first article (Introduction to Reinforcement Learning), we spoke about the Reinforcement Learning process:

At each time step, we receive a tuple (state, action, reward, new_state). We learn from it (we feed the tuple in our neural network), and then throw this experience.

Our problem is that we give sequential samples from interactions with the environment to our neural network. And it tends to forget the previous experiences as it overwrites with new experiences.

For instance, if we are in the first level and then the second (which is totally different), our agent can forget how to behave in the first level.

As a consequence, it can be more efficient to make use of previous experience, by learning with it multiple times.

Our solution: create a “replay buffer.” This stores experience tuples while interacting with the environment, and then we sample a small batch of tuple to feed our neural network.

Think of the replay buffer as a folder where every sheet is an experience tuple. You feed it by interacting with the environment. And then you take some random sheet to feed the neural network

This prevents the network from only learning about what it has immediately done.

Reducing correlation between experiences

We have another problem — we know that every action affects the next state. This outputs a sequence of experience tuples which can be highly correlated.

If we train the network in sequential order, we risk our agent being influenced by the effect of this correlation.

By sampling from the replay buffer at random, we can break this correlation. This prevents action values from oscillating or diverging catastrophically.

It will be easier to understand that with an example. Let’s say we play a first-person shooter, where a monster can appear on the left or on the right. The goal of our agent is to shoot the monster. It has two guns and two actions: shoot left or shoot right.

We learn with ordered experience. Say we know that if we shoot a monster, the probability that the next monster comes from the same direction is 70%. In our case, this is the correlation between our experiences tuples.

Let’s begin the training. Our agent sees the monster on the right, and shoots it using the right gun. This is correct!

Then the next monster also comes from the right (with 70% probability), and the agent will shoot with the right gun. Again, this is good!

And so on and on…

The problem is, this approach increases the value of using the right gun through the entire state space.

And if our agent doesn’t see a lot of left examples (since only 30% will probably come from the left), our agent will only finish by choosing right regardless of where the monster comes from. This is not rational at all.

We have two parallel strategies to handle this problem.

First, we must stop learning while interacting with the environment. We should try different things and play a little randomly to explore the state space. We can save these experiences in the replay buffer.

Then, we can recall these experiences and learn from them. After that, go back to play with updated value function.

As a consequence, we will have a better set of examples. We will be able to generalize patterns from across these examples, recalling them in whatever order.

This helps avoid being fixated on one region of the state space. This prevents reinforcing the same action over and over.

This approach can be seen as a form of Supervised Learning.

We’ll see in future articles that we can also use “prioritized experience replay.” This lets us present rare or “important” tuples to the neural network more frequently.

Our Deep Q-Learning algorithm

First a little bit of mathematics:

Remember that we update our Q value for a given state and action using the Bellman equation:

In our case, we want to update our neural nets weights to reduce the error.

The error (or TD error) is calculated by taking the difference between our Q_target (maximum possible value from the next state) and Q_value (our current prediction of the Q-value)

Initialize Doom Environment EInitialize replay Memory M with capacity N (= finite capacity)Initialize the DQN weights wfor episode in max_episode: s = Environment state for steps in max_steps: Choose action a from state s using epsilon greedy. Take action a, get r (reward) and s' (next state) Store experience tuple  in M s = s' (state = new_state) Get random minibatch of exp tuples from M Set Q_target = reward(s,a) + γmaxQ(s') Update w = α(Q_target - Q_value) * ∇w Q_value

There are two processes that are happening in this algorithm:

  • We sample the environment where we perform actions and store the observed experiences tuples in a replay memory.
  • Select the small batch of tuple random and learn from it using a gradient descent update step.

Implementemos nuestra red neuronal Deep Q

Hicimos un video donde implementamos un agente de Deep Q-learning con Tensorflow que aprende a jugar Atari Space Invaders? ️ ?.

Ahora que sabemos cómo funciona, implementaremos nuestra Deep Q Neural Network paso a paso. Cada paso y cada parte del código se explica directamente en el cuaderno de Jupyter vinculado a continuación.

Puede acceder a él en el repositorio del curso de aprendizaje de refuerzo profundo.

¡Eso es todo! Acabas de crear un agente que aprende a jugar a Doom. ¡Increíble!

No olvide implementar cada parte del código usted mismo. Es muy importante intentar modificar el código que te di. Intente agregar épocas, cambiar la arquitectura, agregar valores Q fijos, cambiar la tasa de aprendizaje, usar un entorno más difícil (como Health Gathering)… y así sucesivamente. ¡Diviértase!

En el próximo artículo, discutiré las últimas mejoras en Deep Q-learning:

  • Valores Q fijos
  • Prioritized Experience Replay
  • Double DQN
  • Dueling Networks

But next time we’ll work on Policy Gradients by training an agent that plays Doom, and we’ll try to survive in an hostile environment by collecting health.

If you liked my article, please click the ? below as many time as you liked the article so other people will see this here on Medium. And don’t forget to follow me!

If you have any thoughts, comments, questions, feel free to comment below or send me an email: [email protected], or tweet me @ThomasSimonini.

Keep learning, stay awesome!

Deep Reinforcement Learning Course with Tensorflow ?️

? Syllabus

? Video version

Part 1: An introduction to Reinforcement Learning

Part 2: Diving deeper into Reinforcement Learning with Q-Learning

Part 3: An introduction to Deep Q-Learning: let’s play Doom

Part 3+: Improvements in Deep Q Learning: Dueling Double DQN, Prioritized Experience Replay, and fixed Q-targets

Part 4: An introduction to Policy Gradients with Doom and Cartpole

Part 5: An intro to Advantage Actor Critic methods: let’s play Sonic the Hedgehog!

Part 6: Proximal Policy Optimization (PPO) with Sonic the Hedgehog 2 and 3

Part 7: Curiosity-Driven Learning made easy Part I