首页 > 解决方案 > 如何为 REINFORCE 算法的多维连续动作空间采样动作

问题描述

因此,我正在处理的问题可以总结如下:

  1. 观察空间是一个 8x1 向量,都是连续值。其中一些在 [-inf, inf] 范围内,一些在 [-360, 360] 范围内。

  2. 动作空间是一个 4x1 向量。所有值都在 [-1, 1] 范围内。

  3. 目前,我正在尝试使用策略梯度算法,特别是 REINFORCE 算法来解决它。

  4. 由于动作空间是连续的,在输出层我得到了 4 mu 和 4 sigma 的值,我将它们用作正态分布的参数来对动作进行采样。

  5. 使用神经网络作为函数逼近器和 NN 架构是:

    • 输入层:8个神经元
    • 隐藏层 1:256 个具有 ReLU 激活的神经元
    • 隐藏层 2:具有 ReLU 激活的 256 个神经元
    • 输出层:8个神经元
    • 没有激活函数的 mu 有 4 个神经元,因此可以取 [-inf, inf] 范围内的任何值。但是,稍后在对动作进行采样后,我将它们的值剪辑在 [-1, 1] 之间。用于 sigma 的 4 个神经元,激活 ELU +0.001,以将标准偏差值保持在 [0.001, inf] 范围内。
  6. 我的奖励功能是在一个情节中,

    • 在代理处于某个目标区域内的每个时间步长上,它都会获得 +6000 奖励
    • 每次不在区域内的时间步都会得到 -20
    • 在剧集结束时,如果它不在目标区域内,它会得到 -20000
    • 如果它在剧集中进入 BAD 状态,它将获得 -100000 奖励并且剧集立即结束。
  7. 损失函数是:

    • loss = - log_prob(action) * R
  8. 解决方案似乎没有收敛,因为平均值不断增加并且 sigma 值停留在 0.001(这是它们的最小可能值)。我想问的问题是:

    • 我对动作进行采样的方式是否正确?
    • 损失函数看起来对吗?
    • 我是否也应该在输入层使用 ReLU 激活(虽然这对我来说听起来不对,但是,在我看到的一些 PPO 算法的实现中,人们也在输入端使用 ReLU)
  9. 如果需要指出问题,我也可以共享代码。

  10. 也欢迎任何其他建议。

编辑:顺便说一句,我为这个问题编写了自己的健身房环境,这就是为什么您可能会注意到我的代码与用于解决 OpenAI 健身房相关问题的典型 RL 代码之间存在一些不一致的原因。运行 num_episodes 的主循环是:

def main():
    global num_episodes, normalized_reward_history, reward_history
    env = gym.make('gymXplane-v2')

    pi = Policy()

    for n_epi in range(1, TOTAL_EPISODES+1):
        env.reset()
        sleep(2)
        done = False
        initial_obs = (env.getObservationSpace())
        obs= torch.from_numpy(initial_obs).float().squeeze()
        steps = 0

        while not done:
            steps += 1
            step_arr.append(steps)

            output = pi.forward(obs, softmax_dim=1)

            means = output[:int(ACTION_SPACE_SIZE / 2)]
            sigs = output[int(ACTION_SPACE_SIZE / 2):]

            dists = torch.distributions.Normal(means, sigs)
            action_samples = dists.sample().clamp(-1.0, 1.0)

            obs_prime, reward, done, info = env.step(action_samples)
            pi.put_data((reward), (action_samples, dists))

            obs = torch.t(torch.from_numpy(obs_prime).float())[0]
        pi.train_net()
    env.close()

py.train_net()如下_

    def train_net(self):
        global normalized_reward_history, reward_history
        R = 0
        self.optimizer.zero_grad()

        cumulative = 0
        discounted_rewards = np.zeros(len(self.reward_arr))
        for t in reversed(range(len(self.reward_arr))):  # get discounted rewards
            cumulative = cumulative * GAMMA + self.reward_arr[t]
            discounted_rewards[t] = cumulative

        normalized_rewards = discounted_rewards - np.mean(discounted_rewards)
        if np.std(discounted_rewards) != 0:
            normalized_rewards /= np.std(normalized_rewards)

        data = list(zip(normalized_rewards, self.action_arr))

        for R, action in data[::-1]:
            samples = action[0]
            dists = action[1]

            loss = - dists.log_prob(samples) * R

            loss = loss.mean()

            loss.backward()

        self.optimizer.step()

标签: pythonpytorchreinforcement-learningpolicy-gradient-descent

解决方案


推荐阅读