强化学习_02_贝尔曼方程简单实现

参考: 《用Python动手学强化》

一、贝尔曼方程

1.1 价值计算

在t时刻选择行动的价值 G t = ∑ k = 0 T − t − 1 γ k r t + 1 + k G_t=\sum_{k=0}^{T-t-1}\gamma^kr_{t+1+k} Gt=k=0Tt1γkrt+1+k, 即未来每个时刻的及时奖励乘以折扣率( γ \gamma γ)的累积和
【注:】

  • γ \gamma γ:折扣率
  • r r r: 及时奖励
  • t+1+k: 下标表示未来某一时刻
  • k: k >= 0 ; k <= T-t-1;
  • T:为最终获得奖励的时间

我们可以将这个方程改成递归的形式:
G t = r t + 1 + γ G t + 1 G_t=r_{t+1} + \gamma G_{t+1} Gt=rt+1+γGt+1
即我们可以从未来往回逐步估算出 G t G_t Gt的值。

1.2 增加策略的价值计算

我们已经知道了一个时刻状态下的期望价值计算方法。那么在加上该状态下的不同行动的行动概率 π ( a ∣ s ) \pi(a|s) π(as),以及采取行动后对应的环境中的状态变化的概率 T ( s ′ ∣ s , a ) T(s'|s, a) T(ss,a)

【注:】

  • π ( a ∣ s ) \pi(a|s) π(as): 状态s下采取行动a的概率
  • T ( s ′ ∣ s , a ) T(s'|s, a) T(ss,a): 状态s下采取行动a后下一时刻的状态
  • s’: 为下一时刻的状态
    在这里插入图片描述
    这样我们就可以得到当前状态的价值了(以相乘的方式计算期望):
    V π ( s ) = ∑ a π ( a ∣ s ) ∑ s ′ T ( s ′ ∣ s , a ) [ r t + 1 + γ G t + 1 ] V_\pi(s) = \sum_a\pi(a|s)\sum_{s'}T(s'|s, a)[r_{t+1} + \gamma G_{t+1}] Vπ(s)=aπ(as)sT(ss,a)[rt+1+γGt+1]
    将G统一改为V,t+1用'简化,然后当前的奖励用奖励函数 R R R替换,得到最终公式(Bellman Equation):
    V π ( s ) = ∑ a π ( a ∣ s ) ∑ s ′ T ( s ′ ∣ s , a ) [ R ( s , s ′ ) + γ V ( s ′ ) ] V_\pi(s) = \sum_a\pi(a|s)\sum_{s'}T(s'|s, a)[R(s, s') + \gamma V(s')] Vπ(s)=aπ(as)sT(ss,a)[R(s,s)+γV(s)]

当基于价值最大化选择行动的情况下,我们可以对方程修改为下式:
V ( s ) = m a x a ∑ s ′ T ( s ′ ∣ s , a ) [ R ( s , s ′ ) + γ V ( s ′ ) ] V(s) = max_a \sum_{s'}T(s'|s, a)[R(s, s') + \gamma V(s')] V(s)=maxasT(ss,a)[R(s,s)+γV(s)]
如果奖励函数只与当前状态相关,那么可以进一步简化。(下面的脚本主要也是基于这个公式来写的)
V ( s ) = R ( s ) + γ m a x a ∑ s ′ T ( s ′ ∣ s , a ) V ( s ′ )      . . . . . . . . .     公 式 ( 1 ) V(s) = R(s) + \gamma max_a \sum_{s'}T(s'|s, a)V(s') \ \ \ \ ......... \ \ \ 公式(1) V(s)=R(s)+γmaxasT(ss,a)V(s)    .........   (1)

二、基于价值的贝尔曼方程实现

主要方程

V ( s ) = R ( s ) + γ m a x a ∑ s ′ T ( s ′ ∣ s , a ) V ( s ′ )      . . . . . . . . .     公 式 ( 1 ) V(s) = R(s) + \gamma max_a \sum_{s'}T(s'|s, a)V(s') \ \ \ \ ......... \ \ \ 公式(1) V(s)=R(s)+γmaxasT(ss,a)V(s)    .........   (1)
计算不同状态链路的递归的时候会对一些状态进行重复计算,所以我们用lru_cache做简单优化。

from functools import lru_cache

@lru_cache(maxsize=128)
def V(s, gamma=0.99): # 递归
	# 等价于 公式(1)
    return R(s) + gamma * max_V_on_next_state(s)

奖励函数

def R(s):
    if s == 'happy_end':
        return 1
    elif s == 'bad_end':
        return -1
    else:
        return 0

行动概率与状态转移函数

为了简单示意,我们仅仅定义

  • 两个行动
    • UP, DOWN
  • 状态转移概率
    • 和行动一致的转移概率90%,和相反行动的转移概率为10%

最终结束条件

  • 最多行动5次
    • 当行动少于5次 则返回 {下一状态(s, UP):概率, 下一状态(s, DOWN):概率}
  • up >= 4次为happy_end, 否则为bad_end
def max_V_on_next_state(s):
    # 如果游戏结束,则期望为0
    if s in ['happy_end', 'bad_end']:
        return 0
    
    actions = ['up', 'down']
    values = []
    for a in actions:
        trainsition_probs = transit_func(s, a)
        v = 0
        for next_state, prob in trainsition_probs.items():
            v += prob * V(next_state) # 递归
        values.append(v)
    # 拿取行动中最大效益的值
    return max(values)


def transit_func(s, a):
	"""
	param s: 状态: 定义成 初始_行动_行动...  如: state_up_down_up | state | state_up 等
	param a: 行动: {'up', 'down'}
	"""
    actions = s.split('_')[1:]
    LIMIT_GAME_COUNT = 5
    HAPPY_END_BORDER = 4
    MOVE_PROB = 0.9

    def next_state(state, action):
        return "_".join([state, action])
    # 结束条件
    if len(actions) == LIMIT_GAME_COUNT:
        up_count = sum([1 if a == 'up' else 0 for a in actions])
        state = 'happy_end' if up_count >= HAPPY_END_BORDER else 'bad_end'
        prob = 1.0
        return {state: prob}
    else:
    	# 状态转移函数
        opposite = 'up' if a == 'down' else 'down'
        return {
            next_state(s, a): MOVE_PROB,
            next_state(s, opposite): 1- MOVE_PROB
        }

简单示例

从所有可能的未来逐步计算到当前。

if __name__ == "__main__":
    # 固定上下走动, 状态叠加在后面
    # state_up_up_up_up_up_up -> 1 + 0                            = 1
    # state_up_up_up_up_up    -> 0 + 0.99 * (0.9*1 + 0.1*1)       = 0.99
    # state_up_up_up_up       -> 0 + 0.99 * (0.9*0.99 + 0.1*0.99) = 0.9801
    print(V('state_up_up_up_up'))
    print(V('state_up_down_up_up'))
    print(V('state_down_up_up_up'))


"""
0.9801
0.78408
0.78408
"""
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Scc_hy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值