En este artículo aprenderemos qué es el aprendizaje por refuerzo, lo más novedoso y ambicioso a día de hoy en Inteligencia artificial, veremos cómo funciona, sus casos de uso y haremos un ejercicio práctico completo en Python: una máquina que aprenderá a jugar al pong sóla, sin conocer las reglas ni al entorno.
Nuestra Agenda
Los temas que veremos incluyen:
- ¿Qué es el Reinforcement Learning?
- Diferencias con los clásicos
- Componentes
- Casos de Uso
- Y los videojuegos?
- Cómo funciona el RL?
- premios y castigos
- fuerza bruta
- Q-Learning
- Ecuación de Bellman
- Explorar vs Explotar
- El juego del Pong en Python
- Clase Agente
- Clase Environment
- El juego
- La tabla de Políticas
- Conclusiones
- Recursos Adicionales
Comencemos!!
¿Qué es el Aprendizaje por Refuerzo?
Seguramente ya conocerás las 2 grandes áreas de aprendizaje tradicional del Machine Learning, el aprendizaje supervisado y el aprendizaje no supervisado. Parece difícil que aquí hubiera espacio para otras opciones; sin embargo sí la hay y es el Aprendizaje por refuerzo. En aprendizaje por refuerzo (ó Reinforcement Learning en inglés) no tenemos una “etiqueta de salida”, por lo que no es de tipo supervisado y si bien estos algoritmos aprenden por sí mismos, tampoco son de tipo no supervisado, en donde se intenta clasificar grupos teniendo en cuenta alguna distancia entre muestras.
Si nos ponemos a pensar, los problemas de ML supervisados y no supervisados son específicos de un caso de negocio en particular, sea de clasificación ó predicción, están muy delimitados, por ejemplo, clasificar “perros ó gatos“, ó agrupar “k=5” clusters. En contraste, en el mundo real contamos con múltiples variables que por lo general se interrelacionan y que dependen de otros casos de negocio y dan lugar a escenarios más grandes en donde tomar decisiones. Para conducir un coche no basta una inteligencia que pueda detectar un semáforo en rojo, verde ó amarillo; tendremos muchísimos factores -todos a la vez- a los que prestar atención: a qué velocidad vamos, estamos ante una curva?, hay peatones?, es de noche y debemos encender las luces?.
Una solución sería tener múltiples máquinas de ML supervisadas y que interactúan entre si -y esto no estaría mal- ó podemos cambiar el enfoque… Y ahí aparece el Reinforcement Learning (RL) como una alternativa, tal vez de las más ambiciosas en las que se intenta integrar el Machine Learning en el mundo real, sobre todo aplicado a robots y maquinaria industrial.
El Reinforcement Learning entonces, intentará hacer aprender a la máquina basándose en un esquema de “premios y castigos” -cómo con el perro de Pablov- en un entorno en donde hay que tomar acciones y que está afectado por múltiples variables que cambian con el tiempo.
Diferencias con “los clásicos”
En los modelos de Aprendizaje Supervisado (o no supervisado) como redes neuronales, árboles, knn, etc, se intenta “minimizar la función coste”, reducir el error.
En cambio en el RL se intenta “maximizar la recompensa“. Y esto puede ser, a pesar de a veces cometer errores ó de no ser óptimos.
Componentes del RL
El Reinforcement Learning propone un nuevo enfoque para hacer que nuestra máquina aprenda, para ello, postula los siguientes 2 componentes:
- el Agente: será nuestro modelo que queremos entrenar y que aprenda a tomar decisiones.
- Ambiente: será el entorno en donde interactúa y “se mueve” el agente. El ambiente contiene las limitaciones y reglas posibles a cada momento.
Entre ellos hay una relación que se retroalimenta y cuenta con los siguientes nexos:
- Acción: las posibles acciones que puede tomar en un momento determinado el Agente.
- Estado (del ambiente): son los indicadores del ambiente de cómo están los diversos elementos que lo componen en ese momento.
- Recompensas (ó castigos!): a raíz de cada acción tomada por el Agente, podremos obtener un premio ó una penalización que orientarán al Agente en si lo está haciendo bien ó mal.
Entonces, la “foto final” nos queda así:
En un primer momento, el agente recibe un estado inicial y toma una acción con lo cual influye é interviene en el ambiente. Esto está muy bien, pues es muy cierto que cuando tomamos decisiones en el mundo real lo estamos modificando, ¿no?. Y esa decisión tendrá sus consecuencias: en la siguiente iteración el ambiente devolverá al agente el nuevo estado y la recompensa obtenida. Si la recompensa es positiva estaremos reforzando ese comportamiento para el futuro. En cambio si la recompensa es negativa lo estaremos penalizando, para que ante la misma situación el agente actúe de manera distinta. El esquema en el que se apoya el Reinforcement Learning es en el de Proceso de Decisión de Markov.
Casos de Uso del Aprendizaje por Refuerzo
El aprendizaje por refuerzo puede ser usado en robots, por ejemplo en brazos mecánicos en donde en vez de enseñar instrucción por instrucción a moverse, podemos dejar que haga intentos “a ciegas” e ir recompensando cuando lo hace bien.
También puede usarse en ambientes que interactúan con el mundo real, como en otro tipo de maquinaria industrial y para el mantenimiento predictivo, pero también en el ambiente financiero, por ejemplo para decidir cómo conformar una cartera de inversión sin intervención humana.
Otro caso de uso que está ganando terreno es el de usar RL para crear “webs personalizadas” para cada internauta. Y si lo piensas… tiene algo de sentido tomar el concepto de “premiar” al algoritmo si acierta con las sugerencias que hace al usuario si hace clic ó penalizar al modelo si sus recomendaciones no le son de utilidad.
También se utiliza el Reinforcement Learning para entrenar sistemas de navegación de coches, drones ó aviones.
Y los Videojuegos? que pintan en todo esto?
Los videojuegos suelen ser ejemplos del uso de RL, ¿porque? te preguntarás. Pues porque los videojuegos son un entorno YA programado en el que se está simulando un ambiente y en el que ocurren eventos a la vez. Por lo general el jugador es el agente que debe decidir qué movimientos hacer. En el Starcraft tenemos ejércitos enemigos movilizados e intentando aniquilarnos, hay que desplazar distintas unidades que tienen variadas cualidades y hay que hacerlo rápido, atacar, defender, conquistar. ¿Cómo haríamos esto con un modelo de ML tradicional? es suficiente una sola red neuronal? muchas? cómo interactúan?. Pero sobre todo… ¿cómo crearíamos el grupo de “etiquetas de salida” para entrenar a la red, ante un juego imprevisible? Estamos diciendo que hay cientos de miles de combinaciones de salidas posibles.
Entonces, ¿Cómo funciona el RL?
Bien, vamos a comentar cómo funcionaría la secuencia de un algoritmo que aprende por refuerzo.
Cómo dijimos antes, el agente deberá tomar decisiones para interactuar con el ambiente, dado un estado. Pero, de qué manera tomar esas decisiones?
Premios y Castigos
Al principio de todo, nuestro agente está “en blanco”, es decir, no sabe nada de nada de lo que tiene que hacer ni de cómo comportarse. Entonces podemos pensar en que tomará una de las posibles acciones aleatoriamente. E irá recibiendo pistas de si lo está haciendo bien ó mal en base a las recompensas. Entonces irá “tomando nota”, esto bien, esto mal.
Una recompensa para un humano es algún estímulo que le de placer. Podría ser un aumento de sueldo, chocolate, una buena noticia. Para nuestro modelo de ML la recompensa es sencillamente un Score: un valor numérico.
Supongamos que la acción “A” nos recompensa con 100 puntos. El Agente podría pensar “genial, voy a elegir A nuevamente para obtener 100 puntos” y puede que el algoritmo se estanque en una única acción y nunca logre concretar el objetivo global que queremos lograr.
Es decir que tenemos que lograr un equilibrio entre “explorar lo desconocido y explotar los recursos” en el ambiente. Eso es conocido como el dilema de exploración/explotación.
El agente explorará el ambiente e irá aprendiendo “cómo moverse” y cómo ganar recompensas (y evitar las penalizaciones). Al final almacenará el conocimiento en unas normas también llamadas “políticas“.
Pero… debo decir que es probable que el agente “muera” ó pierda la partida las primeras… ¿mil veces? Con esto me refiero a que deberemos entrenar miles y miles de veces al agente para que cometa errores y aciertos y pueda crear sus políticas hasta ser un buen Agente.
¿Fuerza Bruta? En serio? estamos en 2020, por favor!
Bueno a decir la verdad si… esto es un poco vergonzoso… pero cierto. La realidad es que para hacerle aprender a un coche autónomo a conducir, debemos hacerlo chocar, acelerar, conducir contramano y cometer todo tipo de infracciones para decirle “eso está mal, te quito los puntos” y para ello, hay que hacer que ejecute miles y miles de veces en un entorno de simulado.
Para entrenar a DeepMind a dominar al Starcraft ha tenido que jugar el equivalente a miles de horas humanas de juego, y miles de partidas, puede que lo que le llevaría a una persona años, se logra en 8 horas. Y con ese aprendizaje logra vencer a los campeones jugadores humanos.
Esto tiene un lado bueno y uno malo. El malo ya lo vemos; tenemos que usar la fuerza bruta para que aprenda. Lo bueno es que contamos con equipos muy potentes que nos posibilitan realizar esta atrocidad. Por otra parte, recordemos que estamos apuntando a un caso de uso mucho más grande y ambicioso que el de “sólo distinguir entre perritos y gatitos” 😉
Q-Learning, el algoritmo más usado
Ahora vamos a comentar uno de los modelos usados en Reinforcement Learning para poder concretar un ejemplo de su implementación. Es el llamado “Q-Learning”.
Repasemos los elementos que tenemos:
- Políticas: Es una tabla (aunque puede tener n-dimensiones) que le indicará al modelo “como actuar” en cada estado.
- Acciones: las diversas elecciones que puede hacer el agente en cada estado
- Recompensas: si sumamos ó restamos puntaje con la acción tomada
- Comportamiento “avaro” (greedy en inglés) del agente. Es decir, si se dejará llevar por grandes recompensas inmediatas, ó irá explorando y valorando las riquezas a largo plazo
El objetivo principal al entrenar nuestro modelo a través de las simulaciones será ir “rellenando” la tabla de Políticas de manera que las decisiones que vaya tomando nuestro agente obtengan “la mayor recompensa” a la vez que avanzamos y no nos quedamos estancados, es decir, pudiendo cumplir el objetivo global (ó final) que deseamos alcanzar.
A la política la llamaremos “Q” por lo que:
Q(estado, acción) nos indicará el valor de la política para un estado y una acción determinados.
Y para saber cómo ir completando la tabla de políticas nos valemos de la ecuación de Bellman.
Ecuación de Bellman
La ecuación matemática que utilizaremos será:
No lo explicaré en detalle, pues tomaría mucho, pero en resumen; lo que explica la ecuación es cómo ir actualizando las políticas Q^(s,a) en base al valor actual más una futura recompensa que recibiremos, en caso de tomar dicha acción. Hay dos ratios que afectan a la manera en que influye esa recompensa: el ratio de aprendizaje, que regula “la velocidad” en la que se aprende, y la “tasa de descuento” que tendrá en cuenta la recompensa a corto o largo plazo.
Ejercicio Python de RL: Pong con Matplotlib
Hagamos una máquina que aprenda a jugar al Pong sóla (código completo en github).
Para no tener que instalar ningún paquete adicional… usaremos el propio matplotlib como interface gráfica del juego.
Este es el plan: simularemos el ambiente del juego y su compotamiento en la Jupyter Notebook.
El agente será el “player 1” y sus acciones posible son 2:
- mover hacia arriba
- mover hacia abajo
Y las reglas del juego:
- El agente tiene 3 vidas.
- Si pierde… castigo, restamos 10 puntos.
- Cada vez que le demos a la bola, recompensa, sumamos 10.
- Para que no quede jugando por siempre, limitaremos el juego a
- 3000 iteraciones máximo ó
- alcanzar 1000 puntos y habremos ganado.
Agreguemos los imports que usaremos:
1 2 3 4 5 6 7 8 |
import numpy as np import matplotlib.pyplot as plt from random import randint from time import sleep from IPython.display import clear_output from math import ceil,floor %matplotlib inline |
La clase Agente
Dentro de la clase Agente encontraremos la tabla donde iremos almacenando las políticas. En nuestro caso la tabla cuenta de 3 coordenadas:
- La posición actual del jugador.
- La posición “y” de la pelota.
- La posición en el eje “x” de la pelota.
Además en esta clase, definiremos el factor de descuento, el learning rate y el ratio de exploración.
Los métodos más importantes:
- get_next_step() decide la siguiente acción a tomar en base al ratio de exploración si tomar “el mejor paso” que tuviéramos almacenado ó tomar un paso al azar, dando posibilidad a explorar el ambiente
- update() aquí se actualizan las políticas mediante la ecuación de Bellman que vimos anteriormente. Es su implementación en python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
class PongAgent: def __init__(self, game, policy=None, discount_factor = 0.1, learning_rate = 0.1, ratio_explotacion = 0.9): # Creamos la tabla de politicas if policy is not None: self._q_table = policy else: position = list(game.positions_space.shape) position.append(len(game.action_space)) self._q_table = np.zeros(position) self.discount_factor = discount_factor self.learning_rate = learning_rate self.ratio_explotacion = ratio_explotacion def get_next_step(self, state, game): # Damos un paso aleatorio... next_step = np.random.choice(list(game.action_space)) # o tomaremos el mejor paso... if np.random.uniform() <= self.ratio_explotacion: # tomar el maximo idx_action = np.random.choice(np.flatnonzero( self._q_table[state[0],state[1],state[2]] == self._q_table[state[0],state[1],state[2]].max() )) next_step = list(game.action_space)[idx_action] return next_step # actualizamos las politicas con las recompensas obtenidas def update(self, game, old_state, action_taken, reward_action_taken, new_state, reached_end): idx_action_taken =list(game.action_space).index(action_taken) actual_q_value_options = self._q_table[old_state[0], old_state[1], old_state[2]] actual_q_value = actual_q_value_options[idx_action_taken] future_q_value_options = self._q_table[new_state[0], new_state[1], new_state[2]] future_max_q_value = reward_action_taken + self.discount_factor*future_q_value_options.max() if reached_end: future_max_q_value = reward_action_taken #maximum reward self._q_table[old_state[0], old_state[1], old_state[2], idx_action_taken] = actual_q_value + \ self.learning_rate*(future_max_q_value -actual_q_value) def print_policy(self): for row in np.round(self._q_table,1): for column in row: print('[', end='') for value in column: print(str(value).zfill(5), end=' ') print('] ', end='') print('') def get_policy(self): return self._q_table |
La clase Environment
En la clase de Ambiente encontramos implementada la lógica y control del juego del pong. Se controla que la pelotita rebote, que no se salga de la pantalla y se encuentran los métodos para graficar y animar en matplotlib.
Por Defecto se define una pantalla de 40 pixeles x 50px de alto y si utilizamos la variable “movimiento_px = 5” nos quedará definida nuestra tabla de políticas en 8 de alto y 10 de ancho (por hacer 40/5=8 y 50/5=10). Estos valores se pueden modificar a gusto!
Además, muy importante, tenemos el control de cuándo dar las recompensas y penalizaciones, al perder cada vida y detectar si el juego a terminado
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
class PongEnvironment: def __init__(self, max_life=3, height_px = 40, width_px = 50, movimiento_px = 3): self.action_space = ['Arriba','Abajo'] self._step_penalization = 0 self.state = [0,0,0] self.total_reward = 0 self.dx = movimiento_px self.dy = movimiento_px filas = ceil(height_px/movimiento_px) columnas = ceil(width_px/movimiento_px) self.positions_space = np.array([[[0 for z in range(columnas)] for y in range(filas)] for x in range(filas)]) self.lives = max_life self.max_life=max_life self.x = randint(int(width_px/2), width_px) self.y = randint(0, height_px-10) self.player_alto = int(height_px/4) self.player1 = self.player_alto # posic. inicial del player self.score = 0 self.width_px = width_px self.height_px = height_px self.radio = 2.5 def reset(self): self.total_reward = 0 self.state = [0,0,0] self.lives = self.max_life self.score = 0 self.x = randint(int(self.width_px/2), self.width_px) self.y = randint(0, self.height_px-10) return self.state def step(self, action, animate=False): self._apply_action(action, animate) done = self.lives <=0 # final reward = self.score reward += self._step_penalization self.total_reward += reward return self.state, reward , done def _apply_action(self, action, animate=False): if action == "Arriba": self.player1 += abs(self.dy) elif action == "Abajo": self.player1 -= abs(self.dy) self.avanza_player() self.avanza_frame() if animate: clear_output(wait=True); fig = self.dibujar_frame() plt.show() self.state = (floor(self.player1/abs(self.dy))-2, floor(self.y/abs(self.dy))-2, floor(self.x/abs(self.dx))-2) def detectaColision(self, ball_y, player_y): if (player_y+self.player_alto >= (ball_y-self.radio)) and (player_y <= (ball_y+self.radio)): return True else: return False def avanza_player(self): if self.player1 + self.player_alto >= self.height_px: self.player1 = self.height_px - self.player_alto elif self.player1 <= -abs(self.dy): self.player1 = -abs(self.dy) def avanza_frame(self): self.x += self.dx self.y += self.dy if self.x <= 3 or self.x > self.width_px: self.dx = -self.dx if self.x <= 3: ret = self.detectaColision(self.y, self.player1) if ret: self.score = 10 else: self.score = -10 self.lives -= 1 if self.lives>0: self.x = randint(int(self.width_px/2), self.width_px) self.y = randint(0, self.height_px-10) self.dx = abs(self.dx) self.dy = abs(self.dy) else: self.score = 0 if self.y < 0 or self.y > self.height_px: self.dy = -self.dy def dibujar_frame(self): fig = plt.figure(figsize=(5, 4)) a1 = plt.gca() circle = plt.Circle((self.x, self.y), self.radio, fc='slategray', ec="black") a1.set_ylim(-5, self.height_px+5) a1.set_xlim(-5, self.width_px+5) rectangle = plt.Rectangle((-5, self.player1), 5, self.player_alto, fc='gold', ec="none") a1.add_patch(circle); a1.add_patch(rectangle) #a1.set_yticklabels([]);a1.set_xticklabels([]); plt.text(4, self.height_px, "SCORE:"+str(self.total_reward)+" LIFE:"+str(self.lives), fontsize=12) if self.lives <=0: plt.text(10, self.height_px-14, "GAME OVER", fontsize=16) elif self.total_reward >= 1000: plt.text(10, self.height_px-14, "YOU WIN!", fontsize=16) return fig |
El juego: Simular miles de veces para enseñar
Finalmente definimos una función para jugar, donde indicamos la cantidad de veces que queremos iterar la simulación del juego e iremos almacenando algunas estadísticas sobre el comportamiento del agente, si mejora el puntaje con las iteraciones y el máximo puntaje alcanzado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
def play(rounds=5000, max_life=3, discount_factor = 0.1, learning_rate = 0.1, ratio_explotacion=0.9,learner=None, game=None, animate=False): if game is None: game = PongEnvironment(max_life=max_life, movimiento_px = 3) if learner is None: print("Begin new Train!") learner = PongAgent(game, discount_factor = discount_factor,learning_rate = learning_rate, ratio_explotacion= ratio_explotacion) max_points= -9999 first_max_reached = 0 total_rw=0 steps=[] for played_games in range(0, rounds): state = game.reset() reward, done = None, None itera=0 while (done != True) and (itera < 3000 and game.total_reward<=1000): old_state = np.array(state) next_action = learner.get_next_step(state, game) state, reward, done = game.step(next_action, animate=animate) if rounds > 1: learner.update(game, old_state, next_action, reward, state, done) itera+=1 steps.append(itera) total_rw+=game.total_reward if game.total_reward > max_points: max_points=game.total_reward first_max_reached = played_games if played_games %500==0 and played_games >1 and not animate: print("-- Partidas[", played_games, "] Avg.Puntos[", int(total_rw/played_games),"] AVG Steps[", int(np.array(steps).mean()), "] Max Score[", max_points,"]") if played_games>1: print('Partidas[',played_games,'] Avg.Puntos[',int(total_rw/played_games),'] Max score[', max_points,'] en partida[',first_max_reached,']') #learner.print_policy() return learner, game |
Para entrenar ejecutamos la función con los siguientes parámetros:
- 6000 partidas jugará
- ratio de explotación: el 85% de las veces será avaro, pero el 15% elige acciones aleatorias, dando lugar a la exploración.
- learning rate = se suele dejar en el 10 por ciento como un valor razonable, dando lugar a las recompensas y permitiendo actualizar la importancia de cada acción poco a poco. Tras más iteraciones, mayor importancia tendrá esa acción.
- discount_factor = También se suele empezar con valor de 0.1 pero aquí utilizamos un valor del 0.2 para intentar indicar al algoritmo que nos interesa las recompensas a más largo plazo.
1 2 |
learner, game = play(rounds=6000, discount_factor = 0.2, learning_rate = 0.1, ratio_explotacion=0.85) |
Y vemos la salida del entreno, luego de unos 2 minutos:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Begin new Train! -- Partidas[ 500 ] Avg.Puntos[ -234 ] AVG Steps[ 116 ] Max Score[ 10 ] -- Partidas[ 1000 ] Avg.Puntos[ -224 ] AVG Steps[ 133 ] Max Score[ 100 ] -- Partidas[ 1500 ] Avg.Puntos[ -225 ] AVG Steps[ 134 ] Max Score[ 230 ] -- Partidas[ 2000 ] Avg.Puntos[ -223 ] AVG Steps[ 138 ] Max Score[ 230 ] -- Partidas[ 2500 ] Avg.Puntos[ -220 ] AVG Steps[ 143 ] Max Score[ 230 ] -- Partidas[ 3000 ] Avg.Puntos[ -220 ] AVG Steps[ 145 ] Max Score[ 350 ] -- Partidas[ 3500 ] Avg.Puntos[ -220 ] AVG Steps[ 144 ] Max Score[ 350 ] -- Partidas[ 4000 ] Avg.Puntos[ -217 ] AVG Steps[ 150 ] Max Score[ 350 ] -- Partidas[ 4500 ] Avg.Puntos[ -217 ] AVG Steps[ 151 ] Max Score[ 410 ] -- Partidas[ 5000 ] Avg.Puntos[ -216 ] AVG Steps[ 153 ] Max Score[ 510 ] -- Partidas[ 5500 ] Avg.Puntos[ -214 ] AVG Steps[ 156 ] Max Score[ 510 ] Partidas[ 5999 ] Avg.Puntos[ -214 ] Max score[ 510 ] en partida[ 5050 ] |
En las salidas vemos sobre todo cómo va mejorando en la cantidad de “steps” que da el agente antes de perder la partida.
Veamos el resultado!
Ya contamos con nuestro agente entrenado, ahora veamos qué tal se comporta en una partida de pong, y lo podemos ver jugar, pasando el parámetro animate=True.
Antes de jugar, instanciamos un nuevo agente “learner2” que utilizará las políticas que creamos anteriormente. A este agente le seteamos el valor de explotación en 1, para evitar que tome pasos aleatorios.
1 2 3 |
learner2 = PongAgent(game, policy=learner.get_policy()) learner2.ratio_explotacion = 1.0 # con esto quitamos las elecciones aleatorias al jugar player = play(rounds=1, learner=learner2, game=game, animate=True) |
Y veremos nuestro juego de Pong en acción!
En mi caso, con las 6 mil iteraciones de entrenamiento fue suficiente alcanzar los 500 puntos y ganar (puedes ir variando el objetivo a 500 puntos ó a 1000, la cantidad de vidas, etc.)
La Tabla de políticas resultante
Quiero brevemente comentar la tabla de políticas que hemos creado luego de entrenar.
En este ejemplo, mostraré una tabla de 3 coordenadas. La primera toma valores del 0 al 7 (posición del jugador), la segunda también 8 valores (altura de la bola de pong) y la tercera va del 0 al 9 con el desplazamiento horizontal de la pelota.
Supongamos que el player está situado en la posición “de abajo de todo”, es decir, en la posición cero.
Dentro de esa posición queda conformada la siguiente tabla:
Si nos fijamos en la coordenada de la bola (x8, y1) vemos los valores 1.9 para subir y -9 para bajar. Claramente la recompensa mayor está en la acción de subir. Pero si la pelotita estuviera en (x9,y4) la mejor acción será Bajar, aunque tenga un puntaje negativo de -16,7 será mejor que restar 46.
Conclusiones
Hay muchos más detalles y lecturas adicionales para dominar el tema, pero en este artículo hemos explicado los conceptos básicos del reinforcement learning, sus diferencias con el aprendizaje supervisado y sus características.
Además conocimos su implementación más conocida, el Q-Learning y realizamos un juego completo en Python en donde el Agente sin tener conocimiento previo de las reglas ni del entorno logra aprender y volverse un muy buen jugador de Pong tras miles de simulaciones.
Debo decir que una evolución muy interesante del Aprendizaje por Refuerzo es el Aprendizaje por Refuerzo Profundo en donde aparecen las redes neuronales a mejorar y perfeccionar al modelo. Escibiré sobre ello en un próximo artículo!
Deseos Finales
Aprovecho a desearles un muy buen fin de año y a que puedan empezar el 2021 con muchos planes y muchas ganas de seguir aprendiendo sobre Machine Learning y la ciencia de datos.
También les invito a descargar ó comprar “el libro del blog” en formato digital y como novedad, he logrado publicar en la tienda de Amazon la versión del libro en formato papel, en gran parte por algunos de vosotros que me lo pidieron. Así que mil gracias porque gracias a ese empuje y ánimo que me dieron, puedo decir que termino el año con mi primer libro publicado, lo cual para mi es un sueño cumplido! Y -perdón la insistencia con esto- pero ciertamente este año ha sido un año muy difícil para mi al igual que para todos y jamás hubiera pensado haberlo podido conseguir. Es un hito en mi vida.
Muchas gracias querido lector, desde aquí te envío un sincero abrazo virtual!.
Material del Artículo
Descarga la notebook completa desde GitHub aqui
Recursos Adicionales
Otros artículos relacionados:
- RL a simple Python example
- Introducción al RL (en español!)
- Introducción al mundo del RL (en español!)
Suscripción al Blog
Recibe los próximos artículos sobre Machine Learning, estrategias, teoría y código Python en tu casilla de correo!
NOTA: algunos usuarios reportaron que el email de confirmación y/o posteriores a la suscripción entraron en su carpeta de SPAM. Te sugiero que revises y recomiendo que agregues nuestro remitente info @ aprendemachinelearning.com a tus contactos para evitar problemas. Gracias!
El libro del Blog
Si te gustan los contenidos del blog y quieres darme una mano, puedes comprar el libro en papel, ó en digital.
Muy buen articulo.
se entiende sin tener conocimientos previos
un pequeño detalle, cuando comentas las tabla de politicas
creo que hay uan errata. cuando comentas:
“Si nos fijamos en la coordenada de la bola (x8, y1) vemos los valores 1.9 para subir y -9 para bajar”
creo que las coordenas son (x8,y2) según los valores que comentas.
perdona que sea tan quisquilloso
gracias de nuevo por el articulo.