0% encontró este documento útil (0 votos)
15 vistas8 páginas

CA So Practico Python

El documento describe la implementación de un agente de aprendizaje por refuerzo para jugar al Pong, incluyendo la clase del agente que gestiona políticas y decisiones de acción, así como la clase del entorno que controla la lógica del juego. Se detalla el proceso de entrenamiento del agente a través de simulaciones, donde se ajustan parámetros como el factor de descuento y la tasa de aprendizaje. Finalmente, se presentan resultados del entrenamiento y cómo el agente mejora su desempeño a lo largo de las partidas.

Cargado por

Andrea Caustica
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
15 vistas8 páginas

CA So Practico Python

El documento describe la implementación de un agente de aprendizaje por refuerzo para jugar al Pong, incluyendo la clase del agente que gestiona políticas y decisiones de acción, así como la clase del entorno que controla la lógica del juego. Se detalla el proceso de entrenamiento del agente a través de simulaciones, donde se ajustan parámetros como el factor de descuento y la tasa de aprendizaje. Finalmente, se presentan resultados del entrenamiento y cómo el agente mejora su desempeño a lo largo de las partidas.

Cargado por

Andrea Caustica
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

• La clase de agente: En la parte interna de la clase de agente se encontrará la tabla donde se irá

recopilando las políticas. En este caso la tabla consta de de 3 coordenadas. a) la posición actual
del jugador. b) la posición (y) de la pelota. c) la posición en el eje (x) de la pelota. aquí se definirá
el factor descuento el learning rate y el ratio de la exploración.
Sus métodos más importantes son:
• get_next_step: Este es el que decide la siguiente acción a tomar en base al ratio de exploración
si se toma el mejor paso que estuviera almacenado o tomar un paso a zar, dando la posibilidad
de que pueda estudiar el ambiente.
• Update: A través de este se actualizan las políticas mediante la ecuación de Bellman. Y su
implementación en python queda de la siguiente manera.
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

CLASS PONGAGENT.

• Clase Environment: En esta clase se encuentra implementada la lógica y el control de juego del pong.
Se puede controlar el rebote de la pelotica y que esta no se salga de la pantalla y se hallan los
métodos para graficar y animar en matplotlip. Por lo que se define una pantalla de 40 pixeles x 50 px
de alto y se utiliza la variable movimiento_px=5 la tabla de políticas quedará definida en 8 de alto y
de ancho (40/5=8 y 50/5=10). Valores que puedes modificar si lo deseas.
Lo mejor de todo, es que se tiene el control de cuando dar las recompensas y las penalizaciones, esto
sucede al perder cada vida y detectar si el juego ha terminado.

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

CLASS PONGENVIRONMENT.

Podemos simular el juego miles de veces para enseñar. Para eso, se define una función para jugar donde
es indicada la cantidad de veces que se quiere iterar la simulación del juego y se irá almacenando algunas
estadísticas sobre el comportamiento del agente, si hay mejoría del puntaje con las iteraciones y puntaje
máximo alcanzado.
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

FUNCIÓN PARA JUGAR.

Para poder entrenar se ejecutó la función con los siguientes parámetros.


• Se podrán jugar 6000 partidas.
• El ratio de explotación: Para el 85% de las veces será avaro, mientras que el 15% elige acciones
aleatorias, dando lugar a la exploración.
• Learning rate: Aquí se suele dejar en el 10% como un valor razonable, proporcionando lugar a
las recompensas y permitiendo actualizar la importancia de cada acción poco a poco. Después
de más iteraciones, mayor importancia tendrá esa acción.
• Discount_factor: Se suele empezar con valor de 0.1 pero aquí no se utiliza un valor del 0.2 para
intentar mostrar al algoritmo que nos interesa las recompensas de largo plazo.

learner, game = play(rounds=6000, discount_factor = 0.2, learning_rate = 0.1, ratio_explotacion=0.85)

En esta se ve la salida del entreno después de 2 minutos:


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 ]

SALIDA DE ESTRENO LUEGO DE 2 MINUTOS.

En las salidas se va viendo más que todo como va mejorando en la cantidad de step que proporciona el
agente antes de perder la partida.
Podemos saber el resultado final, ya que contamos con un agente entrenado. Ahora, vamos a ver qué tal
será su comportamiento en una partida de pong, y se puede ver jugando pasando el parámetro
animate=True.
Antes de comenzar a jugar vamos a instanciar un agente nuevo learner2, el cual utilizará las políticas que
fueron creadas anteriormente. A dicho agente le agregamos el valor de exploración en 1 para poder evitar
que tome pasos aleatorios.

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)

En la tabla de políticas resultantes se mostrará un ejemplo de una tabla de 3 coordenadas. En la primera


se tomaran valores de o a 7 (posición del jugador), en la segunda o valores (la altura de la bola de pong) y
en tercer lugar va de 0 a 9 con el desplazamiento horizontal de la pelota.
Supongamos que el player está ubicado en la posición “de debajo de todo” lo que es igual en la posición
0, quedando la tabla conformada de la siguiente manera:

TABLA DE 3 COORDENADAS.

Aquí observamos la tabla con las acciones a tomar si el jugador está en la posición cero y según donde se
encuentre la bola en los valores x e y. Recordando que, tenemos creadas 8 tablas como esta para cada
posición del player.
Si vemos bien, en la coordenada de la bola (x8, y1) vemos los valores 1.9 para subir y -9 para bajar. En
ella se nota claramente que la recompensa mayor está en la acción de subir. Pero, si la pelotita estuviera
en (x9,y4) la mejor acción seria bajar, aunque tenga un puntaje negativo de -16,7 será mejor que restar
46.

También podría gustarte