Dus wat is A3C? De A3C-berekening werd onlangs door Google’s DeepMind-bende gelost, en het maakte een sprankeltje door… in principe verouderde DQN. Het was sneller, gemakkelijker, steeds krachtiger, en klaar om veel betere scores te behalen op de standaard batterij van Profound RL ondernemingen. Over het geheel genomen kon het werken in consistente net zo discrete activiteitenruimtes. Gezien dit, is het de duik naar Diepe RL berekening geworden voor nieuwe testkwesties met complexe toestands- en activiteitsruimten. De waarheid is dat OpenAI net een uitvoering van A3C heeft ontladen als hun “algemene startspecialist” voor het werken met hun nieuwe (en zeer verschillende) set van Universumsituaties.

De 3 Vanaf A3C

Een beetje speelruimte voor Entertainer Pundit is een serieus stuk. Wat dacht je ervan om te beginnen met het uitladen van de naam, en vanaf dat moment beginnen we met het uitladen van de mechanica van de berekening zelf.

Nonconcurrent: Niet zoals DQN, waar een solitaire neurale operator met een solitair systeem samenwerkt met een solitaire situatie, gebruikt A3C verschillende verschijningsvormen van het bovenstaande om zich des te productiever aan te passen. In A3C is er een wereldwijd systeem en verschillende gespecialiseerde operators die elk hun eigen opstelling van systeemparameters hebben. Elk van deze operatoren verbindt zich met zijn eigen duplicaat van de aarde, terwijl verschillende specialisten tegelijkertijd met hun omgeving communiceren. De verklaring voor het feit dat dit beter werkt dan het hebben van een eenzame specialist (voorbij de snelheid van het bereiken van meer werk), is dat de ervaring van elke operator vrij is van de ervaring van de anderen. In die zin blijkt de algemene ervaring die toegankelijk is voor de voorbereiding geleidelijk aan te variëren.

Entertainer Pundit: Tot nu toe heeft deze regeling zich geconcentreerd op het waarderen van accentueringsstrategieën, bijvoorbeeld Q-learning, of benaderingstechnieken, bijvoorbeeld Strategy Slope. On-screen karakter Pundit consolideert de voordelen van de twee methoden. Op basis van A3C zal ons systeem zowel een waardetoestand V(s) (hoe groot een specifieke toestand moet zijn) als een strategie π(s) (veel waarschijnlijkheid van activiteiten) beoordelen. Deze zullen elk volledig onafhankelijk zijn van elkaar en op het hoogste punt van het systeem zitten. In principe gebruikt de operator de waardemeter (de pundit) om de strategie (de entertainer) slimmer op te frissen dan de conventionele hellingshoekstrategieën.

Implementatie van het algoritme

https://miro.medium.com/max/1316/1*Hzql_1t0-wwDxiz0C97AcQ.png

Gedurende de tijd dat ik dit gebruik van de A3C berekening heb gestructureerd, heb ik als referentie de kwaliteitsuitvoeringen van DennyBritz en OpenAI gebruikt. Die twee schrijf ik diepgaand voor in het geval dat je in tegenstelling tot mijn code hier opties zou willen zien. Elk segment dat hier wordt ingevoegd, wordt buiten elke relevante verbinding met het betreffende onderwerp genomen voor instructiedoeleinden, en zal niet alleen lopen. Om de volledige, nuttige A3C uitvoering te bekijken en uit te voeren, zie mijn Github kluis.

Het algemene schema van de code engineering is:

AC_Network – Deze klasse bevat alle Tensorflow-bewerkingen om de systemen zelf te maken.

Specialist – Deze klasse bevat een duplicaat van AC_Network, een domeinklasse, net als alle redenen om samen te werken met de natuur, en het wereldwijde systeem op te frissen.

Verhoogde niveaucode voor het opbouwen van de Specialist voorvallen en het parallel laten lopen ervan.

De A3C-berekening begint met de ontwikkeling van het wereldwijde systeem. Dit systeem zal bestaan uit convolutionele lagen om ruimtelijke condities te verwerken, gevolgd door een LSTM-laag om vluchtige condities te verwerken, tot slot, waarde en strategie opbrengstlagen. Hieronder volgt de modelcode voor het opzetten van de systeemkaart zelf.

klasse AC_Network():

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

met tf.variable_scope(scope):

#Invoer en visuele coderingslagen

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

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

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

inputs=self.imageIn,num_outputs=16,

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

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

inputs=self.conv1,num_outputs=32,

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

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

#Recurrent netwerk voor temporele afhankelijkheden

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

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

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

self.state_init = [c_init, h_init].

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

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

self.state_in = (c_in, h_in)

rnn_in = tf.expand_dims(verborgen, [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,

time_major=False)

lstm_c, lstm_h = lstm_state

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

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

#Outputlagen voor beleids- en waardeschattingen

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

activering_fn=tf.nn.softmax,

gewichten_initialisator=normaliseerde_kolommen_initialisator(0.01),

biases_initialisator=Niet)

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

activering_fn=Niet,

gewichten_initialisator=normaliseerde_kolommen_initialisator(1.0),

biases_initialisator=Niet)

Vervolgens worden er veel laboranten gemaakt, elk met hun eigen systeem en conditie. Elk van deze arbeiders wordt op een andere processorstring gedraaid, dus er zouden geen grotere aantallen arbeiders moeten zijn dan er strings op uw CPU staan.

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

master_network = AC_Network(s_size,a_size,’global’,None) # Generate global network

num_workers = multiprocessing.cpu_count() # Set workers ot aantal beschikbare CPU threads

werknemers = []

# Creëer arbeidersklassen

voor i in bereik (num_workers):

workers.append(Worker(DoomGame(),i,s_size,a_size,trainer,saver,model_path))

met tf.Session() als sess:

gecoördineerd = tf.train.coördinator()

als load_model == Waar:

print ‘Laadmodel…’

ckpt = tf.train.get_checkpoint_state(model_path)

saver.restore(sess,ckpt.model_checkpoint_path)

anders:

sess.run(tf.global_variables_initializer())

# Dit is waar de asynchrone magie gebeurt.

# Start het “werk” proces voor elke werknemer in een aparte bedreiging.

worker_threads = []

voor werknemers:

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

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

t.start()

worker_threads.append(t)

coord.join(worker_threads)

Elke arbeider begint met het instellen van zijn systeemparameters op die van het wereldwijde systeem. Dit kunnen we doen door een Tensorflow-operatie te ontwikkelen die elke factor in het systeem van de buurtspecialist op de gelijke variabele stimulans in het wereldwijde systeem zet.

Elke specialist op dat moment associeert zich met zijn eigen duplicaat van de natuur en verzamelt begrip. Ieder houdt een overzicht van ervaringspunten (perceptie, activiteit, beloning, gedaante, waardering) die voortdurend worden toegevoegd aan de communicatie met de aarde.

lass Worker():

….

….

….

def work(self,max_episode_length,gamma,global_AC,sess,coord):

episode_count = 0

totaal_stap_telling = 0

afdruk “Startende werknemer” + str(self.number)

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

terwijl niet coord.should_stop():

sess.run(self.update_local_ops)

episode_buffer = []

episode_waarden = []

episode_frames = []

episode_beloning = 0

episode_step_count = 0

d = vals

zelf.env.new_episode()

s = self.env.get_state().screen_buffer

episode_frames.append(s)

s = process_frame(s)

rnn_state = zelf.local_AC.state_init

terwijl self.env.is_episode_finished() ==Vals:

#Neem een actie met behulp van waarschijnlijkheden uit de beleidsnetwerkuitvoer.

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],

self.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 = self.env.is_episode_finished()

als d == Vals:

s1 = zelf.env.get_state().screen_buffer

episode_frames.append(s1)

s1 = process_frame(s1)

anders:

s1 = s

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

episode_values.append(v[0,0])

episode_beloning += r

s = s1

totaal_stappen += 1

episode_step_count += 1

#Specifiek voor VizDoom. We slapen het spel voor een bepaalde tijd.

als zelf.slaap_tijd>0:

sleep(self.sleep_time)

# Als de aflevering niet is geëindigd, maar de ervaringsbuffer is vol, dan zijn we

# maak een update stap met behulp van die ervaring roll-out.

if len(episode_buffer) == 30 en d != True en episode_step_count != max_episode_length – 1:

# Aangezien we niet weten wat de ware eindopbrengst is, “bootenstrap” we van onze huidige

# waarde schatting.

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

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

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

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

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

episode_buffer = []

sess.run(self.update_local_ops)

als d == Waar:

pauze

self.episode_rewards.append(episode_reward)

self.episode_lengths.append(episode_step_count)

self.episode_mean_values.append(np.mean(episode_values))

# Update het netwerk met behulp van de ervaringsbuffer aan het einde van de aflevering.

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

Wanneer de ervaringsgeschiedenis van de arbeider enorm genoeg is, gebruiken we die om te beslissen over een beperkte terugkeer en een beetje speelruimte, en gebruiken die om de waarde te berekenen en tegenslagen te benaderen. Daarnaast stellen we een entropie (H) van de aanpak vast. Dit is vergelijkbaar met de spreiding van de waarschijnlijkheid van activiteiten. Bij de kans dat de strategie activiteiten oplevert met gematigde relatieve waarschijnlijkheden zal de entropie op dat moment hoog zijn, maar bij de kans dat de regeling een solitaire activiteit met een enorme kans aanbeveelt, zal de entropie op dat moment laag zijn. We gebruiken de entropie als een methode om het onderzoek te verbeteren, door aan te dringen op een traditionalistisch model met betrekking tot de zekerheid van de juiste activiteit.

Waardeverlies: L = Σ(R – V(s))²

Beleidsverlies: L = -log(π(s)) * A(s) – β*H(π)

Een arbeider maakt op dat moment gebruik van deze tegenslagen om hoeken te verwerven met betrekking tot zijn systeemparameters. Elk van deze hoeken wordt gewoonlijk afgeknipt om te anticiperen op buitensporig grote parametervernieuwingen die de aanpak kunnen destabiliseren.

Een specialist op dat moment gebruikt de neigingen om de wereldwijde systeemparameters op te frissen. Op deze manier wordt het wereldwijde systeem voortdurend ververst door elk van de specialisten, omdat ze samenwerken met hun conditie.

klasse AC_Network():

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

….

….

….

als scope != ‘globaal’:

zelf.acties = tf.plaatshouder(vorm=[geen],dtype=tf.int32)

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

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

zelf.voordelen = tf.plaatshouder (vorm=[Geen],dtype=tf.float32)

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

#Verlies van functies

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

zelf.entropie = – tf.reduce_sum(self.policy * tf.log(self.policy))

zelf.beleid_verlies = -tf.reduce_sum(tf.log(self.responsible_outputs)*self.voordelen)

self.loss = 0.5 * self.value_loss + self.policy_loss – self.entropy * 0.01

#Get gradiënten van het lokale netwerk met behulp van lokale verliezen

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

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

self.var_norms = tf.global_norm(local_vars)

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

#Toepassen van lokale gradiënten op het wereldwijde netwerk

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

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

klassewerker():

….

….

….

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

uitrol = np.array(uitrol)

waarnemingen = uitrol[:,0]

acties = uitrol[:,1]

beloningen = uitrol[:,2]

volgende_waarnemingen = uitrol[:,3]

waarden = uitrol[:,5]

# Hier nemen we de beloningen en waarden van de uitrol, en gebruiken deze om

# genereer het voordeel en de verdisconteerde opbrengsten.

# De voordeelfunctie maakt gebruik van “Generalized Advantage Estimation”.

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

Discounted_rewards = korting(self.rewards_plus,gamma)[:-1].

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

voordelen = beloningen + gamma * self.value_plus[1:] – self.value_plus[:-1].

voordelen = korting (voordelen,gamma)

# Update het wereldwijde netwerk met behulp van gradiënten van verlies

# Genereer netwerkstatistieken om periodiek op te slaan

rnn_state = zelf.local_AC.state_init

feed_dict = {self.local_AC.target_v:discounted_rewards,

self.local_AC.inputs:np.vstack(waarnemingen),

zelf.lokale_AC.acties: acties,

self.local_AC.advantages: voordelen,

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

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

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

zelf.lokaal_AC.beleid_verlies,

zelf_AC.entropie,

self.local_AC.grad_norms,

self.local_AC.var_norms,

self.local_AC.apply_grads],

feed_dict=feed_dict)

terugkeer v_l / len(uitrol),p_l / len(uitrol),e_l / len(uitrol), g_n,v_n

Wanneer een effectieve update van het wereldwijde systeem wordt uitgevoerd, wordt de hele procedure opnieuw uitgevoerd! De arbeider stelt op dat moment zijn eigen systeemparameters terug naar die van het wereldwijde systeem, en de procedure begint opnieuw.