Cos’è l’A3C? Il calcolo dell’A3C è stato scaricato di recente dal gruppo DeepMind di Google, e ha fatto una spruzzata di… fondamentalmente ossessionante DQN. È stato più veloce, più facile, sempre più vigoroso e pronto a ottenere punteggi molto migliori sulla batteria standard delle imprese di Profound RL. Nel complesso, poteva funzionare in spazi di attività altrettanto discreti. Dato questo, è diventata l’immersione al calcolo di Deep RL per nuovi problemi di test con spazi di stato e di attività complessi. A dire il vero, OpenAI ha appena scaricato una versione dell’A3C come “specialista di avviamento generale” per lavorare con il loro nuovo (ed estremamente diverso) insieme di situazioni dell’Universo.

Il 3 A partire da A3C

Il Bit of leeway non corrente Entertainer Pundit è un pezzo serio. Che ne dite di iniziare scaricando il nome, e da quel punto, iniziare a scaricare la meccanica del calcolo stesso.

Non concomitante: per niente come DQN, dove un operatore solitario a cui si parla da un sistema neurale solitario collabora con una situazione solitaria, A3C utilizza diverse manifestazioni di quanto sopra in modo da adattarsi tanto più produttivamente. In A3C c’è un sistema mondiale e diversi operatori specializzati che hanno ciascuno la propria disposizione dei parametri del sistema. Ognuno di questi operatori si collega con il proprio duplicato della terra contemporaneamente, mentre diversi specialisti comunicano con l’ambiente circostante. La spiegazione che funziona meglio di avere uno specialista solitario (oltre la velocità di realizzare più lavoro), è che l’esperienza di ogni operatore è libera dall’esperienza degli altri. In questo senso, l’esperienza generale accessibile per la preparazione si rivela progressivamente assortita.

Intrattenitore Pundit: Finora questa disposizione si è concentrata sulle strategie di enfasi sulla stima, per esempio, Q-learning, o sulle tecniche del ciclo di approccio, per esempio, Strategy Slope. Il personaggio a video Pundit consolida i vantaggi delle due metodologie. A causa dell’A3C, il nostro sistema valuterà sia una V(e) capacità di valore (quanto grande deve essere uno stato specifico) sia una π(e) strategia (molte probabilità di attività). Ognuna di queste sarà indipendente e completamente associata a strati che si trovano nel punto più alto del sistema. Fondamentalmente, l’operatore utilizza il misuratore di valore (l’esperto) per aggiornare la strategia (l’intrattenitore) in modo più intelligente rispetto alle strategie convenzionali di inclinazione della disposizione.

Implementazione dell’algoritmo

Durante il tempo trascorso a strutturare questo utilizzo del calcolo A3C, ho utilizzato come riferimento le esecuzioni di qualità di DennyBritz e OpenAI. I due dei quali prescrivo profondamente nel caso in cui vogliate vedere delle opzioni in contrasto con il mio codice qui. Ogni segmento inserito qui è preso al di fuori di qualsiasi connessione rilevante al problema in questione a scopo didattico, e non verrà eseguito da solo. Per visualizzare ed eseguire l’esecuzione completa e utile dell’A3C, consultate il mio Github vault.

Il diagramma generale dell’ingegneria del codice è:

AC_Network – Questa classe contiene tutte le operazioni Tensorflow per realizzare i sistemi stessi.

Specialista – Questa classe contiene un duplicato di AC_Network, una classe di dominio, proprio come tutte le ragioni per cooperare con la natura, e rinfrescare il sistema mondiale.

Elevato codice di livello per costruire le occorrenze degli Specialisti ed eseguirle in parallelo.

Il calcolo A3C inizia con lo sviluppo del sistema mondiale. Questo sistema sarà composto da strati convoluzionali per elaborare le condizioni spaziali, trainati da uno strato LSTM per elaborare condizioni fugaci, infine, strati di valore e di rendimento strategico. Di seguito è riportato il codice del modello per l’impostazione del grafico del sistema stesso.

classe AC_Network():

    def __init__(auto,s_size,a_size,scope,trainer):

        con tf.variable_scope(scope):

            #Strati di ingresso e di codifica visiva

            self.inputs = tf.placeholder(shape=[None,s_size],dtype=tf.float32)

            self.imageIn = tf.reshape(self.inputs,shape=[-1,84,84,84,1])

            self.conv1 = slim.conv2d(activation_fn=tf.nn.elu,

                inputs=self.imageIn,num_outputs=16,

                kernel_size=[8,8],stride=[4,4],padding=’VALIDO’)

            self.conv2 = slim.conv2d(activation_fn=tf.nn.elu,

                inputs=self.conv1,num_outputs=32,

                kernel_size=[4,4],stride=[2,2],padding=’VALIDO’)

            nascosto = slim.fully_connected(slim.flatten(self.conv2),256,activation_fn=tf.nn.elu)

            #Rete ricorrente per le dipendenze temporali

            lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(256,state_is_tuple=True)

            c_init = np.zeri((1, lstm_cell.state_size.c), np.float32)

            h_init = np.zeri((1, lstm_cell.state_size.h), np.float32)

            self.state_init = [c_init, h_init]

            c_in = tf.segnaposto(tf.float32, [1, lstm_cell.state_size.c])

            h_in = tf.segnaposto(tf.float32, [1, lstm_cell.state_size.h])

            self.state_in = (c_in, h_in)

            rnn_in = tf.expand_dims(hidden, [0])

            step_size = tf.shape(self.imageIn)[:1]

            state_in = tf.nn.rnn_cell.LSTMStateTuple(c_in, h_in)

            lstm_outputs, lstm_state = tf.nn.dynamic_rnn(

                lstm_cell, rnn_in, initial_state=state_in, sequence_length=step_size,

                tempo_maggiore=Falso)

            lstm_c, lstm_h = lstm_state

            self.state_out = (lstm_c[:1, :], lstm_h[:1, :])

            rnn_out = tf.reshape(lstm_outputs, [-1, 256])

            #Livelli di output per le stime di politica e di valore

            self.policy = slim.fully_connected(rnn_out,a_size,

                activation_fn=tf.nn.softmax,

                pesi_inizializzatore=colonne_inizializzatore_normalizzato(0.01),

                biases_initializer=Nessuno)

            self.value = slim.fully_connected(rnn_out,1,

                activation_fn=Nessuno,

                pesi_inizializzatore=colonne_inizializzatore_normalizzato(1.0),

                biases_initializer=Nessuno)

Poi, molti operatori di manodopera, ognuno con il proprio sistema e la propria condizione. Ognuno di questi operai è eseguito su una stringa di processore diversa, quindi non dovrebbe esserci un numero di operai maggiore di quello delle stringhe sulla CPU.

con tf.device (“/cpu:0”):

    master_network = AC_Network(s_size,a_size,a_size,global’,None) # Generare una rete globale

    num_workers = multiprocessing.cpu_count() # Imposta i lavoratori sul numero di thread della CPU disponibili

    lavoratori = []

    # Creare classi di lavoratori

    per i nella gamma(num_lavoratori):

        workers.append(Lavoratore(Lavoratore(DoomGame(),i,s_size,a_size,allenatore,risparmiatore,percorso_modello)))

con tf.Session() come sess:

    coord = tf.train.coordinator()

    se load_model == True:

        stampa ‘Modello di caricamento…’.

        ckpt = tf.train.get_checkpoint_state(percorso_modello)

        salvatore.restore(sess,ckpt.model_checkpoint_path)

    altro:

        sess.run(tf.global_variables_initializer())

    # È qui che avviene la magia asincrona.

    # Iniziare il processo di “lavoro” per ogni lavoratore in una minaccia separata.

    worker_threads = []

    per lavoratori in lavoratori:

        worker_work = lambda: worker.work.work(max_episode_length,gamma,master_network,sess,coord)

        t = threading.Threading(target=(worker_work))

        t.start()

        worker_threads.append(t)

    coord.join(worker_threads)

Ogni operaio inizia impostando i parametri del proprio sistema su quelli del sistema mondiale. Possiamo fare questo sviluppando un’operazione Tensorflow che imposta ogni fattore del sistema specialistico di quartiere all’equivalente incentivo variabile nel sistema mondiale.

Ogni specialista a quel punto si associa al proprio duplicato della natura e raccoglie la comprensione. Ognuno mantiene una serie di tuple di esperienza (percezione, attività, retribuzione, fatto, stima) che si aggiunge continuamente alla comunicazione con la terra.

ragazza Lavoratrice():

      ….

      ….

      ….

      def lavoro (auto,max_episodio_lunghezza,gamma,global_AC,sess,coord):

        episodio_conteggio = 0

        total_step_count = 0

        stampa “Iniziare a lavorare” + str(self.number)

        con sess.as_default(), sess.graph.as_default():                 

            mentre non coord.should_stop():

                sess.run(self.update_local_op)

                episode_buffer = []

                Episodio_valori = []

                episode_frames = []

                episode_reward = 0

                episode_step_count = 0

                d = Falso

                auto.env.nuovo_episodio()

                s = auto.env.get_state().screen_buffer

                episode_frames.append(s)

                s = processo_telaio(i)

                rnn_state = auto.local_AC.state_init

                mentre self.env.is_episode_finished() == Falso:

                    #effettuare un’azione usando le probabilità dall’output della rete di policy.

                    a_dist,v,rnn_state = sess.run([self.local_AC.policy,self.local_AC.value,self.local_AC.state_out],

                        feed_dict={self.local_AC.inputs:[s],

                        auto.local_AC.state_in[0]:rnn_state[0],

                        self.local_AC.state_in[1]:rnn_state[1]})

                    a = np.random.choice(a_dist[0],p=a_dist[0])

                    a = np.argmax(a_dist == a)

                    r = self.env.make_action(self.actions[a]) / 100.0

                    d = auto.env.is_episode_finished()

                    se d == Falso:

                        s1 = auto.env.get_state().screen_buffer

                        episode_frames.append(s1)

                        s1 = process_frame(s1)

                    altro:

                        s1 = s

                    episode_buffer.append([s,a,r,s1,d,v[0,0]])

                    episodio_valori.append(v[0,0])

                    episode_reward += r

                    s = s1 

                    totale_passi += 1

                    episodio_step_conteggio += 1

                    #Specifico per VizDoom. Dormiamo il gioco per un tempo specifico.

                    se auto.sleep_time>0:

                        dormire(auto.dormire_tempo)

                    # Se l’episodio non è finito, ma il buffer di esperienza è pieno, allora noi

                    # fai un passo di aggiornamento usando quel rollout di esperienza.

                    se len(episode_buffer) == 30 e d != True e episode_step_count != max_episode_length – 1:

                        # Dal momento che non sappiamo quale sia il vero ritorno finale, noi “bootstrap” dalla nostra corrente

                        # stima del valore.

                        v1 = sess.run(auto.local_AC.value,

                            feed_dict={self.local_AC.inputs:[s],

                            auto.local_AC.state_in[0]:rnn_state[0],

                            auto.local_AC.state_in[1]:rnn_state[1]}) [0,0][0,0

                        v_l,p_l,e_l,e_l,g_n,v_n,v_n = self.train(global_AC,episode_buffer,sess,gamma,v1)

                        episode_buffer = []

                        sess.run(self.update_local_op)

                    se d == Vero:

                        pausa

                self.episode_rewards.append(episode_reward)

                auto.episode_lengths.append(episode_step_count)

                Append(np.media(valori dell’episodio))

                # Aggiorna la rete utilizzando il buffer di esperienza alla fine dell’episodio.

                v_l,p_l,e_l,e_l,g_n,v_n,v_n = self.train(global_AC,episode_buffer,sess,gamma,0.0)

Quando la storia dell’esperienza del lavoratore è abbastanza enorme, la usiamo per decidere un ritorno limitato e un po’ di margine di manovra, e li utilizziamo per calcolare il valore e affrontare le disgrazie. Inoltre, accertiamo un’entropia (H) dell’approccio. Questo si confronta con la diffusione delle probabilità di attività. Nella remota possibilità che la strategia produca attività con probabilità moderatamente comparative, a quel punto l’entropia sarà alta, ma nella remota possibilità che l’accordo raccomandi un’attività solitaria con un’enorme probabilità, a quel punto l’entropia sarà bassa. Utilizziamo l’entropia come metodo per migliorare l’indagine, esortando il modello ad essere tradizionalista rispetto alla sua consapevolezza della giusta attività.

Perdita di valore: L = Σ(R – V(s))²

Perdita della polizza: L = -log(π(s)) * A(s) – β*H(π)

Un operaio a quel punto utilizza queste disgrazie per acquisire angoli riguardanti i parametri del suo sistema. Ognuno di questi angoli è comunemente tagliato in modo da anticipare un aggiornamento dei parametri eccessivamente enorme che può destabilizzare l’approccio.

Uno specialista a quel punto utilizza le inclinazioni per aggiornare i parametri del sistema in tutto il mondo. In questo modo, il sistema mondiale viene continuamente rinfrescato da tutti gli specialisti che collaborano con la loro condizione.

classe AC_Network():

    def __init__(auto,s_size,a_size,scope,trainer):

        ….

        ….

        ….

        se portata != ‘globale’:

            self.actions = tf.placeholder(shape=[None],dtype=tf.int32)

            self.actions_onehot = tf.one_hot(self.actions,a_size,dtype=tf.float32)

            self.target_v = tf.segnaposto(shape=[None],dtype=tf.float32)

            self.advantages = tf.placeholder(shape=[None],dtype=tf.float32)

            self.responsible_outputs = tf.reduce_sum(self.policy * self.actions_onehot, [1])

            #Funzioni di perdita

            self.value_loss = 0,5 * tf.reduce_sum(tf.square(self.target_v – tf.reshape(self.value,[-1])))

            auto.entropia = – tf.reduce_sum(self.policy * tf.log(self.policy))

            self.policy_loss = -tf.reduce_sum(tf.log(self.responsible_outputs)*self.advantages)

            self.loss = 0,5 * self.value_loss + self.policy_loss – self.entropy * 0,01

            #Ricevete i gradienti dalla rete locale utilizzando le perdite locali

            local_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope)

            self.gradients = tf.gradients(self.loss,local_vars)

            auto.var_norme = tf.global_norm(local_vars)

            grads,self.grad_norms = tf.clip_by_global_norm(self.gradients,40.0)

            #Applicare gradienti locali alla rete globale

            global_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, ‘globale’)

            self.apply_grads = trainer.apply_gradients(zip(grads,global_vars))

classe Lavoratore():

      ….

      ….

      ….

      Def train(self,global_AC,rollout,sess,gamma,bootstrap_value):

        rollout = np.array(rollout)

        osservazioni = lancio[:,0]

        azioni = lancio[:,1]

        premi = lancio[:,2]

        next_observations = rollout[:,3]

        valori = lancio[:,5]

        # Qui prendiamo i premi e i valori del lancio e li usiamo per

        # Genera il vantaggio e i rendimenti scontati.

        # La funzione di vantaggio utilizza la “Stima del vantaggio generalizzato”.

        self.rewards_plus = np.asarray(rewards.tolist() + [bootstrap_value])

        discounted_rewards = sconto(self.rewards_plus,gamma)[:-1]

        self.value_plus = np.asarray(values.tolist() + [bootstrap_value])

        vantaggi = premi + gamma * auto.value_plus[1:] – auto.value_plus[:-1]

        vantaggi = sconto (vantaggi,gamma)

        # Aggiornare la rete globale utilizzando i gradienti di perdita

        # Genera statistiche di rete per salvare periodicamente

        rnn_state = auto.local_AC.state_init

        feed_dict = {self.local_AC.target_v:discounted_rewards,

            auto.local_AC.inputs:np.vstack(osservazioni),

            self.local_AC.actions:actions,

            self.local_AC.advantages:vantaggi,

            auto.local_AC.state_in[0]:rnn_state[0],

            auto.local_AC.state_in[1]:rnn_state[1]}

        v_l,p_l,e_l,e_l,g_n,v_n,_ = sess.run([self.local_AC.value_loss,

            auto.locale_AC.policy_loss,

            auto.locale_AC.entropia,

            auto.locale_AC.grad_norme,

            auto.local_AC.var_norm,

            auto.local_AC.apply_grads],

            feed_dict=feed_dict)

        return v_l / len(rollout),p_l / len(rollout),e_l / len(rollout), g_n,v_n

Quando si effettua un aggiornamento efficace del sistema mondiale, l’intera procedura si ripete! L’operaio a quel punto resetta i propri parametri di sistema a quelli del sistema mondiale e la procedura ricomincia da capo.