Aprendizaje de refuerzo en piedras de inversión

En este tutorial explicaré el aprendizaje por refuerzo. Explicaré qué es el Aprendizaje automático si ya está familiarizado con esto, puede saltar a Piedras de inversión. Explicaré el aprendizaje de refuerzo y usaré un ejemplo que puedes usar en AIgaming.com para el juego Reversing Stones.

Puedes encontrar el código en GitHub.

El aprendizaje automático es una técnica en la que, en lugar de escribir un programa que resuelve un problema determinado, se escribe un programa que se enseña a sí mismo a solucionar un problema determinado. Las soluciones de aprendizaje automático se pueden clasificar en las siguientes ramas:

Aprendizaje supervisado; Aprendizaje no supervisado; Aprendizaje semi supervisado; Aprendizaje de refuerzo.

Aprendizaje supervisado

Para entrenar un modelo (algoritmo) que utiliza aprendizaje supervisado, se coloca un conjunto de datos (grande). Este conjunto de datos tiene tanto la entrada como la salida deseada. Un conjunto de datos generalmente se divide en datos de entrenamiento y datos de prueba. El modelo se entrena con los datos de entrenamiento y luego intenta predecir la salida de los datos de prueba y luego se compara con la salida real. La proporción es probable entre 30% -40% de datos de prueba y 60-70% de datos de entrenamiento.

Redes neuronales

Tanto el aprendizaje supervisado como el aprendizaje por refuerzo pueden hacer uso de redes neuronales. Estas son estructuras que se basan en el cerebro humano. Una red neuronal consta de diferentes "capas". Cada capa consta de un cierto número de nodos. Todos los nodos se conectan tradicionalmente a todos los nodos de la capa siguiente y anterior, y todas estas conexiones tienen un peso. Las entradas establecen los valores de la capa de entrada, luego van a la (s) capa (s) oculta (s) y terminan en la capa de salida. Cuando se entrena un modelo / red neuronal, los pesos entre los nodos se modifican para intentar acercarse a la salida deseada.

Al utilizar el aprendizaje por refuerzo, no necesita ningún dato, en su lugar, debe generar los datos en sí. El modelo intenta hacer lo que quiere que haga (voltear las fichas) y usted lo recompensa si está haciendo algo bueno (gana el juego) o lo castiga cuando está mal. Estas recompensas son muy importantes, ya que el modelo intentará alcanzar la mayor recompensa posible. Esto puede significar que el modelo hará algo completamente inesperado. Usando esta técnica, el modelo puede jugar miles o incluso millones de juegos en unas pocas horas o días.

El agente

El agente es el que toma acciones, decide qué movimientos realizar y el componente que se está capacitando para un mejor desempeño. Una vez finalizada la capacitación, tomamos al agente y lo colocamos en otro entorno similar (en AIgaming.com).

El entorno

Aquí es donde el agente realiza acciones. El entorno es un lugar que tiene un conjunto determinado de reglas. En nuestro caso es el juego, el entorno es el tablero, las piedras del oponente, nuestras piedras y las fichas vacías.

El interprete

Esta es la parte que entiende cuando una acción es buena o mala. Esto entonces recompensa o castiga al agente en consecuencia. Esto solo se usa durante la capacitación y se implementa principalmente como una función de recompensas.

El juego comienza con un tablero con cuatro piedras (2 oscuras y 2 claras) y se le asignará aleatoriamente el color oscuro o claro.

La oscuridad debe colocar una piedra con el lado oscuro hacia arriba en el tablero, en una posición tal que exista al menos una línea recta (horizontal, vertical o diagonal) ocupada entre la piedra nueva y otra piedra oscura, con una o más luces contiguas piedras entre ellos.

Después de colocar la piedra, la oscuridad gira (voltea, captura) todas las piedras claras que se encuentran en una línea recta entre la piedra nueva y las piedras oscuras que se anclan.

Luego es el turno de la luz y ellos hacen lo mismo y voltean piedras oscuras. Si un jugador no puede hacer un movimiento válido, se omite su turno.

El juego termina cuando ningún jugador puede hacer un movimiento válido o el tablero está lleno. El ganador es siempre el jugador que tiene más piedras de su color.

Puede encontrar más información sobre la instalación de tensorflow aquí. Tenga en cuenta que tensorflow requiere una instancia de Python 3 de 64 bits.

Para jugar al juego en sí, vaya a la página de descargas de AIgaming y descargue la biblioteca aigamingReversingStones.

Yo uso las siguientes bibliotecas para este proyecto:

aigamingReversingStones; Tensorflow; Numpy.

Primero necesitaremos importar todos los módulos requeridos.

A continuación, realizaremos algunas configuraciones, de esta manera, si decidimos utilizar un tamaño de tablero diferente, podemos modificar estas variables y comenzar a entrenar.

CONFIGURACIONES: Una lista de todos los tamaños posibles de tablas;USE_CONFIGURACIÓN: El índice de la configuración que utilizamos;BOARD_SIZE: El tamaño del tablero.

Esta es una función que inicializa el modelo. Creamos una red neuronal que tiene una capa oculta que tiene el mismo número de nodos que la capa de entrada y salida. Inicializamos cada capa a un valor pseudoaleatorio. Luego conectamos las capas e inicializamos un optimizador de pendiente de gradiente.

Nota: A continuación no se muestran los valores reales. Solo tienen un valor si llama a sess.run ((Las variables de las que quiere saber el valor), feed_dict = {valores para marcadores de posición})

Posiciones de entrada: Las entradas de la red / la capa de entrada;etiquetas: El resultado esperado de la red. Esto se hace utilizando la acción real que tomó en lugar de la lista de probabilidades que produce la red. Se representa utilizando el índice del ‘1’ en la lista;tasa de aprendizaje: Cuánto aprende el modelo de la jugada actual. Esto depende de la acción tomada y de cuán buena haya sido esa acción;W1: Los pesos que conectan la capa de entrada a la capa oculta;b1: Los sesgos de la capa oculta (este es un valor diferente para cada nodo);h1: La capa oculta real. Esto contiene los valores de los nodos de la capa oculta;W2: Los pesos que conectan la capa oculta a la capa de salida;b2: Los sesgos de la capa de salida;logits: Los valores de la capa de salida;probabilidades: Los valores de la capa de salida en el rango (0; 1);cross_entropy: Las diferencias entre los logits y las etiquetas. Convertido a valores entre (0; 1);paso de tren: Esto le dice al modelo cómo minimizar la cross_entropy usando el tamaño de paso determinado por la learning_rate.

Simplemente podemos inicializar un juego usando la biblioteca. aigamingReversingStones. los inicializar La función tiene los siguientes parámetros:

player_index (0): El índice del jugador que inicializa el juego. Esto no afecta el juego;player_ids (("Player0", "Player1")): Los nombres de los jugadores en el juego. Esto no afecta el juego;move_time (3000): El tiempo que tiene que responder cada jugador en ms;board_dimensions ((8, 8)): Las dimensiones del tablero (#columns, #rows);forma ("Cuadrado"): Actualmente no está en uso;agujeros (Falso): Actualmente no está en uso.

Esta función devuelve un dict con los siguientes campos:

Resultado: "ÉXITO" si el juego fue creado exitosamente;StepTexts: Mantendrá una descripción en inglés que el juego ha comenzado;Estatus de juego específico: Un gamestate similar al que obtienes cuando juegas en AIgaming.com;GeneralGameStates: Una lista de uno o más estados de juego. Use la última entrada en esta lista para hacer el primer movimiento.

Para hacer un movimiento, necesitamos proceder a través de la red neuronal. Una vez hecho esto, tenemos una lista de probabilidades. Solo queremos hacer un movimiento válido, por lo que eliminamos todos los movimientos imposibles de las probabilidades y recalculamos.

Tenga en cuenta que np.random.choice necesita que la suma de todas las probabilidades sea exactamente 1. Por lo tanto, tomamos todos los valores con seis decimales. Luego, volvemos a calcular todas las probabilidades para que la suma sea exactamente 1. Si no hay más posibilidades, cambiamos la lista para que todas las movidas válidas tengan la misma oportunidad.

Nos movemos en el juego usando la biblioteca. aigamingReversingStones. los movimiento La función tiene los siguientes parámetros:

player_index (0): El índice del jugador que está haciendo el movimiento. Esto debe ser igual a gamestate ("Mover");player_ids (("Player0", "Player1")): Los nombres de los jugadores en el juego. Esto no afecta el juego;gamestate ({}): El estado de juego más reciente, es el que contiene todos los datos del juego;movimiento_actual ((8, 8)): El movimiento que desea realizar, está en el formato {“Fila”: int, “Columna”: int}.

Esta función devuelve un dict con los siguientes valores:

Resultado: O "SUCCESS" si el movimiento fue válido, "INVALID_MOVE" si el movimiento no fue válido o "GAME_HAS_ENDED" cuando el movimiento terminó el juego;StepTexts: Mantendrá una descripción en inglés del movimiento que se realizó;Estatus de juego específico: Un gamestate similar al que obtienes cuando juegas en AIgaming.com;GeneralGameStates: Una lista de 1 o más jugadores. Use la última entrada en esta lista para hacer el próximo movimiento.

Para jugar un juego completo, primero inicializaremos player_index, player_ids y resultado. El resultado mantendrá el estado del juego y toda la información utilizada por la biblioteca. También hay algunos registros que necesitan ser inicializados.

El juego sigue funcionando mientras los movimientos tengan éxito. Una vez finalizado el juego. resultado ("Resultado") cambiará a "GAME_HAS_ENDED" y escaparemos del bucle. Cada movimiento consiste en el mismo patrón:

Obtenemos el jugador actual; obtenemos el tablero actual; el tablero se convierte a una entrada uniforme, esto se hace para que el algoritmo siempre juegue con '0'; registramos el tablero actual para que podamos usarlo para entrenar más tarde; El modelo devuelve un movimiento que luego convertimos al formato correcto; luego realizamos el movimiento y actualizamos resultadoLuego, registramos la acción tomada y la probabilidad de esa acción.

Cuando el juego ha terminado de jugar, devolvemos todos los registros y el estado final del juego.

Cuando el juego termina, resultado ("WinnerIndex") mantendrá uno de los tres valores. 0 o 1 si ese jugador ganó o -1 si el juego terminó en un empate. Por lo general, creará una función de recompensas que recompensa al jugador por cada movimiento individualmente, dependiendo de la contribución que se haya hecho para ganar el juego. Para mantener este tutorial comprensible, le doy a todos los movimientos la misma recompensa. Un juego ganador resultará en una recompensa de 1 por cada movimiento. Esto hace que sea más probable que el modelo vuelva a hacer ese movimiento si alguna vez se encuentra en una situación similar. Sin embargo, si el jugador no ganó, le doy una recompensa de 0. Tenga en cuenta que esto no impide que el modelo vuelva a hacer ese movimiento. Esto se debe a que no sabemos si ese movimiento es malo, solo sabemos que la secuencia de movimientos realizada por ese jugador no resultó en una victoria esta vez.

Nota: Este código está incluido en la parte de entrenamiento.

Para probar con qué éxito aprendió el algoritmo, creé una función que le permite al modelo jugar un juego contra un jugador que se mueve aleatoriamente. Esta función es similar a la jugar un juego función.

Para ejecutar este código, simplemente puede llamarlo. Imprimirá los resultados después de cada 100 juegos jugados y devolverá el porcentaje general.

Antes de comenzar el entrenamiento, queremos ejecutar todas las funciones de inicialización. También tienes que crear e inicializar una sesión de Tensorflow.

ALFA Es un multiplicador de los pasos de entrenamiento que realizará el modelo. Este es un parámetro que evita el desajuste y el desajuste. Esto depende mucho del algoritmo y cuando, por ejemplo, cambias las recompensas, necesitas encontrar el valor que funcione mejor para ese algoritmo. Esto se hace simplemente probando diferentes valores (normalmente lo cambio con un factor de 10 hasta que esté satisfecho con el resultado).

los todos_ Las variables son para fines de registro.

Hago bastante registro durante la capacitación para saber qué está sucediendo. Todas las declaraciones de impresión y las llamadas de tiempo están directamente relacionadas con el registro. El resultado es que sé cuánto tiempo tomó la capacitación y cuánto tiempo tomará terminarla. NUMERO DE JUEGOS Define cuántos juegos se juegan durante el entrenamiento.

Un juego consta de los siguientes pasos:

Primero, se está jugando el juego real; registramos todas las cosas que queremos analizar; imprimimos el progreso cada porcentaje; para ambos jugadores, verificamos si ganaron y recompensamos en consecuencia; luego entrenamos para cada jugador, cada movimiento del juego con la entrada y qué movimiento tomaron realmente. Luego hacemos un paso de entrenamiento que depende de ALFA Y como fue su juego.

Una vez finalizado el juego, registramos algunos datos que pueden ser de su interés.

Nota: En este juego, "Promedio del último paso" no define qué tan bien está haciendo el modelo. En otro juego donde podría haber un progreso más explícito, es posible que desee imprimirlo.

Nota: Si está utilizando la notebook jupyter, puede volver a ejecutar esta celda para seguir mejorando el modelo.

Antes de que podamos usar el modelo que necesitamos para guardarlo, esto se puede hacer de varias maneras, prefiero usar tf.train.Saver ().

Antes de cargar, debe inicializar todas las variables de la misma manera que la capacitación, luego puede cargar el modelo desde estos archivos. Sepa que necesita todos los archivos que creó el protector. Cuando el modelo está cargado, puedes usarlo como lo hice en el entrenamiento.

Lo mejor es que su código juegue contra el código de otras personas. Esto se puede hacer en AIgaming.com. Necesitas usar load_model, initialise_tf y guess_move sin muchos cambios (deshabilitar el benchmarking).

Para que el algoritmo funcione, necesitamos el modelo. Utilizo Google Drive para que mi modelo sea accesible a Internet. Puede hacer esto creando un enlace que se pueda compartir y copiando la identificación (obtendrá algo como esto: "https://drive.google.com/file/d/{id}/view?usp=sharing" o como esto: "Https://drive.google.com/open?id={id}"). Haga esto para los cuatro archivos y reemplace los identificadores ‘xxxxx’ en la lista de enlaces. Puedes usar un servicio diferente si lo prefieres, esta es solo una forma de hacerlo y esta es la que implementé en mi código.

los calcularMover La función es la función principal del programa. Esto se ejecuta cada vez que necesitas hacer un movimiento. Primero debemos verificar si el modelo existe en la carpeta / tmp (esta es la única carpeta a la que puede acceder). Si el modelo no está allí, entonces ponlo allí. Si el modelo está ahí, carga la sesión y adivina un movimiento. Simplemente devuelve ese movimiento en el formato correcto y listo.

Si todo funciona, serás capaz de vencer la práctica de las tareas domésticas con facilidad.

Si logró que esto funcionara, puede comenzar a iterar y crear un modelo / algoritmo más exitoso.

Una de las mejoras más importantes que puedes hacer es recompensar los movimientos. Actualmente, todos los movimientos en un juego tienen la misma calificación, si escribiera una función que pudiera detectar qué movimiento es mejor y qué es peor, podría realizar mejoras significativas.

Un ejemplo de esto sería una función que cuenta cuántas piedras conviertes. A continuación, califica cada movimiento en consecuencia y recompensa los movimientos mejores, más los movimientos peores (negativo o 0). Puedes aumentar esta recompensa si hay menos piedras del oponente en el tablero. Otra cosa a considerar es si las piedras tienen alguna importancia estratégica más adelante en el juego o si la piedra está en una buena ubicación.

Otra cosa que podrías querer hacer es usar múltiples modelos. Puede, por ejemplo, usar un modelo para cada color o uno para la primera parte del juego y otro para terminar el juego o combinar los dos.

Cuando te sientas seguro, te sugiero encarecidamente que intentes crear un algoritmo para entrenar en un juego o desafío diferente.

Sobre el Autor

Este artículo está escrito por William Verhaeghe.