强化学习组队学习task02——马尔可夫决策过程及表格型方法

一、马尔科夫决策过程

马尔科夫过程描述了强化学习的框架。在马尔科夫过程中,环境是完全可以观测的,但是很多时候环境里面有些量是不可观测的,但是这个部分观测的问题也可以转换成一个 MDP 的问题。

在介绍马尔可夫决策过程之前,先梳理一下马尔可夫链、马尔可夫奖励过程。这两个过程是马尔可夫决策过程的一个基础。

1.马尔科夫链

当一个状态满足马尔科夫特征时,要求未来的转移只取决于现在的状态,与过去无关。马尔可夫性质是所有马尔可夫过程的基础。

下图为一个马尔科夫链示例:
在这里插入图片描述

这张图中有七个状态,这七个状态不断转移,以s1为例:

  • s1有0.6的概率继续存活在s1状态
  • s1有0.4的概率转换到s2

其余节点与s1类似。我们可以用一个状态转移方程来描述这种状态转移,每一行描述了从一个节点到达所有其它节点的概率

在这里插入图片描述

2.马尔科夫奖励过程

马尔可夫奖励过程(Markov Reward Process, MRP) 是马尔可夫链再加上了一个奖励函数。

在 MRP 中,转移矩阵跟它的这个状态都是跟马尔可夫链一样的,多了一个奖励函数(reward function) 。奖励函数是一个期望,就是说当到达某一个状态的时候,可以获得多大的奖励,然后这里另外定义了一个 discount factor。

依旧以上面的马尔科夫链为例,将奖励加上,即到达每一个状态时,都会得到一个奖励。例如到达s1时,得到5的奖励,到达s7时,得到10的奖励,其他状态没有任何奖励,所以我们可以用一个向量来表示这个奖励。
在这里插入图片描述
一些概念:

  • horizon:它说明了同一个 episode 或者是整个一个轨迹的长度,它是由有限个步数决定的。
  • return:奖励的逐步叠加,discount factor说明我们其实更希望得到现有的奖励,未来的奖励就要把它打折扣。
    在这里插入图片描述
  • 状态价值函数:某一状态的价值,可以看作关于 return 的期望。也可以看成是一个对未来可能获得奖励的当前价值的一个表现。
    在这里插入图片描述
  • discounted factor:折扣因子,折扣因子在状态价值函数中扮演着重要作用,原因如下:
    • 马尔可夫过程是带环的,这个无穷的奖励。
    • 希望尽可能快地得到奖励
    • 设置为0时,只关心当前奖励,设为1时,未来和当前奖励一样,可作为超参数

依旧以之前的马尔科夫链为例,假设折扣系数为0.5,s1奖励为5,s7奖励为10,其余为0
在这里插入图片描述
对于马尔科夫链s4、s5、s6、s7,价值为0+0* 1/2+0* 1/4+10* 1/8=1.25
计算价值函数有如下方法:

(1)贝尔曼公式(Bellman equation)

Bellman Equation 定义了当前状态与未来状态的迭代关系,表示当前状态的值函数可以通过下个状态的值函数来计算。
在这里插入图片描述
第一部分为当前立刻可以得到的奖励,第二部分是未来打了折扣的奖励之和。

s’可看作未来的所有状态,P(s’|s)指从当前状态转移到未来状态的概率,V(S’)代表的是未来某一个状态的价值,最后把未来的奖励打折扣。

以矩阵形式表示价值函数:
在这里插入图片描述
在这里插入图片描述
得到的解析解:
在这里插入图片描述
需要注意的是,这种方法时间复杂度很高,只能求比较小的马尔科夫价值。

(2)迭代法

迭代的方法就有几种,比如说动态规划的方法、也可以通过蒙特卡罗办法,即通过采样的办法去计算它、另外可以通过 Temporal-Difference Learning 的办法,这个 Temporal-Difference Learning 叫TD Leanring ,就是动态规划和蒙特卡罗的一个结合。

蒙特卡罗办法

下面是蒙特卡罗方法的伪代码

在这里插入图片描述
蒙特卡罗办法的具体思想是当得到一个 MRP 后,从某一个状态开始,随机产生很多轨迹。产生了一个轨迹过后,就会得到一个奖励,直接把它的 discounted 的奖励算出来。算出来后就积累起来,当积累到一定的轨迹数量后,然后直接除以轨迹的数量,然后就会得到它的这个价值。

动态规划方法

下面是动态规划的伪代码:

在这里插入图片描述
动态规划办法通过一直去迭代 Bellman Equation,最后达到收敛。即最后更新的状态跟上一个状态变化并不大的时候,这个更新就可以停止,最终输出最新的V(S’)。

3.马尔科夫决策过程

马尔可夫决策过程(Markov Decision Process) 多了一个 action ,其它的定义跟 MRP 都是类似的。状态转移也多了一个条件,就是采取的某一种行为会导致未来的状态会不同。价值函数也多了一个条件,即当前的状态以及你采取的行为会决定当前可能得到的奖励多少。
在这里插入图片描述
在这里插入图片描述
MDP中的决策(policy):

  • Policy 定义了在某一个状态应该采取什么样的行为
  • 知道当前状态后,带入 policy function,会得到一个决定采取什么行动的概率或者直接输出一个值
  • 决策函数:
    在这里插入图片描述
  • 概率函数是静态的(stationary),不同时间采取的行为都是对 policy function 进行采样。

MDP 跟 MRP 之间可以进行转换。已知一个 MDP 和一个决策函数π的时候,可以把 MDP 转换成MRP。在 MDP 里面,转移函数 是基于它当前状态以及它当前的 action,现在已知 policy function,那么可以直接把这个 action 进行加和,直接把这个 action 去掉,这样就会得到一个类似于 MRP的奖励函数。

MDP的价值函数

  • 状态价值函数(state-value function):定义是跟 MRP 是类似,这个期望是基于采取的 policy,通过对 policy 进行采样来得到一个期望,那么就可以计算出它的这个价值函数。
    在这里插入图片描述

  • Q 函数(action-value function):定义的是在某一个状态采取某一个行为,然后可能得到的 return 的一个期望。这里期望其实也是基于 policy function。所以需要对这个 policy function 进行一个加和,最后得到它的这个价值。
    在这里插入图片描述

  • 对 Q 函数中的行为函数进行加和,就可以得到状态价值函数。
    在这里插入图片描述

  • 通过贝尔曼公式,可以将状态价值函数变换为Q函数
    在这里插入图片描述

  • Bellman Expectation Equation :对状态-价值函数进行一个分解,得到类似于之前 MRP 的 Bellman Equation。定义了当前状态跟未来状态之间的一个关联。
    在这里插入图片描述

  • Q 函数的 Bellman Expectation Equation:对于 Q 函数,也可以做类似的分解
    在这里插入图片描述

  • 当前时刻的 Q 函数跟未来时刻的 Q 函数之间的关联
    在这里插入图片描述

  • 当前状态的价值跟未来状态价值之间的关联
    在这里插入图片描述

  • policy evaluation:计算价值函数的过程,也可以理解成评估这个策略会得到多大的奖励。

例子

在这里插入图片描述
假设环境里面有两种行为:往左走和往右走。奖励函数是只要达到s1,会有5的奖励,达到s7,有10的奖励,其余无奖励。对于如下的三种情况:

  1. 假设采取的策略是不管在任何状态都是往左走,折扣因子是0。那么对于 deterministic policy,最后估算出的价值函数是一致的。直接通过 Bellman Expectation Equation 不停地迭代,最后会收敛。收敛过后的值就是每一个状态的价值。
  2. 假设采取的策略是不管在任何状态都是往左走,折扣因子是 0.5,通过如下等式进行迭代,最后。就会得到它的状态
    在这里插入图片描述
  3. 假设采取的策略是0.5 的概率往左走,有 0.5 的概率往右走,折扣因子是 0.5。开始的时候,可以初始化不同的V(S’)都会有一个值,那么放到Bellman Expectation Equation去迭代,最后是v ,然后就会算出来。

4.马尔科夫决策过程的决策评价

MDP 的Prediction 是给定一个 MDP 以及一个 policy ,去计算value function,就相当于每个状态它的价值函数是多少,可以通过动态规划去解决。

MDP是满足动态规划的要求的,在 Bellman Equation 里可以把它分解成一个递归结构。当我们把它分解成一个递归结构时,如果我们的子问题子状态能得到一个值,那么它的未来状态因为跟子状态是直接相连的,也可以继续推算出来,所以这个价值函数就可以储存它以及重用它的最佳的解。

对于 policy evaluation问题,使用的方法是反复迭代Bellman Expectation Backup直到收敛,Bellman Expectation Backup公式如下:
在这里插入图片描述
由于已经给定了这个函数的 policy function,那么可以直接把它简化成一个 MRP 的表达形式,就相当于我们把这个a去掉,如下式所示:
在这里插入图片描述

这样它就只有价值函数跟转移函数了。通过去迭代这个函数,我们也可以得到每个状态的价值。因为不管是在 MRP 以及 MDP,价值函数包含的变量都是只跟状态有关,就相当于进入某一个状态,未来可能得到多大的价值。

5.马尔科夫决策过程的控制

MDP 的Control 是去寻找一个最佳的策略,它的 input 就是MDP,输出是最佳价值函数(optimal valuefunction)以及最佳策略(optimal policy),可以通过动态规划去解决。

最佳价值函数

搜索一种 policy ,然后我们会得到每个状态它的状态值最大的一个情况, V*就是到达每一个状态,它的值的极大化情况。
在这里插入图片描述

最佳策略

在出现上面的极大化情况是得到的策略。可能有多个最佳的 policy,多个 policy 可以取得相同的最佳价值。
在这里插入图片描述
寻找最佳的 policy可以通过对 Q 函数进行极大化,得到最佳价值。当所有东西都收敛后,因为 Q 函数是关于状态跟动作的函数,所以对某一个状态采取一个行为,然后可以使得这个 Q 函数最大化,那么就这个行为就应该是最佳的行为。所以就可以直接提取出它的最佳策略。
在这里插入图片描述

Bellman Optimality Equation

整个 MDP 已经到达最佳的状态时满足Bellman Optimality Equation。当到达最佳状态过后,对于 Q 值,取最大的 action 时候的那个值,直接等于最佳 value function。
在这里插入图片描述
将该式与Q函数结合就会得到 Q 函数之间的转移
在这里插入图片描述

策略搜索办法

  1. 穷举法:假设我们有有限多个状态、有限多个行为可能性,每个状态可以采取有限种行为的策略。把这些可能的policy穷举一遍,然后算出每种策略的 value function,然后对比一下可以得到最佳策略。这种方法的缺点是非常没有效率。
  2. policy iteration:这个方法主要有两个步骤,这两个步骤一直在迭代,直到收敛:
    1. policy evaluation:先保证 policy 不变,去估计当前的价值,即v函数。
      在这里插入图片描述

    2. policy improvement:取得 v 函数过后可以进一步推算出Q 函数。通过在得到的 Q 函数上面做一个贪心的搜索,这样就会进一步改进它的策略。
      在这里插入图片描述

  3. Value iteration:将 Bellman Optimality Equation 作为更新规则,不断进行迭代直到收敛
    在这里插入图片描述
    在这里插入图片描述
    在进行价值迭代后可以通过下式得到最优决策
    在这里插入图片描述

二、表格型方法

1.Q表格与状态价值

P函数和R函数: P函数反应的是状态转移的概率,即反应的环境的随机性,R函数就是Reward function。但是我们通常处于一个未知的环境(即P函数和R函数是未知的)。

Q表格型表示方法: 表示形式是一种表格形式,其中横坐标为 action(agent)的行为,纵坐标是环境的state,其对应着每一个时刻agent和环境的情况,并通过对应的reward反馈去做选择。一般情况下,Q表格是一个已经训练好的表格,不过,我们也可以每进行一步,就更新一下Q表格,然后用下一个状态的Q值来更新这个状态的Q值(即时序差分方法)。

时序差分(Temporal Difference): 步步更新。不用知道全局,走一步看一步的做自身引导。即此时与下一时刻的价值函数差分(也可以理解是现实与预测值的差距)来近似代替蒙特卡洛中的完整价值。

采用时序差分法的强化学习可以分为两类,一类是在线控制(On-policy Learning),即一直使用一个策略来更新价值函数和选择新的动作,代表就是Sarsa。而另一类是离线控制(Off-policy Learning),会使用两个控制策略,一个策略用于选择新的动作,另一个策略用于更新价值函数,代表就是Q-Learning。

2.Sarsa算法

在这里插入图片描述
Sarsa的思想是,如上图从上到下,先基于当前状态S,使用ϵ−贪婪法按一定概率选择动作A,然后得到奖励R,并更新进入新状态S′,基于状态S′,使用ϵ−贪婪法选择A′(即在线选择,仍然使用同样的ϵ−贪婪)。算法每次更新值函数需要知道前一步的状态(state),前一步的动作(action)、奖励(reward)、当前状态(state)、将要执行的动作(action)。
在这里插入图片描述
算法流程为:
在这里插入图片描述
建立一个Q Table来保存状态s和将会采取的所有动作a,Q(s,a)。在每个回合中,先随机初始化第一个状态,再对回合中的每一步都先从Q Table中使用ϵ−贪婪基于当前状态 s (如果Q表没有该状态就创建s-a的行,且初始为全0)选择动作 a,执行a,然后得到新的状态s’和当前奖励r,同时使用ϵ−贪婪得到在s’时的a’,直接利用a’更新表中Q(s,a)的值,继续循环到终点。

代码实现:

class SarsaAgent(object):
    def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greed=0.1):
        self.act_n = act_n      # 动作维度,有几个动作可选
        self.lr = learning_rate # 学习率
        self.gamma = gamma      # reward的衰减率
        self.epsilon = e_greed  # 按一定概率随机选动作
        self.Q = np.zeros((obs_n, act_n))

    # 根据输入观察值,采样输出的动作值,带探索
    def sample(self, obs):
        if np.random.uniform(0, 1) < (1.0 - self.epsilon): #根据table的Q值选动作
            action = self.predict(obs)
        else:
            action = np.random.choice(self.act_n) #有一定概率随机探索选取一个动作
        return action

    # 根据输入观察值,预测输出的动作值
    def predict(self, obs):
        Q_list = self.Q[obs, :]
        maxQ = np.max(Q_list)
        action_list = np.where(Q_list == maxQ)[0]  # maxQ可能对应多个action
        action = np.random.choice(action_list)
        return action

    # 学习方法,也就是更新Q-table的方法
    def learn(self, obs, action, reward, next_obs, next_action, done):
        """ on-policy
            obs: 交互前的obs, s_t
            action: 本次交互选择的action, a_t
            reward: 本次动作获得的奖励r
            next_obs: 本次交互后的obs, s_t+1
            next_action: 根据当前Q表格, 针对next_obs会选择的动作, a_t+1
            done: episode是否结束
        """
        predict_Q = self.Q[obs, action]
        if done:
            target_Q = reward # 没有下一个状态了
        else:
            target_Q = reward + self.gamma * self.Q[next_obs, next_action] # Sarsa
        self.Q[obs, action] += self.lr * (target_Q - predict_Q) # 修正q
def run_episode(env, agent, render=False):
    total_steps = 0 # 记录每个episode走了多少step
    total_reward = 0

    obs = env.reset() # 重置环境, 重新开一局(即开始新的一个episode)
    action = agent.sample(obs) # 根据算法选择一个动作

    while True:
        next_obs, reward, done, _ = env.step(action) # 与环境进行一个交互
        next_action = agent.sample(next_obs) # 根据算法选择一个动作
        # 训练 Sarsa 算法
        agent.learn(obs, action, reward, next_obs, next_action, done)

        action = next_action
        obs = next_obs  # 存储上一个观察值
        total_reward += reward
        total_steps += 1 # 计算step数
        if render:
            env.render() #渲染新的一帧图形
        if done:
            break
    return total_reward, total_steps

env = gym.make("CliffWalking-v0")  # 0 up, 1 right, 2 down, 3 left

# 创建一个agent实例,输入超参数
agent = SarsaAgent(
        obs_n=env.observation_space.n,
        act_n=env.action_space.n,
        learning_rate=0.1,
        gamma=0.9,
        e_greed=0.1)


# 训练500个episode,打印每个episode的分数
for episode in range(500):
    ep_reward, ep_steps = run_episode(env, agent, False)
    print('Episode %s: steps = %s , reward = %.1f' % (episode, ep_steps, ep_reward))

3.Q-learning算法

在这里插入图片描述
Q-Learnig的思想就是,如上图从上到下,先基于当前状态S,使用ϵ−贪婪法按一定概率选择动作A,然后得到奖励R,并更新进入新状态S′,基于状态S′,直接使用贪婪法从所有的动作中选择最优的A′(即离线选择,不是用同样的ϵ−贪婪)。
在这里插入图片描述
算法流程为:
在这里插入图片描述
建立一个Q Table来保存状态s和将会采取的所有动作a,Q(s,a)。在每个回合中,先随机初始化第一个状态,再对回合中的每一步都先从Q Table中使用ϵ−贪婪基于当前状态 s (如果Q表没有该状态就创建s-a的行,且初始为全0)选择动作 a,执行a,然后得到新的状态s’和当前奖励r,同时更新表中Q(s,a)的值,继续循环到终点。整个算法就是一直不断更新 Q table 里的值,再根据更新值来判断要在某个 state 采取怎样的 action最好。

代码实现:

class QLearningAgent(object):
    def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greed=0.1):
        self.act_n = act_n      # 动作维度,有几个动作可选
        self.lr = learning_rate # 学习率
        self.gamma = gamma      # reward的衰减率
        self.epsilon = e_greed  # 按一定概率随机选动作
        self.Q = np.zeros((obs_n, act_n))

    # 根据输入观察值,采样输出的动作值,带探索
    def sample(self, obs):
        if np.random.uniform(0, 1) < (1.0 - self.epsilon): #根据table的Q值选动作
            action = self.predict(obs)
        else:
            action = np.random.choice(self.act_n) #有一定概率随机探索选取一个动作
        return action

    # 根据输入观察值,预测输出的动作值
    def predict(self, obs):
        Q_list = self.Q[obs, :]
        maxQ = np.max(Q_list)
        action_list = np.where(Q_list == maxQ)[0]  # maxQ可能对应多个action
        action = np.random.choice(action_list)
        return action

    # 学习方法,也就是更新Q-table的方法
    def learn(self, obs, action, reward, next_obs, done):
        """ off-policy
            obs: 交互前的obs, s_t
            action: 本次交互选择的action, a_t
            reward: 本次动作获得的奖励r
            next_obs: 本次交互后的obs, s_t+1
            done: episode是否结束
        """
        predict_Q = self.Q[obs, action]
        if done:
            target_Q = reward # 没有下一个状态了
        else:
            target_Q = reward + self.gamma * np.max(self.Q[next_obs, :]) # Q-learning
        self.Q[obs, action] += self.lr * (target_Q - predict_Q) # 修正q
def run_episode(env, agent, render=False):
    total_steps = 0 # 记录每个episode走了多少step
    total_reward = 0

    obs = env.reset() # 重置环境, 重新开一局(即开始新的一个episode)

    while True:
        action = agent.sample(obs) # 根据算法选择一个动作
        next_obs, reward, done, _ = env.step(action) # 与环境进行一个交互
        # 训练 Q-learning算法
        agent.learn(obs, action, reward, next_obs, done)

        obs = next_obs  # 存储上一个观察值
        total_reward += reward
        total_steps += 1 # 计算step数
        if render:
            env.render() #渲染新的一帧图形
        if done:
            break
    return total_reward, total_steps

env = gym.make("CliffWalking-v0")  # 0 up, 1 right, 2 down, 3 left

# 创建一个agent实例,输入超参数
agent = QLearningAgent(
    obs_n=env.observation_space.n,
    act_n=env.action_space.n,
    learning_rate=0.1,
    gamma=0.9,
    e_greed=0.1)


# 训练500个episode,打印每个episode的分数
for episode in range(500):
    ep_reward, ep_steps = run_episode(env, agent, False)
    print('Episode %s: steps = %s , reward = %.1f' % (episode, ep_steps, ep_reward))

4.on-policy与off-policy的区别

首先就判断on-policy和off-policy就在于估计时所用的策略与更新时所用的策略是否为同一个策略。on-policy 在学习的过程中,只存在一种策略,比如Sarsa选了什么动作来估计Q值就一定会用什么动作来更新state,一定会执行该动作(会有贪婪率);而off-policy 在学习的过程中,有两种不同的策略。第一个策略是我们希望学到一个最佳的目标策略,另外一个策略是探索环境的策略,比如Q-Learning,估Q值是一回事,但执行动作时一定是会选max的,即使用了两套策略,属于off-policy。

而之所以要叫on或off是因为,off-policy基本上都是要基于replay memory,即估计出的动作值肯定是最优的,但在生成策略的时候,却选择了价值最大的综合memory的max Q 的action。而on-policy每次都是选择最优的action。

Q-learning 算法被提出的时间更早,Sarsa 算法是 Q-learning 算法的改进。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页