强化学习笔记:基于价值的学习之价值迭代(python实现)

news2025/1/13 6:04:12

目录

1. 前言

2. 数学原理

3. 实现

3.1 Planner类        

3.2 ValueIterationPlanner类

4. 运行结果及分析        


1. 前言

        在强化学习中,根据是否依赖于(环境的)模型,可以分为有模型(model-based)学习和无模型(model-free)学习。根据行动的决策基准,可以分为基于价值的学习(value-based)和基于策略学习(policy-based)。

        在基于价值的学习中,根据状态值函数(state-value function)值或者动作值函数的值,进行行动决策。总是选择从当前状态出发可能到达的下一个状态中价值最大的那个状态所对应的行动。

         这里的关键在于状态(或者动作)值函数的估计。在基于模型(model-based)的方法中,如果已知迁移函数(T represent transit or transfer)和奖励函数(两者可以合并为Pr(s',r|s,a))的话,可以基于动态规划的方法进行状态值函数的求解。对状态值函数的精确求解有比较严格的条件限制,更有实际应用意义的是对值函数进行近似求解,也称价值近似(value approximation)。价值近似可以通过价值迭代(value iteration)的方式进行。在上一篇(强化学习笔记:基于价值的学习方法之价值估计(python实现))中讨论了基于贝尔曼方程的状态值函数的基本求解方法(求严格解)。但是,这种方法计算量巨大,运行时间随递归搜索深度指数级上升。

        本文(以及接下来的文章)描述价值估计或者近似,通常称为价值迭代(value iteration)的原理和实现。

2. 数学原理

        首先,如上一篇所述,在基于价值的学习方法中,价值函数可以简化如下:

                        V(s) = \max\limits_a \{ \sum\limits_{s'} T(s'|s,a) [R(s,s') + \gamma V(s')]\}        (1) 

        迭代计算的关键要点是:

        (a) 对所有各状态值可以随机初始化(而不像上一篇中那样总是需要从最后的确定性的终局状态开始回溯)

        (b) 重复执行式(1)所代表的计算,每一轮遍历所有的状态进行更新计算,称为一个iteration。

        (c) 每一iteration的计算是基于上一次iteration后所得到的结果

 

        价值迭代的数学表达式如下所示:

                ​​​​​​​        V_{i+1}(s) = \max\limits_a \{ \sum\limits_{s'} T(s'|s,a) [R(s,s') + \gamma V_i(s')]\}           (2)

        式(2)与式(1)相比仅有细微的区别,等式左边和右边的V分别追加了下表{i} 和 {i+1},用于表示iteration序号。正是这小小的一点修改带来了魔法式的效果。

3. 实现

        (其实是参考文献【2】的代码的摘抄学习。。。但是基于我的理解追加了解说)

3.1 Planner类        

class Planner():

    def __init__(self, env):
        self.env = env
        self.log = []
        self.V_grid = []

    def initialize(self):
        self.env.reset()
        self.log = []

    def plan(self, gamma=0.9, threshold=0.0001):
        raise Exception("Planner have to implements plan method.")

    def transitions_at(self, state, action):
        transition_probs = self.env.transit_func(state, action)
        for next_state in transition_probs:
            prob = transition_probs[next_state]
            reward, _ = self.env.reward_func(next_state)
            yield prob, next_state, reward

    def dict_to_grid(self, state_reward_dict):
        grid = []
        for i in range(self.env.row_length):
            row = [0] * self.env.column_length
            grid.append(row)
        for s in state_reward_dict:
            grid[s.row][s.column] = state_reward_dict[s]

        return grid
    
    def print_value_grid(self):
        for i in range(len(self.V_grid)):
            for j in range(len(self.V_grid[0])):
                print('{0:6.3f}'.format(self.V_grid[i][j]), end=' ' )
            print('')

         如上所示,首先实现了一个Planner类(但是这个类名以及plan()方法名都感觉并不是很合适)作为基类,后面价值迭代和策略迭代都将继承该类进行实现。

        plan()方法是价值迭代和策略迭代都需要实现的,这里只是给出一个接口定义,具体实现交给子类去实现。如果子类没有实现的话,会报告错误。这里涉及面向对象编程中的覆盖(override)的概念,点到为止。

        transitions_at()方法实现迁移函数T(s'|s,a)。为了节约内存使用,采用yield将其实现为一个生成器,这样在使用时是按需生成,而不是一次性地将所有的状态转移数据全部生成,对于大型问题,状态数非常之多时这个非常重要。

        dict_to_grid()和print_value_grid()只是两个helper函数,用于数据格式转换和打印,不多解释。

3.2 ValueIterationPlanner类

class ValueIterationPlanner(Planner):

    def __init__(self, env):
        super().__init__(env)

    def plan(self, gamma=0.9, threshold=0.0001):
        self.initialize()
        actions = self.env.actions
        V = {}
        for s in self.env.states:
            # Initialize each state's expected reward.
            V[s] = 0

        while True:
            delta = 0
            self.log.append(self.dict_to_grid(V))
            for s in V:
                if not self.env.can_action_at(s):
                    continue
                expected_rewards = []
                for a in actions:
                    r = 0
                    for prob, next_state, reward in self.transitions_at(s, a):
                        r += prob * (reward + gamma * V[next_state])
                    expected_rewards.append(r)
                max_reward = max(expected_rewards)
                delta = max(delta, abs(max_reward - V[s]))
                V[s] = max_reward

            if delta < threshold:
                break

        self.V_grid = self.dict_to_grid(V)

        其中plan()方法实现了上一节式(2)所表示的迭代运行过程。

        变量V一开始初始化为全0。

        每次迭代对所有的状态值更新后,与上一轮结束时的值进行比较求所有各状态值得变化的绝对值。如果该变化绝对值小于预设门限threshold则认为已经收敛,停止迭代。

4. 运行结果及分析        

        测试代码如下所示:

if __name__ == "__main__":

    # Create grid environment
    grid = [
        [0, 0, 0, 1],
        [0, 9, 0, -1],
        [0, 0, 0, 0]
    ]
        
    env = Environment(grid)
    valueIterPlanner = ValueIterationPlanner(env)
    valueIterPlanner.plan(0.9,0.001)
    valueIterPlanner.print_value_grid()

        运算结果如下:

0.610  0.766  0.928  0.000
0.487  0.000  0.585  0.000
0.374  0.327  0.428  0.189

        首先,运行时间相比上一篇的基本实现几乎可以忽略不计。

        其次,上一篇的基本实现中,递归深度为7和8时grid[2][0]的结果分别为0.339和0.488,与上面的0.374并不吻合,这是为什么呢?

        最后,如上所示,grid[0][3], grid[1][1], 和grid[1][3]的值均为0,这是符合定义的。因为grid[1][1]不能进入,另外两个是导致回合结束的点,它们的未来预期奖励都应该为0。但是,这里牵出了一个问题。比如说,当前agent处于grid[0][2]的话,由于grid[0][3]就是reward cell,所以最优行动显然是应该向右移动。但是根据以上结果,以及基于价值的方法中的行动决策机制,agent应该是要向左移动!这个困惑了我很久。。。这里似乎存在状态值的定义与基于价值的方法的行动决策机制之间的矛盾。其本质问题是什么呢?

        完整代码参见:reinforcement-learning/value_eval at main · chenxy3791/reinforcement-learning (github.com)

参考文献:

【1】Sutton, et, al, Introduction to reinforcement learning (2020)

【2】久保隆宏著,用Python动手学习强化学习

        

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

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

相关文章

通信原理简明教程 | 模拟调制传输

文章目录1 模拟幅度调制1.1 模拟幅度调制的基本原理1.2 DSB-SC调制和AM调制1.3 SSB调制和VSB调制2 模拟角度调制2.1 角度调制的基本概念2.2 窄带调频和宽带调频2.3 调频信号的产生方法3 模拟调制系统的解调3.1 相干解调3.2 非相干解调4 模拟调制系统的抗噪声性能4.1 抗噪声性能…

Service Mesh

Service Mesh 参考如下文章&#xff1a;可以将此文章看作为下面文章的结合&#xff1a; https://zhuanlan.zhihu.com/p/61901608 https://philcalcado.com/2017/08/03/pattern_service_mesh.html https://zhuanlan.zhihu.com/p/153105848?from_voters_pagetrue 微服务演化进…

浅谈 开源许可证

目录浅谈 开源许可证一、什么是开源许可证1.1 什么是开源1.2 什么是开源许可证Copyleft 许可证&#xff08;Copyleft 许可证&#xff09;宽松许可证&#xff08;permissive 许可证&#xff09;二、为什么要有开源许可证2.1、No License&#xff1a;没有开源许可证意味着什么2.2…

38.Isaac教程--AprilTags

AprilTags ISAAC教程合集地址文章目录AprilTags源码Isaac Codelet运行示例应用程序在主机系统上运行示例应用程序在 Jetson 上运行应用程序在 Websight 中查看应用程序的输出AprilTags 是一种流行的基准标记形式。 它在机器人技术中有广泛的应用&#xff0c;包括对象跟踪、视觉…

数据挖掘领域十大经典算法

一、什么是数据挖掘&#xff1f;数据挖掘是人工智能和数据库领域研究的热点问题&#xff0c;所谓数据挖掘是指从数据库的大量数据中揭示出隐含的、先前未知的并有潜在价值的信息的非平凡过程。数据挖掘是一种决策支持过程&#xff0c;它主要基于人工智能、机器学习、模式识别、…

蓝桥杯STM32G431RBT6学习——USART

蓝桥杯STM32G431RBT6学习——USART 前言 串口在蓝桥杯近几届中考频也相对较高&#xff08;十三、十二届均考&#xff09;&#xff0c;因此必然也要学习一下。 作为后来之秀的开源项目DAP Link不仅支持SWD调试下载&#xff0c;同时还支持串口调试功能&#xff0c;国信长天开…

软件课设(Ⅲ)——padavan-ng编译以及内核模块修改

我记得今年的很多笔试面试都遇到了linux相关的操作&#xff0c;答题状况都挺……昂。算是补课吧&#xff0c;正好大四的毕业实习、软3还有研0的项目都需要linux的环境进行推进&#xff0c;记录一下&#xff0c;聊作纪念。 实验要求 编译系统&#xff0c;下载并提交&#xff0c;…

大数据技术之Hadoop(Yarn)

第1章 Yarn资源调度器 我们先来思考下面几个问题&#xff1a; 1&#xff09;如何管理集群资源&#xff1f; 2&#xff09;如何给任务合理分配资源&#xff1f; Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统平…

图形编辑器:修改图形 x、y、width、height、rotation

大家好&#xff0c;我是前端西瓜哥。图形编辑器的一个需求&#xff0c;就是可以通过属性面板的输入框设置选中元素的属性值。 项目地址&#xff0c;欢迎 star&#xff1a; https://github.com/F-star/suika 线上体验&#xff1a; https://blog.fstars.wang/app/suika/ 最终效果…

Express框架连接MongoDB数据库操作

在上一篇中已经在Node.js中引入使用了mongoose进行MongoDB数据库的基本操作&#xff0c;在本篇当中在Express框架中来连接数据库以及操作数据库&#xff1b; Express 项目环境 这里是通过全局安装Express框架生产的项目环境&#xff0c;也可以通过局部安装的方式&#xff0c;安…

【MySQL】第十一部分 SELECT的执行过程

【MySQL】第十一部分 SELECT的执行过程 文章目录【MySQL】第十一部分 SELECT的执行过程11. SELECT的执行过程11.1 SQL92语法的结构11.2 SQL92语法的结构11.3 语句执行顺序11.4 解释之前遗留问题总结11. SELECT的执行过程 11.1 SQL92语法的结构 SELECT ... FROM TABLE WHERE 多…

STM32G431—ADC+E2PROM读写实验

目录 1.ADC介绍 配置cubemx 代码 2.IIC 通信 原理图 AT24C02 代码 i2C.c 主函数 1.ADC介绍 ADC 有多达 18 个转换通道&#xff0c;其中通道 0~通道 15 是外部通道&#xff0c;使用的 GPIO 引脚如表 所示。 ADC引脚GPIO引脚GPIO配置ADC引脚GPIO引脚GPIO配置IN0PA0模拟输…

Aspose.PDF for .NET提取矢量图像的支持

Aspose.PDF for .NET提取矢量图像的支持 增加了对提取矢量图像的支持。 改进了PDF到Microsoft Excel的转换。 添加了对创建“PrinterMark”批注的支持。 增加了检测PDF文件是否包含矢量图形的功能。 Aspose.PDF for.NET是一个高级PDF处理和解析API&#xff0c;用于在跨平台应用…

Linux常用命令——setsid命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) setsid 在新的会话中运行程序。 补充说明 setsid命令子进程从父进程继承了&#xff1a;SessionID、进程组ID和打开的终端。子进程如果要脱离这些&#xff0c;代码中可通过调用setsid来实现。&#xff0c;而命令…

C#中的基本概念(类_对象_属性_方法)

C#中的基本概念(类_对象_属性_方法) 对象的概念: 任何存在的实体都是对象,对象是真实存在的, 它包括“静态特征”和“动态特征” 对象包含2个方面: 静态特征:表示对象的属性,用来存储对象本身的数据 动态特征(行为):表示对象的方法,用来说明对象能做什么 例如: 一…

云服务器部署Node.js前后端分离项目

云服务器部署Node.js 前后端分离项目 准备工作 1.拥有一台服务器 自行选择阿里云&#xff0c;腾讯云… 2.重装系统 以腾讯云为例&#xff0c;安装centos 7.6系统 重置一下密码 3.使用远程管理工具 以宝塔工具为例,添加连接 4.安装宝塔面板 宝塔面板 - 简单好用的Linux…

基于ImageAI的图像识别

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

每日学术速递1.25

CV - 计算机视觉 今天带来的是北航IRIP实验室被国际计算机视觉与模式识别会议CVPR 2022接收的6篇论文。 CVPR是由IEEE主办的计算机视觉、模式识别及人工智能等领域最具影响力和最重要的国际顶级会议。CVPR官网显示&#xff0c;此次会议有超过8161篇的大会论文投稿&#xff0c;…

测试篇(三):测试用例的万能公式、对水杯和登录页面设计测试用例、测试用例的设计方法

目录一、测试用例的万能公式二、对登录页面设计测试用例三、测试用例的设计方法3.1 基于需求的设计方法3.2 等价类3.3 边界值3.4 判定表3.5 正交排列3.6 场景设计法3.7 错误猜测法四、面试真题一、测试用例的万能公式 首先&#xff0c;为"水杯"设计一个测试用例&…

计算机网络基础(二)

文章目录1. 应用层1.1 定制应用层协议1.2 网络版计算器实现1.3 应用层细分1.4 HTTP协议1.4.1 认识网址(URL)1.4.2 HTTP协议简易了解1.4.3 简易版HTTP服务器1.4.4 HTTP请求报文详解1.4.5 响应报文1.4.6 HTTP的一些安全问题1.5 HTTPS协议1.5.1 HTTPS和SSL/TLS1.5.2 短链接和长链接…