使用强化学习破解迷宫实战

大家好,本文将实现一种强化学习算法来解决迷宫问题,并完成以下步骤:创建迷宫环境、定义迷宫类,以及使用值迭代算法(Value Iteration algorithm)找到穿越迷宫的最优策略。为了使这一过程可视化,使用PyGame来模拟迷宫求解过程,从而使学习过程更加有趣和愉悦。

设置项目

在开始之前,通过创建虚拟环境和安装所需的依赖项来设置项目。

# 创建虚拟环境
python -m venv venv# 在 Windows 上激活虚拟环境
venv\Scripts\activate.bat# 在 macOS 上激活虚拟环境
source venv/bin/activate# 安装依赖项
pip install -r requirements.txt

创建迷宫类

将首先定义迷宫类,它将代表迷宫环境。该类将包括与迷宫创建和强化学习相关的属性和方法。

import numpy as np
import random
from typing import Tupleclass Maze:def __init__(self, level, goal_pos: Tuple[int, int], MAZE_HEIGHT=600, MAZE_WIDTH=600, SIZE=25):# 迷宫配置的属性self.goal = goal_posself.number_of_tiles = SIZEself.tile_size = MAZE_HEIGHT // self.number_of_tilesself.walls = self.create_walls(level)self.goal_pos = goal_posself.state = self.get_init_state(level)self.maze = self.create_maze(level)# 强化学习的属性self.state_values = np.zeros((self.number_of_tiles, self.number_of_tiles))self.policy_probs = np.full((self.number_of_tiles, self.number_of_tiles, 4), 0.25)

创建迷宫

接下来,介绍实现创建迷宫和定义初始状态的方法。

def create_maze(self, level):maze = []walls = []for row in range(len(level)):for col in range(len(level[row])):if level[row][col] == " ":maze.append((row, col))elif level[row][col] == "X":walls.append((row, col))return maze, wallsdef get_init_state(self, level):for row in range(len(level)):for col in range(len(level[row])):if level[row][col] == "P":return (row, col)

进行步骤和计算奖励

现在,定义计算奖励、模拟步骤和获取下一个状态的方法。

def compute_reward(self, state: Tuple[int, int], action: int):next_state = self._get_next_state(state, action)return -float(state != self.goal_pos)def step(self, action):next_state = self._get_next_state(self.state, action)reward = self.compute_reward(self.state, action)done = next_state == self.goalreturn next_state, reward, donedef simulate_step(self, state, action):next_state = self._get_next_state(state, action)reward = self.compute_reward(state, action)done = next_state == self.goalreturn next_state, reward, donedef _get_next_state(self, state: Tuple[int, int], action: int):if action == 0:next_state = (state[0], state[1] - 1)elif action == 1:next_state = (state[0] - 1, state[1])elif action == 2:next_state = (state[0], state[1] + 1)elif action == 3:next_state = (state[0] + 1, state[1])else:raise ValueError("Action value not supported:", action)if (next_state[0], next_state[1]) not in self.walls:return next_statereturn state

解迷宫

最后,使用值迭代算法来解决迷宫问题并找到最优策略。

def solve(self, gamma=0.99, theta=1e-6):delta = float("inf")while delta > theta:delta = 0for row in range(self.number_of_tiles):for col in range(self.number_of_tiles):if (row, col) not in self.walls:old_value = self.state_values[row, col]q_max = float("-inf")for action in range(4):next_state, reward, done = self.simulate_step((row, col), action)value = reward + gamma * self.state_values[next_state]if value > q_max:q_max = valueaction_probs = np.zeros(shape=(4))action_probs[action] = 1self.state_values[row, col] = q_maxself.policy_probs[row, col] = action_probsdelta = max(delta, abs(old_value - self.state_values[row, col]))

solve方法是强化学习算法的核心,用于找到穿越迷宫的最佳策略。它采用了值迭代技术,这是一种迭代算法,可以逐步更新每个状态的估计值,直到它们收敛到最佳值。

1. 初始化:

  • gamma:未来奖励的折扣系数(默认值:0.99)。该系数决定了即时奖励相对于未来奖励的重要性。gamma值越高,代理程序就越重视长期奖励,而gamma值越低,代理程序就越重视即时奖励。

  • theta:收敛阈值(默认值:1e-6)。该参数定义了被视为收敛状态值的最小变化量。一旦状态值的变化低于这个阈值,算法就会停止迭代。

  • delta:初始化为无穷大的变量,用于测量迭代过程中状态值的变化量。

2. 迭代值更新:

  • 该方法使用一个while循环,一直持续到状态值的变化量(delta)小于指定的收敛阈值(theta)为止。

  • 在循环中,每次迭代前都会将delta变量重置为0,以跟踪所有状态下状态值的最大变化量。

3. 值迭代:

  • 对于迷宫中的每个单元(不包括墙壁),算法会计算所有可能行动(上、下、左、右)的Q值(q_max)。

  • Q值表示代理程序在给定状态下采取特定行动并在此后遵循最优策略时所能获得的预期累积奖励。

  • Q值是根据simulate_step方法得到的即时奖励和下一个状态值的折现值(gamma * self.state_values[next_state])确定的。

  • 选择具有最大Q值(q_max)的行动作为当前状态下采取的最佳行动。

  • 为了更新策略,相应的策略概率(action_probs)会被更新,以反映该行动被选中的概率最高。所有其他行动的概率都设置为0

4. 更新状态值和策略概率:

  • 在计算给定状态的所有行动的Q值后,将该状态的状态值(self.state_values[row, col])更新为所有动作中的最大Q值(q_max)。

  • 将该状态的策略概率(self.policy_probs[row, col])更新为具有最大Q值的动作的高概率(1.0),并将所有其他动作的概率设置为0

  • 此过程对迷宫中的所有状态进行迭代,不断更新状态值和策略概率,直到满足收敛阈值为止。

5. 收敛检查:

  • 在更新迷宫中所有状态的状态值和策略概率后,该方法会检查此迭代过程中状态值的最大变化量(delta)是否小于收敛阈值(theta)。

  • 如果满足条件,循环终止,迷宫求解过程被认为已收敛。此时,self.state_values数组包含了每个状态的最优值,self.policy_probs数组反映了在迷宫中导航的最优策略。

通过使用值迭代(Value Iteration)算法,代理程序可以学习最优的迷宫导航策略,最大化预期的累积奖励,同时避开墙壁并高效地到达目标状态。最终的策略概率会指导代理程序的行动,从而实现智能和高效的迷宫解决策略。

使用PyGame模拟

在本节中,将使用PyGame可视化机器人在迷宫中的导航,将建造墙壁、放置宝藏,并控制玩家的移动,以观察它是如何通过实际操作解决迷宫问题的。

首先,创建一个名为main.py的新Python脚本,并添加以下代码:

import pygame
import numpy as np
from maze import Maze
import threading# 常量
GAME_HEIGHT = 600
GAME_WIDTH = 600
NUMBER_OF_TILES = 25
SCREEN_HEIGHT = 700
SCREEN_WIDTH = 700
TILE_SIZE = GAME_HEIGHT // NUMBER_OF_TILES# 迷宫布局
level = ["XXXXXXXXXXXXXXXXXXXXXXXXX","X XXXXXXXX          XXXXX","X XXXXXXXX  XXXXXX  XXXXX","X      XXX  XXXXXX  XXXXX","X      XXX  XXX        PX","XXXXXX  XX  XXX        XX","XXXXXX  XX  XXXXXX  XXXXX","XXXXXX  XX  XXXXXX  XXXXX","X  XXX      XXXXXXXXXXXXX","X  XXX  XXXXXXXXXXXXXXXXX","X         XXXXXXXXXXXXXXX","X             XXXXXXXXXXX","XXXXXXXXXXX      XXXXX  X","XXXXXXXXXXXXXXX  XXXXX  X","XXX  XXXXXXXXXX         X","XXX                     X","XXX         XXXXXXXXXXXXX","XXXXXXXXXX  XXXXXXXXXXXXX","XXXXXXXXXX              X","XX   XXXXX              X","XX   XXXXXXXXXXXXX  XXXXX","XX    XXXXXXXXXXXX  XXXXX","XX        XXXX          X","XXXX                    X","XXXXXXXXXXXXXXXXXXXXXXXXX",
]# 创建迷宫环境
env = Maze(level,goal_pos=(23, 20),MAZE_HEIGHT=GAME_HEIGHT,MAZE_WIDTH=GAME_WIDTH,SIZE=NUMBER_OF_TILES,
)
env.reset()
env.solve()# 初始化Pygame
pygame.init()# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_HEIGHT, SCREEN_WIDTH))
pygame.display.set_caption("Maze Solver")# 创建绘制迷宫的表面
surface = pygame.Surface((GAME_HEIGHT, GAME_WIDTH))# 设置帧率
clock = pygame.time.Clock()# 游戏循环的运行标志
running = True# 获取初始玩家和目标位置
treasure_pos = env.goal_pos
player_pos = env.statedef reset_goal():# 检查玩家是否到达目标位置,然后重置目标位置if env.state == env.goal_pos:env.reset()env.solve()# 游戏循环
while running:# 启动一个新线程来检查和重置目标位置x = threading.Thread(target=reset_goal)x.daemon = Truex.start()for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 清空表面surface.fill((27, 64, 121))# 绘制迷宫中的墙壁for row in range(len(level)):for col in range(len(level[row])):if level[row][col] == "X":pygame.draw.rect(surface,(241, 162, 8),(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE),)# 绘制玩家的位置pygame.draw.rect(surface,(255, 51, 102),pygame.Rect(player_pos[1] * TILE_SIZE,player_pos[0] * TILE_SIZE,TILE_SIZE,TILE_SIZE,).inflate(-TILE_SIZE / 3, -TILE_SIZE / 3),border_radius=3,)# 绘制目标位置pygame.draw.rect(surface,"green",pygame.Rect(env.goal_pos[1] * TILE_SIZE,env.goal_pos[0] * TILE_SIZE,TILE_SIZE,TILE_SIZE,).inflate(-TILE_SIZE / 3, -TILE_SIZE / 3),border_radius=TILE_SIZE,)# 更新屏幕screen.blit(surface, ((SCREEN_HEIGHT - GAME_HEIGHT) / 2

代码解释

导入库并创建常量:

  • 代码导入了所需的库,包括Pygame、NumPy和自定义Maze类。

  • 还定义了一些常量来设置迷宫环境、屏幕尺寸和磁贴大小。

创建迷宫环境:

  • 迷宫布局使用名为level的字符串列表定义。

  • 创建一个Maze类实例,并将level和目标位置作为参数传递。

  • 然后使用env对象重置迷宫,并使用solve方法找到最佳策略。

初始化PyGame

游戏主循环:

  • 程序进入一个循环,一直运行到running变量变为“False”为止。

  • reset_goal函数会在一个单独的线程中调用,以检查玩家是否已达到目标,并在必要时重置目标。

绘制迷宫:

  • 在屏幕上绘制迷宫时,会遍历level列表,并根据墙上的字符("X")绘制地砖。

  • 玩家的位置被绘制成一个填充特定颜色(红色)的矩形,并位于迷宫单元的中心。

  • 目标位置则绘制为带圆角的绿色矩形。

更新游戏状态和玩家移动:

  • 根据玩家所在位置的当前策略(env.policy_probs)确定玩家的行动。使用np.argmax选择概率最高的行动。

  • 根据选择的行动,如果是有效的移动(不撞墙),就会更新玩家的位置。

  • 玩家在env对象中的位置也会更新。

退出游戏:

  • running变量变为“False”时,游戏循环退出,通常是由用户关闭游戏窗口触发。

  • Pygame会通过pygame.quit()关闭。

  • 现在只需运行main.py即可看到代码的运行。

综上,现在已经成功地使用强化学习实现了值迭代算法来解决迷宫问题,还使用PyGame将迷宫求解过程可视化,使其更具互动性和趣味性。大家可以随意尝试不同的迷宫配置、学习率和折扣系数,观察它们对学习过程的影响。

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模板方法模式——定义算法的框架

1、简介 1.1、概述 模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中。在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法…

RabbitMQ 教程 | 第11章 RabbitMQ 扩展

👨🏻‍💻 热爱摄影的程序员 👨🏻‍🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻‍🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…

webpack基础知识一:说说你对webpack的理解?解决了什么问题?

一、背景 Webpack 最初的目标是实现前端项目的模块化,旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候,我们会通过文件划分的形式实现模块化,也就是将每个功能及其相关状态数据各自单独放到不同的JS 文件中 约定每个文件是一…

Java thymeleaf bug排查记录

刚学Java 做项目时报了一个错误 一时间看的莫名其妙 EL1008E: Property or field createTime cannot be found on object of type java.util.HashMap - maybe not public or not valid? 随即向上排查至第一个报错,发现是thymeleaf渲染时报错。 Exception proces…

leetcode 1290.二进制链表转整数

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;二进制链表转整数 ps&#xff1a; 1 0 1 (0 << 1) 1 0 1 1 (1 << 1) 0 2 0 2 (2 << 1) 1 4 1 5代码&#xff1a; int getDecimalValue(struct ListNode* head) {int ans 0;while(head !…

【数据结构】常见的排序算法

常见的排序算法 常见的排序算法插入排序之直接插入排序时间复杂度特性总结 插入排序之希尔排序时间复杂度 选择排序之直接选择排序特性总结 选择排序之堆排序时间复杂度特性总结 交换排序之冒泡排序特性总结 交换排序之快速排序hoare版本挖坑法双指针法快速排序的优化1&#xf…

PyCharm安装使用2023年教程,PyCharm与现流行所有编辑器对比。

与PyCharm类似的功能和特性的集成开发环境&#xff08;IDE&#xff09;和代码编辑器有以下几种&#xff1a; Visual Studio Code&#xff08;VS Code&#xff09;&#xff1a;由Microsoft开发&#xff0c;VS Code是一个高度可定制和可扩展的代码编辑器。它支持多种编程语言&am…

微信小程序nodejs+vue+uniapp高校食堂线上预约点餐系统

本次设计任务是要设计一个食堂线上预约点餐系统&#xff0c;通过这个系统能够满足管理员及学生的食堂线上预约点餐分享功能。系统的主要包括首页、个人中心、学生管理、菜品分类管理、菜品管理、关于我们管理、意见反馈、系统管理、订单管理等功能。 开发语言 node.js 框架&am…

使用ubuntu-base制作根文件系统

1&#xff1a;ubuntu官网下载最小根文件系统&#xff1a; 放置到电脑的ubuntu中&#xff0c; Mkdir Ubuntu_rootfs Cd Ubuntu_rootfs Sudo tar –zxvf Ubuntu-bash-xxxxxx.tar.gz 2&#xff1a;电脑的ubuntu安装qemu搭建arm模拟系统 将/usr/bin/qemu-arm-static/(64位拷贝…

css滚动条样式指南

css滚动条样式指南 滚动条是网页设计中经常被忽视的元素。虽然它看起来像是一个小细节&#xff0c;但它在网站导航中起着至关重要的作用。默认的滚动条可能看起来不合适&#xff0c;有损整体美观。本文将介绍如何使用 CSS 自定义滚动条。 在 Chrome、Edge 和 Safari 中设置滚…

python字符串输入输出与注解

目录 数据输入 前言 数据输出 字符串 字符串的三种定义方法 引号嵌套 字符串的拼接 字符串格式化 拼接字符串缺点 python常用的格式符号 格式化的精度控制 字符串快速格式化 快速格式化特点 对表达式进行格式化 具体案例 字符串的大小比较 字符串比较方式 变…

【数据结构和算法】排序算法

说明&#xff1a;以下排序如无特别说明&#xff0c;都是从小到大升序排序 1. 冒泡排序 核心思想&#xff1a;每个元素与其相邻元素比较&#xff0c;如果前者大于后者则交换&#xff0c;每次循环结束后会将最大值放到最后&#xff0c;像小水泡从底下冒到上面成大水泡一样&…

day52-Redis

Redis 1.Redis 1.1 RESP连接Redis 1.2 定义&#xff1a;是一个高性能的key-value数据库&#xff08;非关系型数据库&#xff09; 1.3 数据类型&#xff1a; key键的类型是字符串类型&#xff1b; 值的类型有五种&#xff1a;字符串String&#xff0c;哈希hash&#xff0…

Ubuntu安装JDK与IntelliJ IDEA

目录 前言 Ubuntu 安装 JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Ubuntu安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 APT&#xff08;Advanced Package Tool&…

使用手机相机检测电脑屏幕刷新率Hz

使用手机相机检测电脑屏幕刷新率Hz 1、电脑打开https://www.testufo.com/frameskipping 2、相机专业模式&#xff1a;快门1/10、ISO自动&#xff0c;拍摄一张照片。120Hz至少要有12个亮块&#xff0c;50Hz至少有6个亮块。 更改刷新速率 1、选择 “开始>设置>系统>显示…

Linux操作系统~Linux基础知识相关题

整卷阅览&#xff1a; 想要获取试卷原版请点击以下链接下载&#xff1a; https://download.csdn.net/download/qq_53142796/88168132https://download.csdn.net/download/qq_53142796/88168132 解题过程&#xff1a; 选择题&#xff08;每小题2分&#xff0c;共30分&#xff…

心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

文章目录 前言介绍系统框架原项目地址本项目开发开源地址硬件PCB软件功能 详细内容硬件外壳制作WS2812级联及控制MAX30102血氧传感器0.96OLEDFreeRTOS 效果视频总结 前言 在好几年前&#xff0c;我好像就看到了焊武帝 jiripraus在纪念结婚五周年时&#xff0c;制作的一个心跳跟…

Xcode protobuf2.5添加arm64编译器补丁生成静态库

项目需求&#xff0c;protobuf源码编成静态库使用 但是&#xff0c;github上的protobuf源码没有对应arm64的编译器定义&#xff0c;编译出来的静态库使用时报错。 下面的连接是arm64编译器代码补丁包&#xff0c;把编译器代码放到src/google/protobuf/stubs/atomicops_intern…

第一课-前提-Stable Diffusion 教程

学习 SD 的前提是电脑配置! SD 参考配置: 建议选择台式机 i5 CPU, 内存16GB,N卡 RTX3060, 8G显存以上的配置(最低配) 在此基础上的配置越高越好。 比如,cpu i7 更好,显卡能有 RTX4090 更好,32显存要能有最好,嘿嘿嘿。 如何查看自己的显卡配置? Win+R 输入 “dxdiag…

变压器参数测定中空载实验和短路实验的理解

确定变压器的参数是在《电机学》和《电力系统分析》中非常重要的一个环节&#xff0c;这里用自己习惯的方式讲一下怎样理解 首先要讲下变压器的额定参数&#xff0c;这个也是个常考的知识点 额定功率&#xff0c;即视在功率&#xff0c;电压电流&#xff0c;单位是VA或者kVA额…