В настоящее время я работаю над многоагентной проблемой обучения с подкреплением для решения проблемы координации. Я пытаюсь реализовать алгоритм MADDPG Р. Лоу. Это расширение обычного подхода Actor-Criti c -Approach для многоагентных сред. Поскольку я использую tenorflow 2.0, я не нашел много примеров по inte rnet, поэтому я начал разрабатывать его сам с нуля.
Прямо сейчас я сталкиваюсь с проблемой, что мой средний критический c убыток и средняя потеря актера скорее взрывается, чем конвертируется, как вы можете видеть на картинке. Для мониторинга я рассчитал среднюю потерю нескольких критиков, а также актеров.
Средний актер и криты c потери за 500 эпизодов
К сожалению, я не совсем уверен, как интерпретировать эти потери. Поскольку потеря должна показывать разницу между прогнозируемым значением и фактическим значением, она должна сходиться к нулю в процессе обучения.
Модель актера определяется следующим образом:
class Actor(tf.keras.Model):
def __init__(self, state_size, num_actions, learning_rate, num_agents):
super(Actor, self).__init__()
self.state_size = state_size
self.num_actions = num_actions
self.learning_rate = learning_rate
self.num_agents = num_agents
self.obs_input = Input(self.num_agents, name="obs_input", dtype='float64')
self.h1 = Dense(50, activation='relu', dtype='float64', name='TEST1')
self.h2 = Dense(20, activation='relu', dtype='float64', name='TEST2')
self.out = Dense(self.num_actions, activation='linear', name='actor_output', dtype='float64')
# Create optimizer
self.opt = tf.optimizers.Adam(learning_rate = self.learning_rate)
@tf.function
def call(self, inputs):
x = self.h1(inputs)
x = self.h2(x)
out = self.out(x)
return out
Критика c:
class Critic(tf.keras.Model):
def __init__(self, obs_dim, action_dim, critic_learning_rate, num_agents):
super(Critic, self).__init__()
self.obs_dim = obs_dim
self.action_dim = action_dim
self.learning_rate = critic_learning_rate
self.num_agents = num_agents
self.obs_input = Input(shape=(num_agents, obs_dim), name="obs_input", dtype='float64')
self.obs_dense = Dense(1, activation='relu', dtype='float64', name="obs_dense")
self.action_input = Input(shape=(1, action_dim), name="actions_input", dtype='float64')
self.action_dense = Dense(1, activation='relu', dtype='float64', name="action_dense")
self.other_action_input = Input(shape=(num_agents-1, action_dim), name="other_actions_input", dtype='float64')
self.other_action_dense = Dense(1, activation='relu', dtype='float64', name="other_action_dense")
self.merged_input = Concatenate([self.obs_dense, self.action_dense])
self.first_dense = Dense(30, activation='relu', dtype='float64')
self.second_dense = Dense(20, activation='relu', dtype='float64')
self.flatten = Flatten()
self.out = Dense(1, activation='linear', name="q_output", dtype='float64')
self.opt = tf.optimizers.Adam(learning_rate = self.learning_rate)
self.initialize_trainable_weights()
@tf.function
def call(self, obs_inputs, action_inputs, other_action_inputs):
obs_x = self.obs_dense(obs_inputs)
act_input = tf.concat([action_inputs, other_action_inputs], axis=1)
act_x = self.action_dense(act_input)
x = tf.keras.layers.concatenate([obs_x, act_x])
x = self.first_dense(x)
x = self.second_dense(x)
x = self.flatten(x)
out = self.out(x)
return out
Обновление выполняется этой функцией с использованием tf.GradientTape () :
@tf.function
def update(self, indiv_reward_batch, indiv_obs_batch, global_state_batch, other_action_inputs, agent_action_inputs, global_next_state_batch, other_next_action_inputs, agent_next_action_inputs, batch_size, all_agents):
"""
indiv_reward_batch : only rewards of agent i
indiv_obs_batch : only observations of agent i
global_state_batch : observations of all agents are concatenated
global actions_batch : actions of all agents are concatenated
global_next_state_batch : observations of all agents are concatenated
next_global_actions : actions of all agents are concatenated
"""
# --------------------- Update Critic ---------------------
avg_critic_loss = 0
indiv_reward_batch = tf.cast(indiv_reward_batch, dtype=tf.float64)
indiv_reward_batch = tf.reshape(indiv_reward_batch, (batch_size, 1))
with tf.GradientTape() as tape:
tape.watch(self.critic.trainable_variables)
current_q = self.critic(global_state_batch, agent_action_inputs, other_action_inputs)
next_Q = self.critic_target(global_next_state_batch, agent_next_action_inputs, other_next_action_inputs)
y = indiv_reward_batch + self.gamma * next_Q
critic_loss = tf.reduce_mean((y - current_q)**2)
critic_grads = tape.gradient(critic_loss, self.critic.trainable_variables)
critic_grads_and_vars = zip(critic_grads, self.critic.trainable_variables)
self.critic.opt.apply_gradients(critic_grads_and_vars)
avg_critic_loss = critic_loss
# --------------------- Update Actor ---------------------
with tf.GradientTape() as tape:
tape.watch(self.actor.trainable_variables)
policy_loss = -tf.reduce_mean(self.critic(global_state_batch, self.actor(indiv_obs_batch), other_action_inputs))
grads = tape.gradient(policy_loss, self.actor.trainable_variables)
grads_and_vars = zip(grads, self.actor.trainable_variables)
self.actor.opt.apply_gradients(grads_and_vars)
Я не привык выполнять обновление градиента вручную, поэтому я не совсем уверен, есть ли ошибка. Глядя на уравнения в MADDPG-Paper, я считаю, что функции потерь правильны.
Я был бы очень признателен, если бы у кого-то было представление, откуда может возникнуть проблема или из каких частей мне следует ближе посмотри на. Если кто-то знает пример реализации MADDPG-алгоритма с использованием TF 2.0, я также был бы очень благодарен (единственные примеры, которые я нашел, когда использовали Pytorch).
Любые идеи приветствуются! :)
Спасибо!