Bootstrap

论文学习「MDP」:马尔可夫决策过程原理与代码实现

最近在学习 RL ,不得不先接触一下“ 马尔可夫决策过程 ”,这里找到了 David Silver 的课程: UCL Course on RL

http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html),这里我将按课程 PPT 中的顺序讲述我的理解已经如何用代码实现相应的计算过程。

目录

一、马尔可夫过程(Markov Process)

(一)MDPs论述

(二)马尔科夫特性

(三)状态转移矩阵

(四)马尔可夫过程

(五)样例

二、马尔可夫报酬过程(Markov Reward Process)

(一)马尔可夫报酬过程

(二)回报

(三)值函数

(四)样例

(五)MRPs的Bellman等式

(六)Bellman等式

(七)Bellman等式的矩阵形式

三、马尔可夫决策过程(Markov Decision Process)

(一)马尔可夫决策过程

(二)策略

(三)值函数

(四)Bellman等式的矩阵形式

四、最优值函数(Optimal Value Function)


一、马尔可夫过程(Markov Process)

(一)MDPs论述

马尔可夫决策过程形式化地描述了强化学习的环境 ,这里的环境是完全可见的,例如,当前的状态完全描述了这个过程。几乎所有的 RL 问题都可以形式化地表示为 MDPs

(二)马尔科夫特性

The future is independent of the past given the present ”,也就是说对当前而言,未来与过去是毫无关系的。马尔可夫状态定义如下图1

83eba9e08dacd33ae7569bf61094b1b4.png

图1:马尔科夫状态

上诉定义的意思是:当前状态的前提下,下个状态发生的概率 = 当前状态及其之前所有状态的前提下,下一个状态发生的概率。可以理解为,当前状态已经包含了历史所有信息。

(三)状态转移矩阵

定义了一个从当前马尔可夫状态 23886b06defa7f636055c3a44b8cb8c1.gif 到后续状态 s' 的 state transition probability (状态转移概率):

05b3183f1cf704cffdad32c14b9374bc.png

同时定义了一个从所有当前状态 23886b06defa7f636055c3a44b8cb8c1.gif 到后续状态 s' 的状态转移矩阵 6325ac7a6a3ea0b7773f7bac03a8f653.gif

cbc436908a1f04fa9886e6a81d7fdf8b.png

 这个很好理解,比如 P_{ij} 表示从状态 c41d653023a050de9bcff8a9260a5ecc.gif 到状态 a3b031d9c4d560bcf826e44bcafbf969.gif 的概率,注意可以存在从状态 c41d653023a050de9bcff8a9260a5ecc.gif 转移到状态 c41d653023a050de9bcff8a9260a5ecc.gif 的可能性,而且矩阵 6325ac7a6a3ea0b7773f7bac03a8f653.gif 的每一行的和为 1

(四)马尔可夫过程

马尔可夫过程是一个无记忆的随机过程,例如一个满足马尔可夫特性的随机状态序列 e3a590a253ecdd9cd999c17799669d9a.gif ,定义如下图2

d72cff132b8dba2d75131d0628310571.png

图2:马尔科夫过程

马尔可夫过程(又叫马尔可夫链)是一个元组 c7ed1a964d35ec4399bd8f5bf3add643.gif  ,cdbb209c1a89ed546a2f99d1706f3648.gif 是一个有限状态集, 6325ac7a6a3ea0b7773f7bac03a8f653.gif 是上诉状态转移概率矩阵。简单地理解就是给一个状态,再给一个转移概率,就会发生一个“ 过程 ” 。

(五)样例

David Silver 给出了一个研究生的例子,如图3

386a9040d9c153b5f5132c3aa2d073af.png

图3:研究生马尔科夫链

可以看出从 S_{1}=C_{1} 开始存在无数个马尔可夫链。

  • 9459a39f45c45b8c4a33e63ffd6a95c2.gif
  • df0c44428770536240c72dc854d7a128.gif
  • ...

同时,从图3 中我们也可以得到状态转移概率矩阵 6325ac7a6a3ea0b7773f7bac03a8f653.gif

3625c3d4ddbcccdada412dacc6392c63.png

这里需要注意的一点是,作者认为 David Silver 的课程 PPT 这里存在一点问题,即 P_{Sleep,Sleep} 应该为 0 ,如果用 PPT 中的 1 ,在后续计算过程中存在十分明显的错误,而且从图3 看到,状态 Sleep 到状态 Sleep 之间并不存在转移情况。

截止到这里的内容比较容易理解,就不过多赘述了,下面开始详述马尔可夫报酬过程。

二、马尔可夫报酬过程(Markov Reward Process)

(一)马尔可夫报酬过程

马尔可夫报酬过程是具有价值的马尔可夫链,定义如下图4

fabc10643cf57ccfb24ee103f06bef3b.png

图4:马尔可夫报酬过程

这里增加了报酬函数 72e58e5129f5cdec2c294f7b9743ef72.gif ,表示当前状态 S_{t}=s 情况下,下一个阶段的报酬 44e4e89ed58c5146cacbd0acb6c854be.gif 的期望。折扣因子 84c608448a5de6bf14c33007799422ff.gif 。研究生马尔可夫报酬过程如下图5 所示:

22d642c773884bd16ac83ddee6383b94.png

图5:研究生马尔可夫报酬过程

(二)回报

这里我先用语言描述一下马尔可夫决策过程的回报。首先我们设想一下,现在我们处于“ 大学生 ”状态,之后可能的状态有“ 读研 ”和“ 找工作 ”,选择不同的“ 状态 ”将会有不同的“ 未来 ”,未来的“ 收入 ”当然也就有所区别了。现在我们假设选择了“ 读研 ”,以经济学中“ 折现 ”的概念来理解未来的“ 收入 ”,我们现在的选择其实已经一定程度上转换成了“ 一定折扣的未来收入 ”。这就是所谓的回报,用公式表示如下图6

9ee65de93b013a89c4d94ccb50639bde.png

图6:回报

这里的 return bd996e1a056229905c5a1b01e109cbb0.gif  表示从 b5eeaedf6ad956f27dfd8421ea1c8e45.gif 步开始全部的折扣报酬,其中折扣因子 b2b2fde0c5d66d9bb0cf41d710bf8577.gif 表示未来报酬的当前价值。 b2b2fde0c5d66d9bb0cf41d710bf8577.gif  越小表示“ 目标短浅 ”只专注于眼前, b2b2fde0c5d66d9bb0cf41d710bf8577.gif  越大表示“ 远见 ”决策者更关注于对未来的展望。

(三)值函数

就上诉回报内容,值函数 0db2562dd7641073bacee1547b44e3eb.gif 给出了状态 23886b06defa7f636055c3a44b8cb8c1.gif 的长期价值,定义如下图7

90eef2784de77562841e7fbc9086a573.png

图7:值函数

bd996e1a056229905c5a1b01e109cbb0.gif  表示确定的状态序列下的未来报酬的折扣,但是我们得清楚,在实际决策过程中,状态转移是依据状态转移概率矩阵 6325ac7a6a3ea0b7773f7bac03a8f653.gif 来转移的,所以从当前状态 23886b06defa7f636055c3a44b8cb8c1.gif 开始的 MRP 期望就得用上述定义来表示了。

(四)样例

这里以 S_{1}=C_{1} ,\gamma = \frac{1}{2} 为例,计算 0b0c2788f4f3fda1210cc0e9cd8f1099.gif

3a1a634ba707afa285b0112906d6357e.png

  • 9459a39f45c45b8c4a33e63ffd6a95c2.gif          d8a6f43bf64b991e5db81c73aa15fe00.gif
  • df0c44428770536240c72dc854d7a128.gif     0aeed5899f73ebd83db1f4cf4b07dd62.gif
  • ...

这里读者可能会想,每一个状态的马尔可夫链不是无数个吗,给定一个马尔可夫链求 bd996e1a056229905c5a1b01e109cbb0.gif 容易,但是求值函数 0db2562dd7641073bacee1547b44e3eb.gif 却是几乎不可能的,这里借助于 Bellman 等式能够很好的解决这个问题。

(五)MRPs的Bellman等式

计算过程如下,读者就自行理解吧!

025fb39b4192e2015092d4afb90f7c4a.png

然后给出了值函数 0db2562dd7641073bacee1547b44e3eb.gif 的计算公式:

3aff78cc12684d2a9c0700ece589d689.png

为了理解这个公式,直接给出一张图8

f57a32e46c906f3dd04ffd166e0272f7.png

图8:Bellman Equation for MRPs

这里需要注意一点,作者认为 David Silver 的课程 PPT c6015109472465f7a5bf7cd7dfd22a91.gif 的位置存在一点瑕疵,容易误导读者,正确的位置应该是箭头所指方向。

解释一下吧,图8 中,状态 23886b06defa7f636055c3a44b8cb8c1.gif 对应 0db2562dd7641073bacee1547b44e3eb.gif ,状态 {s}' 对应 55b3ceb6c60c1cb41bf5354d3c969917.gifc6015109472465f7a5bf7cd7dfd22a91.gif 表示当前状态 23886b06defa7f636055c3a44b8cb8c1.gif 在下一阶段的报酬。我们再看看值函数 0db2562dd7641073bacee1547b44e3eb.gif 的计算公式,用白话解释就是:某个状态 23886b06defa7f636055c3a44b8cb8c1.gif 的值函数 0db2562dd7641073bacee1547b44e3eb.gif  = 当前状态 23886b06defa7f636055c3a44b8cb8c1.gif 在下一阶段的报酬 72e58e5129f5cdec2c294f7b9743ef72.gif + 与当前状态 23886b06defa7f636055c3a44b8cb8c1.gif 相接的后续状态 {s}' 的值函数 55b3ceb6c60c1cb41bf5354d3c969917.gif  0c019347dda46c33be36d7bfb176d0ae.gif 相应的状态转移概率 P_{s{s}'} 的求和(后续状态可能有一个或多个,这里其实就是一个求期望的过程)的折扣。

下面给个例子来简单描述一下这个计算过程,如图9

e3bdfaeb1824539a53a84992308097f0.png

图9:值函数的计算

这张图中描述了值函数 0db2562dd7641073bacee1547b44e3eb.gif 是如何计算出来的。

读者可能又有疑问,要计算状态 23886b06defa7f636055c3a44b8cb8c1.gif 的值函数0db2562dd7641073bacee1547b44e3eb.gif ,得知道后续状态 {s}' 的值函数 55b3ceb6c60c1cb41bf5354d3c969917.gif ,这不是又陷入了一个闭环了嘛!

这里给出两种解决方法:

  1. Bellman等式
  2. Bellman等式的矩阵形式

(六)Bellman等式

迭代法就是我们令最初的值函数全部为 0 ,通过多次迭代,使得迭代次数达到指定值或者值函数趋于稳定,这里就直接放代码啦!

"""这是MRP迭代过程"""


# 迭代
def next_v(_lambda, r_list, old_v_list, weight_list):
    new_v_list = []
    for j in range(len(old_v_list)):
        if j != len(old_v_list) - 1:
            j_sum = .0
            # 与当前状态相接的后续状态的值函数相应的状态转移概率的求和的折扣
            for k in range(len(weight_list[j])):
                j_sum += weight_list[j][k][0] * old_v_list[weight_list[j][k][1]]

            # 当前状态在下一阶段的报酬
            new_v_list.append(r_list[j] + _lambda * j_sum)

    # Sleep状态无后续状态,故直接赋值0
    new_v_list.append(0.0)
    return new_v_list


if __name__ == '__main__':
    # γ
    my_lambda = 1

    # 报酬顺序:Class 1、Class 2、Class 3、Pass、Pub、Facebook、Sleep,分别对应0, 1, 2, 3, 4, 5, 6
    # 后续顺序皆与此相同
    my_r_list = [-2., -2., -2., 10., 1., -1., 0.]

    # 初始化值函数
    my_old_v_list = [0, 0, 0, 0, 0, 0, 0]

    # 状态转移概率(这里没有用概率矩阵,方法有点笨,读者可以用矩阵来表示)
    # 这里以[[0.5, 1], [0.5, 5]]为例解释一下,该列表记录Class 1的状态:
    # [0.5, 1]表示以0.5的概率转移到Class 2
    # [0.5, 5]表示以0.5的概率转移到Facebook
    my_weight_list = [[[0.5, 1], [0.5, 5]],
                      [[0.8, 2], [0.2, 6]],
                      [[0.6, 3], [0.4, 4]],
                      [[1, 6]],
                      [[0.2, 0], [0.4, 1], [0.4, 2]],
                      [[0.1, 0], [0.9, 5]],
                      [[0, 0]]]

    my_new_v_list = []
    # 指定迭代次数
    for i in range(100):
        my_new_v_list = next_v(my_lambda, my_r_list, my_old_v_list, my_weight_list)

        # 用新生成的值函数列表替换旧的值函数列表
        my_old_v_list = my_new_v_list

    print(my_new_v_list)

运行结果与图9 近似,通过增加迭代次数可提高结果准确性:

[-12.418287702397645, 1.4703089405374907, 4.3371337110593915, 10.0, 0.8410368812854547, -22.318009521720207, 0.0]

四舍五入:

[-12, 1.5, 4.3, 10, 0.8, -22, 0]

(七)Bellman等式的矩阵形式

Bellman 等式用矩阵形式表示出来,并进行线性变换:

2d1965be10b5f6d3b16d7166ba49d5e3.png

我们可以看到值函数 0db2562dd7641073bacee1547b44e3eb.gif 的计算不再需要后续状态的值函数 55b3ceb6c60c1cb41bf5354d3c969917.gif ,只需要知道折扣因子 b2b2fde0c5d66d9bb0cf41d710bf8577.gif 、状态概率转移矩阵 6325ac7a6a3ea0b7773f7bac03a8f653.gif 和报酬 ddfe2a175e23e49d70fd49f77c4c8221.gif

给出代码:

import numpy as np


# γ
_lambda = 1

# 状态转移概率矩阵
p = [[0, 0.5, 0, 0, 0, 0.5, 0],
     [0, 0, 0.8, 0, 0, 0, 0.2],
     [0, 0, 0, 0.6, 0.4, 0, 0],
     [0, 0, 0, 0, 0, 0, 1],
     [0.2, 0.4, 0.4, 0, 0, 0, 0],
     [0.1, 0, 0, 0, 0, 0.9, 0],
     [0, 0, 0, 0, 0, 0, 0]]
# 报酬矩阵
r = [[-2],
     [-2],
     [-2],
     [10],
     [1],
     [-1],
     [0]]
# 单位矩阵
i = [[1, 0, 0, 0, 0, 0, 0],
     [0, 1, 0, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 0, 1]]

p_mat = np.matrix(p)
r_mat = np.matrix(r)
i_mat = np.matrix(i)

# Bellman等式的矩阵形式
v_mat = (i_mat - _lambda * p_mat).I * r_mat
# v_mat = np.dot(np.linalg.inv(i_mat - p_mat), r_mat)

print(v_mat)

通过这种方法计算得到的结果较第一种方法准确,结果如下:

[[-12.54320988]
 [  1.45679012]
 [  4.32098765]
 [ 10.        ]
 [  0.80246914]
 [-22.54320988]
 [  0.        ]]

四舍五入:

[[-13 ]
 [ 1.5]
 [ 4.3]
 [ 10 ]
 [ 0.8]
 [-23 ]
 [  0  ]]

三、马尔可夫决策过程(Markov Decision Process)

(一)马尔可夫决策过程

马尔可夫决策过程是伴有决策的的马尔可夫报酬过程,给出定义如下图10

a2e0f8ca88d16ae95e384f5a57513769.png

图10:马尔可夫决策过程

简单来说,马尔可夫决策过程就是比马尔可夫报酬过程多了一个有限动作集 4fafd386308302bc8cabb2d69d4dcd35.gif ,这里所说的决策其实可以理解为决策者在某个状态 23886b06defa7f636055c3a44b8cb8c1.gif 下执行某个动作 be1db303922bd29d8f5e8cff1bfd6d76.gif 的概率分布。

这里给出研究生马尔可夫决策过程,如下图11

a5f8f331c2a32f007bf4a3dcd032d91b.png

图11:研究生马尔可夫决策过程

需要注意的一点是,作者认为如上图11 David Silver 的课程 PPT 中红框标注的部分,应该标为 Pass 。因为原先状态图中,旁边的状态为 Pass ,而且同样都是 Study 动作,报酬不同有点不合理,“课程通过 ”可能才配得上报酬 10 吧,哈哈!

这里结构上与图3 存在明显的不同就是取消了状态 Pub ,变成了现在的动作 Pub ,然后该动作可以将 Class 3 状态转移到 Class 1 Class 2Class 3,这里这样修改是为了下面更具普遍性的说明,可以说 David Silver 也是别有用心呀。

(二)策略

policy f3ba312640e02d9d3ae0263b04693c72.gif 是给定状态下动作的分布,定义如下图12

cb60fec1b68723ffeffc5398cbd535a7.png

图12:策略π

理解起来也很简单, \pi (a|s) 就是在当前状态 S_{t}=s  前提下,执行动作 A_{t}=a 的概率。

我们再来看看状态转移概率 P_{s{s}'}^{\pi } 和 R_{s}^{\pi } 现在怎么计算:

d8e48cf8aff60046dd6a3f9e831f639a.png

我用白话解释一下:执行动作 Study,以 Class 1 状态到Class 2 状态为例计算 P_{Class1, Class2}^{\pi } ,根据图11 ,我们可以发现 P_{Class1,Class2}^{\pi }=\pi (Study|Class1)P_{Class1,Class2}^{Study} ,解释一下就是,从状态 Class 1 到状态 Class 2 只有执行动作 Study 才行,而且执行动作 Study 后,可以百分之百从状态 Class 1 转移到状态 Class 2 ,所以 P_{Class1,Class2}^{Study}=1 。同时我们可以看到状态 Class 1 情况下,可执行的动作有两个 Study Facebook ,所以这里的 \pi (Study|Class1)=0.5 。从状态 Class 3 执行动作 Pub 的情况比较特殊,读者需要注意,这里的 概率 P_{Class3,Class1}^{Pub}=0.2 ,剩下的就靠读者自己思考啦!

(三)值函数

现在就出现了两种值函数:状态值函数和动作值函数,定义如下图13 ,就不过多解释啦:

fd8c26efed56355b5ae0bca006a8642a.png

图13:状态值函数和动作值函数

展示一个使用 Bellman 等式计算的样例,图14

4ec53f8d2d6e9077308e9f4b1bc53f2b.png

图14:Bellman 等式计算的样例

这里直接给出 Bellman 等式的矩阵形式:

a68917ffc76bc559343838d41a3af87f.png

同样的需要状态转移概率矩阵 P^{\pi }  和 报酬 R^{\pi } 。 

(四)Bellman等式的矩阵形式

根据图11 ,可得到如下状态转移概率矩阵:

30de7f984ec97ee7f01956d78c6c6595.png

每个状态转移的平均报酬可如下计算:

a4e49e90a5c729b94cf476dbee3935f2.png

可以计算出报酬 ddfe2a175e23e49d70fd49f77c4c8221.gif

77a6081d2e33e3b180841b5de984bc21.png

然后就可以计算值函数啦!这里分别给出使用 Bellman 等式和 Bellman 等式的矩阵表示的代码,建议读者使用 Bellman 等式的矩阵表示代码。 

  • Bellman 等式
"""这是MDP迭代过程"""


def next_v(pi, r_list, old_v_list, weight_list):
    new_v_list = []
    for j in range(len(old_v_list)):
        if j != len(old_v_list) - 1:
            j_sum = .0
            for k in range(len(weight_list[j])):
                if type(weight_list[j][k][0]) is not list:
                    j_sum += pi * (r_list[weight_list[j][k][1]] + old_v_list[weight_list[j][k][0]])
                else:
                    m_sum = .0
                    for m in range(len(weight_list[j][k][0])):
                        m_sum += old_v_list[weight_list[j][k][0][m][0]] * weight_list[j][k][0][m][1]
                    j_sum += pi * (r_list[weight_list[j][k][1]] + m_sum)
            new_v_list.append(j_sum)

    new_v_list.append(0.0)
    return new_v_list


if __name__ == '__main__':
    my_pi = 0.5
    # 报酬顺序:study pass pub facebook quit sleep
    my_r_list = [-2., 10., 1., -1., 0., 0.]
    my_old_v_list = [0, 0, 0, 0, 0]
    my_weight_list = [[[1, 0], [3, 3]],
                      [[2, 0], [4, 5]],
                      [[[[0, 0.2], [1, 0.4], [2, 0.4]], 2], [4, 1]],
                      [[0, 4], [3, 3]],
                      []]

    my_new_v_list = []
    # my_new_v_list = next_v(my_pi, my_r_list, my_old_v_list, my_weight_list)
    for i in range(100):
        my_new_v_list = next_v(my_pi, my_r_list, my_old_v_list, my_weight_list)
        my_old_v_list = my_new_v_list

    print(my_new_v_list)

结果:

[-1.3076923099959044, 2.6923076920317515, 7.384615384159404, -2.3076923112229597, 0.0]

四舍五入:

[-1.3, 2.7, 7.4, -2.3, 0.0]

  • Bellman 等式的矩阵表示
import numpy as np


# π、γ
_pi = 0.5
_lambda = 1

p = [[0, _pi, 0, _pi, 0],
     [0, 0, _pi, 0, _pi],
     [_pi*0.2, _pi*0.4, _pi*0.4, 0, _pi],
     [_pi, 0, 0, _pi, 0],
     [0, 0, 0, 0, 0]]
r = [[_pi*-2 + _pi*-1],
     [_pi*-2 + _pi*0],
     [_pi*1 + _pi*10],
     [_pi*0 + _pi*-1],
     [0]]
i = [[1, 0, 0, 0, 0],
     [0, 1, 0, 0, 0],
     [0, 0, 1, 0, 0],
     [0, 0, 0, 1, 0],
     [0, 0, 0, 0, 1]]

p_mat = np.matrix(p)
r_mat = np.matrix(r)
i_mat = np.matrix(i)

v_mat = (i_mat - _lambda * p_mat).I * r_mat
# v_mat = np.dot(np.linalg.inv(i_mat - p_mat), r_mat)

print(v_mat)

结果:

[[-1.30769231]
 [ 2.69230769]
 [ 7.38461538]
 [-2.30769231]
 [ 0.        ]]

四舍五入:

[[-1.3]
 [ 2.7]
 [ 7.4]
 [-2.3]
 [ 0.  ]]

四、最优值函数(Optimal Value Function)

注意,这里求解的 MDP 状态值函数,每个状态的回报是根据转移概率计算的平均回报,这称为贝尔曼期望方程(Bellman Expectation Equation)。而在强化学习中,通常是选取使得价值最大的动作执行,这种解法称为最优值函数(Optimal Value Function),得到的解不再是期望值函数,而是理论最大值函数。此时相当于策略 π 已经改变,且非线性,线性方程组不再适用,需要通过数值计算的方式求出。通常的做法是设置状态值函数 0db2562dd7641073bacee1547b44e3eb.gif 和状态-动作值函数 da3f65e98cdc1032dd9f65ed896e8bd3.gif 迭代求解。最终得到:

1b66faeb17245925cfbea97ac0a58d8a.png

这里给出计算 76bf4ed5df2ba470b7d6199226e8fa78.gif 的计算代码:

"""这是OVF迭代过程"""


def next_v(pi, r_list, old_v_list, weight_list):
    new_v_list = []
    for j in range(len(old_v_list)):
        if j != len(old_v_list) - 1:
            max_list = []
            for k in range(len(weight_list[j])):
                if type(weight_list[j][k][0]) is not list:
                    max_list.append(pi * (r_list[weight_list[j][k][1]] + old_v_list[weight_list[j][k][0]]))
                else:
                    m_sum = .0
                    for m in range(len(weight_list[j][k][0])):
                        m_sum += old_v_list[weight_list[j][k][0][m][0]] * weight_list[j][k][0][m][1]
                    max_list.append(pi * (r_list[weight_list[j][k][1]] + m_sum))
            new_v_list.append(max(max_list))

    new_v_list.append(0.0)
    return new_v_list


if __name__ == '__main__':
    my_pi = 1
    # study pass pub facebook quit sleep
    my_r_list = [-2., 10., 1., -1., 0., 0.]
    my_old_v_list = [0, 0, 0, 0, 0]
    my_weight_list = [[[1, 0], [3, 3]],
                      [[2, 0], [4, 5]],
                      [[[[0, 0.2], [1, 0.4], [2, 0.4]], 2], [4, 1]],
                      [[0, 4], [3, 3]],
                      []]

    my_new_v_list = []
    # my_new_v_list = next_v(my_pi, my_r_list, my_old_v_list, my_weight_list)
    for i in range(100):
        my_new_v_list = next_v(my_pi, my_r_list, my_old_v_list, my_weight_list)
        my_old_v_list = my_new_v_list

    print(my_new_v_list)

结果:

[6.0, 8.0, 10.0, 6.0, 0.0]

结果如下图15 所示:

d5f8c9a225a068b4a9a1b0f6b6038c5b.png

图15:最优值函数

写到这里有点累了,具体公式读者就看 PPT 吧,这里讲一个简单的计算最优动作值函数 1e6b554a1b279e6c8007c5c1890af2bc.gif 的方法,我们先看看下一张图16 吧:

401f7e696a405cd5594c82407c672dd3.png

图16:最优动作值函数

最优值函数我们已经用代码算出来了,计算最优动作值函数 1e6b554a1b279e6c8007c5c1890af2bc.gif 就变得简单多了:当前动作值函数 =  动作指向的值函数 + 当前动作的报酬(或者是期望)。

更多内容大家自己阅读 PPT 吧,内容以上传到我的博客。

;