Q-table 未在 FrozenLake-v1 环境中使用 Q-learning 进行更新

问题描述 投票:0回答:1

我目前正在 OpenAI Gym 中为 FrozenLake-v1 环境实施 Q-learning。然而,我的 Q 表似乎在训练期间没有更新,并且仍然充满零。我已经多次检查了我的代码,但我无法查明问题所在。

这是我正在使用的代码:

import gymnasium as gym
import numpy as np
import random


def run():
    env = gym.make("FrozenLake-v1") # setup env
    Q = np.zeros((env.observation_space.n, env.action_space.n)) # empty q_table

    alpha = 0.7
    gamma = 0.95
    epsilon = 0.9
    epsilon_decay = 0.005
    epsilon_min = 0.01
    episode = 0
    episodes = 10000

    state, info = env.reset()

    print("Before training")
    print(Q)

    while episode < episodes:

        if epsilon > epsilon_min:
            epsilon -= epsilon_decay
        if random.random() < epsilon:
            action = env.action_space.sample()
        else:
            action = np.argmax(Q[state])

        new_state, reward, terminated, truncated, info = env.step(action)

        Q[state, action] = Q[state, action] + alpha * (float(reward) + gamma * np.max(Q[new_state]) - Q[state, action])

        state = new_state

        if terminated or truncated:
            episode += 1
            state, info = env.reset()  # Reset the environment

    print("After training")
    print(Q)
    env.close()


run()

我怀疑这个问题可能与我更新 Q 表或处理环境状态的方式有关。任何识别和解决问题的帮助将不胜感激。

我添加了打印语句来显示中间值,包括训练期间选定的操作、奖励和 Q 表本身。这是为了检查值是否按预期更新。我尝试用较少数量的剧集来训练代理,以简化问题并观察 Q 表是否开始更新。然而,即使剧集数量减少,Q 表仍然充满零。我重新审视了 Q 表更新公式,以确保它与 Q 学习算法保持一致。公式看起来是正确的,但问题仍然存在。

我预计 Q 表会在训练期间逐渐更新,反映智能体对状态-动作对的学习值。然而,即使在运行指定次数的训练循环后,Q 表也保持不变,并用零填充。

python openai-gym q-learning
1个回答
0
投票

该问题是由两个问题共同造成的:

  • 你的 epsilon 会很快衰减到最小值(178 步),
  • 您正在使用 NumPy 的 argmax 函数。

如果数组中有多个最大值,

np.argmax
将返回出现最大值的第一个索引。最初,Q 表中的所有值都是 0,因此每当您采取利用步骤时,您将采取第一个操作,在本例中是“向左移动”。

除了到达目标状态外,所有奖励都是零,因此只有在您第一次找到目标状态(并获得奖励1)之后,Q表才会开始包含非零值。 你的智能体不太可能在前几百集中找到目标状态,并且由于 epsilon 很快衰减到 0.01,所以你大部分时间都在采取利用步骤(即向左移动),获得 0 的奖励,并且不使对 Q 表进行任何有意义的更新。

我建议使用以下函数,而不是

np.argmax
,该函数返回出现最大值的随机索引:

def argmax(arr):
    arr_max = np.max(arr)
    return np.random.choice(np.where(arr == arr_max)[0])

此外,epsilon 的这些超参数更加合理。 使用此方法,epsilon 将在一半左右达到最小值 培训内容:

epsilon = 1
epsilon_decay = (2 * epsilon) / episodes
epsilon_min = 0.001
© www.soinside.com 2019 - 2024. All rights reserved.