文章目录

  • 1、Cliff Walking 环境
  • 2、策略迭代(Policy Iteration)
    • 1)策略评估(Policy Evaluation)
    • 2)策略提升(Policy Improvement)
    • 3)策略迭代算法
  • 3、价值迭代(Value Iteration)
  • 4、参考文献

动态规划的基本思想是将待求解问题分解成若干子问题,先求解子问题,然后从这些子问题的解得到原问题的解

基于动态规划的强化学习算法有两种:

  • 策略迭代(Policy Iteration):有两部分组成:策略评估(Policy Evaluation)和策略提升(Policy Improvement);使用贝尔曼方程来得到一个策略的状态价值函数
  • 价值迭代(Value Iteration):直接使用贝尔曼最优方程来进行动态规划,得到最终的最优状态价值

本blog将讨论如何使用动态规划的思想来求解马尔科夫决策过程中的最优策略

1、Cliff Walking 环境

使用策略迭代和价值迭代来求解Cliff Walking这个环境的最优策略。下图是环境的样子

Cliff Walking 是一个非常经典的强化学习环境,它要求一个智能体从起点出发,避开悬崖行走,最终到达目标位置。如图所示,有一个 4 * 12 的网格世界,每一个网格是一个状态,起点是左下角的状态,目标是右下角的状态。智能体在每一个状态都可以采取 4 种动作:上,下,左,右,如果采取动作后触碰到边界墙壁则状态不发生改变,否则就会相应到达下一个状态。其中有一段悬崖,智能体到达目标状态或掉入悬崖都会结束并回到起点,也就是说它们是终止状态。每走一步的奖励是-1,掉入悬崖的奖励是-100

import copyclass CliffWalkingEnv:""" Cliff Walking环境"""def __init__(self, ncol=12, nrow=4):self.ncol = ncol # 定义环境的宽self.nrow = nrow # 定义环境的高self.P = self.createP() # 转移矩阵P[state][action] = [(p, next_state, reward, done)],包含下一个状态和奖励def createP(self):P = [[[] for j in range(4)] for i in range(self.nrow * self.ncol)] # 初始化change = [[0, -1], [0, 1], [-1, 0], [1, 0]] # 4 种动作, 0:上, 1:下, 2:左, 3:右。原点(0,0)定义在左上角for i in range(self.nrow):for j in range(self.ncol):for a in range(4):if i == self.nrow - 1 and j > 0:  # 位置在悬崖或者终点,因为无法继续交互,任何动作奖励都为0P[i * self.ncol + j][a] = [(1, i * self.ncol + j, 0, True)]continue# 其他位置next_x = min(self.ncol - 1, max(0, j + change[a][0]))next_y = min(self.nrow - 1, max(0, i + change[a][1]))next_state = next_y * self.ncol + next_xreward = -1done = Falseif next_y == self.nrow - 1 and next_x > 0: # 下一个位置在悬崖或者终点done = Trueif next_x != self.ncol - 1: # 下一个位置在悬崖reward = -100P[i * self.ncol + j][a] = [(1, next_state, reward, done)]return P

2、策略迭代(Policy Iteration)

策略迭代是策略评估和策略提升这两个过程的不断循环交替,直至最后得到最优策略

1)策略评估(Policy Evaluation)

这一过程用来计算一个策略的状态价值函数。之前的贝尔曼期望方程:

其中π(a∣s)\pi(a|s)π(a∣s)是策略π\piπ在状态 s 下采取动作 a 的概率。当知道奖励函数和状态转移函数的时候,可以根据下一个状态的价值来计算当前状态的价值。

根据DP的思想,可以将下一个可能状态的价值当成一个子问题,计算当前状态的价值看成当前问题;考虑所有的状态,就变成了用上一轮的状态价值函数来计算当前这一轮的状态价值函数

2)策略提升(Policy Improvement)

再用策略评估计算得到当前策略的状态价值函数之后,可以改进策略,这个步骤就是策略提升。

假设此时对于策略 π\piπ,已经知道了策略函数 VπV_{\pi}Vπ​,也就是知道了从每一个状态 s 出发一直根据策略 π\piπ 最终得到的期望回报;如何改变策略来获得在状态 s 下更高的期望回报是一个问题。

假设在状态 s 下采取动作 a 之后的动作依旧遵循策略 π\piπ, 此时得到的期望回报其实是动作价值 Qπ(s,a)>Vπ(s)Q_\pi(s,a)>V_\pi(s)Qπ​(s,a)>Vπ​(s),则说明在状态 s 下采取动作 a 会比原来的策略 π(a∣s)\pi(a|s)π(a∣s) 得到更高的期望回报。现在假设存在一个确定性策略 π′\pi'π′,在任意一个状态 s 下,都满足:
Qπ(s,π′(s))>=Vπ(s)Q_\pi(s,\pi'(s)) >= V_\pi(s) Qπ​(s,π′(s))>=Vπ​(s)

于是在状态 s 下,就有:
Vπ′(s)>=Vπ(s)V_{\pi'}(s) >= V_\pi(s) Vπ′​(s)>=Vπ​(s)

于是可以直接贪心的在每一个状态选择动作价值最大的动作:

3)策略迭代算法

综上所述:策略迭代算法首先对当前策略进行策略评估,得到其状态价值函数,然后该状态价值函数根据策略提升来得到一个更好的新策略,之后继续评估、提升,循环往复,直到收敛:

算法:

策略迭代python代码:

class PolicyIteration:""" 策略迭代 """def __init__(self, env, theta, gamma):self.env = envself.v = [0] * self.env.ncol * self.env.nrow  # 初始化价值为0self.pi = [[0.25, 0.25, 0.25, 0.25] for i in range(self.env.ncol * self.env.nrow)]  # 初始化为均匀随机策略self.theta = theta  # 策略评估收敛阈值self.gamma = gamma  # 折扣因子def policy_evaluation(self): # 策略评估cnt = 1 # 计数器while 1:max_diff = 0new_v = [0] * self.env.ncol * self.env.nrowfor s in range(self.env.ncol * self.env.nrow):qsa_list = []for a in range(4):qsa = 0for res in self.env.P[s][a]:p, next_state, r, done = resqsa += p * (r + self.gamma * self.v[next_state] * (1-done))  # 本章节环境比较特殊,奖励和下一个状态有关,所以需要和状态转移概率相乘qsa_list.append(self.pi[s][a] * qsa)new_v[s] = sum(qsa_list)  # 状态价值函数和动作价值函数之间的关系max_diff = max(max_diff, abs(new_v[s] - self.v[s]))self.v = new_vif max_diff < self.theta: breakcnt += 1print("策略评估进行%d轮后完成" % cnt)def policy_improvement(self): # 策略提升for s in range(self.env.nrow * self.env.ncol):qsa_list = []for a in range(4):qsa = 0for res in self.env.P[s][a]:p, next_state, r, done = resqsa += p * (r + self.gamma * self.v[next_state] * (1-done))qsa_list.append(qsa)maxq = max(qsa_list)cntq = qsa_list.count(maxq)self.pi[s] = [1/cntq if q == maxq else 0 for q in qsa_list]  # 让相同的动作价值均分概率print("策略提升完成")return self.pidef policy_iteration(self): # 策略迭代while 1:self.policy_evaluation()old_pi = copy.deepcopy(self.pi) # 将列表进行深拷贝,方便接下来进行比较new_pi = self.policy_improvement()if old_pi == new_pi: break

为了展现最终策略,增加一个打印策略函数来打印当前策略每个状态的价值以及会采取的动作。对于打印出来的动作,^o<0表示相等的概率执行向上向左,ooo>只采取向右走的动作:

def print_agent(agent, action_meaning, disaster=[], end=[]):print("状态价值:")for i in range(agent.env.nrow):for j in range(agent.env.ncol):print('%6.6s' % ('%.3f' % agent.v[i * agent.env.ncol + j]), end=' ') # 为了输出美观,保持输出6个字符print()print("策略:")for i in range(agent.env.nrow):for j in range(agent.env.ncol):if (i * agent.env.ncol + j) in disaster: # 一些特殊的状态,例如Cliff Walking中的悬崖print('****', end=' ')elif (i * agent.env.ncol + j) in end: # 终点print('EEEE', end=' ')else:a = agent.pi[i * agent.env.ncol + j]pi_str = ''for k in range(len(action_meaning)):pi_str += action_meaning[k] if a[k] > 0 else 'o'print(pi_str, end=' ')print()

执行策略迭代:

env = CliffWalkingEnv()
action_meaning = ['^', 'v', '<', '>']
theta = 0.001
gamma = 0.9
agent = PolicyIteration(env, theta, gamma)
agent.policy_iteration()
print_agent(agent, action_meaning, list(range(37, 47)), [47])-----------------------------------------------------------------
策略评估进行60轮后完成
策略提升完成
策略评估进行72轮后完成
策略提升完成
策略评估进行44轮后完成
策略提升完成
策略评估进行12轮后完成
策略提升完成
策略评估进行1轮后完成
策略提升完成
状态价值:
-7.712 -7.458 -7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710
-7.458 -7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710 -1.900
-7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710 -1.900 -1.000
-7.458  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000
策略:
ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovoo
ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovoo
ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ovoo
^ooo **** **** **** **** **** **** **** **** **** **** EEEE

3、价值迭代(Value Iteration)

价值迭代可以看成认为是一种策略评估只进行了一次更新的策略迭代

价值迭代可以看成是一个动态规划的过程,利用的是贝尔曼方程:

将其写成迭代更新的方式:

价值迭代按照以上的方式进行更新,等到 Vk+1V_{k+1}Vk+1​和VkV_kVk​一样时,就是贝尔曼最优方程的不动点,此时对应着最优状态价值函数 V∗V_*V∗​,然后从中恢复出最优策略即可:

算法:

python实现代码:

class ValueIteration:""" 价值迭代 """def __init__(self, env, theta, gamma):self.env = envself.v = [0] * self.env.ncol * self.env.nrow  # 初始化价值为0self.theta = theta  # 价值收敛阈值self.gamma = gammaself.pi = [None for i in range(self.env.ncol * self.env.nrow)] # 价值迭代结束后得到的策略def value_iteration(self):cnt = 0while 1:max_diff = 0new_v = [0] * self.env.ncol * self.env.nrowfor s in range(self.env.ncol * self.env.nrow):qsa_list = []for a in range(4):qsa = 0for res in self.env.P[s][a]:p, next_state, r, done = resqsa += p * (r + self.gamma * self.v[next_state] * (1-done))qsa_list.append(qsa) # 这一行和下一行是和策略迭代的主要区别new_v[s] = max(qsa_list)max_diff = max(max_diff, abs(new_v[s] - self.v[s]))self.v = new_vif max_diff < self.theta: breakcnt += 1print("价值迭代一共进行%d轮" % cnt)self.get_policy()def get_policy(self): # 根据价值函数导出一个贪心策略for s in range(self.env.nrow * self.env.ncol):qsa_list = []for a in range(4):qsa = 0for res in self.env.P[s][a]:p, next_state, r, done = resqsa += r + p * self.gamma * self.v[next_state] * (1-done)qsa_list.append(qsa)maxq = max(qsa_list)cntq = qsa_list.count(maxq)self.pi[s] = [1/cntq if q == maxq else 0 for q in qsa_list]  # 让相同的动作价值均分概率
env = CliffWalkingEnv()
action_meaning = ['^', 'v', '<', '>']
theta = 0.001
gamma = 0.9
agent = ValueIteration(env, theta, gamma)
agent.value_iteration()
print_agent(agent, action_meaning, list(range(37, 47)), [47])-------------------------------------------------------------------
价值迭代一共进行14轮
状态价值:
-7.712 -7.458 -7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710
-7.458 -7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710 -1.900
-7.176 -6.862 -6.513 -6.126 -5.695 -5.217 -4.686 -4.095 -3.439 -2.710 -1.900 -1.000
-7.458  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000  0.000
策略:
ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovoo
ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovo> ovoo
ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ovoo
^ooo **** **** **** **** **** **** **** **** **** **** EEEE

4、参考文献

  • Reinforcement Learning : An Introduction
  • 深入浅出强化学习:原理入门
  • Shusen Wang的《强化学习基础》视频,link:https://www.youtube.com/watch?v=XRGquU0ZJok
  • 动手学强化学习,link:https://hrl.boyuai.com/

强化学习中的动态规划算法(Dynamic Programming)相关推荐

  1. 深度强化学习中Double DQN算法(Q-Learning+CNN)的讲解及在Asterix游戏上的实战(超详细 附源码)

    需要源码和环境搭建请点赞关注收藏后评论区留下QQ~~~ 一.核心思想 针对DQN中出现的高估问题,有人提出深度双Q网络算法(DDQN),该算法是将强化学习中的双Q学习应用于DQN中.在强化学习中,双Q ...

  2. 动态规划算法 dynamic programming

    在大三上算法设计课程的时候,开始接触了动态规划,初学的时候没什么感觉,唯一的印象就是这种方法能逐步根据最优子结构得到最终的最优解.也就是保证每一个子问题的解决得到的都是最优解,那最终得到的答案肯定也是 ...

  3. matlab实现k-l算法,Matlab实现动态规划算法 (dynamic programming algorithm)

    function [p_opt,fval]=dynprog(x,DecisFun,ObjFun,TransFun) % [p_opt,fval]=dynprog(x,DecisFun,ObjFun,T ...

  4. 强化学习(二)- 动态规划(Dynamic Programming)

    3.动态规划 3.1 介绍 术语动态规划(DP:Dynamic Programming) 指的是一个算法集合,可以用来计算最优策略,给定一个完美的环境模型,作为马尔可夫决策过程(MDP).经典的DP算 ...

  5. 数据结构与算法(C++)– 动态规划(Dynamic Programming)

    动态规划(Dynamic Programming) 理解动态规划的好文:https://www.sohu.com/a/153858619_466939 1.基础 **定义:**递归算法经常会有一些重复 ...

  6. 转载:强化学习中Bellman最优性方程背后的数学原理?

    一. Bellman最优 贝尔曼方程在强化学习(RL)中无处不在,它是由美国应用数学家理查德·贝尔曼(Richard Bellman)提出,用于求解马尔可夫决策过程. 贝尔曼最优性方程 贝尔曼最优性方 ...

  7. 动态规划(Dynamic Programming, DP)简介

    动态规划(Dynamic programming,DP)是一种在数学.计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法. 动态规划常常适用于有重叠子问题和最优子结 ...

  8. 一道有关动态规划(Dynamic Programming)的网易面试题

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:机器学习算法实验室 最近遇到一道很经典的有关动态规划的网 ...

  9. 强化学习中的脉冲神经网络

    简 介: 脉冲强化学习是最近兴起的将脉冲神经网络应用到强化学习中的一个研究领域.固然脉冲神经网络的引入会给强化学习带来一些新的东西,但目前的研究仍然仅仅满足于如何让算法收敛,而没有发挥出脉冲神经网络独 ...

最新文章

  1. Navicat 12连接PostgreSQL11.3数据库服务器
  2. 素数问题是物质的几何学问题
  3. jdk的一条命令查看运行参数
  4. linux切换root权限
  5. win10家庭版gpedit.msc无法打开本地组策略
  6. python画五角星代码_008-python绘制五个五角星
  7. MKL学习——矩阵向量操作
  8. 手把手教你用C#做疫情传播仿真
  9. Leetcode--845. 数组中的最长山脉
  10. Django里面的sql查询语句
  11. Nodejs实时通讯 在线聊天室(Socket.io)_收藏
  12. 升级macOS Big Sur 无法开机/死机怎么办?
  13. potplayer播放器没有声音的解决方案
  14. 计算机网络教学常用哪些软件,仿真软件在计算机网络教学中的应用
  15. oracle 存储过程body,【随手记】Oracle存储过程报错 Compilation errors for PACKAGE BODY
  16. 使用 关键字来创建python自定义函数_python 自定义函数
  17. 传智博客JAVA基础第二十三天
  18. 何钦铭版C语言第3章答案,何钦铭版C语言第3章答案
  19. 【Jetson-Nano】SD卡重新格式化
  20. 实现1-100之间的阶乘

热门文章

  1. 接口大师v3.8.0版本更新,首页改版+组合套餐+微信登录+独立App
  2. html, css知识点
  3. chrome 打开默认页 被篡改_为什么 Chrome 浏览器的主页会被篡改为 hao123 ?遇到这种情况要如何修复?...
  4. 10 – 音效的添加
  5. Django--在线相册管理系统(1)
  6. java构造函数调用构造函数
  7. 总算把凯利公式说明白了
  8. 基于NLP的COVID-19虚假新闻检测
  9. 窄带物联网,开启万物互联新篇章
  10. docker php安装gd扩展_docker php 容器安装GD库