python - ¿Por qué mi Deep Q Network no domina un simple Gridworld(Tensorflow)?(Como evaluar una Deep-Q-Net)
neural-network deep-learning (3)
Así que hace bastante tiempo escribí esta pregunta, pero parece que todavía hay bastante interés y solicitud para el código en ejecución. Finalmente decidí crear un repositorio de github.
Ya que hace bastante tiempo lo escribí y así sucesivamente no se agotará, pero no debería ser tan difícil hacerlo funcionar. Así que aquí está la red q profunda y el ejemplo que escribí en el momento en que funcionaba entonces, espero que lo disfruten: Enlace al repositorio q profundo
¡Sería bueno ver alguna contribución y si lo arregla y lo hace funcionar, haga una solicitud de extracción!
Intento familiarizarme con Q-learning y Deep Neural Networks, actualmente intento implementar Atari con Deep Reinforcement Learning .
Para probar mi implementación y jugar con ella, me di cuenta de que probé un simple gridworld. Donde tengo una cuadrícula de N x N, comienzo en la esquina superior izquierda y termina en la parte inferior derecha. Las acciones posibles son: izquierda, arriba, derecha, abajo.
A pesar de que mi implementación se ha vuelto muy similar a this (espero que sea buena) parece que no aprendió nada. Mirando los pasos totales que necesita terminar (supongo que el promedio sería de 500 con un tamaño de cuadrícula de 10x10, pero también valores muy bajos y altos), me parece más aleatorio que cualquier otra cosa.
Lo probé con y sin capas convolucionales y jugué con todos los parámetros, pero para ser honesto, no tengo idea si algo con mi implementación está mal o si necesita entrenar más tiempo (lo dejo entrenar durante bastante tiempo) o qué. siempre. Pero al menos parece que convergen, aquí la trama de la pérdida valora una sesión de entrenamiento:
Entonces, ¿cuál es el problema en este caso?
Pero también, y quizás más importante, cómo puedo "depurar" este Deep-Q-Nets, en el entrenamiento supervisado hay conjuntos de entrenamiento, prueba y validación y, por ejemplo, con precisión y recuperación es posible evaluarlos. ¿Qué opciones tengo para el aprendizaje sin supervisión con Deep-Q-Nets, de modo que la próxima vez quizás pueda solucionarlo yo mismo?
Finalmente aquí está el código:
Esta es la red:
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)
Y aquí el entrenamiento.
# 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
¡Aprecio cada ayuda e ideas que pueda tener!
He implementado un DQN de juguete simple sin capas CNN, y funciona. Aquí hay algunos hallazgos durante mi implementación, espero que ayude.
De acuerdo con el documento de DeepMind que no usaron la capa de agrupación máxima, la razón es que la imagen se volverá invariante en la posición, lo que no es bueno para el juego. La posición del agente es crucial para la información del juego. Arquitectura DQN
Si desea omitir el entorno de gimnasio de CNN, use por primera vez (como lo que he hecho para la implementación del juguete), durante mi desarrollo, aquí hay algunas cosas que encontré:
- Codifique su estado de entorno mediante la codificación de una sola aplicación, aumentará la eficiencia de la capacitación.
- Solo uso una matriz de pesos con forma de [número de estado, número de acción], para hacer la multiplicación de la matriz con el estado de entrada codificada en caliente. Sin sesgo, sin función de activación (aumentará el tiempo de entrenamiento, supongo, nunca funcionará después de agregar otra capa o algo).
Estas son dos cosas que encontré extremadamente cruciales para que mi implementación funcione, no entiendo completamente la razón detrás de esto, espero que mi respuesta pueda darles un poco de información.
Para aquellos interesados, ajusté aún más los parámetros y el modelo, pero la mayor mejora fue el cambio a una red de avance simple con 3 capas y aproximadamente 50 neuronas en la capa oculta. Para mí entonces convergió en un tiempo bastante decente.
Por cierto, se aprecian más consejos para la depuración!