2016-02-14 3 views
19

Provo a familiarizzare con Q-learning e Deep Neural Networks, attualmente provo ad implementare Playing Atari with Deep Reinforcement Learning.Perché il mio Deep Q Network non è in grado di padroneggiare un semplice Gridworld (Tensorflow)? (Come valutare una Deep-Q-Net)

Per testare la mia implementazione e giocarci, ho provato a provare un semplice gridworld. Dove ho una griglia N x N e inizio nell'angolo in alto a sinistra e termina in basso a destra. Le azioni possibili sono: sinistra, su, destra, giù.

Anche se la mia implementazione è diventata molto simile a this (spero sia buona), non sembra imparare nulla. Osservando i passaggi totali che deve finire (suppongo che la media sia di 500 attorno a una gridsize di 10x10, ma anche di valori molto bassi e alti), mi sembra più casuale di qualsiasi altra cosa per me.

Ho provato con e senza strati convoluzionali e ho giocato con tutti i parametri, ma ad essere sincero, non ho idea se qualcosa con la mia implementazione è sbagliato o ha bisogno di allenarsi più a lungo (lo lascio allenare per un bel tempo) o cosa mai. Ma almeno cuciture a convergere, qui la trama del sessione di allenamento valore di perdita:

Loss image

Allora, qual è il problema in questo caso?

Ma anche, e forse ancora più importante, come posso eseguire il "debug" di questa Deep-Q-Net, nella formazione supervisionata ci sono set di training, test e validazione e ad esempio con precisione e richiamo è possibile valutarli. Quali opzioni ho per l'apprendimento senza supervisione con Deep-Q-Nets, in modo che la prossima volta forse posso ripararlo da solo?

Infine ecco il codice:

Questa è la rete:

ACTIONS = 5 

# Inputs 
x = tf.placeholder('float', shape=[None, 10, 10, 4]) 
y = tf.placeholder('float', shape=[None]) 
a = tf.placeholder('float', shape=[None, ACTIONS]) 

# Layer 1 Conv1 - input 
with tf.name_scope('Layer1'): 
    W_conv1 = weight_variable([8,8,4,8]) 
    b_conv1 = bias_variable([8])  
    h_conv1 = tf.nn.relu(conv2d(x, W_conv1, 5)+b_conv1) 

# Layer 2 Conv2 - hidden1 
with tf.name_scope('Layer2'): 
    W_conv2 = weight_variable([2,2,8,8]) 
    b_conv2 = bias_variable([8]) 
    h_conv2 = tf.nn.relu(conv2d(h_conv1, W_conv2, 1)+b_conv2) 
    h_conv2_max_pool = max_pool_2x2(h_conv2) 

# Layer 3 fc1 - hidden 2 
with tf.name_scope('Layer3'): 
    W_fc1 = weight_variable([8, 32]) 
    b_fc1 = bias_variable([32]) 
    h_conv2_flat = tf.reshape(h_conv2_max_pool, [-1, 8]) 
    h_fc1 = tf.nn.relu(tf.matmul(h_conv2_flat, W_fc1)+b_fc1) 

# Layer 4 fc2 - readout 
with tf.name_scope('Layer4'): 
    W_fc2 = weight_variable([32, ACTIONS]) 
    b_fc2 = bias_variable([ACTIONS]) 
    readout = tf.matmul(h_fc1, W_fc2)+ b_fc2 

# Training 
with tf.name_scope('training'): 
    readout_action = tf.reduce_sum(tf.mul(readout, a), reduction_indices=1) 
    loss = tf.reduce_mean(tf.square(y - readout_action)) 
    train = tf.train.AdamOptimizer(1e-6).minimize(loss) 

    loss_summ = tf.scalar_summary('loss', loss) 

Ed ecco la formazione:

# 0 => left 
# 1 => up 
# 2 => right 
# 3 => down 
# 4 = noop 

ACTIONS = 5 
GAMMA = 0.95 
BATCH = 50 
TRANSITIONS = 2000 
OBSERVATIONS = 1000 
MAXSTEPS = 1000 

D = deque() 
epsilon = 1 

average = 0 
for episode in xrange(1000): 
    step_count = 0 
    game_ended = False 

    state = np.array([0.0]*100, float).reshape(100) 
    state[0] = 1 

    rsh_state = state.reshape(10,10) 
    s = np.stack((rsh_state, rsh_state, rsh_state, rsh_state), axis=2) 

    while step_count < MAXSTEPS and not game_ended: 
     reward = 0 
     step_count += 1 

     read = readout.eval(feed_dict={x: [s]})[0] 

     act = np.zeros(ACTIONS) 
     action = random.randint(0,4) 
     if len(D) > OBSERVATIONS and random.random() > epsilon: 
      action = np.argmax(read) 
     act[action] = 1 

     # play the game 
     pos_idx = state.argmax(axis=0) 
     pos = pos_idx + 1 

     state[pos_idx] = 0 
     if action == 0 and pos%10 != 1: #left 
      state[pos_idx-1] = 1 
     elif action == 1 and pos > 10: #up 
      state[pos_idx-10] = 1 
     elif action == 2 and pos%10 != 0: #right 
      state[pos_idx+1] = 1 
     elif action == 3 and pos < 91: #down 
      state[pos_idx+10] = 1 
     else: #noop 
      state[pos_idx] = 1 
      pass 

     if state.argmax(axis=0) == pos_idx and reward > 0: 
      reward -= 0.0001 

     if step_count == MAXSTEPS: 
      reward -= 100 
     elif state[99] == 1: # reward & finished 
      reward += 100 
      game_ended = True 
     else: 
      reward -= 1 


     s_old = np.copy(s) 
     s = np.append(s[:,:,1:], state.reshape(10,10,1), axis=2) 

     D.append((s_old, act, reward, s)) 
     if len(D) > TRANSITIONS: 
      D.popleft() 

     if len(D) > OBSERVATIONS: 
      minibatch = random.sample(D, BATCH) 

      s_j_batch = [d[0] for d in minibatch] 
      a_batch = [d[1] for d in minibatch] 
      r_batch = [d[2] for d in minibatch] 
      s_j1_batch = [d[3] for d in minibatch] 

      readout_j1_batch = readout.eval(feed_dict={x:s_j1_batch}) 
      y_batch = [] 

      for i in xrange(0, len(minibatch)): 
       y_batch.append(r_batch[i] + GAMMA * np.max(readout_j1_batch[i])) 

      train.run(feed_dict={x: s_j_batch, y: y_batch, a: a_batch}) 

     if epsilon > 0.05: 
      epsilon -= 0.01 

Apprezzo ogni aiuto e le idee si possono avere!

+0

Il mio primo istinto sono gli strati di convoluzioni e il massimo pooling fa sì che l'agente perda dettagli nella posizione di griglie/oggetti/giocatori, qualcosa di importante in un mondo di grid. Forse provare a utilizzare un pool medio invece del pool massimo? – Adam

+0

Vedi il mio caposquadra ma comunque grazie bello avere più interni ma potrebbe esserti utile provare IT per vedere un po 'di tempo :) – natschz

+0

Buona domanda, sto lottando lo stesso problema per circa 5 settimane e non riesco a scoprire cosa c'è che non va. La rete viene convertita controllando i valori di perdita ma la ricompensa di 100 passi è ancora troppo bassa. Può essere che ho bisogno di fare più lavoro sul debug di DQN, semplificare la rete è una scelta (aggiungo troppe cose alla rete: CNN/Duel-DQN/DQN doppio ...). –

risposta

5

Per gli interessati, ho ulteriormente regolato i parametri e il modello, ma il più grande miglioramento è stato il passaggio a una rete di feed-forward semplice con 3 livelli e circa 50 neuroni nel livello nascosto. Per me è poi converguto in un tempo abbastanza decente.

Ulteriori suggerimenti per debuggin sono apprezzati!

+0

Sarei interessato a vedere il codice finale. Puoi aggiornare il tuo post plz! – Wontonimo

+0

Probabilmente potrei, ma l'ultimo che ha chiesto il codice ha cancellato il suo commento prima che potessi pubblicare il codice su github. Quindi non sono sicuro che tu mi senti ...? Non voglio fare i compiti per gli altri o pubblicare qualcosa che viene incollato solo sulla copia. – natschz

+0

Basta dire che "così tante persone pubblicano le loro scoperte gratuitamente, perché traggono molto profitto dal materiale gratuito. Questa è una buona abitudine per accademici e sviluppatori. – MarcoMeter

2

Quindi è un bel tempo fa, che ho scritto questa domanda ma cuciture che ci sia ancora un po 'di interesse e richiesta di codice in esecuzione ho finalmente deciso di creare un repository github

Dal momento che è un po di tempo fa ho lo ha scritto e così via non finirà mai, ma non dovrebbe essere così difficile farlo funzionare. Quindi ecco la rete q profonda e l'esempio che ho scritto all'epoca che funzionava allora, spero vi piaccia: Link to deep q repository

Sarebbe bello vedere qualche contributo e se lo aggiustate e lo fate funzionare fate una richiesta di pull!

Problemi correlati