价值迭代求解马尔可夫决策过程

news2024/12/26 1:06:02

Value Iteration Algorithm

其算法思想是: 在每一个状态s下,
之迭代算法流程如下:
初始化状态价值state value,即对每个状态的价值都赋一个初始值,一般是0
计算每一个状态-动作对的 动作价值函数,通常通过创建一个二维表格,称为q表格
对每个状态s,最优策略 a ∗ = arg max ⁡ a q ( s , a ) a^*=\argmax_a q(s,a) a=argmaxaq(s,a)
策略更新: π ( a ∣ s ) = 1 \pi(a \mid s)=1 π(as)=1 if a = a ∗ a=a^* a=a
价值更新:

policy update:
π k + 1 ( s ) = arg ⁡ max ⁡ π ∑ a π ( a ∣ s ) ( ∑ r p ( r ∣ s , a ) r + γ ∑ s ′ p ( s ′ ∣ s , a ) v k ( s ′ ) ) ⏟ q k ( s , a ) , s ∈ S \pi_{k+1}(s)=\arg \max _{\pi} \sum_{a} \pi(a \mid s) \underbrace{\left(\sum_{r} p(r \mid s, a) r+\gamma \sum_{s^{\prime}} p\left(s^{\prime} \mid s, a\right) v_{k}\left(s^{\prime}\right)\right)}_{q_{k}(s, a)}, \quad s \in \mathcal{S} πk+1(s)=argπmaxaπ(as)qk(s,a) (rp(rs,a)r+γsp(ss,a)vk(s)),sS

value update
v k + 1 ( s ) = ∑ a π k + 1 ( a ∣ s ) ( ∑ r p ( r ∣ s , a ) r + γ ∑ s ′ p ( s ′ ∣ s , a ) v k ( s ′ ) ) ⏟ q k ( s , a ) , s ∈ S v_{k+1}(s)=\sum_{a} \pi_{k+1}(a \mid s) \underbrace{\left(\sum_{r} p(r \mid s, a) r+\gamma \sum_{s^{\prime}} p\left(s^{\prime} \mid s, a\right) v_{k}\left(s^{\prime}\right)\right)}_{q_{k}(s, a)}, \quad s \in \mathcal{S} vk+1(s)=aπk+1(as)qk(s,a) (rp(rs,a)r+γsp(ss,a)vk(s)),sS
因为这里的 π k + 1 \pi_{k+1} πk+1是贪婪方法,所以上式可以简化成:
v k + 1 ( s ) = max ⁡ a q k ( a , s ) v_{k+1}(s)=\max_a q_k(a,s) vk+1(s)=amaxqk(a,s)
在这里插入图片描述
步骤1:更新策略,求 π k + 1 \pi_{k+1} πk+1

一个例子

下图是一个例子,如何在一个2*2网格世界中,找到任何一个网格到蓝色方格的最短路径,即寻找最优策略pi。

状态空间 S = { s i } i = 1 4 S=\{s_i\}_{i=1}^4 S={si}i=14
动作空间 A = { a i } i = 1 5 A=\{a_i\}_{i=1}^5 A={ai}i=15 a 1 a_1 a1(向上移动), a 2 a_2 a2(向右移动), a 3 a_3 a3(向下移动), a 4 a_4 a4(向左移动), a 5 a_5 a5(原地不动);
奖励为: r b o u n d a r y = r f o r b i d d e n = − 1 , r t a r g e t = 1 r_{boundary}=r_{forbidden}=-1,r_{target}=1 rboundary=rforbidden=1,rtarget=1
折扣率 γ = 0.9 \gamma=0.9 γ=0.9

手推求解

初始化所有 v ( s i ) = 0 , i = 1 , 2 , 3 , 4 v(s_i)=0,i=1,2,3,4 v(si)=0,i=1,2,3,4
初始化q表格,根据动作价值函数 q ( s , a ) q(s,a) q(s,a)表达式写出q表格如下:

第1轮迭代:


v 0 ( s 1 ) = v 0 ( s 2 ) = v 0 ( s 3 ) = v 0 ( s 4 ) = 0 v_0(s_1)=v_0(s_2)=v_0(s_3)=v_0(s_4)=0 v0(s1)=v0(s2)=v0(s3)=v0(s4)=0,将 v 0 ( s i ) v_0(s_i) v0(si)带入刚才的q表格,有:

有了上方表格,可以进行Policy update,并将该策略绘制出来:
π 1 ( a 5 ∣ s 1 ) = 1 \pi_1(a_5 \mid s_1)=1 π1(a5s1)=1
π 1 ( a 3 ∣ s 2 ) = 1 \pi_1(a_3 \mid s_2)=1 π1(a3s2)=1
π 1 ( a 2 ∣ s 3 ) = 1 \pi_1(a_2 \mid s_3)=1 π1(a2s3)=1
π 1 ( a 5 ∣ s 4 ) = 1 \pi_1(a_5 \mid s_4)=1 π1(a5s4)=1

有了策略可以进行Value update
v 1 ( s 1 ) = 0 v_1(s_1)=0 v1(s1)=0
v 1 ( s 2 ) = 1 v_1(s_2)=1 v1(s2)=1
v 1 ( s 3 ) = 1 v_1(s_3)=1 v1(s3)=1
v 1 ( s 4 ) = 0 v_1(s_4)=0 v1(s4)=0

继续迭代k=1,将 v 1 ( s i ) v_1(s_i) v1(si)的值,带入q表格中:

有了上方表格,可以进行Policy update,并将该策略表示出来:
π 2 ( a 3 ∣ s 1 ) = 1 \pi_2(a_3 \mid s_1)=1 π2(a3s1)=1
π 2 ( a 3 ∣ s 2 ) = 1 \pi_2(a_3 \mid s_2)=1 π2(a3s2)=1
π 2 ( a 2 ∣ s 3 ) = 1 \pi_2(a_2 \mid s_3)=1 π2(a2s3)=1
π 2 ( a 5 ∣ s 4 ) = 1 \pi_2(a_5 \mid s_4)=1 π2(a5s4)=1

有了策略可以进行Value update
v 2 ( s 1 ) = γ 1 = 0.9 v_2(s_1)=\gamma1=0.9 v2(s1)=γ1=0.9
v 2 ( s 2 ) = 1 + γ = 1.9 v_2(s_2)=1+\gamma=1.9 v2(s2)=1+γ=1.9
v 2 ( s 3 ) = 1 + γ = 1.9 v_2(s_3)=1+\gamma=1.9 v2(s3)=1+γ=1.9
v 2 ( s 4 ) = 1 + γ = 1.9 v_2(s_4)=1+\gamma=1.9 v2(s4)=1+γ=1.9

此时,肉眼观察,已经得出最优策略。在编程时,则需要继续迭代k=2,3,…,直至 ∣ ∣ v k − v k + 1 ∣ ∣ < ε , ε → 0 ||v_k-v_{k+1}||<\varepsilon,\varepsilon \to 0 ∣∣vkvk+1∣∣<ε,ε0

2 编程求解

定义网格世界GridWorld如下图,求解每个状态的价值函数。
在这里插入图片描述
状态空间 :

`{0: (0, 0), 1:  (0, 1), 2:  (0, 2), 3:  (0, 3), 4:  (0, 4), 
  5: (1, 0), 6:  (1, 1), 7:  (1, 2), 8:  (1, 3), 9:  (1, 4), 
 10: (2, 0), 11: (2, 1), 12: (2, 2), 13: (2, 3), 14: (2, 4), 
 15: (3, 0), 16: (3, 1), 17: (3, 2), 18: (3, 3), 19: (3, 4), 
 20: (4, 0), 21: (4, 1), 22: (4, 2), 23: (4, 3), 24: (4, 4)}`

动作空间:有5种动作,上右下左,不动

{0: '↑', 1: '→', 2: '↓', 3: '←', 4: '○'}

import numpy as np

class GridWorldEnv:

    def __init__(self, isSlippery=False):
        self.seed = np.random.seed(47)
        self.shape = (5, 5)
        self.gridWorld = np.zeros(shape=self.shape, dtype=np.int64)
        self.forbiddenGrid = [(1, 1), (1, 2), (2, 2), (3, 1), (3, 3), (4, 1)]
        self.targetGrid = (3, 2)

        self.stateSpace = self.initStateSpace()
        self.actionSpace = {0: "↑", 1: "→", 2: "↓", 3: "←", 4: "○", }

        self.action_dim = len(self.actionSpace)
        self.state_dim = np.prod(self.shape)
        self.buildGridWorld()
        self.curState = 0

        print("状态空间", self.stateSpace)
        print("动作空间", self.actionSpace)
        print("网格世界\n", self.gridWorld)

    def buildGridWorld(self):
        for x in range(5):
            for y in range(5):
                if (x, y) in self.forbiddenGrid:
                    self.gridWorld[x][y] = -1
        self.gridWorld[3][2] = 1

    def initStateSpace(self):
        stateSpace = {}
        for x in range(5):
            for y in range(5):
                stateSpace[5 * x + y] = (x, y)

        return stateSpace

    def step(self, a):
        x, y = divmod(self.curState, 5)
        oldState = 5 * x + y

        if a == 0: x -= 1  # 上
        if a == 1: y += 1  # 右
        if a == 2: x += 1  # 下
        if a == 3: y -= 1  # 左

        reward = 0
        nextState = 5 * x + y
        done = False
        # 尝试越过边界,奖励-1
        if (x < 0 or y < 0) or (x > 4 or y > 4):
            reward = -1
            nextState = oldState
            self.curState = oldState
        # 进入forbidden区域,奖励-10
        if (x, y) in self.forbiddenGrid:
            reward = -10
            done = True
        # 达到目标点,奖励1
        if (x, y) == self.targetGrid:
            reward = 1
            done = True

        return nextState, reward, done

    def reset(self, state=None):

        if state is None:
            self.curState = 0
            return 0
        else:
            self.curState = state
            return state


class ValIter:
    def __init__(self, env: GridWorldEnv):
        self.env = env
        self.policy = np.zeros(shape=self.env.state_dim, dtype=np.int64)
        self.value = np.zeros(shape=self.env.state_dim, dtype=np.float64)
        self.q_table = np.zeros(shape=(env.state_dim, env.action_dim))
        self.trace = {"pi": [self.policy], "v": [self.value], "q_table": [self.q_table]}

    def policyUpdate(self, q_table):
        for s in self.env.stateSpace:
            self.policy[s] = np.argmax(q_table[s])
        self.trace["pi"].append(self.policy)

    def valueUpdate(self, q_table):
        for s in self.env.stateSpace:
            self.value[s] = np.max(q_table[s])
        self.trace["v"].append(self.value)
        self.trace["q_table"].append(self.q_table)

    def stateValFunc(self, s):
        return self.value[s]

    def actionValFunc(self, s, a):
        self.env.reset(s)
        next_state, reward, _ = self.env.step(a)
        return reward + 0.9 * self.stateValFunc(next_state)

    def valueIteration(self):

        iter = 0
        while True:
            for s in self.env.stateSpace.keys():
                for a in self.env.actionSpace:
                    self.q_table[s][a] = self.actionValFunc(s, a)

            old_state_val = np.sum(self.value)

            self.policyUpdate(self.q_table)
            self.valueUpdate(self.q_table)

            new_state_val = np.sum(self.value)
            iter += 1

            if np.abs(new_state_val - old_state_val) < 1e-6:
                print("iter=", iter)
                break

        pi = self.trace["pi"][-1]
        v = self.trace["v"][-1]
        q_table = self.trace["q_table"][-1]
        for s in self.env.stateSpace.keys():
            a = pi[s]
            print(self.env.actionSpace[a], end="\t")
            if (s + 1) % 5 == 0:
                print()
        for s in self.env.stateSpace.keys():
            print("%.4f" % v[s], end="\t")
            if (s + 1) % 5 == 0:
                print()
        print(q_table)


if __name__ == '__main__':
    env = GridWorldEnv()
    valIter = ValIter(env)
    valIter.valueIteration()

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/430016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目管理(PMP)考试:易混淆知识点汇总

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; PMP考试中经常出现&#xff0c;但容易混淆的一些内容&#xff0c;包含15个会议、40个分析、6个矩阵、5个清单、5个审计、5个报告、4个分解结构、4个评估、3个日志…

谷歌人机验证Google reCAPTCHA

reCAPTCHA是Google公司推出的一项验证服务&#xff0c;使用十分方便快捷&#xff0c;在国外许多网站上均有使用。它与许多其他的人机验证方式不同&#xff0c;它极少需要用户进行各种识图验证。 它的使用方式如下如所示&#xff0c;只需勾选复选框即可通过人机验证。 虽然简单…

Python项目之中国数据可视化

文章目录关键词一、做什么二、怎么做1、获取数据&&处理数据2、数据库设计&&存储数据3、开发后端接口4、前端页面编写三、效果展示四、总结关键词 PythonDjangoPython网络爬虫echarts可视化阅读者&#xff08;Python基础、Django基础、H5基础&#xff09; 一、…

Linux学习笔记——UDP协议

文章目录UDP协议端格式UDP的特点面向数据报UDP的缓冲区基于UDP的应用层协议UDP使用注意事项16位的UDP校验和的校验原理UDP协议端格式 16位源端口号&#xff1a;数据从哪一个端口发出来的&#xff0c;也就是数据从哪一个进程发送出来的。在编写应用层代码的时候&#xff0c;用ui…

Git安装使用教程

Git - Downloadshttps://git-scm.com/downloads 安装 Git。可以在 Git 官网上下载安装包并按照提示进行安装。 GitHub或Gitee官网上注册一个账号&#xff0c;注册好后&#xff0c;桌面右键选择Git Bash&#xff0c;进行账号配置&#xff0c;命令如下&#xff1a; # 配置用户名…

spark第八章:Pyspark

系列文章目录 spark第一章&#xff1a;环境安装 spark第二章&#xff1a;sparkcore实例 spark第三章&#xff1a;工程化代码 spark第四章&#xff1a;SparkSQL基本操作 spark第五章&#xff1a;SparkSQL实例 spark第六章&#xff1a;SparkStreaming基本操作 spark第七章&#…

带隙基准基本原理

目录 负温度系数电压 正温度系数电压 带隙基准 小结 如何产生一个不受温度变化&#xff0c;保持恒定的电压基准呢&#xff1f; 我们假设&#xff0c;如果将两个具有相反温度系数&#xff08;TC&#xff09;的量以适当的权重相加&#xff0c;那么结果就会成为零温度系数&am…

MIT6.824 lab2C2D实验总结

2C 就是持久化一些变量&#xff0c;日志&#xff0c;任期&#xff0c;投票给谁&#xff0c;2D(lastincludeterm, lastincludeindex, snapshot)。同时最难受的是Figure8Unreliable这个测试点&#xff0c;总是几百次出现一两个错误。最后发现是对论文一句话的歧义。这里讲解一下…

Linux(DHCP原理与配置)

文章目录一 、什么是DHCP1.1DHCP定义1.2DHCP好处1.3DHCP的分配方式二 、DHCP 的工作过程三 、DHCP中的设置3.1 DHCP参数3.2 相关操作步骤一 、什么是DHCP 1.1DHCP定义 DHCP&#xff08;动态主机配置协议&#xff09;是一个局域网的网络协议。指的是由服务器控制一段IP地址范围…

swagger文件上传接口没有选择文件按钮问题解决 使用@RequestPart注解

在使用文件上传API时&#xff0c;swagger没有选择文件按钮 在MultipartFile前面加上RequestPart注解 PostMapping("/importFile")ApiOperation(value "文件上传API")public Object importFile(ApiParam(value "文件流", required true) Reque…

超越ChatGpt,最近爆火的AutoGPT 究竟是什么

一、AutoGPT是什么 最近几天&#xff0c;一款基于GPT-4的最强语言模型AutoGPT火遍了整个AI圈。众所周知&#xff0c;此前爆火AI圈的ChatGPT&#xff0c;唯一不太好用的地方就是需要人类不断的prompt。因此&#xff0c;如果你想要ChatGPT帮你去做一件复杂的事情&#xff0c;那么…

第九章 法律责任与法律制裁

第九章 法律责任与法律制裁_副本 目录 第一节 法律责任的概念 一 法律责任的含义二 法律责任的特点 第二节 法律责任的分类与竞合 一 法律责任的分类 &#xff08;一&#xff09;根据责任行为所违反的法律的性质 民事责任&#xff1a;刑事责任行政责任违宪责任 &#xff08;二…

【云原生 • Docker】cAdvisor+Prometheus+Grafana 10分钟搞定Docker容器监控平台

文章目录cAdvisorPrometheusGrafana 10分钟搞定Docker容器监控平台cAdvisor部署Prometheus部署Grafana部署cAdvisorPrometheusGrafana 10分钟搞定Docker容器监控平台 cAdvisor(Container Advisor) 是 Google 开源的一个容器监控工具&#xff0c;可用于对容器资源的使用情况和性…

企业级信息系统开发讲课笔记3.1 基于配置文件整合SSM框架实现用户登录

文章目录零、本节学习目标一、采用MVC架构二、用户登录运行效果三、基于XML配置方式整合SSM框架实现用户登录&#xff08;一&#xff09;创建数据库与表1、创建数据库2、创建用户表3、在用户表里插入记录&#xff08;二&#xff09;创建Maven项目&#xff08;三&#xff09;项目…

【手把手刷CCF】202303-2-垦田计划100分(超简单思路,含详细解释注释与代码)

文章目录&#xff1a;故事的开头总是极尽温柔&#xff0c;故事会一直温柔……&#x1f49c;一、&#x1f333;代码如下&#xff1a;二、&#x1f335;解题思路❤️❤️❤️忙碌的敲代码也不要忘了浪漫鸭&#xff01;故事的开头总是极尽温柔&#xff0c;故事会一直温柔……&…

vector使用+模拟实现

目录 vector介绍 常见接口 构造函数 迭代器 容量操作 元素访问 增删查改 模拟实现 模拟实现要点图解 整体代码 迭代器失效问题 内部失效 外部失效 深浅拷贝问题 vector介绍 vector是表示可变大小数组的序列式容器。vector采用连续的空间存储元素&#xff0c;大小…

HTML5 <meta> 标签

HTML5 <meta> 标签 实例 描述 HTML 文档的元数据&#xff1a; <head> <meta name"description" content"免费在线教程"> <meta name"keywords" content"HTML,CSS,XML,JavaScript"> <meta name"auth…

全志v851s 在 eyesee-mpp 中添加一个hello_world sample 的流程

1. 为什么要在eyesee-mpp 中添加sample&#xff1f; 1&#xff09;保持整个openwrt 应用程序编写的完成性&#xff1b; 2&#xff09;eyesee-mpp 中包含了几乎所有全志视频音频模块的sample 以及 头文件&#xff0c;参考以及头文件调用起来非常方便&#xff0c;而且可以学习各种…

MongoDB 聚合管道中使用数组表达式运算符合并数组($concatArrays)

数组表达式运算符主要用于文档中数组的操作&#xff0c;接上一篇&#xff1a;MongoDB 聚合管道中使用数组表达式运算符&#xff08;$slice截取数组&#xff09;https://blog.csdn.net/m1729339749/article/details/130130328本篇我们主要介绍数组表达式运算符中用于合并数组的操…

InnoSetup制作安装包(EXE)

功能描述 1.666666.war为项目war包&#xff0c;666666.bat为启动war包脚本&#xff0c;通过InnoSetup将它们打包到安装包666666.exe 2.666666.exe安装包安装过程中将666666.bat注册为自启动服务&#xff0c;安装结束自动执行脚本启动项目666666.war --------------------------…