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

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()

结果:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

迎难而上,阿里高频考点2023Java岗面试突击手册

上周我接到一位粉丝的私信说目前互联网形势实在对他太不友好&#xff0c;感觉自己每个技术栈都会一点&#xff0c;但不是完全精通。基本二面三面的时候就挂了&#xff0c;已经完全不知道该朝哪个方向努力了&#xff0c;希望可以给他一些建议和方法指导。那么&#xff0c;本次就…

【两阶段鲁棒优化】利用列-约束生成方法求解两阶段鲁棒优化问题(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

MySQL--表的使用--0409

目录 1.表的基本操作 1.1 创建表 2. 查看表结构 3.修改表 3.1 新增一列 3.2 修改列属性 3.3 修改名字 3.3.1 修改表名字 3.3.2 修改表内列名字 3.4删除 3.4.1 删除列 3.4.2 删除表 1.表的基本操作 查看自己目前在哪个数据库里面 mysql> select database(); 1.1 创…

基于PCA与LDA的数据降维实践

基于PCA与LDA的数据降维实践 描述 数据降维&#xff08;Dimension Reduction&#xff09;是降低数据冗余、消除噪音数据的干扰、提取有效特征、提升模型的效率和准确性的有效途径&#xff0c; PCA&#xff08;主成分分析&#xff09;和LDA&#xff08;线性判别分析&#xff0…

状态错误 MSB8040,此项目需要缓解了 Spectre 漏洞的库。从 Visual Studio 安装程序(单个组件选项卡)为正在使用的任何工具集和体

“Spectre Mitigation”缓解错误 如果出现“Spectre Mitigation”这种错误&#xff0c;就要了解下PIPE技术&#xff1a;流水线技术&#xff0c;比如3级流水线&#xff0c;避免CPU空闲&#xff0c;不浪费时间&#xff0c;但是前提是没有跳转&#xff0c;指令都是顺序执行的&…

3.9、互斥锁(互斥量)

3.9、互斥锁&#xff08;互斥量&#xff09;1.互斥锁&#xff08;互斥量&#xff09;的介绍2. 互斥量相关操作函数3.互斥量函数的使用介绍①pthread_mutex_init②pthread_mutex_destroy③pthread_mutex_lock④pthread_mutex_trylock⑤pthread_mutex_unlock3.利用互斥锁实现线程…

王小川,才是深「爱」李彦宏的那个人?

在推出中国首个类ChatGPT产品「文心一言」后&#xff0c;李彦宏在接受专访时断言&#xff0c;中国基本不会再出一个OpenAI了&#xff0c;「创业公司重新做一个ChatGPT其实没有多大意义&#xff0c;基于大语言模型开发应用机会很大&#xff0c;没有必要再重新发明一遍轮子。」 听…

SPARQL endpoint with Ontop CLI部署,python使用SPARQLWrapper

Ontop CLI部署&#xff0c;避免踩坑0.前言1.提示2.详细部署流程3.python操作4.碎碎念0.前言 教程&#xff1a;Setting up an Ontop SPARQL endpoint with Ontop CLI照着教程来&#xff0c;不知道为啥&#xff0c;总是报错&#xff0c;后来发现&#xff0c;手机搜到的跟电脑不一…

pytorch 数据类型

文章目录一、tensor如何表示字符串数据类型类型判断Dimension 0Dimension 1Dimension 2Dimension 3Dimension 4mixed二、创建Tensorimport from numpyimport from listuninitialized 未初始化set default typerand/rand_like, randintfulllinspaceindex切片三、维度变换总结一、…

尚硅谷大数据技术Scala教程-笔记04【集合】

视频地址&#xff1a;尚硅谷大数据技术之Scala入门到精通教程&#xff08;小白快速上手scala&#xff09;_哔哩哔哩_bilibili 尚硅谷大数据技术Scala教程-笔记01【Scala课程简介、Scala入门、变量和数据类型、运算符、流程控制】尚硅谷大数据技术Scala教程-笔记02【函数式编程】…

交换机Access模式和Trunk模式配置演示

一.Access配置 1.创建VLAN 2.设置为接口模式&#xff0c;将接口划入不同VLAN 3.测试 二.Trunk配置 1. 接口VLAN配置 2.设置允许VLAN流量通过&#xff0c;可写all 3.测试 一.Access配置 实现VLAN10 和 VLAN20之间通信隔离 1.创建VLAN [s1]vlan 10 [s1]vlan 20[s1]vlan…

Android中的AsyncTask

近期写了一个项目&#xff0c;在前台刷新界面的时候需要操作数据库&#xff0c;进行数据操作&#xff0c;在UI线程更新数据会导致ANR&#xff0c;程序十分卡&#xff0c;因此用了AsyncTask进行后台数据处理。 介绍 AsyncTask是一个用于在后台线程执行异步任务并在主线程更新U…

set/multiset容器

1、set/multiset容器简介 但是 set 容器只有键值&#xff0c;在插入数据的时候会自动根据 键值 进行排序&#xff0c;所以不允许有相同的键值存在&#xff0c;也不能修改 set 容器元素值&#xff0c;会破坏 set 的数据结构。set 容器的迭代器是只读迭代器 2、set容器 API 操作…

读懂AUTOSAR :DiagnosticLogAndTrace DLT(四)-- API解析

一、周期调用的函数&#xff1a;Dlt_TxFunction 根据参数DltGeneralTrafficShapingSupport&#xff0c;决定如何去发送DLT消息。如果为TRUE&#xff0c;那需要参考参数DltLogChannelTrafficShapingBandwidth为每个Log通道设置发送带宽&#xff1b;如果为FALSE&#xff0c;那么…

纯虚函数和抽象类

什么时候使用纯虚函数: 某些类,在现实角度和项目实现角度,都不需要实例化(不需要创建它的对象),这个类中定义的某些成员函数,只是为了提供一个形式上的借口,准备让子类来做具体化的实现,此时,这个方法就可以定义为"纯虚函数",包含纯虚函数的类,就称为抽象类. 纯虚函…

Java入坑之集合、流与序列化

一、集合 1.1集合定义 集合概念&#xff1a; 保存和盛装数据的容器&#xff0c;将许多元素组合成一个单一单元的容器对象。集合&#xff0c;可用于存储/检索/操作/传输/聚合数据集合框架&#xff1a; 表示和操作集合的体系&#xff0c;包括接口、实现类&#xff0c;集合框架的…

python真的如此好吗?

作为一名合格的&#xff08;准&#xff09;程序员&#xff0c;必做的一件事是关注编程语言的热度&#xff0c;编程榜代表了编程语言的市场占比变化&#xff0c;它的变化更预示着未来的科技风向和机会&#xff01; Python霸占榜首 只因它真的很强 Python&#xff0c;年龄可能比…

这篇文章价值很大:股票历史分时成交数据怎么简单获取?【干货】

文章目录前言一、准备二、使用步骤1.引入库2&#xff0c;使用这个API查询历史分时数据&#xff1a;3.查询完整历史分时数据4.其他查询方法参数格式&#xff1a;[(市场代码, 股票代码), ...]参数&#xff1a;市场代码, 股票代码, 文件名, 起始位置, 数量参数&#xff1a;市场代码…

MySQL-binlog+dump备份还原

目录 &#x1f341;binlog日志恢复 &#x1f342;binlog介绍 &#x1f342;Binlog的用途 &#x1f342;开启binary log功能 &#x1f342;配置binlog &#x1f341;mysqldump &#x1f342;数据库的导出 &#x1f342;数据库的导入 &#x1f341;mysqldumpbinlog &#x1f990;…

【Python_Scrapy学习笔记(一)】Scrapy框架简介

Scrapy框架简介 前言 Scrapy 框架是一个用 python 实现的为了爬取网站数据、提取数据的应用框架&#xff0c;使用 Twisted 异步网络库来处理网络通讯&#xff0c;可以高效的完成数据爬取。本文主要介绍 Scrapy 框架的构成与工作原理。 正文 1、Scrapy安装 Windows安装&…