news 2026/5/1 6:55:43

强化学习蒙特卡洛策略迭代方法求最优策略的代码实现(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
强化学习蒙特卡洛策略迭代方法求最优策略的代码实现(一)

基本思想:

MC_basic.py

注意:由于使用贪心策略,因此不支持stochastic策略。

from collections import defaultdict import numpy as np from env import GridWorldEnv from utils import drow_policy class MonteCarloPolicyIteration(object): def __init__(self, env: GridWorldEnv, gamma=0.9, samples=1): self.env = env self.action_space_size = self.env.num_actions # 上下左右原地 self.reward_space_size = self.env.reward_space_size # 执行每个动作的reward self.state_space_size = self.env.num_states self.reward_list = self.env.reward_list self.gamma = gamma self.samples=samples self.policy = np.zeros((self.state_space_size, self.action_space_size)) self.policy[:,0]=1.0 # 初始动作都是向上 self.action_value = np.zeros((self.state_space_size, self.action_space_size, self.samples)) # action value q(s,a) self.state_value= np.zeros((self.env.size,self.env.size)) def solve(self, iterations=20): for i in range(iterations): for s in range(self.state_space_size): for a in range(self.action_space_size): for k in range(self.samples): # 从(s,a)出发,遵循策略policy采样若干个episodes,并获得return的平均值 episodes = self.generate_episodes(s, a) returns = self.compute_returns(episodes) self.action_value[s,a,k]=returns qvalues = self.action_value.mean(axis=2) # k次采样的平均值 shape: [state_size, 5] best_a = np.argmax(qvalues, axis=1) # 每个state使得平均return最大的action index shape: [state_size] for s in range(self.state_space_size): if s in self.env.terminal: self.policy[s] = np.eye(self.action_space_size)[4] continue else: a_star = best_a[s] # 当前状态 s 的最优动作 index self.policy[s] = np.eye(self.action_space_size)[a_star] self.state_value = np.sum(self.policy * qvalues, axis=1).reshape(self.env.size,self.env.size) def generate_episodes(self, start_state, start_action, max_steps=200): ''' :param start_state: 当前状态的state_id :param start_action: 当前动作 :return: [(state_id, action,reward),(...)] ''' episode = [] state = start_state action = start_action for _ in range(max_steps): next_state, reward, done = self.env.step(state, action) episode.append((state, action, reward)) if done: break state = next_state action = np.random.choice(self.action_space_size, p=self.policy[state]) # 从[0,action_space_size)随机选一个,每个action的概率为policy[state] return episode def compute_returns(self, episodes): ''' :param episodes: 一条轨迹 [(state_id, action,reward),(...)] :return: 一条轨迹的累计return ''' G = 0 for (_, _, r) in reversed(episodes): G = r + self.gamma * G # 最后一步->第一步 return G if __name__ == '__main__': # transition_prob = { # "forward": 0.8, # "left": 0.05, # "right": 0.15 # } env = GridWorldEnv( size=5, forbidden=[(1, 2),(2,4)], terminal=[(4, 4)], r_boundary=-10, r_other=0, r_terminal=1, r_forbidden=-1 ) vi = MonteCarloPolicyIteration(env=env, gamma=0.9) vi.solve(iterations=20) print("\n state value: ") print(vi.state_value) print("\n 策略 π(s):") print(vi.policy) drow_policy(vi.policy, env)

env.py修改地方:

1. self.terminal和self.forbidden存储termina和forbiddenl对应的state_id,而不是传入的list。修改后要修改其他是用到self.terminal和self.forbidden的地方。

self.terminal = {self.state_id(x, y) for (x, y) in terminal} self.forbidden = {self.state_id(x, y) for (x, y) in forbidden} def build_reward_list(self): reward = set() reward.add(self.r_forbidden) reward.add(self.r_other) reward.add(self.r_terminal) reward.add(self.r_boundary) self.reward_list = sorted(list(reward)) self.reward_space_size = len(self.reward_list)

2. 分别为边界、其他、forbidden、terminal设置reward,而不是使用传入的list列表。

def __init__(self, size: int, terminal, forbidden, r_forbidden=-1, r_other=0, r_terminal=1, r_boundary=-1, transition_prob=None): ... self.r_forbidden = r_forbidden self.r_other = r_other self.r_terminal = r_terminal self.r_boundary = r_boundary ...

3. 新增step方法。

def step(self, state, action): ''' :param action: 当前所在的state_id :param action: 当前采取的动作 :return: state,reward,done 到达的下一个状态的state_id,获取的奖励,是否走到了终点 ''' if state in self.terminal: return state, self.r_terminal, True i, j = divmod(state, self.size) moves = { 0: (-1, 0), # 上 1: (0, 1), # 右 2: (1, 0), # 下 3: (0, -1), # 左 4: (0, 0) # 原地 } di, dj = moves[action] ni, nj = i + di, j + dj if not (0 <= ni < self.size and 0 <= nj < self.size): next_state = self.state_id(i,j) else: next_state = self.state_id(ni,nj) reward = self.reward_func(state, next_state, action) done = next_state in self.terminal return next_state, reward, done

相同配置下,policy iteration, value iteration与MC PI运行结果:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 12:52:07

ComfyUI-Florence2模型加载问题终极解决方案

ComfyUI-Florence2模型加载问题终极解决方案 【免费下载链接】ComfyUI-Florence2 Inference Microsoft Florence2 VLM 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Florence2 在使用ComfyUI-Florence2项目时&#xff0c;许多用户都会遇到一个令人头疼的问题&a…

作者头像 李华
网站建设 2026/5/1 5:56:58

Nginx反向代理

1、后端环境搭建---前后端联调前端发送的请求地址&#xff0c;例如&#xff1a;http://localhost/api/employee/login后端接收的接口地址&#xff0c;例如&#xff1a;http://localhost:8080/api/employee/login前端请求地址与后端接口地址并不匹配&#xff0c;这时候需要采取N…

作者头像 李华
网站建设 2026/4/30 14:18:52

PAT 1162 Postfix Expression

这一题的大意是让我们输出后缀表达式&#xff0c;那么很明显直接按照左右根的顺序输出即可&#xff0c;可是需要注意的是当左孩子不存在&#xff0c;右孩子存在的这一种情况&#xff0c;需要先输出根&#xff0c;再输出右孩子&#xff0c;而不是原来的左右根的顺序。 完整的代码…

作者头像 李华
网站建设 2026/5/1 5:57:44

详细分析 Vue2 中的 a-form-item基本知识(附Demo)

目录前言1. 基本知识2. Demo3. 实战前言 Java基本知识&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;【Java项目】实战CRUD的功能整理&#xff08;持续更新&#xff09; 奔着从实战中出发剖析基本知识 1. 基本知识 a-…

作者头像 李华
网站建设 2026/5/1 5:58:55

用Lambda表达式高效处理Python列表

文章目录1. 实战目标2. 核心知识点2.1 Lambda表达式2.1.1 概念2.1.2 语法2.1.3 示例2.2 map() 函数2.2.1 概念2.2.2 语法2.2.3 示例2.3 组合使用&#xff1a;map lambda3. 实战演示3.1 数值处理 —— 每个数翻倍3.2 字符串清洗 —— 去除空格并转小写3.3 多列表操作 —— 对应…

作者头像 李华