【强化学习算法】Q-learning原理及实现

实现代码github仓库:RL-BaselineCode
代码库将持续更新,希望得到您的支持⭐,让我们一起进步!

文章目录

    • 1. 原理讲解
      • 1.1 Q值更新公式
      • 1.2 ε-greedy随机方法
    • 2. 算法实现
      • 2.1 算法简要流程
      • 2.2 游戏场景
      • 2.3 算法实现
    • 3. 参考文章

1. 原理讲解

Q-learning算法实际上相当简单,仅仅维护一个Q值表即可,表的维数为(所有状态S,所有动作A),表的内容称为Q值,体现该状态下采取当前动作的未来奖励期望。智能体每次选择动作时都会查询Q值表在当前状态下采取何种动作得到的未来奖励可能最多,当然也会添加一些随机性,使智能体可能选择别的可能当前认为未来奖励并不多的动作,以便跳出局部最优解,尽量得到全局最优解。

1.1 Q值更新公式

Q值更新公式为:

Q [ S , A ] = ( 1 − α ) × Q [ S , A ] + α × ( R + γ × m a x ( Q [ S n e x t , : ] ) ) Q[S,A]=(1-\alpha)\times Q[S,A]+\alpha\times (R+\gamma\times max(Q[S_{next}, :])) Q[S,A]=(1α)×Q[S,A]+α×(R+γ×max(Q[Snext,:]))

其中,α为学习速率(learning rate),γ为折扣因子(discount factor)。根据公式可以看出,学习速率α越大,保留之前训练的效果就越少。折扣因子γ越大, m a x ( Q [ S n e x t , : ] ) max(Q[S_{next}, :]) max(Q[Snext,:])所起到的作用就越大。

其中, m a x ( Q [ S n e x t , : ] ) max(Q[S_{next}, :]) max(Q[Snext,:])指以前学习到的新状态下可能得到的最大奖励期望,也就是**记忆中的利益。**如果智能体在过去的游戏中于位置 S n e x t S_{next} Snext的某个动作上吃过甜头(例如选择了某个动作之后获得了100的奖赏),这个公式就可以让它提早地得知这个消息,以便使下回再通过位置S时选择正确的动作继续进入这个吃甜头的位置 S n e x t S_{next} Snext

但如果下一步就是终点,那么Q值更新公式变为: Q [ S , A ] = ( 1 − α ) × Q [ S , A ] + α × R Q[S,A]=(1-\alpha)\times Q[S,A]+\alpha\times R Q[S,A]=(1α)×Q[S,A]+α×R

其中,减少了最后一项 γ × m a x ( Q [ S n e x t , : ] ) \gamma\times max(Q[S_{next}, :]) γ×max(Q[Snext,:]),这是因为当下一个状态就是最终目标时我们不需要知道下个状态在未来可能的收益,因为下个状态就可以得到游戏结束的即时收益。一般Q值更新公式之所以多了这一步也正是因为对于下一步不是终点的状态,这一步的奖励R一般来说是0或-1,拿不到即时奖励,但是又需要记录该节点的该操作在未来的可能贡献。

1.2 ε-greedy随机方法

前面提到我们为了跳出局部最优解,尽量得到全局最优解,我们采用的方法为ε-greedy方法:每个状态以ε(epsilon 探索速率)的概率进行探索(Exploration),此时将随机选取动作,而剩下的1-ε的概率则进行利用(Exploitation),即选取当前状态下效用值较大的动作。

在这里插入图片描述

2. 算法实现

2.1 算法简要流程

算法流程:

初始化 Q = {};
while Q 未收敛:初始化智能体的位置S,开始新一轮游戏while S != 终结状态:使用策略π,获得动作a=π(S) 使用动作a进行游戏,获得智能体的新位置S',与奖励R(S,a)Q[S,A] ← (1-α)*Q[S,A] + α*(R(S,a) + γ* max Q[S',a]) // 更新QS ← S'

在这里插入图片描述

2.2 游戏场景

在这里插入图片描述

假设机器人必须越过迷宫并到达终点。有地雷,机器人一次只能移动一个地砖。如果机器人踏上矿井,机器人就死了。机器人必须在尽可能短的时间内到达终点。
得分/奖励系统如下:

  • 机器人在每一步都失去1点。这样做是为了使机器人采用最短路径并尽可能快地到达目标。

  • 如果机器人踩到地雷,则点损失为100并且游戏结束。

  • 如果机器人获得动力⚡️,它会获得1点。

  • 如果机器人达到最终目标,则机器人获得100分。
    现在,显而易见的问题是:我们如何训练机器人以最短的路径到达最终目标而不踩矿井?

2.3 算法实现

  1. 超参数设置
np.random.seed(2)  # 确保结果可复现
row = 5  # 游戏表格行数
col = 6  # 游戏表格列数
ACTIONS = ['up', 'right', 'down', 'left']  # 可采取的动作
EPSILON = 0.9  # ε-greedy随机方法中的ε
ALPHA = 0.1  # learning rate
GAMMA = 0.9  # discount factor
MAX_EPISODES = 5000  # 游戏共学多少轮
targetXY = [4, 4]  # 游戏的最终目标位置
env_list = ['--+---', '-*--*-', '--+--+', '*--*--', '-+--T-']  # 游戏地图
  1. 初始化Q值表
def build_q_table(row, col, actions):table = pd.DataFrame(np.zeros((row * col, len(actions))),  # q_table initial valuescolumns=actions,  # actions' name)# print(table)    # show tablereturn table
  1. 选择动作A
def choose_action(state, q_table):  # ε-greedy随机方法# This is how to choose an actionstate_actions = q_table.iloc[state[0] * col + state[1], :]if (np.random.uniform() > EPSILON) or ((state_actions == 0).all()):  # act non-greedy or state-action have no valueaction_name = np.random.choice(ACTIONS)else:  # act greedyaction_name = state_actions.idxmax()# replace argmax to idxmax as argmax means a different function in newer version of pandasreturn action_name
  1. 状态S下采取动作A到达新位置A’,并得到奖励/惩罚
def getR(S):str = env_list[S[0]][S[1]]if str == '-':return -1elif str == '*':return -100elif str == '+':return 1else:return 100def get_env_feedback(S, A):# This is how agent will interact with the environmentif A == 'up':  # move upif S[0] == targetXY[0]+1 and S[1] == targetXY[1]:  # 到达终点S_ = 'terminal'R = 100elif S[0] == 0:  # 向上碰壁S_ = SR = -1else:  # 正常移动S_ = [S[0] - 1, S[1]]R = getR(S_)if R == -100:  # 碰到炸弹直接结束S_ = 'terminal'elif A == 'right':  # move rightif S[0] == targetXY[0] and S[1] == targetXY[1] - 1:  # 到达终点S_ = 'terminal'R = 100elif S[1] == col - 1:  # 向右碰壁S_ = SR = -1else:  # 正常移动S_ = [S[0], S[1] + 1]R = getR(S_)if R == -100:  # 碰到炸弹直接结束S_ = 'terminal'elif A == 'down':  # move downif S[0] == row - 1:  # 向下碰壁S_ = SR = -1elif S[0] == targetXY[0] - 1 and S[1] == targetXY[1]:  # 到达终点S_ = 'terminal'R = 100else:  # 正常移动S_ = [S[0] + 1, S[1]]R = getR(S_)if R == -100:  # 碰到炸弹直接结束S_ = 'terminal'else:  # move leftif S[0] == targetXY[0] and S[1] == targetXY[1] + 1:  # 到达终点S_ = 'terminal'R = 100elif S[1] == 0:  # 向左碰壁S_ = SR = -1else:  # 正常移动S_ = [S[0], S[1] - 1]R = getR(S_)if R == -100:  # 碰到炸弹直接结束S_ = 'terminal'return S_, R
  1. 更新Q值表
q_predict = q_table.loc[S[0] * col + S[1], A]  # 当前位置的动作价值
if S_ != 'terminal':  # next state is not terminalq_target = R + GAMMA * q_table.iloc[S_[0] * col + S_[1], :].max()  
else:q_target = R  # next state is terminalis_terminated = True  # terminate this episode
# 当前位置的动作价值+新位置的状态价值
q_table.loc[S[0] * col + S[1], A] = (1 - ALPHA) * q_predict + ALPHA * q_target  
S = S_  # move to next state

3. 参考文章

  1. 强化学习入门:基本思想和经典算法

  2. Q-learning 的具体过程

  3. 【强化学习】Q-Learning算法详解以及Python实现【80行代码】

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

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

相关文章

DBS note7 (end):DB Design

目录 一、前言 二、引言 三、Entity-Relationship Models(实体-关系模型) 1、关系约束 三、函数依赖和正则化 1、BCNF分解 2、无损分解 3、依赖关系保留分解 一、前言 略读过一遍CS186,对于CS186来说,绝对不止这 7 篇笔记…

10. 哈希表

哈希表(hash table),又称散列表,其通过建立键 key 与值 value 之间的映射,实现高效的元素查询。具体而言,我们向哈希表输入一个键 key ,则可以在 \(O(1)\) 时间内获取对应的值 value 。 给定 n 个学生,每个…

Docker Registry(镜像仓库)——4

目录: 什么是 Docker Registry镜像仓库生活案例镜像仓库分类镜像仓库工作机制常用的镜像仓库镜像仓库命令 命令清单docker logindocker pulldocker pushdocker searchdocker logout镜像命令[部分] docker imagesdocker image inspectdocker tag容器命令[部分] dock…

通义灵码简单使用例子

首先我们需要了解到通义灵码的能力: 行/函数级实时续写: 当我们在 idea进行代码编写时(确认开启了自动云端生成的模式),通义灵码会根据当前代码文件及相关代码文件的上下文,自动为你生成代码建议。你可以不用,也可以t…

Verilog 入门(九)(建模实例)

文章目录 建模的不同方式条件操作建模通用移位寄存器状态机建模Moore 有限状态机建模Mealy 型有限状态机建模 建模的不同方式 分别使用数据流方式、行为方式和结构方式对下图所示的电路进行建模: 数据流方式:使用连续赋值语句对电路建模 module Save_M…

viple模拟器使用(四):unity模拟器中实现两距离局部最优迷宫算法

名字解读 两距离:指的是左侧距离和右侧距离 局部最优:对当前状态来说最好的选择,至于整体能不能达到最优,是无法确定的。 从节点1到节点5,一共有3条路 第1条路线:1→2→4→5,对应的花销是&…

机器学习笔记 - 什么是模型量化压缩技术?

一、简述 我们都知道现实世界是连续的状态,而计算机世界是离散的状态,这是什么意思呢?我们看一下下图,最右边的马力欧(高清)的状态,可以想象现实世界是连续的状态,而电脑世界在图像上呈现的是一格一格子的状态(左图)是离散的状态。 所以在计算机世界如果想要…

51单片机应用从零开始(十)·指针

指针 C语言指针是一种保存变量地址的数据类型。它可以让程序直接访问内存中的数据,而不需要通过变量名来访问。指针变量存储的是一个地址,这个地址指向内存中的某个位置,该位置存储了一个值。 在C语言中,可以使用&运算符取得一…

【计算机网络笔记】物理层——数据通信基础

系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…

绝地求生在steam叫什么?

绝地求生在Steam的全名是《PlayerUnknowns Battlegrounds》,简称为PUBG。作为一款风靡全球的多人在线游戏,PUBG于2017年3月23日正式上线Steam平台,并迅速成为一部热门游戏。 PUBG以生存竞技为核心玩法,玩家将被投放到一个辽阔的荒…

CRM简单小结

思想 对于三层架构,一个模块对应一个controller,controller实际就是Servlet;一张表对应一个domain类对应一个dao接口对应一个mapper文件;service层没有严格规定,如果两张表内容相近,用一个service接口也可以…

数据结构:图文详解双向链表的各种操作(头插法,尾插法,任意位置插入,查询节点,删除节点,求链表的长度... ...)

目录 一.双向链表的概念 二.双向链表的数据结构 三.双向链表的实现 节点的插入 头插法 尾插法 任意位置插入 节点的删除 删除链表中第一次出现的目标节点 删除链表中所有与关键字相同的节点 节点的查找 链表的清空 链表的长度 四.模拟实现链表的完整代码 前言&am…

检测下我的饺子皮擀的怎么样(圆度)

😄😊😆😃😄😊😆😃 各位老铁周末愉快。 快乐的时间做充实的事,好久没有吃饺子了,俗话说好吃不过饺子。 我个人觉得会包饺子不算本事,会擀饺子皮…

Linux 上的容器技术

容器实现封闭的环境主要要靠两种技术,一种是看起来是隔离的技术,称为 namespace(命名空间)。在每个 namespace 中的应用看到的,都是不同的 IP 地址、用户空间、进程 ID 等。另一种是用起来是隔离的技术,称为…

【csdn默认使用操作详解】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

使用PCSS实现的实时阴影效果

PCSS的技术可以使得阴影呈现出近硬远软的效果,并且能够实时实现。 其核心理念是通过模拟光源的面积来产生更自然、更柔和的阴影边缘。 具体步骤: 1、生成shadowmap 2、在进行阴影的比较时候进行平均,并非之前的shadow map 或者之后完全的阴影…

YOLOv8创新魔改教程(二)如何添加注意力机制

YOLOv8创新魔改教程(二)如何添加注意力机制 (一)找代码 github找各种注意力机制的代码 (二)融合 1.创建文件 在ultralytics/nn/attention.py创建attention.py 文件 将找到的代码粘贴进来 2.修改task…

【计算机组成原理】存储器知识

目录 1、存储器分类 1.1、按存储介质分类 1.2、按存取方式分类 1.3、按信息的可改写性分类 1.4、按信息的可保存性分类 1.5、按功能和存取速度分类 2、存储器技术指标 2.1、存储容量 2.2、存取速度 3、存储系统层次结构 4、主存的基本结构 5、主存中数据的存放 5.…

prometheus|云原生|轻型日志收集系统loki+promtail的部署说明

一, 日志聚合的概念说明 日志------ 每一个程序,服务都应该有保留日志,日志的作用第一是记录程序运行的情况,在出错的时候能够记录错误情况,简单来说就是审计工作,例如nginx服务的日志,kuber…

C++-模板

目录 一.泛型编程 二.模板的分类 三.函数模板 1.函数模板的概念 2.函数模板格式 3.函数模板的原理 4.函数模板的实例化 a.隐式实例化 b.显式实例化 5.模板参数的匹配原则 四.类模板 1.类模板的定义格式 2.类模板的实例化 五.class和typename的区别 六.非类型模板…