В обучающем агенте подкрепления обучения не происходит

Я пытаюсь реализовать метод глубокого детерминированного градиента в тензорном потоке и керасе, однако, похоже, застрял. Кажется, что обучения не происходит, действия, предпринимаемые моделью, вообще не меняются, и градиент, применяемый к сети акторов, также очень мал (порядка величины е ^-5). Я использовал другую реализацию в качестве ссылки, и она очень хорошо работает с точно такими же гиперпараметрами и сетевыми архитектурами (за исключением того, что она реализована с помощью tflearn и включает в себя уровни пакетной нормализации), что заставляет меня поверить, что где-то в моем коде есть ошибка. Может быть, кто-то здесь может заметить это. Спасибо за ваше время!

Редактировать: Я думаю, что причина плохой производительности в том, что градиент сети критика по отношению к действию исчезает. Однако я не могу понять, почему. Может быть, мое использование связанного слоя неверно?

class AIInterface(object):

def __init__(self, sim):

    self.sim = sim

    self.pedal_pos = 0
    self.steering_pos = 0

    self.sess = tf.Session()

    self.learning_rate = 10e-4
    self.BATCH_SIZE = 64
    self.epsilon = .75 #amount of random exploration
    self.epsilon_decay = .997
    self.gamma = .99 #reward discount factor
    self.tau = .00125 #target update factor

    self.rewards = deque(maxlen=100000)
    self.memory = deque(maxlen=100000)

    # Actor stuff
    self.actor_model, self.actor_var_in = self.initialize_actor()
    self.target_actor, _ = self.initialize_actor()

    self.actor_critic_grad = tf.placeholder(tf.float32, [None, 1])

    self.actor_model_weights = self.actor_model.trainable_weights

    with tf.name_scope("actor_gradients"):
        self.actor_grads = tf.gradients(self.actor_model.output, self.actor_model_weights, -self.actor_critic_grad)
        self.normalized_actor_grads = list(map(lambda x: tf.div(x, self.BATCH_SIZE), self.actor_grads))

    grads = zip(self.normalized_actor_grads, self.actor_model_weights)
    self.optimize = tf.train.AdamOptimizer(self.learning_rate).apply_gradients(grads)

    # Critic stuff
    self.critic_model, self.critic_var_in, self.critic_action_in = self.initialize_critic()
    self.target_critic, _, _ = self.initialize_critic()

    with tf.name_scope("CriticGrads"):
        self.critic_grads = tf.gradients(self.critic_model.output, self.critic_action_in)

    self.sess.run(tf.global_variables_initializer())

    self.target_actor.set_weights(self.actor_model.get_weights())
    self.target_critic.set_weights(self.critic_model.get_weights())

    self.global_step = 0

def initialize_actor(self):

    state_variable_input = Input(shape=(3, ))

    init = TruncatedNormal(mean=0.0, stddev=0.02)

    dense = Dense(128, activation="relu", kernel_initializer=init)(state_variable_input)
    dense2 = Dense(128, activation="relu", kernel_initializer=init)(dense)

    output = Dense(1, activation="tanh", kernel_initializer=RandomUniform(-3e-3, 3e-3))(dense2)

    model = Model(inputs=state_variable_input,
                  outputs=output)

    model.compile(optimizer="adam", loss="mse")

    return model, state_variable_input


def initialize_critic(self):

    state_variable_input = Input(shape=(3, ))
    action_input = Input(shape=(1, ))

    init = TruncatedNormal(mean=0.0, stddev=0.02)
    dense_state = Dense(128, activation="relu", kernel_initializer=init)(state_variable_input)

    merge = Concatenate()([dense_state, action_input])
    dense2 = Dense(128, activation="relu", kernel_initializer=init)(merge)

    output = Dense(1, activation="linear", kernel_initializer=RandomUniform(-3e-3, 3e-3))(dense2)

    model = Model(inputs=[state_variable_input, action_input],
                  outputs=output)

    model.compile(optimizer="adam", loss="mse")

    return model, state_variable_input, action_input


def train(self):

    if len(self.memory) < self.BATCH_SIZE:
        return

    samples = random.sample(self.memory, self.BATCH_SIZE)

    samples = [np.concatenate(x) for x in zip(*samples)]

    self.train_critic(samples)
    self.train_actor(samples)
    self.global_step += 1


def train_critic(self, samples):

    cur_state_var, action, reward, new_state_var = samples

    predicted_action = self.target_actor.predict([new_state_var])

    future_reward = self.target_critic.predict([new_state_var, predicted_action])

    Q = reward + self.gamma*future_reward

    self.critic_model.train_on_batch([cur_state_var,  action], Q)


def train_actor(self, samples):

    cur_state_var, action, reward, new_state_var = samples
    predicted_action = self.actor_model.predict([cur_state_var])

    grads = self.sess.run([self.critic_grads], feed_dict={
        self.critic_var_in: cur_state_var,
        self.critic_action_in: predicted_action})

    self.sess.run(self.optimize, feed_dict={
        self.actor_var_in: cur_state_var,
        self.actor_critic_grad: grads[0]
        })

def update_actor_target(self):

    actor_model_weights = self.actor_model.get_weights()
    actor_target_weights = self.target_actor.get_weights()

    for i in range(len(actor_target_weights)):
        actor_target_weights[i] = self.tau * actor_model_weights[i] + (1-self.tau)*actor_target_weights[i]
    self.target_actor.set_weights(actor_target_weights)

def update_critic_target(self):

    critic_model_weights = self.critic_model.get_weights()
    critic_target_weights = self.target_critic.get_weights()

    for i in range(len(critic_target_weights)):
        critic_target_weights[i] = self.tau * critic_model_weights[i] + (1-self.tau)*critic_target_weights[i]
    self.target_critic.set_weights(critic_target_weights)

def update_model(self):

    self.update_actor_target()
    self.update_critic_target()


def act(self, cur_state_var, noise=None, env=None):

    if env:
        if np.random.random() < self.epsilon:
            return env.action_space.sample()

        else:
            sh = cur_state_var.shape
            action = self.actor_model.predict([cur_state_var], batch_size=1)[0]

            return action

    elif not noise:
        if np.random.random() < self.epsilon:
            return self.sample_action_space()
        return self.actor_model.predict([cur_state_var], batch_size=1)[0]
    else:
        no = noise()
        pred = self.actor_model.predict([cur_state_var], batch_size=1)[0]

        return pred + no

def sample_action_space(self):

    return np.array([random.uniform(-0.5, 0.5), random.uniform(-1.0, 1.0)]).reshape(2, )

def remember(self, cur_state_var, action, reward, new_state_var):

    self.memory.append([cur_state_var, action, reward,  new_state_var])

0 ответов

Другие вопросы по тегам