A2C中如何给演员设置目标?

人工智能 强化学习 喀拉斯 演员批评方法 优势-演员-评论家
2021-11-14 22:11:40

我在 Keras 中做了一个简单的 Actor-Critic 实现,使用 2 个网络,critic 学习每个动作的 Q 值,actor 预测选择每个动作的概率。在训练中,actor的目标概率是一个单热向量,1.0在最大Q值预测位置和0.0其余所有位置,并且简单地使用fit具有均方误差损失函数的actor模型的方法。

但是,我不确定切换到 A2C 时要设置什么作为目标。在我看到的所有指南中都提到,critic 现在每个状态学习一个值,而不是动作空间中的每个动作一个值。

这种变化使得如何为actor设置目标向量变得不清楚。我过去的guides/SE questions没有解释这一点,只是说我们可以使用当前和下一个状态的价值函数(hereherehere)计算优势值,这很好,只是我们只能这样做对于所采取的具体行动,而不是针对行动空间中的每一个行动,因为我们没有为每一个行动的每一个下一个状态的价值。

换句话说,我们只知道A(s,a)我们的记忆a,而我们对其他行动的优势一无所知。

我的一个猜测是你仍然计算 Q-Values,因为毕竟价值函数是由 Q-Values 定义的价值函数是 的每个动作的a总和Q(s,a)*p(a)那么,critic 是否需要学习 Q 值并将它们与策略网络(参与者)生成的概率相乘,并计算每个动作的优势?

更令人困惑的是,在其中一个指南中,他们说评论家实际上学习的是优势值,而不是价值函数(就像所有其他指南所说的那样),这很奇怪,因为您需要使用评论家来预测价值函数状态和下一个状态。此外,优势函数是每个动作,在实现中我看到评论家有一个输出神经元。

我认为在我看到的示例中所做的是训练演员以适合所选动作的单热向量(不是评论家的最佳动作),但使用优势值修改损失函数值(可能影响梯度)。是这样吗?

1个回答

简而言之,我的最后一句话是正确答案。“目标”是选定动作的一个单键,但有一个技巧。


A2C 损失函数

我错过的 A2C 实现的一个非常关键的部分是考虑到优势的自定义损失函数。损失函数将优势乘以当前概率的负对数来选择被选择的动作。

诀窍是,如果优势为负,损失函数将切换符号,因此梯度将应用于相反的方向。

在一个维度上,它更容易理解。假设我的目标预测是1,而我的实际预测是0.6一个简单的损失将被定义为target - prediction,或者在这种情况下0.4,未来的预测将更接近 1。如果我的预测是1.4,那么损失将是-0.4负损失意味着预测未来的结果会更低,而正的结果意味着预测未来的结果会更高。

如果损失函数的符号被切换,预测实际上将远离1

当您将损失函数中的优势相乘时,也会发生同样的事情。负优势意味着该动作比状态值差,因此我们需要避免它,正优势意味着该动作受到鼓励。


在 Keras(Tensorflow 2.0)中:

这是自定义损失函数:

def custom_actor_loss(y_true, y_prediction, advantage):
    prediction = K.clip(y_prediction, 1e-8, 1 - 1e-8)
    log_probabilities = y_true * K.log(prediction)

    return K.sum(-log_probabilities*advantage)

由于未定义 0 的对数,因此对这些值进行了剪裁。

其余的网络建设:

input_layer = Input(shape=self._state_size, name='state_in')
advantage = Input(shape=[1], name='advantage')
target_prediction = Input(shape=self._actions_num, name='target')

inner_layer = Dense(units=layer_size, activation='relu')(input_layer)
actor_out = Dense(units=self._actions_num, activation='softmax', name='actor_out')(inner_layer)

self._actor = Model([input_layer, target_prediction, advantage], actor_out, name='actor')
self._actor.add_loss(custom_actor_loss(actor_out, target_prediction, advantage))
self._actor.compile(optimizer=Adam(learning_rate=actor_learning_rate))

在训练循环中(其中future_rewards_predictioncritic_prediction是当前和下一个状态的批评者的输出(除了设置为 的终端状态future_rewards_prediction0

# Train actor
target_probabilities = np.zeros([1, self._actions_num])
target_probabilities[0][memory[step_idx].action] = 1.0
advantage = memory[step_idx].reward + future_rewards_prediction * self._future_discount - critic_prediction
self._actor.fit((memory[step_idx].state, target_probabilities, advantage), verbose=0)

*请注意,我并没有yfit通话中真正指定 a 。这是因为我在尝试在 Keras 中实现自定义损失函数时遇到了一个问题,这个问题已经解决了。