马尔科夫决策过程

马尔科夫决策(MDP)是强化学习的基础,在这里,我们首先引入状态价值函数和动作价值函数的概念和关系:

\bg_white \bg_blue \bg_red \bg_red \bg_black \huge v_{\pi } = E_{\pi}[G_{t} | S_{t} = s] = \sum _{a} \pi(a | s)\sum_{s', r}p(s', r | s, a)[r + \gamma v_{\pi}(s')]\mathbf{}


\huge q_{\pi, a} = E_{\pi}[G_{t} | S_{t} = s, A_{t} =a]=E_{\pi}[\sum_{k=0}\gamma ^k R_{t+k+1}|S_{t}=s, A_{t}=a] = \sum_{s', a}p(s', r | s, a)[r + \gamma v_{\pi}(s)]


可以很明显的看出来,状态价值函数和动作价值函数只差一个\sum_{a}\pi(a|s),这个是在状态s下选择每个动作的概率。这是很容易理解的,

 看上图,s代表的是状态,a代表执行的动作,r代表通过执行动作获得的回报,p为选择动作的概率, g是执行动作后到下一个状态的概率。如果把圆圈看做  ‘能量’,那么根据全概率公式(类似),s0这个粉圈的 ‘能量’ 是不是就是p1*q(a1)+p2*q(a2)+p3*q(a3)。所以能得出v关于q的关系。

但是,q和v的关系呢?在图中,我们也可以很明显的看到,a1的  ‘能量’ 是不是就是(r1+(s1的‘能量’))*g1 +.....。所以动作价值函数就等于执行动作后到达下一个状态的概率 * (回报+下一个状态的状态价值函数)的总和。 现在看公式是不是就很清晰了。

关于详细计算,可以看这个链接


ps: 我以前也不太理解为什么会有p(s', r | s, a),这个函数的存在,因为我当时接触到的,并且我一直以为的,在执行一个动作之后不就是明确到达下一个状态,后来换了一种思考方式。

       在武侠小说中,有人从悬崖往下跳,在悬崖上可以看做s0,往下跳的动作可以看做a0,但是往下跳之后却会有很多的不同状态,比如,掉到半山腰捡到武功秘籍,看做s1,r很大,这是主角。掉到山谷,但是有树接着,看做s2, r一般大,这是比较重要的配角。掉到地上,可以看做s3,r为负,这是炮灰甲乙丙丁。

所以一个动作会有很多不同的状态。


 接下来就是关于用代码实现求解状态价值函数:

看sutton书上的例题3.5,   

                                                        

 便于计算,我没有用书上的5x5的格子,而是3x3的,A(0,1), A'(2, 1),B去掉。

解法1:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.table import Table
WORLD_SIZE = 3         # 3x3的网格
A_POS = [0, 1]         # A的位置
A_PRIME_POS = [2, 1]   # A'的位置
DISCOUNT = 0.9         # gamma

ACTIONS = [np.array([0, -1]),
           np.array([-1, 0]),
           np.array([0, 1]),
           np.array([1, 0])]

ACTION_PROB = 0.25     # 每个动作选择的概率
# 状态更新

def step(state, action):
    if state == A_POS:
        return A_PRIME_POS, 10
    if state == B_POS:
        return B_PRIME_POS, 5

    next_state = (np.array(state) + action).tolist()
    x, y = next_state
    if x < 0 or x >= WORLD_SIZE or y < 0 or y >=  WORLD_SIZE:
        next_state = state
        reward = -1
    else:
        reward = 0
    return next_state, reward
# 添加表格

def draw_image(images):
    fig, ax = plt.subplots()
    ax.set_axis_off()
    tb = Table(ax, bbox=[0, 0, 1, 1])

    nrows, ncols = images.shape
    height, width = 1.0/ncols, 1.0/nrows

    for (i, j), image in np.ndenumerate(images):
        if [i, j] == A_POS:
            image = str(image) + 'A_POS'
        if [i, j] == B_POS:
            image = str(image) + 'B_POS'
        if [i, j] == A_PRIME_POS:
            image = 'A_PRIME_POS'
        if [i, j] == B_PRIME_POS:
            image = 'B_PRIME_POS'

        tb.add_cell(i, j, width, height, text=image, loc='center',
                    facecolor='white')

    for i in range(len(images)):
        tb.add_cell(i, -1, width, height, text=i+1, loc='right',
                    edgecolor='none', facecolor='none')
        tb.add_cell(-1, i, width, height/2, text=i+1, loc='center',
                    edgecolor='none', facecolor='none')

    ax.add_table(tb)
def figure3_2():
    value = np.zeros((WORLD_SIZE, WORLD_SIZE))
    while True:
        new_value = np.zeros_like(value)
        for i in range(WORLD_SIZE):
            for j in range(WORLD_SIZE):
                state = [i, j]
                for action in ACTIONS:
                    next_state,reward = step(state, action)
                    new_value[i, j] += ACTION_PROB * (reward + DISCOUNT*value[next_state[0], next_state[1]])
        if np.sum(np.abs(value - new_value)) < 1e-4:
            draw_image(np.round(new_value, decimals=2))
            plt.show()
            break
        value = new_value
figure3_2()

最后得出各个状态值为:

 解法1是通过迭代遍历,对每个状态的每个动作都计算对应的动作价值函数,然后通过加权,来计算迭代之后的状态价值函数。然后通过一个很小的阈值,来判断状态价值函数是否最后收敛。这种方法比较麻烦,而且最后的收敛情况和阈值有关系。但是适用于状态、动作比较多的情况。

解法2:

解法2需要对状态价值函数做一个小小的变化:

\bg_white \bg_blue \bg_red \bg_red \bg_black \huge v_{\pi } = E_{\pi}[G_{t} | S_{t} = s] = \sum _{a} \pi(a | s)\sum_{s', r}p(s', r | s, a)[r + \gamma v_{\pi}(s')]\mathbf{}

 因为\sum_{a}\pi(a|s)\sum_{s', r}p(s', r | s, a)是概率完备的,所以他们的和为1。这时候价值状态函数就可以改写为:

\huge v(s) = r + \gamma\sum_{a}\pi(a | s)\sum_{s' ,r}p(s', r | s, a)v(s')

再进行变换:

\huge v(s) = r + \gamma \sum_{s'\epsilon S}P(s' |s) v(s')

 其中\huge p(s'|s)是这个状态转移到下一个状态的概率(相当于上面五颜六色那个图的 p1*g1, p1*g2, ............)。

继续变换, \large \sum_{s' \epsilon S}p(s'|s)写成矩阵的形式P

\large \bg_black v(s) = r + \gamma P v(s) \rightarrow (I - \gamma P)v = r \rightarrow v = (I - \gamma P)^{-1}r

代码如下:

p = [
    [0.5,0.25,0,0.25,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,0],
    [0,0.25,0.5,0,0,0.25,0,0,0],
    [0.25,0,0,0.25,0.25,0,0.25,0,0],
    [0,0.25,0,0.25,0,0.25,0,0.25,0],
    [0,0,0.25,0,0.25,0.25,0,0,0.25],
    [0,0,0,0.25,0,0,0.5,0.25,0],
    [0,0,0,0,0.25,0,0.25,0.25,0.25],
    [0,0,0,0,0,0.25,0,0.25,0.5]
]
p = np.array(p)
r = [-0.5,10,-0.5,-0.25,0,-0.25,-0.5,-0.25,-0.5]
r = np.array(r)
v = np.dot(np.linalg.inv(np.eye(9, 9) - DISCOUNT*p), r)
v

 可以看出,这两个解法的状态值的是一样的。但是,解法2只能运用在状态动作较少的环境中,例如5x5的格子,那么它的状态转移矩阵就是25x25的,并不适用。


综上:就是我对马尔科夫决策过程的全部理解了,如果大家有什么疑问,欢迎大家在评论区留言,咱们一起探讨

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值