以下是使用SARSA算法修改后的代码:

# 开始训练Q表格
all_episode_reward = []  # 用于记录每次迭代的总奖励,这样就可以知道智能体是否有进步了
for i in range(num_episodes):
    ## 初始化环境,得到初始状态
    s, _= env.reset()  # 初始状态值
    rAll = 0  # 用于记录这次游戏的总奖励,这里先初始化为0
    ## The SARSA algorithm
    ## 首先,根据epsilon-greedy选择当前状态s下的动作a
    a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
    for j in range(99):
        if render: env.render()
        ## 与环境交互得到下一个状态s1和即时奖励r
        s1, r, d, _, _ = env.step(a)
        ## 根据epsilon-greedy选择在状态s1下的下一个动作a1
        a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
        ## 使用SARSA更新Q表格
        Q[s, a] = Q[s, a] + lr * (r + lambd * Q[s1, a1] - Q[s, a])
        ## 更新当前状态和动作
        rAll += r
        s = s1
        a = a1
        if d is True:
            break
    if i == 0:
        all_episode_reward.append(rAll)
    else:
        all_episode_reward.append(all_episode_reward[-1] * 0.99 + rAll * 0.01)
    print(
    'Training  | Episode: {}/{}  | Episode Reward: {:.4f}  | all_episode_reward: {:.4f} | Running Time: {:.4f}'.format(
        i + 1, num_episodes, rAll, all_episode_reward[i], time.time() - t0
        )
    )

# 保存Q表格
path = os.path.join('model', '_'.join([alg_name, env_id]))
if not os.path.exists(path):
    os.makedirs(path)
np.save(os.path.join(path, 'Q_table.npy'), Q)

# 绘制迭代的总奖励
plt.plot(all_episode_reward)
if not os.path.exists('image'):
    os.makedirs('image')
plt.savefig(os.path.join('image', '_'.join([alg_name, env_id])))

# 打印Q表格
print("Final Q-Table Values:/n %s" % Q)

相对于原始代码,使用SARSA算法修改后的主要变化是:

在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
使用SARSA更新Q表格时,将下一个状态和动作的Q值Q[s1, a1]考虑进去。
这样就能够实现SARSA算法来训练Q表格,从而实现强化学习任务。


以下是使用SARSA算法修改后的代码:


# 模型评估
path = os.path.join('model', '_'.join([alg_name, env_id]))
Q = np.load(os.path.join(path, 'Q_table.npy'))
sum_rAll = 0
for i in range(num_episodes):
    ## 初始化环境,得到初始状态
    s, _ = env.reset()
    rAll = 0
    ## The SARSA algorithm
    ## 首先,根据epsilon-greedy选择当前状态s下的动作a
    a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
    for j in range(99):
        ## 与环境交互得到下一个状态s1和即时奖励r
        s1, r, d, _, _ = env.step(a)
        ## 根据epsilon-greedy选择在状态s1下的下一个动作a1
        a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
        ## 更新当前状态和动作
        rAll += r
        s = s1
        a = a1
        if d is True:
            break
    print(
        'Testing  | Episode: {}/{}  | Episode Reward: {:.4f}  | Running Time: {:.4f}'.format(
            i + 1, num_episodes, rAll,
            time.time() - t0
        )
    )
    sum_rAll += rAll
print('游戏中成功闯关比例: {:.4f}'.format(sum_rAll/num_episodes))

相对于原始代码,使用SARSA算法修改后的主要变化是:

在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
在模型评估时,使用SARSA算法更新当前状态和动作,并且在选择动作时也根据epsilon-greedy进行选择。

标签: none

添加新评论