RL - 强化学习 蒙特卡洛 (Monte-Carlo) 方法计算状态价值

2023-10-09 19:40

本文主要是介绍RL - 强化学习 蒙特卡洛 (Monte-Carlo) 方法计算状态价值,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎关注我的CSDN:https://spike.blog.csdn.net/
本文地址:https://blog.csdn.net/caroline_wendy/article/details/131102145

MC

在强化学习中,状态价值 (State Value) 是指在特定状态下,智能体能够从该状态开始执行一系列动作,并且按照某个策略进行决策,所能获得的期望累积回报。状态价值函数用于衡量状态的好坏程度,指导智能体在不同状态下,选择最优的行动。

蒙特卡洛方法是一种基于随机采样和统计的强化学习方法,用于估计值函数或优化策略,得名于摩纳哥的蒙特卡洛赌场,因为这种方法使用了大量的随机模拟。在蒙特卡洛方法中,智能体通过与环境的交互来学习,其基本思想是通过多次采样来估计状态或动作的值函数,并根据估计的值函数进行策略改进。蒙特卡洛方法不需要对环境模型进行假设,只需通过与环境的交互来获得样本。

使用蒙特卡洛方法计算状态价值的具体过程,如下:

  1. 使用策略 π \pi π 采样若干条序列。
  2. 对每一条序列中,每一时间步 t t t 的状态 s s s ,更新计数器 N ( s ) ← N ( s ) + 1 N(s) \leftarrow N(s)+1 N(s)N(s)+1,更新总回报 M ( s ) ← M ( s ) + G t M(s) \leftarrow M(s)+G_{t} M(s)M(s)+Gt
  3. 每一个状态的价值被估计为回报的平均值, V ( s ) = M ( s ) N ( s ) V(s)=\frac{M(s)}{N(s)} V(s)=N(s)M(s)

也可以使用增量更新,即
G ← r + γ ∗ G V ( s ) ← V ( s ) + 1 N ( s ) ( G − V ( s ) ) G \leftarrow r + \gamma*G \\ V(s) \leftarrow V(s) +\frac{1}{N(s)}(G-V(s)) Gr+γGV(s)V(s)+N(s)1(GV(s))
序列的单个步骤是(s,a,r,s_next),即从状态s中,(随机)选择a(s,a)的奖励是r,(随机)跳转至s_next

蒙特卡洛方法的采样源码:

# 把输入的两个字符串通过“-”连接,便于使用上述定义的P、R变量
def join(str1, str2):return str1 + '-' + str2def sample(MDP, Pi, timestep_max, number):"""采样函数:param MDP: MDP的元组:param Pi: 策略:param timestep_max: 最长时间步:param number: 采样的序列数:return: 全部采样"""S, A, P, R, gamma = MDPepisodes = []for _ in range(number):episode = []timestep = 0s = S[np.random.randint(4)]  # 随机选择一个除s5以外的状态s作为起点# 当前状态为终止状态或者时间步太长时,一次采样结束while s != "s5" and timestep <= timestep_max:timestep += 1rand, temp = np.random.rand(), 0# 在状态s下根据策略选择动作for a_opt in A:temp += Pi.get(join(s, a_opt), 0)   # 概率逐渐累加至1if temp > rand:  # 最终一定会选择某个动作 a_opta = a_optr = R.get(join(s, a), 0)breakrand, temp = np.random.rand(), 0# 根据状态转移概率得到下一个状态s_nextfor s_opt in S:temp += P.get(join(join(s, a), s_opt), 0)if temp > rand:  # 概率逐渐累加至1s_next = s_opt  # 最终一定会跳转至下个状态s_optbreakepisode.append((s, a, r, s_next))  # 把(s,a,r,s_next)元组放入序列中s = s_next  # s_next变成当前状态,开始接下来的循环episodes.append(episode)return episodes

计算状态价值的源码:

# 对所有采样序列计算所有状态的价值,不断更新V[s]
def MC(episodes, V, N, gamma):for episode in episodes:G = 0for i in range(len(episode) - 1, -1, -1):  #一个序列从后往前计算(s, a, r, s_next) = episode[i]G = r + gamma * GN[s] = N[s] + 1V[s] = V[s] + (G - V[s]) / N[s]

测试输出:

def main():np.random.seed(0)S = ["s1", "s2", "s3", "s4", "s5"]  # 状态集合A = ["保持s1", "前往s1", "前往s2", "前往s3", "前往s4", "前往s5", "概率前往"]  # 动作集合# 状态转移函数P = {"s1-保持s1-s1": 1.0,"s1-前往s2-s2": 1.0,"s2-前往s1-s1": 1.0,"s2-前往s3-s3": 1.0,"s3-前往s4-s4": 1.0,"s3-前往s5-s5": 1.0,"s4-前往s5-s5": 1.0,"s4-概率前往-s2": 0.2,"s4-概率前往-s3": 0.4,"s4-概率前往-s4": 0.4,}# 奖励函数R = {"s1-保持s1": -1,"s1-前往s2": 0,"s2-前往s1": -1,"s2-前往s3": -2,"s3-前往s4": -2,"s3-前往s5": 0,"s4-前往s5": 10,"s4-概率前往": 1,}gamma = 0.5  # 折扣因子MDP = (S, A, P, R, gamma)# 策略1,随机策略Pi_1 = {"s1-保持s1": 0.5,"s1-前往s2": 0.5,"s2-前往s1": 0.5,"s2-前往s3": 0.5,"s3-前往s4": 0.5,"s3-前往s5": 0.5,"s4-前往s5": 0.5,"s4-概率前往": 0.5,}# 采样5次,每个序列最长不超过20步episodes = sample(MDP, Pi_1, 20, 5)print('第一条序列\n', episodes[0])print('第二条序列\n', episodes[1])print('第五条序列\n', episodes[4])timestep_max = 20# 采样1000次,可以自行修改episodes = sample(MDP, Pi_1, timestep_max, 1000)gamma = 0.5V = {"s1": 0, "s2": 0, "s3": 0, "s4": 0, "s5": 0}N = {"s1": 0, "s2": 0, "s3": 0, "s4": 0, "s5": 0}MC(episodes, V, N, gamma)print("使用蒙特卡洛方法计算MDP的状态价值为\n", V)if __name__ == '__main__':main()

输出结果:

# 使用蒙特卡洛方法计算MDP的状态价值{'s1': -1.228923788722258, 's2': -1.6955696284402704, 's3': 0.4823809701532294, 's4': 5.967514743019431, 's5': 0}# 通过MRP计算的状态价值[[-1.22555411] [-1.67666232] [ 0.51890482] [ 6.0756193 ] [ 0.        ]]

状态价值,可以用于计算状态动作价值,具有指导意义。

这篇关于RL - 强化学习 蒙特卡洛 (Monte-Carlo) 方法计算状态价值的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/175120

相关文章

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

Spring 基于XML配置 bean管理 Bean-IOC的方法

《Spring基于XML配置bean管理Bean-IOC的方法》:本文主要介绍Spring基于XML配置bean管理Bean-IOC的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录一. spring学习的核心内容二. 基于 XML 配置 bean1. 通过类型来获取 bean2. 通过

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a