动手学强化学习—第三章马尔可夫决策过程 reshape np.dot np.eye np.linalg.inv join get append

马尔可夫决策过程

3.1 简介

马尔可夫决策过程(Markov decision process,MDP)是强化学习的重要概念。要学好强化学习,我们首先要掌握马尔可夫决策过程的基础知识。前两章所说的强化学习中的环境一般就是一个马尔可夫决策过程。与多臂老虎机问题不同,马尔可夫决策过程包含状态信息以及状态之间的转移机制。如果要用强化学习去解决一个实际问题,第一步要做的事情就是把这个实际问题抽象为一个马尔可夫决策过程,也就是明确马尔可夫决策过程的各个组成要素。本章将从马尔可夫过程出发,一步一步地进行介绍,最后引出马尔可夫决策过程。

3.1 马尔可夫过程

3.2.1随机过程

在随机过程中,随机现象在某时刻的取值是一个向量随机变量,所有可能的状态用集合表示。随机现象便是状态的变化过程。在某时刻的状态通常取决于当前时刻之前的状态。

3.2.2马尔可夫性质

当且仅当某时刻状态只取决于上一时刻的状态时,一个随机过程被称为具有马尔可夫性质,也就是说,当前状态是未来的充分统计量,即下一时刻状态只取决于当前状态而不会受过去状态的影响。需要明确的是,具有马尔可夫性并不代表这个随机过程就和历史完全没有关系。因为虽然t+1时刻的状态只与t时刻的状态有关,但是t时刻的状态其实包含了t-1时刻的状态信息,通过这种链式关系,历史的信息被传递到了现在。马尔可夫性可以大大简化运算,因为只要当前状态可知,所有历史信息都不再需要了,利用当前状态信息就可以决定未来。

3.2.3马尔可夫过程

马尔可夫过程指具有马尔可夫性质的随机过程,也被称为马尔科夫链。我们通常用元组<s,p>描述一个马尔可夫过程,其中s是有限数量的状态集合,p是状态转移矩阵。假设一共有n个状态,此时s={s1,s2,s3,...,sn}。状态转移矩阵p定义了所有状态对之间的概率,即

矩阵p中第i行第j列元素P(sj|si)=P(St+1=sj|St=si)表示从状态si转移到状态sj的概率,我们称p(s‘|s)为状态转移函数。从某个状态出发,到达其他状态的概率和必须为1,即状态转移矩阵p的每一行的和都为1.

3.3马尔可夫奖励过程

在马尔可夫过程的基础上加入奖励函数r和折扣因子​,就可以得到马尔可夫奖励过程。一个马尔可夫奖励过程由​构成,各个组成元素的含义如下所示。

  • S是有限状态的集合

  • P是状态转移矩阵

  • r是奖励函数,某个状态s的奖励r(s)指转移到该状态时可以获得奖励的期望

  • ​是折扣因子,取值范围是[0,1)。引入折扣因子的理由为远期利益具有一定的不确定性,有时我们更希望能够尽快获得一些奖励,所以我们需要对远期利益打一些折扣。接近1的​更关注长期的累计奖励,接近0的​更考虑短期奖励。

3.3.1回报

在一个马尔可夫奖励过程中,从第t时刻状态St开始,知道终止状态时,所有奖励的衰减之和称为回报Gt,公式如下:

 

import numpy as np
np.random.seed(0)
# 定义状态转移概率矩阵P
P = [
    [0.9, 0.1, 0.0, 0.0, 0.0, 0.0],
    [0.5, 0.0, 0.5, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.6, 0.0, 0.4],
    [0.0, 0.0, 0.0, 0.0, 0.3, 0.7],
    [0.0, 0.2, 0.3, 0.5, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
]
P = np.array(P)
​
rewards = [-1, -2, -2, 10, 1, 0]  # 定义奖励函数
gamma = 0.5  # 定义折扣因子
​
​
# 给定一条序列,计算从某个索引(起始状态)开始到序列最后(终止状态)得到的回报
def compute_return(start_index, chain, gamma):
    G = 0
    for i in reversed(range(start_index, len(chain))):
        G = gamma * G + rewards[chain[i] - 1]
    return G
​
​
# 一个状态序列,s1-s2-s3-s6
chain = [1, 2, 3, 6]
start_index = 0
G = compute_return(start_index, chain, gamma)
print("根据本序列计算得到回报为:%s。" % G)

3.3.2 价值函数

在马尔可夫奖励过程中,一个状态的期望回报(即从这个状态出发的未来累计奖励的期望)被称为这个状态的价值。所有状态的价值就组成了价值函数,价值函数的输入为某个状态,输出为这个状态的价值。我们将价值函数写成​,展开为

在上式的最后一个等号中,一方面,即使奖励的期望正是奖励函数的输出,即

另一方面,等式中剩余部分

可以根据从状态s出发的转移概率得到,即可以得到

上式就是马尔可夫奖励过程中非常有名的贝尔曼方程,对每一个状态都成立。若一个马尔科夫奖励过程一共有n个状态,

可以根据上式中的矩阵解析式可以得到每一行的等式都是成立的 都是等式左边一个状态的期望回报

接下来编写代码来实现求解价值函数的解析解方法,并据此计算该马尔可夫奖励过程中所有状态的价值。

def compute(P, rewards, gamma, states_num):
    ''' 利用贝尔曼方程的矩阵形式计算解析解,states_num是MRP的状态数 '''
    rewards = np.array(rewards).reshape((-1, 1))  #将rewards写成列向量形式    将原来的数组转换称为一列的数组   在本题中相当于将奖励数组进行转置
    value = np.dot(np.linalg.inv(np.eye(states_num, states_num) - gamma * P),
                   rewards)
    return value
​
​
V = compute(P, rewards, gamma, 6)
print("MRP中每个状态价值分别为\n", V)
​

3.4马尔可夫决策过程

3.2 节和 3.3 节讨论到的马尔可夫过程和马尔可夫奖励过程都是自发改变的随机过程;而如果有一个外界的“刺激”来共同改变这个随机过程,就有了马尔可夫决策过程(Markov decision process,MDP)。我们将这个来自外界的刺激称为智能体(agent)的动作,在马尔可夫奖励过程(MRP)的基础上加入动作,就得到了马尔可夫决策过程(MDP)。马尔可夫决策过程由元组​构成,其中:

  • S是状态的集合

  • A是动作的集合

  • ​是折扣因子

  • ​是奖励函数,此时奖励可以同时取决于状态s和动作a,在奖励函数只取决于状态s时,则退化为​

  • ​是状态转移函数,表示在状态s执行动作a之后到达状态s‘的概率

我们发现 MDP 与 MRP 非常相像,主要区别为 MDP 中的状态转移函数和奖励函数都比 MRP 多了动作a作为自变量。注意,在上面 MDP 的定义中,我们不再使用类似 MRP 定义中的状态转移矩阵方式,而是直接表示成了状态转移函数。这样做一是因为此时状态转移与动作也有关,变成了一个三维数组,而不再是一个矩阵(二维数组);二是因为状态转移函数更具有一般意义,例如,如果状态集合不是有限的,就无法用数组表示,但仍然可以用状态转移函数表示。我们在之后的课程学习中会遇到连续状态的 MDP 环境,那时状态集合都不是有限的。现在我们主要关注于离散状态的 MDP 环境,此时状态集合是有限的。

不同于马尔可夫奖励过程,在马尔可夫决策过程中,通常存在一个智能体来执行动作。例如,一艘小船在大海中随着水流自由飘荡的过程就是一个马尔可夫奖励过程,它如果凭借运气漂到了一个目的地,就能获得比较大的奖励;如果有个水手在控制着这条船往哪个方向前进,就可以主动选择前往目的地获得比较大的奖励。马尔可夫决策过程是一个与时间相关的不断进行的过程,在智能体和环境 MDP 之间存在一个不断交互的过程。一般而言,它们之间的交互是如图 3-3 循环过程:智能体根据当前状态​选择动作​;对于状态​和动作​,MDP 根据奖励函数和状态转移函数得到​和​并反馈给智能体。智能体的目标是最大化得到的累计奖励。智能体根据当前状态从动作​的集合中选择一个动作的函数,被称为策略。

3.4.1策略

智能体的策略通常用字母​表示。策略​是一个函数,表示再输入状态s情况下采取动作a的概率。当一个策略是确定性策略时,它在每个状态时只输出一个确定性的动作,即只有该动作的概率为1,其他动作的概率为0;当一个策略是随机性策略时,它在每个状态时输出的是关于动作的概率分布,然后根据该分布进行采样就可以得到一个动作。在MDP中,由于马尔可夫性质的存在,策略只需要与当前状态有关,不需要考虑历史状态。回顾一下在MRP中的价值函数,在MDP中也同样可以定义类似的价值函数。但此时的价值函数与策略有关,这意味着对于两个不同的策略来说,他们在同一个状态下的价值也可能是不同的。这很好理解,因为不同的策略会采取不同的动作,从而之后会遇到不同的状态,以及获得不同的奖励,所以它们的累积奖励的期望也就不同,即状态价值不同。

3.4.2状态价值函数

​表示在MDP中基于策略​的状态价值函数,定义为从状态s出发遵循策略​能获得的期望回报,数学表达式为:

从状态s出发并且遵循的是策略​能得到的回报 将所有的可能×相对应的概率即为状态价值 也是只这个状态的价值

3.4.3动作价值函数

不同于MRP,在MDP中,由于动作的存在,定义一个动作价值函数。我们用​表示在MDP遵循策略​时,对当前状态s执行动作a得到的期望回报:

动作价值函数是指在状态s和动作a的情况下得到的回报 相当于是对当前状态下不同动作的评价

状态价值函数和动作价值函数之间的关系:在使用策略​中,状态s的价值等于在该状态下基于策略​采取所有动作的概率与相应的价值相乘再求和的结果:

在使用策略​时,状态s下采取动作a的价值等于即时奖励加上经过衰减后的所有可能的下一个状态的状态转移概率与相应的价值的乘积:​

这个期望分成两部分,一部分是我们获得一步的期望奖励,剩下部分在累加的同时提出一个衰减系数变为​ ​期望式可以由下一时刻状态价值函数根据转移概率权值累加替代,剩下部分就变成了​

3.4.4贝尔曼期望方程

 

S = ["s1", "s2", "s3", "s4", "s5"]  # 状态集合
A = ["保持s1", "前往s1", "前往s2", "前往s3", "前往s4", "前往s5", "概率前往"]  # 动作集合
# 状态转移函数
P = {
    "s1-保持s1-s1": 1.0,
    "s1-前往s2-s2": 1.0,
    "s2-前往s1-s1": 1.0,
    "s2-前往s3-s3": 1.0,
    "s3-前往s4-s4": 1.0,
    "s3-前往s5-s5": 1.0,
    "s4-前往s5-s5": 1.0,
    "s4-概率前往-s2": 0.2,
    "s4-概率前往-s3": 0.4,
    "s4-概率前往-s4": 0.4,
}
# 奖励函数
R = {
    "s1-保持s1": -1,
    "s1-前往s2": 0,
    "s2-前往s1": -1,
    "s2-前往s3": -2,
    "s3-前往s4": -2,
    "s3-前往s5": 0,
    "s4-前往s5": 10,
    "s4-概率前往": 1,
}
gamma = 0.5  # 折扣因子
MDP = (S, A, P, R, gamma)
​
# 策略1,随机策略
Pi_1 = {
    "s1-保持s1": 0.5,
    "s1-前往s2": 0.5,
    "s2-前往s1": 0.5,
    "s2-前往s3": 0.5,
    "s3-前往s4": 0.5,
    "s3-前往s5": 0.5,
    "s4-前往s5": 0.5,
    "s4-概率前往": 0.5,
}
# 策略2
Pi_2 = {
    "s1-保持s1": 0.6,
    "s1-前往s2": 0.4,
    "s2-前往s1": 0.3,
    "s2-前往s3": 0.7,
    "s3-前往s4": 0.5,
    "s3-前往s5": 0.5,
    "s4-前往s5": 0.1,
    "s4-概率前往": 0.9,
}
​
​
# 把输入的两个字符串通过“-”连接,便于使用上述定义的P、R变量
def join(str1, str2):
    return str1 + '-' + str2

 上述内容为将其进行加权求和 将MDP转换为MRP

gamma = 0.5
# 转化后的MRP的状态转移矩阵
P_from_mdp_to_mrp = [
    [0.5, 0.5, 0.0, 0.0, 0.0],
    [0.5, 0.0, 0.5, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.5, 0.5],
    [0.0, 0.1, 0.2, 0.2, 0.5],
    [0.0, 0.0, 0.0, 0.0, 1.0],
]
P_from_mdp_to_mrp = np.array(P_from_mdp_to_mrp)
R_from_mdp_to_mrp = [-0.5, -1.5, -1.0, 5.5, 0]
​
V = compute(P_from_mdp_to_mrp, R_from_mdp_to_mrp, gamma, 5)
print("MDP中每个状态价值分别为\n", V)

3.5蒙特卡洛方法计算状态价值函数

蒙特卡洛方法(Monte-Carlo methods)也被称为统计模拟方法,是一种基于概率统计的数值计算方法。运用蒙特卡洛方法时,我们通常使用重复随机抽样,然后运用概率统计方法来从抽样结果中归纳出我们想求的目标的数值估计。一个简单的例子是用蒙特卡洛方法来计算圆的面积。例如,在图 3-5 所示的正方形内部随机产生若干个点,细数落在圆中点的个数,圆的面积与正方形面积之比就等于圆中点的个数与正方形中点的个数之比。如果我们随机产生的点的个数越多,计算得到圆的面积就越接近于真实的圆的面积。

用蒙特卡洛方法来估计一个策略在一个马尔可夫决策过程中的状态价值函数。一个状态的价值是他的期望回报,那么一个很直观的想法就是用策略在MDP上采样很多条序列,计算从这个状态出发的回报再求其期望就可以了,公式如下:

在一条序列中,可能没有出现过这个状态,可能只出现过一次这个状态,也可能出现过很多次这个状态。我们介绍的蒙特卡洛价值估计方法会在该状态每一次出现时计算它的回报。还有一种选择是一条序列只计算一次回报,也就是这条序列第一次出现该状态时计算后面的累积奖励,而后面再次出现该状态时,该状态就被忽略了。假设我们现在用策略​从状态​开始采样序列,据此来计算状态价值。我们为每一个状态维护一个计数器和总回报,计算状态价值的具体过程如下所示。

def sample(MDP, Pi, timestep_max, number):
    ''' 采样函数,策略Pi,限制最长时间步timestep_max,总共采样序列数number '''
    S, A, P, R, gamma = MDP
    episodes = []
    for _ in range(number):
        episode = []
        timestep = 0
        s = S[np.random.randint(4)]  # 随机选择一个除s5以外的状态s作为起点   最大数值是4
        # 当前状态为终止状态或者时间步太长时,一次采样结束
        while s != "s5" and timestep <= timestep_max:
            timestep += 1
            rand, temp = np.random.rand(), 0
            # 在状态s下根据策略选择动作
            for a_opt in A:
                temp += Pi.get(join(s, a_opt), 0)  # 将动作和状态链接在一起  并且使用get函数在策略函数里搜索   如果能找到返回其对应的概率值  如果没有 返回0
                # print(temp)
                if temp > rand:   # 如果在该状态下选择某个动作的概率大于随机生成数 继续运行  如果不成立则重新选择
                    a = a_opt
                    r = R.get(join(s, a), 0)
                    break
            rand, temp = np.random.rand(), 0
            # 根据状态转移概率得到下一个状态s_next
            for s_opt in S:
                temp += P.get(join(join(s, a), s_opt), 0)
                if temp > rand:
                    s_next = s_opt
                    break
            episode.append((s, a, r, s_next))  # 把(s,a,r,s_next)元组放入序列中
            s = s_next  # s_next变成当前状态,开始接下来的循环
        episodes.append(episode)
    return episodes
MDP = (S, A, P, R, gamma)
​
# 采样5次,每个序列最长不超过20步
episodes = sample(MDP, Pi_1, 20, 5)
print('第一条序列\n', episodes[0])
print('第二条序列\n', episodes[1])
print('第五条序列\n', episodes[4])
​
# 对所有采样序列计算所有状态的价值
def MC(episodes, V, N, gamma):
    for episode in episodes:
        G = 0
        for i in range(len(episode) - 1, -1, -1):  # 一个序列从后往前计算  最后一个参数是步长
            (s, a, r, s_next) = episode[i]
            G = r + gamma * G
            N[s] = N[s] + 1
            V[s] = V[s] + (G - V[s]) / N[s]
​
​
timestep_max = 20
# 采样1000次,可以自行修改
episodes = sample(MDP, Pi_1, timestep_max, 1000)
gamma = 0.5
V = {"s1": 0, "s2": 0, "s3": 0, "s4": 0, "s5": 0}
N = {"s1": 0, "s2": 0, "s3": 0, "s4": 0, "s5": 0}
MC(episodes, V, N, gamma)
print("使用蒙特卡洛方法计算MDP的状态价值为\n", V)

可以看到用蒙特卡洛方法估计得到的状态价值和我们用 MRP 解析解得到的状态价值是很接近的。这得益于我们采样了比较多的序列,感兴趣的读者可以尝试修改采样次数,然后观察蒙特卡洛方法的结果。

3.6占用度量

简单来说,在一个策略下从一个状态到其他两个状态不同的频率即为占用度量

3.7最优策略

在有限状态和动作集合的 MDP 中,至少存在一个策略比其他所有策略都好或者至少存在一个策略不差于其他所有策略,这个策略就是最优策略

python

reshape

numpy中reshape函数的三种常见相关用法

reshape(1,-1)转化成1行:

reshape(2,-1)转换成两行:

reshape(-1,1)转换成1列:

reshape(-1,2)转化成两列

np.arange(16).reshape(2,8) #生成16个自然数,以2行8列的形式显示
​
# Out:
​
# array([[ 0, 1, 2, 3, 4, 5, 6, 7],
​
# [ 8, 9, 10, 11, 12, 13, 14, 15]])
  • mat (or array).reshape(c, -1) 必须是矩阵格式或者数组格式,才能使用 .reshape(c, -1) 函数, 表示将此矩阵或者数组重组,以 c行d列的形式表示

arr.shape # (a,b)
​
arr.reshape(m,-1) #改变维度为m行、d列 (-1表示列数自动计算,d= a*b /m )
​
arr.reshape(-1,m) #改变维度为d行、m列 (-1表示行数自动计算,d= a*b /m )

-1的作用就在此: 自动计算d:d=数组或者矩阵里面所有的元素个数/c, d必须是整数,不然报错)

reshape(-1, m)即列数固定,行数需要计算)

np.dot

np.dot(a,b)函数是用来计算两个数组的点积的

计算规则:

  1. 若a,b为一维数组,则a​b=向量的内积

  2. 若a,b为二维数组,则a​b=矩阵的乘法((等效于矩阵乘法函数matmul(a,b)或者a@b))

np.eye()

np.eye()的函数,除了生成对角阵外,还可以将一个label数组,大小为(1,m)或者(m,1)的数组,转化成one-hot数组。

函数的原型:

numpy.eye(N,M=None,k=0,dtype=<class ‘float’>,order='C)

返回的是一个二维2的数组(N,M),对角线的地方为1,其余的地方为0.

参数介绍:

(1)N:int型,表示的是输出的行数

(2)M:int型,可选项,输出的列数,如果没有就默认为N

(3)k:int型,可选项,对角线的下标,默认为0表示的是主对角线,负数表示的是低对角,正数表示的是高对角。

(4)dtype:数据的类型,可选项,返回的数据的数据类型

(5)order:{‘C’,‘F’},可选项,也就是输出的数组的形式是按照C语言的行优先’C’,还是按照Fortran形式的列优先‘F’存储在内存中

在本函数的应用中是用来生成单位矩阵的

np.linalg.inv

求可逆矩阵的逆

join

连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串

get

  • 1、设置默认返回值

  • 2、嵌套字典取值

  • 3、get() 和 dictkey的区别

  • 4、统计元素计数

dict.get( key, value )
  • key :(必选)指定要搜索的键

  • value :(可选)如果键不存在,就返回指定内容

  • 如果键存在,就返回键对应的值

  • 如果键不存在,就返回指定内容或None

append

append() 函数可以向列表末尾添加元素

list.append( element )
  • element:任何类型的元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值