Autor: Hamwon
Resumen
"Jugar a Atari con aprendizaje por refuerzo profundo" es el primer documento clásico de aprendizaje por refuerzo profundo que combina el aprendizaje por refuerzo con el aprendizaje profundo. Fue diseñado y desarrollado por el equipo de DeepMind. El algoritmo se probó en el entorno de juego Atari 2600 y su rendimiento de prueba en. Algunos juegos eran mejores que los jugadores humanos.
URL del artículo: https://paperswithcode.com/paper/playing-atari-with-deep-reinforcement
01
Crear un proyecto de entorno virtual con Pycharm
El código del proyecto y los resultados de la capacitación se cargaron en Baidu Netdisk y se pueden descargar primero. Sin embargo, debido a que el entorno virtual es demasiado grande, no se cargan. Para operaciones específicas, consulte la introducción. abajo.
Enlace: https://pan.baidu.com/s/1zoh0glqH4xcNSbOUuR2r7g?pwd=00wdCódigo
de extracción: 00wd
Primero cree un nuevo proyecto usando Pycharm y luego agregue el entorno virtual en la configuración como se muestra a continuación:
El propósito de crear un proyecto de entorno virtual es separar el entorno de ejecución del proyecto actual de su propio entorno Python. Luego, instalará los paquetes necesarios en el entorno virtual para evitar afectar su entorno Python anterior. La versión de Pycharm que uso es la versión 2019. La configuración de la nueva versión de Pycharm debería ser similar a Baidu según su propia situación. La ruta de Anaconda de cada persona es diferente y debe elegir el intérprete básico de acuerdo con la ubicación de instalación.
Para la configuración del entorno virtual, consulte el artículo de CSDN: Pycharm crea y gestiona un entorno virtual.
Una vez creado el entorno virtual, aún necesita configurar el programa de terminal en la configuración:
En este momento, abra la pestaña del terminal en Pycharm y podrá ver el mensaje (venv) frente al terminal, que indica que el terminal actual está en un entorno virtual:
En este momento, todos los paquetes que necesitamos los podemos instalar a través de pip en esta terminal.
Recuerde copiar el código de las tres carpetas, las imágenes y el modelo descargados de Baidu Cloud a la carpeta del proyecto actual. Los paquetes de Python necesarios para el proyecto ya están incluidos en el archivo requisitos.tx en la carpeta de código . Abra la pestaña de terminal de Pycharm e ingrese a la carpeta de código mediante el comando cd:
cd code
Luego pip instala los paquetes requeridos:
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
Normalmente, una vez configurado el entorno anterior, el código en la carpeta de códigos debería poder ejecutarse normalmente. Si no puede ejecutarse normalmente, puede haber un problema con el entorno de juego de Atari. Para obtener más detalles, consulte este artículo de CSDN: [gimnasio] Instalación de la nueva versión (0.21 o superior) y configuración del entorno Atari, súper simple (Windows).
02
Explicación del modelo de papel.
En pocas palabras, el documento diseña una red DQN, que apila 4 cuadros consecutivos de imágenes de juegos recortadas en 84X84 en entradas de 4X84X84, y luego usa convolución + ReLU, convolución + ReLU, aplanar, conexión completa + ReLU y conexión completa. el resultado correspondiente a la dimensión de acción. Aquí entrenamos y probamos principalmente el juego BreakOut (pinball y block). Hay 4 tipos de acciones correspondientes a este juego, por lo que la dimensión de salida aquí es 4.
La matriz de 4 dimensiones de salida representa los valores Q (s, a) correspondientes a las cuatro acciones respectivamente. El número correspondiente al valor Q más grande se selecciona como el código de acción generado por la red:
0: significa que no hay movimiento
1: Indica iniciar el juego (si el juego ya comenzó, entonces 1 aún no se mueve)
2: Indica desplazamiento a la derecha
3: Indica desplazamiento a la izquierda
Cálculo del tamaño de la convolución:
Tamaño de salida = (tamaño de entrada - tamaño del núcleo de convolución + 2 x relleno) / zancada + 1
Usando la red DQN anterior como agente, se puede realizar la interacción entre el agente y el entorno del juego. La red genera acciones basadas en las observaciones actuales
, controla el control deslizante en la parte inferior y los cambios en el entorno generan nuevas observaciones
. el control deslizante mueve con éxito la pelota. Rebota y golpea los bloques de arriba. Obtendrás una recompensa = 1 por cada bloque que golpees; de lo contrario, no habrá recompensa = 0.
Lo siguiente que debe resolverse es cómo el algoritmo de aprendizaje por refuerzo actualiza continuamente los parámetros de la red DQN del agente a través de la interacción entre el agente y el entorno, para que el agente aprenda a jugar.
El algoritmo de aprendizaje por refuerzo guarda la experiencia de interacción entre el agente y el entorno y puede obtener una serie de tuplas de experiencia, a saber (observación actual, acción, siguiente observación, recompensa, marca final). se puede expresar como:
Ingresamos la observación actual en la tupla de experiencia en la red, y la salida de la red es una matriz de 4 dimensiones, correspondiente a los valores de 4 acciones tomadas bajo la observación actual. De acuerdo con la acción real realizada por la observación actual en la tupla de experiencia , podemos obtener
de esta matriz el valor correspondiente a
la acción realizada por la observación actual . Este valor está obviamente relacionado con el parámetro actual θ de la red.
De hecho, según la ecuación de Bellman en la que se basa el aprendizaje por refuerzo, también podemos estimar el valor actual a través de la recompensa obtenida después de realizar la acción
y el valor esperado de la siguiente observación correspondiente. Este valor estimado es:
Para la situación de final del juego, solo existe la recompensa obtenida después de realizar la acción, no hay siguiente observación, por lo que la estimación del valor actual es la recompensa.
Para la situación en la que el juego no ha terminado, la estimación del valor actual incluye la recompensa obtenida, más el valor estimado más grande entre las 4 acciones realizadas en la siguiente observación, multiplicado por el factor de descuento γ. Este factor de descuento representa el valor actual y el. valor posterior. ¿Son estrechas las conexiones entre ellos? Si es 0, significa que no está cerca. El valor actual solo depende de la recompensa actual. Cuanto mayor sea γ, más cercana será la conexión.
Ahora tenemos:
El valor estimado correspondiente a la acción tomada por la observación actual obtenida utilizando la red DQN .
El valor actual se estima utilizando la recompensa y el valor máximo estimado de la siguiente observación multiplicado por el factor de descuento . Según la ecuación de Bellman, las dos estimaciones deberían ser iguales; sin embargo, debido a que la estimación del valor de la red es inexacta, existe una diferencia entre las dos estimaciones:
El objetivo del algoritmo de aprendizaje por refuerzo profundo para el entrenamiento de redes es reducir la diferencia entre las dos estimaciones, de modo que la estrategia de la red DQN satisfaga la ecuación de Bellman, de modo que la red DQN pueda aprender la estrategia óptima de este juego. En el proceso de interacción de la red DQN del agente con el entorno, el propósito anterior se puede lograr utilizando las tuplas de experiencia guardadas para calcular la pérdida anterior y luego actualizando los parámetros de la red DQN con descenso de gradiente.
A continuación se brindará la implementación del código específico utilizando el marco MindSpore en el entorno Python y se brindarán las explicaciones correspondientes.
03
Implementación del código Shengsi MindSpore
Abra el archivo playing_atari.py en la carpeta de códigos. El significado específico del código es el siguiente:
3.1 Creación del entorno de juego
Después de importar las bibliotecas correspondientes, primero cree el entorno del entorno del juego:
env = gym.make("BreakoutNoFrameskip-v4") # 游戏环境
env = gym.wrappers.RecordEpisodeStatistics(env)
env = gym.wrappers.ResizeObservation(env, (84, 84)) # 设置图片放缩
env = gym.wrappers.GrayScaleObservation(env) # 设置图片为灰度图
env = gym.wrappers.FrameStack(env, 4) # 4帧图片堆叠在一起作为一个观测
env = MaxAndSkipEnv(env, skip=4) # 跳帧,一个动作维持4帧
El entorno se ha encapsulado aquí
env
y sus imágenes de salida se han preprocesado. Cada salida de observación es una imagen en escala de grises apilada de 4X84X84.
3.2 Definición de red DQN
Utilice Sengsi MindSpore para definir la red DQN, utilice directamente nn.SequentialCell() y defínala de acuerdo con la red diseñada:
class DQN(nn.Cell):
def __init__(self, nb_actions):
super().__init__()
self.network = nn.SequentialCell(
nn.Conv2d(in_channels=4, out_channels=16, kernel_size=8, stride=4, pad_mode='valid'),
nn.ReLU(),
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=4, stride=2, pad_mode='valid'),
nn.ReLU(),
nn.Flatten(),
nn.Dense(in_channels=2592, out_channels=256),
nn.ReLU(),
nn.Dense(in_channels=256, out_channels=nb_actions),
)
def construct(self, x):
return self.network(x / 255.)
construct() representa la salida de la red, similar a forward() en el marco de Pytorch.
3.3 Grupo de almacenamiento de experiencia de diseño
class ReplayBuffer():
def __init__(self, replay_memory_size):
def add(self, obs, next_obs, action, reward, done):
def sample(self, sample_num):
...
return Tensor(temp_obs, ms.float32), Tensor(temp_next_obs, ms.float32), Tensor(temp_action, ms.int32), Tensor(temp_reward, ms.float32), Tensor(temp_done, ms.float32)
El código específico no se publicará aquí. En pocas palabras, realiza el almacenamiento de tuplas de experiencia y el muestreo por lotes para facilitar el entrenamiento posterior de la red neuronal.
3.4 Definición de función de pérdida, optimizador y función de entrenamiento
Primero cree una instancia de una red para la clase DQN definida
q_network
, luego defina el optimizador comonn.Adam
y la función de pérdida comonn.HuberLOss()
q_network = DQN(nb_actions=env.action_space.n) # 网络实例化
optimizer = nn.Adam(params=q_network.trainable_params(), learning_rate=1.25e-4) # 优化器
loss_fn = nn.HuberLoss() # 损失函数
Los siguientes son los pasos exclusivos de MindSpore al definir el entrenamiento de red, llamado diferenciación automática funcional. Puede consultar el tutorial sobre diferenciación automática funcional en el sitio web oficial . Específicamente, primero defina una función de cálculo de pérdida forward_fn
, luego genere una función de cálculo de gradiente basada en la función de cálculo de pérdida grad_fn
y luego use la función de cálculo de gradiente para definir una función para un paso del entrenamiento de la red train_step
. De esta manera, al usar train_step
la función, solo necesita ingresar los datos requeridos y puede actualizar los parámetros de la red una vez y completar la capacitación en un solo paso.
# 损失值计算函数
def forward_fn(observations, actions, y):
current_q_value = q_network(observations).gather_elements(dim=1, index=actions).squeeze() # 把经验对中这个动作对应的q_value给提取出来
loss = loss_fn(current_q_value, y)
return loss
En
forward_fn
la función, se completa el cálculo del valor estimado. En el código
current_q_value
, se requiere que la red DQN calcule el valor Q en esta función. El gradiente de pérdida posterior se propagará hacia atrás a los parámetros de la red DQN en este proceso de cálculo. Actualizaciones para redes neuronales.
Tenga en cuenta
y
que la entrada de la funciónse ingresa después de que se calcula fuera de la función, porque
el cálculo de about también requiere la red DQN, y el gradiente de pérdida no debe propagarse hacia atrás en
el proceso de cálculo de about, de lo contrario, los parámetros de la red no se actualizará. Por lo tanto,
el cálculo sobre debe calcularse fuera de la función y luego ingresarse en
forward_fn
.
# 损失梯度函数
grad_fn = ms.ops.value_and_grad(forward_fn, None, optimizer.parameters)
# 参考:https://www.mindspore.cn/tutorials/zh-CN/r2.1/beginner/autograd.html
# 训练一步的函数
def train_step(observations, actions, y):
loss, grads = grad_fn(observations, actions, y)
optimizer(grads)
return loss
ms.ops.value_and_grad
Utilizando la función de cálculo de pérdidas definidaforward_fn
, se puede devolver una función de cálculo de gradiente grad_fn.Luego, en la función de entrenamiento
train_step
, podemosgrad_fn
calcular el gradiente y luego usar el optimizadoroptimizer
para realizar la retropropagación del gradiente, actualizar los parámetros de la red y completar el entrenamiento en un solo paso.
3.4 Capacitación en red
A continuación, puede entrenar la red. Aquí hay algunas explicaciones de los códigos clave principales:
def Deep_Q_Learning(env, replay_memory_size=100_000, nb_epochs=40000_000, update_frequency=4, batch_size=32,
discount_factor=0.99, replay_start_size=5000, initial_exploration=1, final_exploration=0.01,
exploration_steps=100_000):
Primero, defina los parámetros relevantes necesarios para el entrenamiento, incluido el tamaño de capacidad del grupo de experiencias 100_000, el total de épocas de entrenamiento = 40000_000, los parámetros de red se actualizan cada 4 épocas, el factor de descuento es 0,99, el entrenamiento comienza cuando el grupo de experiencias está lleno de 5000 y la probabilidad de exploración inicial es 1. El total de épocas de exploración es 100_000
La exploración aquí significa que para que DQN aprenda una mejor estrategia, las acciones se generan aleatoriamente para la exploración antes del entrenamiento. La probabilidad de exploración disminuirá gradualmente y luego dependerá completamente de DQN para generar acciones. Esta estrategia se denomina ε-codiciosa. estrategia.
Antes de entrenar, configure la red en modo de entrenamiento:
q_network.set_train() # 设置网络为训练模式
Luego deje que DQN interactúe con el juego, y el código correspondiente para generar acciones es (exploración aleatoria o acciones generadas por DQN):
if random.random() < epsilon: # With probability ε select a random action a
action = np.array(env.action_space.sample())
else: # Otherwise select a = max_a Q∗(φ(st), a; θ)
temp_input = Tensor(obs, ms.float32).unsqueeze(0)
q_values = q_network(temp_input)
action = q_values.argmax(axis=1).item().asnumpy()
Guarde cada tupla de experiencia en el grupo de experiencias:
rb.add(obs, real_next_obs, action, reward, done)
Elija un lote de tuplas de experiencia del grupo de experiencias, calcule los valores y use
train_step
la función para actualizar los parámetros de la red:
data_obs, data_next_obs, data_action, data_reward, data_done = rb.sample(batch_size)
# 这一部分不用求梯度,所以写在forward_fn和train_step函数之外
max_q_value = q_network(data_next_obs).max(1)
y = data_reward.flatten() + discount_factor * max_q_value * (1 - data_done.flatten())
loss = train_step(data_obs, data_action, y)
Tenga en cuenta
que se calcula aquí, porque no es necesario realizar una retropropagación del gradiente en el
proceso de cálculo, por lo que primero se calcula aquí y luego se ingresa a la
train_step
función previamente definida para completar una sesión de entrenamiento.
Luego viene el largo proceso de formación, que duró unos 10 días utilizando mi propio ordenador portátil. Probé la velocidad de entrenamiento en mi computadora portátil y es aproximadamente la misma que la de Pytorch. Ascend MindSpore puede usar Huawei Ascend 910 (chip de IA desarrollado por Huawei) para acelerar el entrenamiento, pero como mal estudiante, lo pienso, así que me gustaría probarlo con vivo50 (`・ω・´).
La curva de entrenamiento es la siguiente. El resultado del entrenamiento realizado por el jefe en github usando Pytorch es de aproximadamente 200. Limitado por la memoria del portátil de 16 g, el mejor resultado que se puede entrenar con la capacidad actual del grupo de experiencias es de aproximadamente 150.
04
Resultados experimentales
Se puede ver que después del entrenamiento, DQN ha aprendido a jugar este juego. Generalmente puede conseguir unos 150 puntos. Si tienes suerte, puedes conseguir 300 puntos de esta manera.
Un programador nacido en los años 90 desarrolló un software de portabilidad de vídeo y ganó más de 7 millones en menos de un año. ¡El final fue muy duro! Google confirmó despidos, relacionados con la "maldición de 35 años" de los codificadores chinos en los equipos Python Flutter Arc Browser para Windows 1.0 en 3 meses oficialmente GA La participación de mercado de Windows 10 alcanza el 70%, Windows 11 GitHub continúa disminuyendo. GitHub lanza la herramienta de desarrollo nativo de IA GitHub Copilot Workspace JAVA. es la única consulta de tipo fuerte que puede manejar OLTP + OLAP. Este es el mejor ORM. Nos encontramos demasiado tarde.