Path: blob/master/site/es-419/agents/tutorials/bandits_tutorial.ipynb
25118 views
Copyright 2023 The TF-Agents Authors.
Tutorial sobre bandidos multibrazo en TF-Agents
Preparación
Si todavía no ha instalado las siguientes dependencias, ejecute estos comandos:
Importaciones
Introducción
El problema de los bandidos multibrazo (MAB, por sus siglas en inglés) es un caso especial de Aprendizaje por Refuerzo: un agente recopila recompensas en un entorno a través de la ejecución de ciertas acciones tras observar parte del estado del entorno. La principal diferencia entre el RL general y los MAB es que, en los MAB, asumimos que la acción ejecutada por el agente no influye en el siguiente estado del entorno. Por lo tanto, los agentes no modelan las transiciones de estado, no acreditan recompensas a las acciones pasadas ni "planifican con antelación" para llegar a estados con abundantes recompensas.
Como en otros dominios del RL, el objetivo de un agente del MAB es el de encontrar una política que recopile la mayor recompensa posible. Sin embargo, sería un error que siempre se intente explotar la acción que promete la mayor recompensa, porque entonces podríamos perder de vista mejores acciones por no explorar lo suficiente. Este es el problema más importante que debemos resolver en (MAB), a menudo conocido como la paradoja exploración-explotación.
Los entornos, las políticas y los agentes de bandidos para MAB se pueden encontrar en los subdirectorios de tf_agents/bandits.
Entornos
En TF-Agents, la clase de entorno cumple la función de dar información sobre el estado actual (esto se llama observación o contexto), recibir una acción como entrada, realizar una transición de estado y generar una recompensa. Esta clase también se encarga del reinicio cuando un episodio termina, para que un nuevo episodio pueda comenzar. Esto se consigue llamando a una función reset
cuando un estado se etiqueta como "último" del episodio.
Para obtener más información, consulte el tutorial sobre entornos de TF-Agents.
Como se mencionó anteriormente, MAB es diferente del RL general en el sentido de que las acciones no influyen sobre la siguiente observación. Otra diferencia es que en Bandits no hay "episodios": cada paso de tiempo se inicia con una nueva observación, independientemente de los pasos de tiempo anteriores.
Para asegurarnos de que las observaciones sean independientes y para abstraer el concepto de episodios de RL, introducimos subclases de PyEnvironment
y TFEnvironment
: BanditPyEnvironment y BanditTFEnvironment. Estas clases exponen dos funciones miembro privadas que deben ser implementadas por el usuario:
y
La función _observe
devuelve una observación. Luego, la política elige una acción en función de esta observación. _apply_action
recibe esa acción como entrada y devuelve la recompensa correspondiente. Estas funciones miembro privadas son llamadas por las funciones reset
y step
, respectivamente.
La clase abstracta provisional que acabamos de describir implementa las funciones _reset
y _step
de PyEnvironment
y expone las funciones abstractas _observe
y _apply_action
para que las implementen las subclases.
Una clase de entorno de ejemplo simple
La clase que se presenta a continuación ofrece un entorno muy simple en el que la observación es un número entero aleatorio comprendido entre -2 y 2, existen 3 acciones posibles (0, 1, 2) y la recompensa es el producto de la acción y la observación.
Ahora podemos utilizar este entorno para obtener observaciones y recibir recompensas por nuestras acciones.
Entornos de TF
Se puede definir un entorno bandido al subclasificar BanditTFEnvironment
o, de manera similar a los entornos de RL, se puede definir un BanditPyEnvironment
y envolverlo con TFPyEnvironment
. Para simplificar, en este tutorial optaremos por esta última opción.
Políticas
En un problema de bandidos, las políticas funcionan igual que en un problema de RL: ofrecen una acción (o una distribución de acciones), a partir de una observación que funciona como entrada.
Para obtener más información, consulte el tutorial sobre políticas de TF-Agents.
Del mismo modo que ocurre con los entornos, hay dos formas de construir una política: se puede crear una PyPolicy
y envolverla con TFPyPolicy
, o crear directamente una TFPy
. Aquí optamos por el método directo.
Como este ejemplo es bastante sencillo, podemos definir la política óptima manualmente. La acción solo depende del signo de la observación, 0 cuando es negativa y 2 cuando es positiva.
Ahora podemos solicitar una observación del entorno, llamar a la política para que elija una acción y, entonces, el entorno emitirá la recompensa:
La forma en que se implementan los entornos bandidos garantiza que cada vez que damos un paso, recibimos tanto la recompensa por la acción efectuada como la siguiente observación.
Agentes
Ahora que ya explicamos los entornos bandidos y las políticas bandidas, debemos definir también los agentes bandidos, que se encargan de cambiar la política en función de muestras de entrenamiento.
La API para los agentes bandido es similar a la de los agentes de RL: el agente solo tiene que implementar los métodos _initialize
y _train
y definir una policy
y una collect_policy
.
Un entorno más complicado
Antes de que escribamos nuestro agente bandido, necesitamos contar con un entorno que sea un poco más difícil de entender. Para hacerlo un poco más interesante, el siguiente entorno siempre dará reward = observation * action
o reward = -observation * action
. Esto se decidirá cuando se inicialice el entorno.
Una política más complicada
Un entorno más complicado requiere una política más complicada. Necesitamos una política que detecte el comportamiento del entorno subyacente. Hay tres situaciones que la política debe gestionar:
El agente aún no ha detectado qué versión del entorno se está ejecutando.
El agente detectó que se está ejecutando la versión original del entorno.
El agente detectó que se está ejecutando la versión invertida del entorno.
Definimos una tf_variable
nombrada _situation
para almacenar esta información codificada como valores en [0, 2]
, luego hacemos que la política se comporte en consecuencia.
El agente
Ahora debemos definir el agente que detecta el signo del entorno y establece la política adecuada.
En el código anterior, el agente define la política y el agente y la política comparten la variable situation
.
Además, el parámetro experience
de la función _train
corresponde a una trayectoria:
Trayectorias
En TF-Agents, trajectories
son tuplas nombradas que contienen muestras de los pasos anteriores. Luego, los agentes usan estas muestras para entrenar y actualizar la política. En el RL, las trayectorias deben contener información sobre el estado actual, el siguiente estado, y sobre si el episodio actual ha terminado. Como en el mundo bandido no necesitamos estos datos, configuramos una función ayudante para crear una trayectoria:
Cómo entrenar un agente
Ya tenemos todo lo que necesitamos para entrenar nuestro agente bandido.
A partir de la salida se puede ver que después del segundo paso (a menos que la observación fuera 0 en el primer paso), la política elige la acción de forma correcta y por lo tanto la recompensa obtenida es siempre no negativa.
Un ejemplo real de bandido contextual
Entorno estocástico estacionario con funciones de recompensa lineales
El entorno que se usa en este ejemplo es StationaryStochasticPyEnvironment. Este entorno toma como parámetro una función (generalmente ruidosa) para ofrecer observaciones (contexto), y para cada brazo toma una función (también ruidosa) que calcula la recompensa en función de la observación dada. En nuestro ejemplo, tomamos muestras del contexto de un cubo d-dimensional uniformemente, y las funciones de recompensa son funciones lineales del contexto, más un poco de ruido gaussiano.
El agente LinUCB
El agente que se muestra a continuación implementa el algoritmo LinUCB.
Métrica de arrepentimiento
La métrica más importante de Bandits es arrepentimiento, y se calcula como la diferencia entre la recompensa obtenida por el agente y la recompensa esperada por una política de oráculo que tenga acceso a las funciones de recompensa del entorno. Por lo tanto, RegretMetric necesita una función baseline_reward_fn que calcule la mejor recompensa esperada alcanzable a partir de una observación. Para nuestro ejemplo, tenemos que tomar el máximo de los equivalentes sin ruido de las funciones de recompensa que ya hemos definido para el entorno.
Entrenamiento
En este paso, reunimos todos los componentes que presentamos anteriormente: el entorno, la política y el agente. Ejecutamos la política sobre el entorno y generamos datos de entrenamiento con la ayuda de un controlador, y capacitamos al agente con los datos.
Tenga en cuenta que hay dos parámetros que se unen para especificar el número de pasos dados. num_iterations
especifica cuántas veces ejecutamos el bucle entrenador, mientras que el controlador dará steps_per_loop
pasos por iteración. La principal razón para mantener ambos parámetros en algunas de estas operaciones es que algunas operaciones se ejecutan por iteración, mientras que a otras las ejecuta en cada paso el controlador. Por ejemplo, la función train
del agente se llama una sola vez por iteración. La diferencia radica en que, si entrenamos más a menudo, nuestra política será más "fresca"; por otro lado, entrenar en lotes más grandes puede resultar más eficiente en función del tiempo.
Tras ejecutar el último fragmento de código, el gráfico resultante (con suerte) mostrará que el arrepentimiento medio disminuye a medida que el agente se entrena y la política mejora su capacidad de predecir cuál es la acción correcta, a partir de la observación.
Siguientes pasos
Para ver más ejemplos prácticos, consulte bandits/agents/examples que tiene ejemplos listos para ejecutar para diferentes agentes y entornos.
La biblioteca TF-Agents también es capaz de gestionar bandidos multibrazo con características por brazo. Para ello, sugerimos que se consulte el tutorial de bandido por brazo.