PyTorch强化学习——基于值迭代的强化学习算法

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

基于值迭代的强化学习算法

基于值迭代的强化学习算法的核心思想与策略评估非常类似,它也是一种迭代算法。从任意策略值开始,然后根据 Bellman 最优方程迭代更新值,直到它们收敛为止。在每次迭代中,选择达到能够获得最大策略值的动作:

V ( s ) : = m a x a [ R ( s , a ) + γ s T ( s , a , s ) V ( s ) ] V^*(s):=max_a[R(s,a)+\gamma \sum_{s'}T(s,a,s')V^*(s')]

其中, V ( s ) V^*(s) 表示最优值,它是最优策略值; T ( s , a , s ) T(s,a,s') 表示采取动作 a a 从状态 s s 转移到状态 s s' 的概率; R ( s , a ) R(s,a) 是在状态 s s 通过采取动作 a a 所获得的奖励。 一旦计算出最佳值,我们就可以轻松地相应地获得最佳策略:

π ( s ) : = a r g m a x a s T ( s , a , s ) [ R ( s , a , s ) + γ V ( s ) ] \pi^*(s):=argmax_a\sum_{s'}T(s,a,s')[R(s,a,s')+\gamma V^*(s')]

使用 PyTorch 实现基于值迭代的强化学习算法

本节,我们使用 PyTorch 实现基于值迭代的强化学习算法来解决 FrozenLake 问题。 首先,我们导入所需的库并创建 FrozenLake 环境实例,并定义折扣因子和判断算法收敛的阈值:

import torch
import gym
env = gym.make('FrozenLake-v0')

gamma = 0.99
threshold = 0.0001
复制代码

接下来,定义函数使用基于值迭代的强化学习算法计算最佳策略值。在基于值函数的强化学习算法中,我们通过迭代应用 Bellman 最优方程来获得最优值函数。 以下是 Bellman 最优方程的另一个版本,它可以处理奖励部分取决于新状态的环境:

V ( s ) : = m a x a s T ( s , a , s ) [ R ( s , a , s ) + γ V ( s ) ] V^*(s):=max_a\sum_{s'}T(s,a,s')[R(s,a,s')+\gamma V^*(s')]

其中, R ( s , a , s ) R(s,a,s') 是通过采取动作 a a 从状态 s s 转移到状态 s s' 而得到的奖励。由于此版本通用性更强,因此我们将基于此式实现 value_function 函数,在函数中执行以下操作:

  • 将策略值初始化为全零张量
  • 根据 Bellman 最优方程更新策略值
  • 计算所有状态下策略值的最大变化
  • 如果最大变化大于阈值,继续更新策略值;否则,终止评估过程,并返回最新值作为最佳值
def value_function(env, gamma, threshold):
    """
    Solve a given environment with value function based algorithm
    env: Gym 环境
    gamma: 折扣因子
    threshold: 当所有状态的值函数都小于阈值使,评估过程终止
    return: 给定环境的最优策略值
    """
    n_state = env.observation_space.n
    n_action = env.action_space.n
    V = torch.zeros(n_state)
    while True:
        V_temp = torch.zeros(n_state)
        for state in range(n_state):
            v_actions = torch.zeros(n_action)
            for action in range(n_action):
                for trans_prob, new_state, reward, _ in env.env.P[state][action]:
                    v_actions[action] += trans_prob * (reward + gamma * V[new_state])
            V_temp[state] = torch.max(v_actions)
        max_delta = torch.max(torch.abs(V - V_temp))
        V = V_temp.clone()
        if max_delta <= threshold:
            break
    return V
复制代码

以定义的环境、折扣因子和收敛阈值为参数执行 value_function 函数,然后打印最佳值:

V_optimal = value_function(env, gamma, threshold)
print('Optimal values:\n{}'.format(V_optimal))
复制代码

打印出的最优值如下所示:

Optimal values:
tensor([0.5404, 0.4966, 0.4681, 0.4541, 0.5569, 0.0000, 0.3572, 0.0000, 0.5905,
        0.6421, 0.6144, 0.0000, 0.0000, 0.7410, 0.8625, 0.0000])
复制代码

得到最优值之后,我们就可以基于最优值实现提取最优策略的函数:

def extract_optimal_policy(env, V_optimal, gamma):
    """
    Obtain the optimal policy based on the optimal values
    env: Gym 环境
    V_optimal: 最优策略值
    gamma: 折扣因子
    return: 最优策略
    """
    n_state = env.observation_space.n
    n_action = env.action_space.n
    optimal_policy = torch.zeros(n_state)
    for state in range(n_state):
        v_actions = torch.zeros(n_action)
        for action in range(n_action):
            for trans_prob, new_state, reward, _ in env.env.P[state][action]:
                v_actions[action] += trans_prob * (reward + gamma * V_optimal[new_state])
        optimal_policy[state] = torch.argmax(v_actions)
    return optimal_policy
复制代码

以环境、折扣因子和最佳值为参数执行 extract_optimal_policy 函数,然后打印最佳策略:

optimal_policy = extract_optimal_policy(env, V_optimal, gamma)
print('Optimal policy:\n{}'.format(optimal_policy))
复制代码

打印出的最优策略如下所示:

Optimal policy:
tensor([0., 3., 3., 3., 0., 0., 0., 0., 3., 1., 0., 0., 0., 2., 1., 0.])
Average total reward under the optimal policy: 0.769
复制代码

最后,我们评估最佳策略的有效性。以最佳策略运行 FrozenLake 环境 1000 回合,并计算平均奖励:

def run_episode(env, policy):
    state = env.reset()
    total_reward = 0
    is_done = False
    while not is_done:
        action = policy[state].item()
        state, reward, is_done, info = env.step(action)
        total_reward += reward
        if is_done:
            break
    return total_reward

n_episode = 1000
total_rewards = []
for episode in range(n_episode):
    total_reward = run_episode(env, optimal_policy)
    total_rewards.append(total_reward)
print('Average total reward under the optimal policy: {}'.format(sum(total_rewards) / n_episode))
复制代码

在最佳策略下,智能体平均有 75% 的概率可以达到目标。由于冰面十分光滑,因此这是我们能够获得的最好的效果:

tensor([0., 3., 3., 3., 0., 0., 0., 0., 3., 1., 0., 0., 0., 2., 1., 0.])
Average total reward under the optimal policy: 0.769
复制代码

猜你喜欢

转载自juejin.im/post/7111312791507730468