2016-02-14 18 views
19

Próbuję zapoznać się z Q-learning i Deep Neural Networks, obecnie próbuję implementować Playing Atari with Deep Reinforcement Learning.Dlaczego moja sieć Deep Q nie opanowała prostego Gridworld (Tensorflow)? (Jak ocenić Deep-Q-Net)

Aby przetestować moją implementację i pogawędzić z nią, pomyślałem, że wypróbuję prosty gridworld. Gdzie mam N x N Grid i zacznij w lewym górnym rogu i kończy się w prawym dolnym rogu. Możliwe działania to: lewo, góra, prawo, dół.

Mimo że moja implementacja stała się bardzo podobna do this (mam nadzieję, że jest dobra), nie wydaje się, aby cokolwiek się nauczyć. Patrząc na całkowite kroki, które trzeba ukończyć (myślę, że średnia wyniosłaby 500 z siłą 10x10, ale są tam również bardzo niskie i wysokie wartości), to szwy są bardziej losowe niż cokolwiek innego.

Próbowałem go bez warstw splotu i bawiłem się wszystkimi parametrami, ale szczerze mówiąc, nie mam pojęcia, czy coś z moją implementacją jest zła, czy musi trenować dłużej (pozwoliłem jej trenować przez dość czas) lub co jeszcze. Ale przynajmniej szwy na zbiegają się tutaj fabuła wartości utrata jednej sesji treningowej:

Loss image

Więc co jest problemem w tym przypadku?

Ale także, a może, co ważniejsze, jak mogę "debugować" te Deep-Q-Nets, w nadzorowanym szkoleniu są zestawy szkoleniowe, testowe i walidacyjne i na przykład z precyzją i przywołaniem można je ocenić. Jakie mam opcje uczenia bez nadzoru z użyciem Deep-Q-Nets, aby następnym razem sam mógłbym to naprawić?

Wreszcie oto kod:

Jest to sieć:

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) 

I tu szkolenia:

# 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 

Doceniam każdą pomoc i pomysły może masz!

+0

Moim pierwszym instynktem są warstwy nawinięć, a maksymalne łączenie powoduje, że agent traci szczegóły dotyczące lokalizacji siatek/obiektów/graczy, co ma znaczenie w sieci. Być może spróbuj użyć puli średniej zamiast puli maksymalnej? – Adam

+0

Zobacz mój awnser ale w każdym razie dzięki miło mieć więcej wnętrz ale IT może nie warto spróbować zobaczyć trochę czasu :) – natschz

+0

Dobre pytanie, walczę z tym samym problemem przez około 5 tygodni i nie mogę się dowiedzieć, co jest nie tak. Sieć jest zbieżna poprzez sprawdzenie wartości strat, ale nagroda w postaci 100 kroków wciąż jest zbyt niska. Być może potrzebuję wykonać więcej pracy przy debugowaniu DQN, uprościć sieć jest wyborem (po prostu dodaję zbyt wiele rzeczy do sieci: CNN/Duel-DQN/Double DQN ...). –

Odpowiedz

5

Dla zainteresowanych, poprawiłem parametry i model dalej, ale największą poprawą było przejście do prostej sieci z 3 warstwami i około 50 neuronami w ukrytej warstwie. Dla mnie to zbiegło się w całkiem przyzwoitym czasie.

Btw dalsze wskazówki dotyczące debugowania są mile widziane!

+0

Chciałbym zobaczyć ostatni kod. Czy możesz zaktualizować swój post! – Wontonimo

+0

Prawdopodobnie mógłbym, ale ostatni facet pytający o kod skasował swój komentarz, zanim zdążyłem opublikować kod na githubie. Więc nie jestem pewien, czy mnie czujesz ...? Nie chcę odrabiać zadań domowych dla innych lub publikować czegoś, co po prostu kopiuje wklejone. – natschz

+0

Po prostu powiedz, że "tak wiele osób publikuje swoje odkrycia za darmo, ponieważ czerpią one tak wiele z darmowego materiału. To dobry nawyk dla nauczycieli akademickich i programistów. – MarcoMeter

2

Więc jest to dość dawno temu, że napisałem to pytanie ale szwy, że jest jeszcze całkiem pewne zainteresowanie i wniosek o bieżącą kodu końcu zdecydowałem się stworzyć repozytorium GitHub

Ponieważ jest to dość dawno temu i napisałem to i tak na nim nie zabraknie, ale nie powinno być tak trudno go uruchomić. Więc tutaj jest głęboka sieć q i przykład, który napisałem w czasie, który wtedy działał, mam nadzieję, że się spodoba: Link to deep q repository

Byłoby miło zobaczyć jakąś składkę, a jeśli ją naprawisz i uruchomisz, zrób wniosek o odciągnięciu!

Powiązane problemy