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

news2024/11/16 15:42:23

大家好,本文将实现一种强化学习算法来解决迷宫问题,并完成以下步骤:创建迷宫环境、定义迷宫类,以及使用值迭代算法(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 Tuple

class Maze:
    def __init__(self, level, goal_pos: Tuple[int, int], MAZE_HEIGHT=600, MAZE_WIDTH=600, SIZE=25):
        # 迷宫配置的属性
        self.goal = goal_pos
        self.number_of_tiles = SIZE
        self.tile_size = MAZE_HEIGHT // self.number_of_tiles
        self.walls = self.create_walls(level)
        self.goal_pos = goal_pos
        self.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, walls

def 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.goal
    return next_state, reward, done

def simulate_step(self, state, action):
    next_state = self._get_next_state(state, action)
    reward = self.compute_reward(state, action)
    done = next_state == self.goal
    return next_state, reward, done

def _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_state
    return state

解迷宫

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

def solve(self, gamma=0.99, theta=1e-6):
    delta = float("inf")
 
    while delta > theta:
        delta = 0
        for 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 = value
                            action_probs = np.zeros(shape=(4))
                            action_probs[action] = 1

                    self.state_values[row, col] = q_max
                    self.policy_probs[row, col] = action_probs

                    delta = 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.state


def reset_goal():
    # 检查玩家是否到达目标位置,然后重置目标位置
    if env.state == env.goal_pos:
        env.reset()
        env.solve()


# 游戏循环
while running:
    # 启动一个新线程来检查和重置目标位置
    x = threading.Thread(target=reset_goal)
    x.daemon = True
    x.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.coloradmin.cn/o/839106.html

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

相关文章

Stable Diffusion系列课程二:ControlNet

AUTOMATIC1111/stable-diffusion-webui参考B站Nenly视频《零基础学会Stable Diffusion》、视频课件推荐网站:stable-diffusion-art、Civitai(魔法) 、libilibi、AI艺术天堂推荐Stable Diffusion整合资料: NovelAI资源整合、《AI绘…

Flowable-网关-并行网关

目录 定义图形标记XML内容使用示例视频教程 定义 并行网关能在一个流程里用来对并发进行建模处理,它能把单条线路拆分成多个路径并行执 行,或者将多个路径合并处理。在一个流程模型里引入并发最直接的网关就是并行网关,它基于进 入和外出顺序…

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测预测效果基本介绍研究内容程序设计参考资料…

Android Studio中使用cmake开发JNI实战

JNI学习大纲 一、JNI编程入门 二、Android Studio中使用cmake开发JNI实战 第一章节我们介绍了JNI的开发步骤,那这一章节我们就开始在Android Studio中实战一下吧,Lets Start。 1. Android Studio中安装CMake插件 AS中菜单栏选择Tools>SDK Manager在…

Servlet是什么和创建、配置第一个servlet

Servlet是什么和创建、配置第一个servlet servlet是什么 2、创建servlet 方式一: 方式二: 方式三:

vscode中无法使用git解决方案

1 首先查看git安装目录 where git 2 找到bash.exe 的路径 比如:C:/Users/Wangzd/AppData/Local/Programs/Git/bin/bash 3 找到vscode的配置项setting.json 4 添加 "terminal.integrated.shell.windowns": "C:/Users/Wangzd/AppData/Local/Pr…

Python如何解决Amazon亚马逊“图文验证码”识别(6)

前言 本文是该专栏的第55篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏前面,笔者有详细介绍多种登录验证码识别方法,感兴趣的同学可往前翻阅。而本文,笔者将单独详细介绍亚马逊Amazon的图文识别验证码的解决方法。 如上图所示,访问或请求频次达到一定程度之…

IPv6地址分类,EUI-64转换规则

1、可聚合的单全球单播地址Global Unique Address: Aggregate global unicast address,前3位是001,即2000::/3,目前IANA已经将一部分可聚合全球单播进行了专门使用,如:2001::/16用于IPV6互联网,…

深挖 Threads App 帖子布局,我进一步加深了对CSS网格布局的理解

当我遇到一个新产品时,我首先想到的是他们如何实现CSS。当我遇到Meta的Threads时也不例外。我很快就探索了移动应用程序,并注意到我可以在网页上预览公共帖子。 这为我提供了一个深入挖掘的机会。我发现了一些有趣的发现,我将在本文中讨论。 …

Docker相关命令与入门

1. Docker 命令 # centos 7 systemctl start docker # 启动服务 systemctl stop docker systemctl restart docker # 重启服务 systemctl status docker systemctl enable docker # 开机自启动1.1 镜像相关的命令 # 查看镜像 docker images docker images -q # 查看…

深度学习:探究Tensor和Numpy

目录 引言 1 pytorch中Tensor 1.1 什么是Tensor 1.2 为什么需要Tensor 1.3 如何创建Tensor 1.3.1 从已有其他数据结构转化创建为Tensor 1.3.2 随机初始化一个Tensor 1.3.3 从已保存文件加载一个Tensor 1.4 Tensor的特性 1.4.1 丰富的常用函数操作 1.4.2 灵活的dtype和…

使用TensorBoard进行可视化

1. TensorBoard介绍 TensorBoard是TensorFlow推出的可视化工具,可以可视化模型结构、跟踪并以表格形式显示模型指标。 TensorBoard的使用包括两个步骤: 在代码中设置TensorBoard,在训练的过程中将会根据设置产生日志文件在浏览器中可视化该…

启动RocketMQ报错

说明:启动RocketMQ消费者时,报以下错误:java.lang.IllegalStateException:Failed to start RocketMQ push consumer. 解决:看下所有的监听器类,检查是不是有相同的消费者组名,注释掉其中一个即可…

文心一言 VS 讯飞星火 VS chatgpt (71)-- 算法导论7.1 1题

参照图 7-1的方法,说明 PARTITION在数组 A(13,19,9,5,12,8,7,4,21,2,6,11)上的操作过程。 文心一言: PARTITION 是一种常…

C++笔记之while循环的帧率监测与控制

C笔记之while循环的帧率监测与控制 code review! 文章目录 C笔记之while循环的帧率监测与控制1.两个时间相关的类2.例程3.运行4.代码 1.两个时间相关的类 2.例程 3.运行 4.代码 // 帧率监测与控制程序 #include <chrono> #include <iostream> #include <thre…

python 连接oracle pandas以简化excel的编写和数据操作

python代码 Author: liukai 2810248865qq.com Date: 2022-08-18 04:28:52 LastEditors: liukai 2810248865qq.com LastEditTime: 2023-07-06 22:12:56 FilePath: \PythonProject02\pandas以简化excel的编写和数据操作.py Description: 这是默认设置,请设置customMade, 打开koro…

Python爬虫的学习day02 requests 模块post 函数, lmxl 模块的 etree 模块

1. requests 模块post 函数 1.1 post 函数的参数 &#xff08;简单版&#xff09; 参数1&#xff1a; url 网络地址 参数2&#xff1a; data 请求数据 &#xff08;一般数据是 账号&#xff0c;密码&#xff09; 参数3&#xff1a; headers 头请求 &#xff08…

概念解析 | 虚拟镜面:超越三次反射的非视线成像

虚拟镜面:超越三次反射的非视线成像 注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:虚拟镜面在非视线成像中的应用。 参考文献:Royo D, Sultan T, Muoz A, et al. Virtual Mirrors: Non-Line-of-Sight Imaging Beyond the Th…

MyBatis关联查询

文章目录 前言多对一关联 association一对多关联 collection 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 关联查询是指在一个查询中同时获取多个表中的数据&#xff0c;将它们结合在一起进行展示。 关联表需要两个及以上的表 数据库代码&#xff1…

初阶C语言——特别详细地介绍函数

系列文章目录 第一章 “C“浒传——初识C语言&#xff08;更适合初学者体质哦&#xff01;&#xff09; 第二章 详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言——特别详细地介绍函数 目录 系列文章目录 前言 一、函数是个什么鬼东西&#xff1f; 二、C语…