J'ai essayé d'implémenter PPO en Python

À propos de PPO

PPO est l'un des algorithmes d'apprentissage par renforcement profond, parmi lesquels il est basé sur des politiques. Une base de politique est un algorithme qui optimise directement une fonction de politique qui génère une probabilité d'action dans un environnement. D'autres algorithmes basés sur des politiques incluent A3C et TRPO. Les algorithmes non basés sur des politiques incluent des algorithmes basés sur des valeurs tels que DQN.

Comparaison avec d'autres méthodes

Tout d'abord, je vais expliquer d'autres méthodes.

À propos d'A3C

Il existe trois techniques typiques utilisées dans A3C: Actor-Critic, Advantage et Asynchronous.

Actor-Critic Actor-Critic est une caractéristique de la structure du réseau. En A3C comme fonction objective de la politique

L_{policy}=A(t)log\pi_{\theta}(a_{t}|s_{t})

Est utilisé. Parmi ceux-ci, A (t) est appelée la fonction avantage.

A(t)=(R(t)-V(s_{t}))

Il est représenté par. Puisque la fonction valeur V (s) est utilisée pour obtenir ce A (t), il s'agit d'une méthode de construction d'un modèle de sorte que la valeur d'état devienne la sortie du réseau en même temps que la politique (distribution de probabilité d'action). Cela vous permettra d'apprendre plus rapidement.

Advantage Utilisez l'erreur suivante pour mettre à jour la fonction de valeur d'état normal $ V (t) $

loss=r(s_{t})+\gamma V(s_{t+1})-V(s_{t})

Nous apprendrons $ V (s) $ à satisfaire. Cependant, avec cette méthode, si le nombre d'étapes dans un épisode est important, le nombre d'apprentissages nécessaires pour se propager aux étapes où l'influence de l'apprentissage est précoce augmente et l'apprentissage devient lent. Par conséquent, Advantage utilise l'erreur suivante.

loss=\sum_{k=1}^n \gamma^{k-1} r(s_{t+k})+\gamma^n V(s_{t+2})-V(s_{t})

En ajustant $ n $ dans cette équation, les effets de l'apprentissage ultérieur se propageront plus rapidement, mais s'il est trop grand, la vitesse d'apprentissage ralentira. Par exemple, CartPole n'est pas très efficace et dans certains cas, il peut être plus rapide de ne pas utiliser Advantage. Asynchronous Asynchrone est une méthode liée aux méthodes d'apprentissage. Normalement, lors d'une recherche avec un agent, la direction de l'apprentissage a tendance à être biaisée. En guise de contre-mesure, la recherche est effectuée à l'aide d'un réseau de neurones partagé et de plusieurs agents, et chacun comporte un nombre fixe d'étapes. Au fil du temps, ou à la fin d'un épisode, chaque agent met à jour les paramètres réseau partagés pour un gradient sur les paramètres de fonction objectif.

Chaque agent dispose également d'un réseau neuronal qui copie les paramètres du réseau partagé et effectue des recherches avant le début de l'épisode. Cela évitera les biais dans l'apprentissage, comme le tampon de relecture dans DQN.

Fonction objectif A3C

La fonction objectif d'A3C utilise trois méthodes: politique, valeur d'état et entropie pour la régularisation.

\begin{align}
L_{policy} &= A(t)log\pi_{\theta}(a_{t}|s_{t})\\
L_{value} &= (R(t)-V(s_{t}))^2\\
L_{entropy} &= \pi_{\theta}(a_{t}|s_{t})log\pi_{\theta}(a_{t}|s_{t})
\end{align}

Il est exprimé comme, et finalement il devient la formule suivante sous forme de combinaison de ceux-ci.

L_{all} = -L_{policy}+C_{value}L_{value}-C_{entropy}L_{entropy}

$ C_ {valeur} $ et $ C_ {entropie} $ représentent des constantes. L'apprentissage se fait en minimisant cela.

À propos de PPO

Dans A3C, le gradient de politique est

\Delta L_{policy} = \Delta log\pi_{\theta}(a_{t}|s_{t})A(t)

Il est exprimé comme, et comme $ log $ est inclus dans l'expression, il devient très grand lors de la mise à jour. Par conséquent, dans PPO, en limitant la mise à jour, il est possible d'éviter une sur-mise à jour. De plus, la fonction objectif est très différente de A3C.

r_{t}(\theta)=\frac{\pi_{\theta_{new}}(a_{t}|s_{t})}{\pi_{\theta_{old}}(a_{t}|s_{t})}\\
L^{CPI}=\mathbb E \big[\,r_{t}(\theta)A(t)\, \big]

Utilisez-la comme fonction d'objectif de substitution et utilisez la fonction de clip lors de la mise à jour pour en faire la fonction objectif de la stratégie. fonction de clip

clip(x,a,b)=\left\{
\begin{array}{ll}
b & (x > b) \\
x & (a \leq x \leq b) \\
a & (x < a)
\end{array}
\right.

Exprimé de cette façon, peu importe comment $ x $ change, il se situera entre $ a $ et $ b $. La fonction objectif utilisant cette fonction

L_{policy}=min \big(\, r_{t}(\theta)A(t),clip(r_{t}(\theta),1-\epsilon,1+\epsilon)\, \big)

Est exprimé comme. En ce qui concerne la fonction de valeur d'état, c'est presque la même chose que PPO.

De plus, PPO apprend également à utiliser Advantage de la même manière que A3C.

la mise en oeuvre

J'ai fait référence au site suivant lors de la mise en œuvre [Renforcement de l'apprentissage] PPO pour apprendre tout en mettant en œuvre [Standing with Cart Pole: Complete with 1 file]

Vue d'ensemble du traitement

main (): créer un thread et effectuer le traitement

Worker(thread_type, thread_name, ppo_brain) -run_thread (): Traitement séparé par type de thread -env_run (): Laisse l'agent explorer dans l'environnement.

ppo_agent(ppo_brain) -action (état): reçoit l'état et émet l'action -greedy_action (state): action de sortie en utilisant la méthode $ \ epsilon-greedy $ -update (mémoire): Apprenez les données enregistrées lors de la recherche en tenant compte de l'avantage ppo_brain() -build_graph: Définissez ici la forme du graphique -update: mise à jour

main

def main(args):
    #Processus pour créer un fil
    with tf.device("/cpu:0"):
        brain = ppo_brain()
        thread=[]
        for i in range(WORKER_NUM):
            thread_name = "local_thread"+str(i)
            thread.append(Worker(thread_type = "train",thread_name = thread_name,brain = brain))
    
    COORD = tf.train.Coordinator()
    SESS.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    
  #Chargez le processus de formation précédent, faites-le après avoir défini le modèle
    if args.load:
        ckpt = tf.train.get_checkpoint_state(MODEL_DIR)
        if ckpt:
            saver.restore(SESS,MODEL_SAVE_PATH)

    runnning_thread=[]
    for worker in thread:
        job = lambda: worker.run_thread()
        t = threading.Thread(target=job)
        t.start()
        runnning_thread.append(t)
    COORD.join(runnning_thread)
   
    #Faites un test lorsque l'apprentissage est terminé
    test = Worker(thread_type = "test",thread_name = "test_thread",brain=brain)
    test.run_thread()

    if args.save:
        saver.save(SESS,MODEL_SAVE_PATH)
        print("saved")

Worker

class Worker:
    def __init__(self,thread_type,thread_name,brain):
        self.thread_type = thread_type
        self.name = thread_name
        self.agent = ppo_agent(brain)
        self.env = gym.make(ENV_NAME)
        #Enregistrez la vidéo au moment du test
        if self.thread_type == "test" and args.video:
            self.env = wrappers.Monitor(self.env, VIDEO_DIR, force = True)
        self.leaning_memory = np.zeros(10)
        self.memory = []
        self.total_trial = 0

    def run_thread(self):
        while True:
            if self.thread_type == "train" and not isLearned:
                self.env_run()
            elif self.thread_type == "train" and isLearned:
                sleep(3)
                break
            elif self.thread_type == "test" and not isLearned:
                sleep(3)
            elif self.thread_type == "test" and isLearned:
                self.env_run()
                break

    def env_run(self):
        global isLearned
        global frame
        self.total_trial += 1

        step = 0
        observation = self.env.reset()

        while True:
            step += 1
            frame += 1
        
       #Choix d'action
            if self.thread_type == "train":
                action=self.agent.greedy_action(observation)
            elif self.thread_type == "test":
                self.env.render()
                sleep(0.01)
                action=self.agent.action(observation)
            
            next_observation,_,done,_ = self.env.step(action)

            reward = 0

            if done:
                if step >= 199:
                    reward = 1 #Au moment du succès
                else:
                    reward =- 1 #Au moment de l'échec
            else:
                #Quand ce n'est pas fini
                reward+=0
            
       #Enregistrer le résultat en mémoire
            self.memory.append([observation,action,reward,done,next_observation])

            observation = next_observation

            if done:
                break

     #Calculez le score moyen de 10 fois
        self.leaning_memory = np.hstack((self.leaning_memory[1:],step))
        print("Thread:",self.name," Thread_trials:",self.total_trial," score:",step," mean_score:",self.leaning_memory.mean()," total_step:",frame)

     #À la fin de l'apprentissage
        if self.leaning_memory.mean() >= 199:
            isLearned = True
            sleep(3)
        else:
            #Mise à jour des paramètres
            self.agent.update(self.memory)
            self.memory = []
        

ppo_agent

class ppo_agent:
    def __init__(self,brain):
        self.brain=brain
        self.memory=[]

    #Agir sans éléments aléatoires
    def action(self,state):
        prob,v = self.brain.predict(state)
        return np.random.choice(ACTION_LIST,p = prob)

    #Agir au hasard avec une certaine probabilité
    def greedy_action(self,state):
        if frame >= EPS_STEPS:   
            eps = EPS_END
        else:
            eps = EPS_START + frame* (EPS_END - EPS_START) / EPS_STEPS  

        if np.random.random() <= eps:
            return np.random.choice(ACTION_LIST)
        else:
            return self.action(state)

    #Traiter le résultat de la recherche et le PPO_Envoyer au cours de cerveau
    def update(self,memory):
        R = sum([memory[j][2] * (GAMMA ** j) for j in range(ADVANTAGE + 1)])
        self.memory.append([memory[0][0], memory[0][1], R,memory[0][3], memory[0][4], GAMMA ** ADVANTAGE])

        #Considérez l'avantage
        for i in range(1, len(memory) - ADVANTAGE):
            R = ((R - memory[i-1][2]) / GAMMA) + memory[i + ADVANTAGE][2] * (GAMMA ** (ADVANTAGE - 1))
            self.memory.append([memory[i][0], memory[i][1], R,memory[i + ADVANTAGE][3], memory[i][4],GAMMA ** ADVANTAGE])
            
        for i in range(ADVANTAGE - 1):
            R = ((R - memory[len(memory) - ADVANTAGE + i][2]) / GAMMA)
            self.memory.append([memory[i][0], memory[i][1], R, True, memory[i][4], GAMMA ** (ADVANTAGE - i)])

        #ppo_Envoyer des données à la classe de cerveau pour mettre à jour
        self.brain.update(self.memory)

        self.memory = []

ppo_brain

class ppo_brain:
    def __init__(self):
        self.build_model()
        self.name="brain"
        self.prob_old=1.0

    def build_model(self):
        self.input=tf.placeholder(dtype=tf.float32,shape=[None,STATE_NUM])
       
        #Ici, l'ancien modèle de paramètre et le nouveau modèle de paramètre sont définis, et la probabilité d'action et la valeur d'état sont sorties pour la même entrée.
        #Nouveau réseau
        with tf.variable_scope("current_brain"):
            hidden1=tf.layers.dense(self.input,HIDDEN_LAYERE,activation=tf.nn.leaky_relu)
            self.prob=tf.layers.dense(hidden1,ACTION_NUM,activation=tf.nn.softmax)
            self.v=tf.layers.dense(hidden1,1)
        #Ancien réseau
        with tf.variable_scope("old_brain"):
            old_hiddend1=tf.layers.dense(self.input,HIDDEN_LAYERE,activation=tf.nn.leaky_relu)
            self.old_prob=tf.layers.dense(hidden1,ACTION_NUM,activation=tf.nn.softmax)
            self.old_v=tf.layers.dense(hidden1,1)

        self.reward=tf.placeholder(dtype=tf.float32,shape=(None,1))
        self.action=tf.placeholder(dtype=tf.float32,shape=(None,ACTION_NUM))

###########Voici la définition de la fonction de perte############
        #Définition de la fonction d'avantage
        advantage = self.reward-self.v

        #Définition faisant partie de la fonction de perte du contrat
        r_theta = tf.div(self.prob + 1e-10, tf.stop_gradient(self.old_prob) + 1e-10)
        action_theta = tf.reduce_sum(tf.multiply(r_theta, self.action), axis = 1, keepdims = True)
        #Calculer le clip de r
        r_clip = tf.clip_by_value(action_theta, 1 - EPSIRON, 1 + EPSIRON)
        #Lorsque vous utilisez la fonction avantage comme fonction objectif de la politique, le gradient n'est pas pris en compte, alors arrêtez_Utiliser le dégradé
        advantage_cpi = tf.multiply(action_theta, tf.stop_gradient(advantage))
        advantage_clip = tf.multiply(r_clip , tf.stop_gradient(advantage))
        self.policy_loss = tf.minimum(advantage_clip , advantage_cpi)

        #Fonction de perte de valeur d'état
        self.value_loss = tf.square(advantage)

        #Définition de l'entropie
        self.entropy = tf.reduce_sum(self.prob*tf.log(self.prob+1e-10),axis = 1,keepdims = True)

        #Définition de la fonction de perte finale
        self.loss = tf.reduce_sum(-self.policy_loss + LOSS_V * self.value_loss - LOSS_ENTROPY * self.entropy)

##############Ce qui suit définit les actions requises pour la mise à jour##############

        #Mise à jour des paramètres (minimisée à l'aide d'Adam)
        self.opt = tf.train.AdamOptimizer(learning_rate = LEARNING_RATE)
        self.minimize = self.opt.minimize(self.loss)

        #Obtenez de nouveaux et anciens paramètres de leurs réseaux respectifs
        self.weight_param = tf.get_collection(key = tf.GraphKeys.TRAINABLE_VARIABLES, scope = "current_brain")
        self.old_weight_param = tf.get_collection(key = tf.GraphKeys.TRAINABLE_VARIABLES, scope = "old_brain")

        #Remplacer de nouveaux paramètres réseau par d'anciens paramètres réseau
        self.insert = [g_p.assign(l_p) for l_p,g_p in zip(self.weight_param,self.old_weight_param)]

    #Probabilité d'action de sortie et valeur d'état à partir de l'état
    def predict(self,state):
        state=np.array(state).reshape(-1,STATE_NUM)
        feed_dict={self.input:state}
        p,v=SESS.run([self.prob,self.v],feed_dict)
        return p.reshape(-1),v.reshape(-1)
    
    #Créer un lot par prétraitement avant de saisir des données
    #Mise à jour
    def update(self,memory):
        length=len(memory)
       
        s_=np.array([memory[j][0] for j in range(length)]).reshape(-1,STATE_NUM)
        a_=np.eye(ACTION_NUM)[[memory[j][1] for j in range(length)]].reshape(-1,ACTION_NUM)
        R_=np.array([memory[j][2] for j in range(length)]).reshape(-1,1)
        d_=np.array([memory[j][3] for j in range(length)]).reshape(-1,1)
        s_mask=np.array([memory[j][5] for j in range(length)]).reshape(-1,1)
        _s=np.array([memory[j][4] for j in range(length)]).reshape(-1,STATE_NUM)

        #Inférer la dernière valeur d'état
        _, v=self.predict(_s)
        #Calculez la récompense en tenant compte de l'avantage
        R=(np.where(d_,0,1)*v.reshape(-1,1))*s_mask+R_
        #Mise à jour des paramètres
        feed_dict={self.input:s_, self.action:a_, self.reward:R}

        SESS.run(self.minimize,feed_dict)
        #Mise à jour du réseau
        SESS.run(self.insert)

Code entier

Le code entier ressemble à ceci:

import argparse
import tensorflow as tf
import numpy as np
import random
import threading
import gym
from time import sleep
from gym import wrappers
from os import path

parser=argparse.ArgumentParser(description="Reiforcement training with PPO",add_help=True)
parser.add_argument("--model",type=str,required=True,help="model base name. required")
parser.add_argument("--env_name",default="CartPole-v0",help="environment name. default is CartPole-v0")
parser.add_argument("--save",action="store_true",default=False,help="save command")
parser.add_argument("--load",action="store_true",default=False,help="load command")
parser.add_argument("--thread_num",type=int,default=5)
parser.add_argument("--video",action="store_true",default=False, help="write this if you want to save as video")
args=parser.parse_args()


ENV_NAME=args.env_name
WORKER_NUM=args.thread_num
#define constants
VIDEO_DIR="./train_info/video"
MODEL_DIR="./train_info/models"
MODEL_SAVE_PATH=path.join(MODEL_DIR,args.model)

ADVANTAGE=2
STATE_NUM=4
ACTION_LIST=[0,1]
ACTION_NUM=2
#epsiron parameter
EPS_START = 0.5
EPS_END = 0.1
EPS_STEPS = 200 * WORKER_NUM**2
#learning parameter
GAMMA=0.99
LEARNING_RATE=0.002
#loss constants
LOSS_V=0.5
LOSS_ENTROPY=0.02
HIDDEN_LAYERE=30

EPSIRON = 0.2

class ppo_brain:
    def __init__(self):
        self.build_model()
        self.name="brain"
        self.prob_old=1.0

    def build_model(self):
        self.input=tf.placeholder(dtype=tf.float32,shape=[None,STATE_NUM])
       
        #Ici, l'ancien modèle de paramètre et le nouveau modèle de paramètre sont définis, et la probabilité d'action et la valeur d'état sont sorties pour la même entrée.
        with tf.variable_scope("current_brain"):
            hidden1=tf.layers.dense(self.input,HIDDEN_LAYERE,activation=tf.nn.leaky_relu)
            self.prob=tf.layers.dense(hidden1,ACTION_NUM,activation=tf.nn.softmax)
            self.v=tf.layers.dense(hidden1,1)
        with tf.variable_scope("old_brain"):
            old_hiddend1=tf.layers.dense(self.input,HIDDEN_LAYERE,activation=tf.nn.leaky_relu)
            self.old_prob=tf.layers.dense(hidden1,ACTION_NUM,activation=tf.nn.softmax)
            self.old_v=tf.layers.dense(hidden1,1)

        self.reward=tf.placeholder(dtype=tf.float32,shape=(None,1))
        self.action=tf.placeholder(dtype=tf.float32,shape=(None,ACTION_NUM))

###########Voici la définition de la fonction de perte############
        #Définition de la fonction d'avantage
        advantage = self.reward-self.v

        #Définition faisant partie de la fonction de perte du contrat
        r_theta = tf.div(self.prob + 1e-10, tf.stop_gradient(self.old_prob) + 1e-10)
        action_theta = tf.reduce_sum(tf.multiply(r_theta, self.action), axis = 1, keepdims = True)
        r_clip = tf.clip_by_value(action_theta, 1 - EPSIRON, 1 + EPSIRON)
        advantage_cpi = tf.multiply(action_theta, tf.stop_gradient(advantage))
        advantage_clip = tf.multiply(r_clip , tf.stop_gradient(advantage))
        self.policy_loss = tf.minimum(advantage_clip , advantage_cpi)

        #Fonction de perte de valeur d'état
        self.value_loss = tf.square(advantage)

        #Définition de l'entropie
        self.entropy = tf.reduce_sum(self.prob*tf.log(self.prob+1e-10),axis = 1,keepdims = True)

        #Définition de la fonction de perte finale
        self.loss = tf.reduce_sum(-self.policy_loss + LOSS_V * self.value_loss - LOSS_ENTROPY * self.entropy)

##############Ce qui suit définit les actions requises pour la mise à jour##############

        #Mise à jour des paramètres (minimisée à l'aide d'Adam)
        self.opt = tf.train.AdamOptimizer(learning_rate = LEARNING_RATE)
        self.minimize = self.opt.minimize(self.loss)

        #Obtenez de nouveaux et anciens paramètres de leurs réseaux respectifs
        self.weight_param = tf.get_collection(key = tf.GraphKeys.TRAINABLE_VARIABLES, scope = "current_brain")
        self.old_weight_param = tf.get_collection(key = tf.GraphKeys.TRAINABLE_VARIABLES, scope = "old_brain")

        #Remplacer de nouveaux paramètres réseau par d'anciens paramètres réseau
        self.insert = [g_p.assign(l_p) for l_p,g_p in zip(self.weight_param,self.old_weight_param)]

    #Probabilité d'action de sortie et valeur d'état à partir de l'état
    def predict(self,state):
        state=np.array(state).reshape(-1,STATE_NUM)
        feed_dict={self.input:state}
        p,v=SESS.run([self.prob,self.v],feed_dict)
        return p.reshape(-1),v.reshape(-1)
    
    #Créer un lot par prétraitement avant de saisir des données
    #Mise à jour
    def update(self,memory):
        length=len(memory)
       
        s_=np.array([memory[j][0] for j in range(length)]).reshape(-1,STATE_NUM)
        a_=np.eye(ACTION_NUM)[[memory[j][1] for j in range(length)]].reshape(-1,ACTION_NUM)
        R_=np.array([memory[j][2] for j in range(length)]).reshape(-1,1)
        d_=np.array([memory[j][3] for j in range(length)]).reshape(-1,1)
        s_mask=np.array([memory[j][5] for j in range(length)]).reshape(-1,1)
        _s=np.array([memory[j][4] for j in range(length)]).reshape(-1,STATE_NUM)

        #Inférer la dernière valeur d'état
        _, v=self.predict(_s)
        #Calculez la récompense en tenant compte de l'avantage
        R=(np.where(d_,0,1)*v.reshape(-1,1))*s_mask+R_
        #Mise à jour des paramètres
        feed_dict={self.input:s_, self.action:a_, self.reward:R}

        SESS.run(self.minimize,feed_dict)
        #Mise à jour du réseau
        SESS.run(self.insert)


class ppo_agent:
    def __init__(self,brain):
        self.brain=brain
        self.memory=[]

    #Agir sans éléments aléatoires
    def action(self,state):
        prob,v = self.brain.predict(state)
        return np.random.choice(ACTION_LIST,p = prob)

    #Agir au hasard avec une certaine probabilité
    def greedy_action(self,state):
        if frame >= EPS_STEPS:   
            eps = EPS_END
        else:
            eps = EPS_START + frame* (EPS_END - EPS_START) / EPS_STEPS  

        if np.random.random() <= eps:
            return np.random.choice(ACTION_LIST)
        else:
            return self.action(state)

    #Traiter le résultat de la recherche et le PPO_Envoyer au cours de cerveau
    def update(self,memory):
        R = sum([memory[j][2] * (GAMMA ** j) for j in range(ADVANTAGE + 1)])
        self.memory.append([memory[0][0], memory[0][1], R,memory[0][3], memory[0][4], GAMMA ** ADVANTAGE])

        #Considérez l'avantage
        for i in range(1, len(memory) - ADVANTAGE):
            R = ((R - memory[i-1][2]) / GAMMA) + memory[i + ADVANTAGE][2] * (GAMMA ** (ADVANTAGE - 1))
            self.memory.append([memory[i][0], memory[i][1], R,memory[i + ADVANTAGE][3], memory[i][4],GAMMA ** ADVANTAGE])
            
        for i in range(ADVANTAGE - 1):
            R = ((R - memory[len(memory) - ADVANTAGE + i][2]) / GAMMA)
            self.memory.append([memory[i][0], memory[i][1], R, True, memory[i][4], GAMMA ** (ADVANTAGE - i)])

        #ppo_Envoyer des données à la classe de cerveau pour mettre à jour
        self.brain.update(self.memory)

        self.memory = []


class Worker:
    def __init__(self,thread_type,thread_name,brain):
        self.thread_type = thread_type
        self.name = thread_name
        self.agent = ppo_agent(brain)
        self.env = gym.make(ENV_NAME)
        #Enregistrez la vidéo au moment du test
        if self.thread_type == "test" and args.video:
            self.env = wrappers.Monitor(self.env, VIDEO_DIR, force = True)
        self.leaning_memory = np.zeros(10)
        self.memory = []
        self.total_trial = 0

    def run_thread(self):
        while True:
            if self.thread_type == "train" and not isLearned:
                self.env_run()
            elif self.thread_type == "train" and isLearned:
                sleep(3)
                break
            elif self.thread_type == "test" and not isLearned:
                sleep(3)
            elif self.thread_type == "test" and isLearned:
                self.env_run()
                break

    def env_run(self):
        global isLearned
        global frame
        self.total_trial += 1

        step = 0
        observation = self.env.reset()

        while True:
            step += 1
            frame += 1

            if self.thread_type == "train":
                action=self.agent.greedy_action(observation)
            elif self.thread_type == "test":
                self.env.render()
                sleep(0.01)
                action=self.agent.action(observation)
            
            next_observation,_,done,_ = self.env.step(action)

            reward = 0

            if done:
                if step >= 199:
                    reward = 1 #Au moment du succès
                else:
                    reward =- 1 #Au moment de l'échec
            else:
                #Quand ce n'est pas fini
                reward+=0
            
       #Enregistrer le résultat en mémoire
            self.memory.append([observation,action,reward,done,next_observation])

            observation = next_observation

            if done:
                break

     #Calculez le score moyen de 10 fois
        self.leaning_memory = np.hstack((self.leaning_memory[1:],step))
        print("Thread:",self.name," Thread_trials:",self.total_trial," score:",step," mean_score:",self.leaning_memory.mean()," total_step:",frame)

     #À la fin de l'apprentissage
        if self.leaning_memory.mean() >= 199:
            isLearned = True
            sleep(3)
        else:
            #Mise à jour des paramètres
            self.agent.update(self.memory)
            self.memory = []

def main(args):
    #Processus pour créer un fil
    with tf.device("/cpu:0"):
        brain = ppo_brain()
        thread=[]
        for i in range(WORKER_NUM):
            thread_name = "local_thread"+str(i)
            thread.append(Worker(thread_type = "train",thread_name = thread_name,brain = brain))
    
    COORD = tf.train.Coordinator()
    SESS.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    
  #Chargez le processus de formation précédent, faites-le après avoir défini le modèle
    if args.load:
        ckpt = tf.train.get_checkpoint_state(MODEL_DIR)
        if ckpt:
            saver.restore(SESS,MODEL_SAVE_PATH)

    runnning_thread=[]
    for worker in thread:
        job = lambda: worker.run_thread()
        t = threading.Thread(target=job)
        t.start()
        runnning_thread.append(t)
    COORD.join(runnning_thread)
   
    #Faites un test lorsque l'apprentissage est terminé
    test = Worker(thread_type = "test",thread_name = "test_thread",brain=brain)
    test.run_thread()

    if args.save:
        saver.save(SESS,MODEL_SAVE_PATH)
        print("saved")

if __name__=="__main__":
    SESS=tf.Session()
    frame=0
    isLearned=False
    
    main(args)

print("end")

Résumé

C'est pourquoi j'ai implémenté PPO cette fois. Il semble qu'une caractéristique majeure de PPO est qu'il produit des résultats élevés malgré son mécanisme simple. J'ai fait un peu de recherche sur TRPO, mais le mécanisme semblait assez difficile, donc j'omettrai une explication détaillée cette fois. Ensuite, je voudrais résumer la mise en œuvre de PPO dans l'espace d'action continue ou d'autres méthodes.

Recommended Posts

J'ai essayé d'implémenter PPO en Python
J'ai essayé d'implémenter la permutation en Python
J'ai essayé d'implémenter PLSA dans Python 2
J'ai essayé d'implémenter ADALINE en Python
J'ai essayé d'implémenter TOPIC MODEL en Python
J'ai essayé d'implémenter le tri sélectif en python
J'ai essayé d'implémenter un pseudo pachislot en Python
J'ai essayé d'implémenter le poker de Drakue en Python
J'ai essayé d'implémenter GA (algorithme génétique) en Python
J'ai essayé d'implémenter un automate cellulaire unidimensionnel en Python
J'ai essayé d'implémenter la fonction d'envoi de courrier en Python
J'ai essayé d'implémenter le blackjack du jeu Trump en Python
J'ai essayé d'implémenter PCANet
J'ai essayé de mettre en œuvre un jeu de dilemme de prisonnier mal compris en Python
J'ai essayé d'implémenter StarGAN (1)
J'ai essayé d'implémenter la régression linéaire bayésienne par échantillonnage de Gibbs en python
J'ai essayé d'implémenter le jeu de cartes de Trump en Python
J'ai essayé de représenter graphiquement les packages installés en Python
Je veux facilement implémenter le délai d'expiration en python
J'ai essayé d'implémenter Mine Sweeper sur un terminal avec python
J'ai essayé de résumer comment utiliser les pandas de python
J'ai essayé d'implémenter Deep VQE
J'ai essayé de toucher Python (installation)
J'ai essayé de mettre en place une validation contradictoire
J'ai essayé d'implémenter Realness GAN
J'ai essayé la notification de ligne en Python
J'ai essayé d'implémenter ce qui semble être un outil de snipper Windows avec Python
J'ai essayé de créer une API list.csv avec Python à partir de swagger.yaml
J'ai essayé "Comment obtenir une méthode décorée en Python"
J'ai fait un chronomètre en utilisant tkinter avec python
J'ai essayé d'implémenter Autoencoder avec TensorFlow
Entrée standard Python3 que j'ai essayé de résumer
J'ai essayé d'utiliser l'optimisation bayésienne de Python
Je voulais résoudre ABC159 avec Python
J'ai essayé d'implémenter CVAE avec PyTorch
[Python] J'ai essayé de calculer TF-IDF régulièrement
J'ai essayé de toucher Python (syntaxe de base)
[Python] J'ai essayé d'implémenter un tri stable, alors notez
J'ai essayé Python> autopep8
Mettre en œuvre des recommandations en Python
Implémenter XENO avec python
J'ai essayé de déboguer.
Implémenter sum en Python
J'ai essayé Python> décorateur
Implémenter Traceroute dans Python 3
J'ai essayé d'implémenter la lecture de Dataset avec PyTorch
Essayez d'implémenter Oni Mai Tsuji Miserable avec python
Python: j'ai pu récurer en lambda
Je veux créer une fenêtre avec Python
J'ai essayé de jouer à un jeu de frappe avec Python
Comment implémenter la mémoire partagée en Python (mmap.mmap)
J'ai essayé d'intégrer Keras dans TFv1.1
J'ai essayé de simuler "Birthday Paradox" avec Python
J'ai écrit "Introduction à la vérification des effets" en Python
J'ai essayé d'obtenir des données CloudWatch avec Python
J'ai essayé de sortir LLVM IR avec Python
Je veux fusionner des dictionnaires imbriqués en Python