Partage de projet | Comment mettre en œuvre l'apprentissage par renforcement pour jouer à des jeux via MindSpore

Auteur : Hamwon 

Résumé

"Playing Atari with Deep Reinforcement Learning" est le premier document classique d'apprentissage par renforcement profond qui combine l'apprentissage par renforcement et l'apprentissage profond. Il a été conçu et développé par l'équipe DeepMind. L'algorithme a été testé dans l'environnement de jeu Atari 2600 et ses performances de test ont été testées. certains jeux étaient meilleurs que les joueurs humains.

URL de l'article : https://paperswithcode.com/paper/playing-atari-with-deep-reinforcement

01

Créer un projet d'environnement virtuel avec Pycharm

Le code du projet et les résultats de la formation ont été téléchargés sur Baidu Netdisk et peuvent être téléchargés en premier. Cependant, comme l'environnement virtuel est trop volumineux, vous devez le télécharger et l'installer vous-même. Pour des opérations spécifiques, veuillez consulter l'introduction. ci-dessous.
Lien : https://pan.baidu.com/s/1zoh0glqH4xcNSbOUuR2r7g?pwd=00wdCode
d'extraction : 00wd

Créez d'abord un nouveau projet à l'aide de Pycharm, puis ajoutez l'environnement virtuel dans les paramètres comme indiqué ci-dessous :

Le but de la création d'un projet d'environnement virtuel est de séparer l'environnement d'exécution du projet actuel de votre propre environnement Python. Vous installerez ensuite les packages requis dans l'environnement virtuel pour éviter d'affecter votre environnement Python précédent. La version de Pycharm que j'utilise est la version 2019. Les paramètres de la nouvelle version de Pycharm devraient être similaires. Vous pouvez Baidu en fonction de votre propre situation. Le chemin Anaconda de chacun est différent et vous devez choisir l'interprète de base en fonction de votre emplacement d'installation.

Pour la configuration de l'environnement virtuel, reportez-vous à l'article CSDN : Pycharm crée et gère un environnement virtuel.

image

Une fois l'environnement virtuel créé, vous devez toujours configurer le programme du terminal dans les paramètres :

image

À ce stade, ouvrez l'onglet terminal sous Pycharm et vous pourrez voir l'invite (venv) devant le terminal, indiquant que le terminal actuel est dans un environnement virtuel :

image

À l’heure actuelle, tous les packages dont nous avons besoin peuvent être installés via pip dans ce terminal.

N'oubliez pas de copier les trois dossiers code, Imgs et modèle téléchargés depuis Baidu Cloud dans le dossier du projet actuel. Les packages Python requis pour le projet sont déjà inclus dans le fichier requis.tx sous le dossier code . Ouvrez l'onglet terminal de Pycharm et entrez le dossier code via la commande cd :

cd code

Ensuite, pip installe les packages requis :

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

Normalement, une fois l'environnement ci-dessus configuré, le code dans le dossier de code devrait pouvoir s'exécuter normalement. S'il ne peut pas fonctionner normalement, il peut y avoir un problème avec l'environnement de jeu d'Atari. Pour plus de détails, veuillez vous référer à cet article CSDN : [gym] Installation d'une nouvelle version (0.21 ou supérieure) et configuration de l'environnement Atari, super simple (Windows).

02

Explication du modèle papier

Pour faire simple, l'article conçoit un réseau DQN, qui empile 4 images consécutives d'images de jeu recadrées en 84X84 en entrée 4X84X84, puis utilise convolution + ReLU, convolution + ReLU, Flatten, connexion complète + ReLU et connexion complète Get . la sortie correspondant à la dimension d’action. Ici nous entraînons et testons principalement le jeu BreakOut (flipper et block). Il existe 4 types d'actions correspondant à ce jeu, donc la dimension de sortie ici est de 4.

Le tableau à 4 dimensions de sortie représente les valeurs Q(s,a) correspondant respectivement aux quatre actions. Le nombre correspondant à la plus grande valeur Q est sélectionné comme code d'action émis par le réseau :

0 : signifie aucun mouvement

1 : Indique le début de la partie (si la partie a déjà commencé, alors 1 ne bouge toujours pas)

2 : Indique un décalage vers la droite

3 : Indique un décalage vers la gauche

Calcul de la taille de convolution :

Taille de sortie = (taille d'entrée - taille du noyau de convolution + 2 x remplissage) / foulée + 1

image

En utilisant le réseau DQN ci-dessus en tant qu'agent, l'interaction entre l'agent et l'environnement de jeu peut être réalisée. Le réseau imagegénère des actions basées sur les observations actuelles image, contrôle le curseur en bas et les changements dans l'environnement génèrent de nouvelles observations image. le curseur déplace avec succès la balle. Rebondissez et frappez les blocs ci-dessus. Vous obtiendrez une récompense = 1 pour chaque bloc que vous frappez, sinon il n'y aura pas de récompense = 0.

La prochaine chose à résoudre est de savoir comment l'algorithme d'apprentissage par renforcement met à jour en permanence les paramètres du réseau DQN de l'agent grâce à l'interaction entre l'agent et l'environnement, afin que l'agent apprenne à jouer au jeu.

L'algorithme d'apprentissage par renforcement enregistre l'expérience d'interaction entre l'agent et l'environnement et peut obtenir une série de tuples d'expérience, à savoir (observation actuelle, action, observation suivante, récompense, marque de fin). peut être exprimé comme suit :

image

Nous entrons l'observation actuelle dans le imagetuple d'expérience dans le réseau, et la sortie du réseau est un tableau à 4 dimensions, correspondant aux valeurs de 4 actions entreprises sous l'observation actuelle. Selon l'action réelle de l'observation actuelle dans le tuple d'expérience , nous pouvons obtenir imageà partir de ce tableau la valeur correspondant à imagel'action de l'observation actuelle . Cette valeur est évidemment liée au paramètre actuel θ du réseau.imageimage

En fait, selon l'équation de Bellman sur laquelle repose l'apprentissage par renforcement, on peut également estimer la valeur actuelle à travers imagela récompense obtenue après avoir effectué l'action imageet la valeur attendue de la prochaine observation correspondante. Cette valeur estimée est :

image

Pour la situation de fin de jeu, il n'y a que la récompense obtenue après avoir effectué l'action, il n'y a pas d'observation suivante, donc l'estimation de la valeur actuelle est la récompense.

Pour la situation où le jeu n'est pas terminé, l'estimation de la valeur actuelle inclut la récompense obtenue, plus la plus grande valeur estimée parmi les 4 actions entreprises dans l'observation suivante, multipliée par le facteur d'actualisation γ. Ce facteur d'actualisation représente la valeur actuelle et la valeur actuelle. valeur ultérieure. Les liens entre eux sont-ils étroits ? Si 0, cela signifie qu'il n'est pas proche. La valeur actuelle dépend uniquement de la récompense actuelle. Plus le γ est grand, plus la connexion est étroite.

Maintenant nous avons:

La valeur estimée correspondant à imagel'action entreprise par l'observation actuelle obtenue à l'aide du réseau DQN .imageimage

La valeur actuelle est estimée en utilisant la récompense et la valeur estimée maximale de l'observation suivante multipliée par le facteur d'actualisation image. Selon l'équation de Bellman, les deux estimations devraient être égales, mais comme l'estimation de la valeur par le réseau est inexacte, il existe une différence entre les deux estimations :

image

L'objectif de l'algorithme d'apprentissage par renforcement profond pour la formation en réseau est de réduire la différence entre les deux estimations, afin que la stratégie du réseau DQN satisfasse l'équation de Bellman, afin que le réseau DQN puisse apprendre la stratégie optimale de ce jeu. Dans le processus d'interaction du réseau DQN d'agent avec l'environnement, l'objectif ci-dessus peut être atteint en utilisant les tuples d'expérience enregistrés pour calculer la perte ci-dessus, puis en mettant à jour les paramètres du réseau DQN avec descente de gradient.

Ce qui suit donnera l'implémentation spécifique du code à l'aide du framework MindSpore dans l'environnement Python et donnera les explications correspondantes.

03

Implémentation du code Shengsi MindSpore

Ouvrez le fichier Playing_atari.py dans le dossier code. La signification spécifique du code est la suivante :

3.1 Création de l'environnement de jeu

Après avoir importé les bibliothèques correspondantes, créez d'abord l'environnement de jeu env :

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帧

L'environnement a été encapsulé ici envet ses images de sortie ont été prétraitées. Chaque sortie d'observation est une image en niveaux de gris empilée 4X84X84.

3.2 Définition du réseau DQN

Utilisez Sengsi MindSpore pour définir le réseau DQN, utilisez directement nn.SequentialCell() et définissez-le en fonction du réseau conçu :

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() représente la sortie du réseau, similaire à forward() dans le framework Pytorch

3.3 Conception d'un pool de stockage d'expérience

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)

Le code spécifique ne sera pas publié ici. En termes simples, il réalise le stockage des tuples d'expérience et l'échantillonnage par lots pour faciliter la formation ultérieure du réseau neuronal.

3.4 Définition de la fonction de perte, de l'optimiseur et de la fonction de formation

Instanciez d'abord un réseau pour la classe DQN définie q_network, puis définissez l'optimiseur comme nn.Adamet la fonction de perte commenn.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()  # 损失函数

Voici les étapes propres à MindSpore lors de la définition de la formation réseau, appelée différenciation automatique fonctionnelle. Vous pouvez vous référer au tutoriel sur la différenciation automatique fonctionnelle sur le site officiel . Plus précisément, définissez d'abord une fonction de calcul de perte forward_fn, puis générez une fonction de calcul de gradient basée sur la fonction de calcul de perte grad_fn, puis utilisez la fonction de calcul de gradient pour définir une fonction pour une étape de formation du réseau train_step. De cette façon, en utilisant train_stepla fonction, il vous suffit de saisir les données requises, et vous pouvez mettre à jour les paramètres du réseau une fois et suivre une formation en une étape.

# 损失值计算函数
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

Dans forward_fnla fonction, le calcul de l'estimation de la valeur est terminé image. Dans le Code current_q_value, le réseau DQN doit calculer la valeur Q dans cette fonction. Le gradient de perte ultérieur sera rétropropagé aux paramètres du réseau DQN dans ce processus de calcul. . Mises à jour pour les réseaux de neurones.

Notez yque l'entrée de la fonction imageest entrée après avoir été calculée en dehors de la fonction, car imagele calcul d'environ nécessite également le réseau DQN, et le gradient de perte ne doit pas être rétropropagé dans imagele processus de calcul d'environ, sinon les paramètres du réseau seront ne soit pas mis à jour. Par conséquent, imagele calcul concernant doit être effectué en dehors de la fonction, puis saisi dans 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_gradEn utilisant la fonction de calcul de perte définie forward_fn, une fonction de calcul de gradient grad_fn peut être renvoyée.

Ensuite, dans la fonction de formation train_step, nous pouvons grad_fncalculer le gradient, puis utiliser l'optimiseur optimizerpour effectuer une rétropropagation du gradient, mettre à jour les paramètres du réseau et effectuer une formation en une étape.

3.4 Formation réseau

Ensuite, vous pouvez entraîner le réseau. Voici quelques explications sur les principaux codes clés :

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):

Tout d'abord, définissez les paramètres pertinents requis pour la formation, y compris la taille de la capacité du pool d'expérience 100_000, le nombre total d'époques de formation = 40 000_000, les paramètres du réseau sont mis à jour toutes les 4 époques, le facteur de remise est de 0,99, la formation commence lorsque le pool d'expérience est plein de 5 000. , et la probabilité d'exploration initiale est de 1. Le nombre total d'époques d'exploration est de 100_000

L'exploration signifie ici que pour que DQN apprenne une meilleure stratégie, les actions sont générées aléatoirement pour l'exploration avant la formation. La probabilité d'exploration diminuera progressivement, puis elle s'appuiera entièrement sur DQN pour générer des actions. Cette stratégie est appelée ε-gourmande. stratégie.

Avant l'entraînement, réglez le réseau en mode entraînement :

q_network.set_train()  # 设置网络为训练模式

Laissez ensuite DQN interagir avec le jeu, et le code correspondant pour générer des actions est (exploration aléatoire ou actions générées par 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()

Enregistrez chaque tuple d’expérience dans le pool d’expériences :

rb.add(obs, real_next_obs, action, reward, done)

Choisissez un lot de tuples d'expérience dans le pool d'expériences, calculez imageles valeurs et utilisez train_stepla fonction pour mettre à jour les paramètres réseau :

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)

Notez imagequ'il est calculé ici, car il n'est pas nécessaire de rétropropager le gradient dans le imageprocessus de calcul, il est donc calculé ici d'abord, puis entré dans la train_stepfonction définie précédemment pour terminer une session de formation.

Vient ensuite le long processus de formation, qui a duré environ 10 jours sur mon propre ordinateur portable. J'ai testé la vitesse d'entraînement sur mon ordinateur portable et c'est à peu près la même chose que Pytorch. Ascend MindSpore peut utiliser Huawei Ascend 910 (puce AI développée par Huawei) pour accélérer la formation, mais en tant qu'étudiant pauvre, j'y pense, alors j'aimerais essayer avec vivo50 (`・ω・´).

La courbe de formation est la suivante.Le résultat de la formation par le patron sur github à l'aide de Pytorch est d'environ 200. Limité par la mémoire du portable de 16 Go, le meilleur résultat pouvant être formé avec la capacité actuelle du pool d'expériences est d'environ 150.

image

04

Résultats expérimentaux

On peut voir qu'après l'entraînement, DQN a appris à jouer à ce jeu. Généralement, il peut obtenir environ 150 points. Si vous avez de la chance, vous pouvez obtenir 300 points comme ceci :

image

 

Un programmeur né dans les années 1990 a développé un logiciel de portage vidéo et en a réalisé plus de 7 millions en moins d'un an. La fin a été très éprouvante ! Google a confirmé les licenciements, impliquant la « malédiction des 35 ans » des codeurs chinois des équipes Flutter, Dart et . Python Arc Browser pour Windows 1.0 en 3 mois officiellement la part de marché de GA Windows 10 atteint 70 %, Windows 11 GitHub continue de décliner l'outil de développement natif d'IA GitHub Copilot Workspace JAVA. est la seule requête de type fort capable de gérer OLTP+OLAP. C'est le meilleur ORM. Nous nous rencontrons trop tard.
{{o.name}}
{{m.nom}}

Je suppose que tu aimes

Origine my.oschina.net/u/4736317/blog/11072521
conseillé
Classement