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:
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!
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
Vedi il mio caposquadra ma comunque grazie bello avere più interni ma potrebbe esserti utile provare IT per vedere un po 'di tempo :) – natschz
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 ...). –