Implementación de una red neuronal para jugar Pong en Atari
import numpy as np
import tensorflow as tf
# Definición de la red neuronal
class QNetwork(tf.keras.Model):
def __init__(self, num_actions):
super(QNetwork, self).__init__()
self.dense1 = tf.keras.layers.Dense(64, activation='relu')
self.dense2 = tf.keras.layers.Dense(num_actions)
def call(self, state):
x = self.dense1(state)
return self.dense2(x)
# Agente de Q-Learning
class QLearningAgent:
def __init__(self, num_actions, epsilon=0.1, gamma=0.99, learning_rate=0.001):
self.num_actions = num_actions
self.epsilon = epsilon
self.gamma = gamma
self.q_network = QNetwork(num_actions)
self.optimizer = tf.keras.optimizers.Adam(learning_rate)
# Método para seleccionar una acción
def select_action(self, state):
if np.random.rand() < self.epsilon:
return np.random.choice(self.num_actions)
else:
q_values = self.q_network(np.expand_dims(state, axis=0))
return np.argmax(q_values.numpy())
# Método para actualizar la red neuronal
def update(self, state, action, reward, next_state, done):
with tf.GradientTape() as tape:
q_values = self.q_network(np.expand_dims(state, axis=0))
target = reward + (1 - done) * self.gamma * np.max(self.q_network(np.expand_dims(next_state, axis=0)))
target_f = q_values.numpy()
target_f[0, action] = target
loss = tf.reduce_mean(tf.square(target_f - q_values))
grads = tape.gradient(loss, self.q_network.trainable_variables)
self.optimizer.apply_gradients(zip(grads, self.q_network.trainable_variables))
# Ejemplo de uso
class YourEnvironment:
def __init__(self):
self.state_space = 4 # Por ejemplo, 4 dimensiones de espacio de estado
self.action_space = 2 # Por ejemplo, 2 acciones posibles
def reset(self):
return np.zeros(self.state_space) # Por ejemplo, devuelve un estado inicial
def step(self, action):
next_state = np.random.rand(self.state_space) # Por ejemplo, estado aleatorio
reward = np.random.rand() # Por ejemplo, recompensa aleatoria
done = np.random.rand() > 0.95 # Terminar el episodio con una probabilidad del 5%
return next_state, reward, done, {}
# Número real de acciones en tu entorno de juego
NumberOfActions = 2 # Por ejemplo, 2 acciones posibles
# Creación del entorno y agente
env = YourEnvironment()
num_actions = NumberOfActions
agent = QLearningAgent(num_actions)
# Configuración de hiperparámetros
num_episodes = 100 # Número de episodios de entrenamiento (reducido para pruebas iniciales)
# Ciclo de entrenamiento
for episode in range(num_episodes):
state = env.reset() # Reiniciar el entorno para un nuevo episodio
total_reward = 0 # Inicializar la recompensa total para el episodio
done = False # Inicializar el estado de finalización del episodio
while not done:
action = agent.select_action(state) # Seleccionar una acción según la política actual
next_state, reward, done, _ = env.step(action) # Tomar un paso en el entorno
agent.update(state, action, reward, next_state, done) # Actualizar la red neuronal del agente
total_reward += reward # Acumular la recompensa total del episodio
state = next_state # Actualizar el estado actual al siguiente estado
print("Episode:", episode, "Total Reward:", total_reward) # Imprimir la recompensa total del episodio
En este ejemplo, la red neuronal recibe la observación del entorno de juego y devuelve los valores Q (el valor esperado de la recompensa total) para cada acción posible. El algoritmo de Q-Learning actualiza los valores Q utilizando la ecuación de Bellman y la red neuronal se entrena en cada paso del episodio utilizando el método train_on_batch(). El parámetro epsilon controla la cantidad de exploración que realiza el agente. A medida que se aprende más, la tasa de exploración disminuye para permitir que el agente seleccione más frecuentemente la acción con el valor Q más alto.