用Python走迷宫|Q-Learning|强化学习

简介: 用Q-learning实现走迷宫。

Q-Learning走迷宫

上文中我们了解了Q-Learning算法的思想,基于这种思想我们可以实现很多有趣的功能和小demo,本文让我们通过Q-Learning算法来实现用计算机来走迷宫。

原理简述

我们先从一个比较高端的例子说起,AlphaGo大家都听说过,其实在AlphaGo的训练过程中就使用了Q-Learning的思想,对于机器下错棋和下对棋的时候给予一定的惩罚和奖励,当经过无数次的训练之后,机器自然就会直接向着奖励前进,直接选择对的位置进行下棋,久而久之在各种场景下都能选择对的位置下棋的机器人就能够把人类打败了。

再回到我们今天要讲的例子上来,走迷宫和下棋的原理其实类似,我们要走的路无非就是两种:顺畅的路和有障碍的路,那我们要做的事也就很明了了,当触碰到障碍的时候给予一定的惩罚,走了正确的路时给予一定的奖励,这样经过不断的训练,机器就应该能够知道该如何”走迷宫“了。我们要走的迷宫示意图如下:

在这里插入图片描述

代码实现

构建画布

我们首先要做的就是来构建画布并且画出迷宫,Python中Tkinter就是一个很好的画图工具(相对于其他的库来说,该库运行快,且不容易卡死)

构建画布的时候,我们除了需要构建基本的图形和迷宫,还需要实现行动的方式,对于简单的迷宫来说,我们只需要设定“上下左右”的行动方式就可以了,如果走到了黑块就得到-1的惩罚并结束回合,走到黄块得到1的奖励并结束回合。其余的解释放在代码注释中,画布代码如下:

# coding: utf-8
import sys
import time
import numpy as np
if sys.version_info.major == 2:
    import Tkinter as tk
else:
    import tkinter as tk


class Maze(tk.Tk, object):
    UNIT = 40  # 像素
    MAZE_H = 6  # 网格高度
    MAZE_W = 6  # 网格宽度

    def __init__(self):
        super(Maze, self).__init__()
        self.action_space = ['U', 'D', 'L', 'R']
        self.n_actions = len(self.action_space)
        self.title('迷宫')
        self.geometry('{0}x{1}'.format(self.MAZE_H * self.UNIT,
                                       self.MAZE_W * self.UNIT))
        self._build_maze()

    # 画矩形
    # x y 格坐标
    # color 颜色
    def _draw_rect(self, x, y, color):
        center = self.UNIT / 2
        w = center - 5
        x_ = self.UNIT * x + center
        y_ = self.UNIT * y + center
        return self.canvas.create_rectangle(x_ - w,
                                            y_ - w,
                                            x_ + w,
                                            y_ + w,
                                            fill=color)

    # 初始化迷宫
    def _build_maze(self):
        h = self.MAZE_H * self.UNIT
        w = self.MAZE_W * self.UNIT
        # 初始化画布
        self.canvas = tk.Canvas(self, bg='white', height=h, width=w)
        # 画线
        for c in range(0, w, self.UNIT):
            self.canvas.create_line(c, 0, c, h)
        for r in range(0, h, self.UNIT):
            self.canvas.create_line(0, r, w, r)

        # 陷阱
        self.hells = [
            self._draw_rect(3, 2, 'black'),
            self._draw_rect(3, 3, 'black'),
            self._draw_rect(3, 4, 'black'),
            self._draw_rect(3, 5, 'black'),
            self._draw_rect(4, 5, 'black'),
            self._draw_rect(1, 0, 'black'),
            self._draw_rect(1, 1, 'black'),
            self._draw_rect(1, 2, 'black'),
            self._draw_rect(1, 4, 'black'),
            self._draw_rect(1, 5, 'black')
        ]
        self.hell_coords = []
        for hell in self.hells:
            self.hell_coords.append(self.canvas.coords(hell))

        # 奖励
        self.oval = self._draw_rect(4, 5, 'yellow')
        # 玩家对象
        self.rect = self._draw_rect(0, 0, 'red')

        self.canvas.pack()  #执行画

    # 重新初始化(用于撞到黑块后重新开始)
    def reset(self):
        self.update()
        time.sleep(0.5)
        self.canvas.delete(self.rect)
        self.rect = self._draw_rect(0, 0, 'red')
        self.old_s = None
        #返回 玩家矩形的坐标 [5.0, 5.0, 35.0, 35.0]
        return self.canvas.coords(self.rect)

    # 走下一步
    def step(self, action):
        s = self.canvas.coords(self.rect)
        base_action = np.array([0, 0])
        if action == 0:  # up
            if s[1] > self.UNIT:
                base_action[1] -= self.UNIT
        elif action == 1:  # down
            if s[1] < (self.MAZE_H - 1) * self.UNIT:
                base_action[1] += self.UNIT
        elif action == 2:  # right
            if s[0] < (self.MAZE_W - 1) * self.UNIT:
                base_action[0] += self.UNIT
        elif action == 3:  # left
            if s[0] > self.UNIT:
                base_action[0] -= self.UNIT

        # 根据策略移动红块
        self.canvas.move(self.rect, base_action[0], base_action[1])
        s_ = self.canvas.coords(self.rect)

        # 判断是否得到奖励或惩罚
        done = False
        if s_ == self.canvas.coords(self.oval):
            reward = 1
            done = True
        elif s_ in self.hell_coords:
            reward = -1
            done = True
        #elif base_action.sum() == 0:
        #    reward = -1
        else:
            reward = 0

        self.old_s = s
        return s_, reward, done

    def render(self):
        time.sleep(0.01)
        self.update()

实现算法

实现算法的过程就是按照我们上一文中所说到的Q-Learning的算法运行方式来进行,代码实现如下:

# coding: utf-8
import pandas as pd
import numpy as np


class q_learning_model_maze:
    def __init__(self,
                 actions,
                 learning_rate=0.01,
                 reward_decay=0.9,
                 e_greedy=0.99):
        self.actions = actions
        self.learning_rate = learning_rate
        self.reward_decay = reward_decay
        self.e_greedy = e_greedy
        self.q_table = pd.DataFrame(columns=actions, dtype=np.float32)

    # 检查状态是否存在
    def check_state_exist(self, state):
        if state not in self.q_table.index:
            self.q_table = self.q_table.append(
                pd.Series(
                    [0] * len(self.actions),
                    index=self.q_table.columns,
                    name=state,
                ))

    # 选择动作
    def choose_action(self, s):
        self.check_state_exist(s)
        if np.random.uniform() < self.e_greedy:

            state_action = self.q_table.loc[s, :]
            state_action = state_action.reindex(
                np.random.permutation(
                    state_action.index))  # 防止相同列值时取第一个列,所以打乱列的顺序
            action = state_action.idxmax()
        else:
            action = np.random.choice(self.actions)
        return action

    # 更新q表
    def rl(self, s, a, r, s_):
        self.check_state_exist(s_)
        q_predict = self.q_table.loc[s, a]  # q估计
        if s_ != 'terminal':
            q_target = r + self.reward_decay * self.q_table.loc[
                s_, :].max()  # q现实
        else:
            q_target = r

        self.q_table.loc[s, a] += self.learning_rate * (q_target - q_predict)
        

训练

训练的时候我们需要做的就是选择状态并执行,最后把执行的结果更新到状态表中。

# coding: utf-8

def update():
    for episode in range(100):
        s = env.reset()
        while True:
            env.render()

            # 选择一个动作
            action = RL.choose_action(str(s))

            # 执行这个动作得到反馈(下一个状态s 奖励r 是否结束done)
            s_, r, done = env.step(action)

            # 更新状态表
            RL.rl(str(s), action, r, str(s_))

            s = s_

            if done:
                print(episode)
                break


if __name__ == "__main__":
    env = Maze()
    RL = q_learning_model_maze(actions=list(range(env.n_actions)))
    env.after(10, update)  # 设置10ms的延迟
    env.mainloop()
相关文章
|
5月前
|
机器学习/深度学习 算法 机器人
使用 Python TorchRL 进行多代理强化学习
本文详细介绍了如何使用TorchRL库解决多代理强化学习(MARL)问题,重点讨论了在多代理环境中应用近端策略优化(PPO)。通过使用VMAS模拟器,该文展示了如何在GPU上并行训练多机器人系统,使其在避免碰撞的同时到达目标。文章涵盖了依赖项安装、PPO原理、策略与评论家网络设计、数据收集及训练循环,并强调了TorchRL在简化开发流程、提升计算效率方面的优势。无论是集中式还是分布式评论家配置,TorchRL均能有效支持复杂的MARL研究与实践。
86 5
使用 Python TorchRL 进行多代理强化学习
|
5月前
|
Python
"揭秘!Python如何运用神秘的正则表达式,轻松穿梭于网页迷宫,一键抓取隐藏链接?"
【8月更文挑战第21天】Python凭借其强大的编程能力,在数据抓取和网页解析领域表现出高效与灵活。通过结合requests库进行网页请求及正则表达式进行复杂文本模式匹配,可轻松提取网页信息。本示例展示如何使用Python和正则表达式解析网页链接。首先确保已安装requests库,可通过`pip install requests`安装。接着,利用requests获取网页内容,并使用正则表达式提取所有`&lt;a&gt;`标签的`href`属性。
62 0
|
2月前
|
机器学习/深度学习 人工智能 算法
强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用
本文探讨了强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用,通过案例分析展示了其潜力,并讨论了面临的挑战及未来发展趋势。强化学习正为游戏AI带来新的可能性。
138 4
|
7月前
|
机器学习/深度学习 存储 算法
使用Python实现深度学习模型:强化学习与深度Q网络(DQN)
使用Python实现深度学习模型:强化学习与深度Q网络(DQN)
567 2
|
5月前
|
机器学习/深度学习 存储 定位技术
强化学习Agent系列(一)——PyGame游戏编程,Python 贪吃蛇制作实战教学
本文是关于使用Pygame库开发Python贪吃蛇游戏的实战教学,介绍了Pygame的基本使用、窗口初始化、事件处理、键盘控制移动、以及实现游戏逻辑和对象交互的方法。
|
5月前
|
算法 Python
【python】python基于 Q-learning 算法的迷宫游戏(源码+论文)【独一无二】
【python】python基于 Q-learning 算法的迷宫游戏(源码+论文)【独一无二】
105 0
|
5月前
|
机器学习/深度学习 存储 算法
【Python】 基于Q-learning 强化学习的贪吃蛇游戏(源码+论文)【独一无二】
【Python】 基于Q-learning 强化学习的贪吃蛇游戏(源码+论文)【独一无二】
240 0
|
6月前
|
算法 索引 Python
逆袭算法界!Python分治法、贪心算法、动态规划深度剖析,带你走出算法迷宫!
【7月更文挑战第8天】分治法,如快速排序,将大问题分解并合并解;贪心算法,选择局部最优解,如活动选择;动态规划,利用最优子结构避免重复计算,如斐波那契数列。Python示例展示这些算法如何解决实际问题,助你精通算法,勇闯迷宫。
58 1
|
6月前
|
机器学习/深度学习 算法 数据挖掘
Python强化学习应用于数据分析决策策略:** - 强化学习让智能体通过环境互动学习决策。
【7月更文挑战第5天】**Python强化学习应用于数据分析决策策略:** - 强化学习让智能体通过环境互动学习决策。 - Python因丰富库(如TensorFlow, PyTorch, Keras, Pandas, NumPy)和生态而受青睐。 - 使用OpenAI Gym构建环境,如`gym.make(&#39;CartPole-v0&#39;)`。 - 选择模型,例如神经网络,定义策略如Q-Learning。 - 训练模型,调整智能体行为,如Q-Learning更新Q表。 - 最后评估模型性能,实现数据驱动决策。
58 3
|
7月前
|
机器学习/深度学习 人工智能 算法
Python与强化学习:AlphaGo背后的编程逻辑
本文介绍了使用Python实现Q-learning算法,以模仿AlphaGo在围棋中的决策过程。强化学习涉及环境、智能体和状态,Q-learning是无模型的学习算法,通过优化Q函数来预测状态动作的预期收益。AlphaGo结合Policy Network和Value Network进行强化学习,而简单的实现可借助OpenAI Gym创建围棋环境,使用Tensorforce库实现Q-learning。不过,要达到AlphaGo的水平,还需深入研究和优化。