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

news2025/1/15 7:57:15

实现代码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]) // 更新Q
        S ← 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 values
      columns=actions,  # actions' name
  )
  # print(table)    # show table
  return table
  1. 选择动作A
def choose_action(state, q_table):  # ε-greedy随机方法
  # This is how to choose an action
  state_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 value
      action_name = np.random.choice(ACTIONS)
  else:  # act greedy
      action_name = state_actions.idxmax()
      # replace argmax to idxmax as argmax means a different function in newer version of pandas
  return action_name
  1. 状态S下采取动作A到达新位置A’,并得到奖励/惩罚
def getR(S):
  str = env_list[S[0]][S[1]]
  if str == '-':
      return -1
  elif str == '*':
      return -100
  elif str == '+':
      return 1
  else:
      return 100
    
def get_env_feedback(S, A):
  # This is how agent will interact with the environment
  if A == 'up':  # move up
      if S[0] == targetXY[0]+1 and S[1] == targetXY[1]:  # 到达终点
          S_ = 'terminal'
          R = 100
      elif S[0] == 0:  # 向上碰壁
          S_ = S
          R = -1
      else:  # 正常移动
          S_ = [S[0] - 1, S[1]]
          R = getR(S_)
          if R == -100:  # 碰到炸弹直接结束
              S_ = 'terminal'
  elif A == 'right':  # move right
      if S[0] == targetXY[0] and S[1] == targetXY[1] - 1:  # 到达终点
          S_ = 'terminal'
          R = 100
      elif S[1] == col - 1:  # 向右碰壁
          S_ = S
          R = -1
      else:  # 正常移动
          S_ = [S[0], S[1] + 1]
          R = getR(S_)
          if R == -100:  # 碰到炸弹直接结束
              S_ = 'terminal'
  elif A == 'down':  # move down
      if S[0] == row - 1:  # 向下碰壁
          S_ = S
          R = -1
      elif S[0] == targetXY[0] - 1 and S[1] == targetXY[1]:  # 到达终点
          S_ = 'terminal'
          R = 100
      else:  # 正常移动
          S_ = [S[0] + 1, S[1]]
          R = getR(S_)
          if R == -100:  # 碰到炸弹直接结束
              S_ = 'terminal'
  else:  # move left
      if S[0] == targetXY[0] and S[1] == targetXY[1] + 1:  # 到达终点
          S_ = 'terminal'
          R = 100
      elif S[1] == 0:  # 向左碰壁
          S_ = S
          R = -1
      else:  # 正常移动
          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 terminal
  q_target = R + GAMMA * q_table.iloc[S_[0] * col + S_[1], :].max()  
else:
  q_target = R  # next state is terminal
  is_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.coloradmin.cn/o/1281415.html

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

相关文章

[架构之路-256]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 软件系统不同层次的复用与软件系统向越来越复杂的方向聚合

目录 前言: 一、CPU寄存器级的复用:CPU寄存器 二、指令级复用:二进制指令 三、过程级复用:汇编语言 四、函数级复用:C语言 五、对象级复用:C, Java, Python 六、组件级复用 七、服务级复用 八、微…

win10下使用内置Linux

Win10安装Ubuntu子系统 #推荐博客 https://www.cnblogs.com/xiaoliangge/p/9124089.html #推荐视频 https://www.bilibili.com/video/BV184411i7As?spm_id_from333.337.search-card.all.click #Ubuntu18.04安装教程 https://edu.csdn.net/skill/gml/gml-214229ddcc6a496ba175…

基于hadoop下的Kafka分布式安装

简介 Kafka是一种分布式流处理平台,它具有高吞吐量、可扩展性、可靠性、实时性和灵活性等优点。它能够支持每秒数百万条消息的传输,并且可以通过增加节点来增加吞吐量和存储容量。Kafka通过将数据复制到多个节点来实现数据冗余和高可用性,即使…

JAVA代码优化:Easy Excel(操作Excel文件的开源工具)

Easy Excel官网: EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com) https://easyexcel.opensource.alibaba.com/ Easy Excel的特点和优势: 简单易用:Easy Excel提供了简洁的API,使用起来非常方便。开发…

xxl-job(分布式调度任务)

简介 针对分布式任务调度的需求,市场上出现了很多的产品: 1)TBSchedule:淘宝推出的一款非常优秀的高性能分布式调度框架,目前被应用于阿里,京东,支付宝,国美等很多互联网企业的流程调度系统中。…

Linux 基本语句_14_信号灯实验

原理: Send进程通过建立共享内存区域,并向其中写入数据,Recive通过与共享内存连接读取其中的数据。 但是如果进程进行读取操作的时候其他进程再次写入会产生数据丢失,产生竞态,为了确保在某段时间内只有一个操作&…

【Node.js】Node.js环境下载与安装教程(Windows系统)

前言 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,可以让你使用JavaScript进行服务器端编程。本教程将向你展示如何在Windows系统上下载和安装Node.js环境。 下载 首先,你需要下载Node.js环境。 打开Node.js官方网站:https://no…

Leetcode2661. 找出叠涂元素

Every day a Leetcode 题目来源:2661. 找出叠涂元素 解法1:哈希 题目很绕,理解题意后就很简单。 由于矩阵 mat 中每一个元素都不同,并且都在数组 arr 中,所以首先我们用一个哈希表 hash 来存储 mat 中每一个元素的…

C语言中的动态内存管理

在C语言中,动态内存管理是通过一系列的标准库函数来实现的,这些函数包括malloc, free, calloc 和 realloc。它们允许程序在运行时动态地分配和释放内存,这是管理复杂数据结构(如链表、树等)时非常有用的功能。 为什么…

为何要3次握手?TCP协议的稳定性保障机制

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…

MYSQL练题笔记-聚合函数-每月交易

一、题目相关内容 1)相关的表和题目 2)帮助理解题目的示例,提供返回结果的格式 二、初步的理解 是需要知道每个月和每个国家/地区的事务数及其总金额,每个月和每个国家/地区已批准的事务数及其总金额;以上的理解还是…

RPC和REST对比

RPC和REST对比 参考学习 RPC 和 REST 之间有什么区别? 当我们对比RPC和REST时,其实是在对比RPC风格的API和REST风格的API,后者通常成为RESTful API。 远程过程调用(RPC)和 REST 是 API 设计中的两种架构风格。API …

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

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

分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测

分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测 目录 分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量…

网络安全现状

威胁不断演变: 攻击者不断变化和改进攻击方法,采用更复杂、更隐秘的技术,以逃避检测和追踪。这包括新型的勒索软件、零日漏洞利用和社交工程攻击等。 供应链攻击: 攻击者越来越关注供应链的弱点,通过在供应链中植入恶…

Gitee拉取代码报错You hasn‘t joined this enterprise! fatal unable to access

文章目录 一、问题二、解决2.1、进入**控制面板**2.2、进入**用户账户**2.3、进入**管理Windows凭据**2.4、**普通凭据**2.4.1、添加2.4.2、编辑 2.5、重新拉取|推送代码 三、最后 一、问题 Gitee拉取仓库代码的时候报错You hasnt joined this enterprise! fatal unable to ac…

小米秒享3--非小米电脑

小米妙享中心是小米最新推出的一款功能,能够为用户们提供更加舒适便利的操作体验。简单的说可以让你的笔记本和你的小米手机联动,比如你在手机的文档,连接小米共享后,可以通过电脑进行操作。 对于非小米电脑想要体验终版秒享AIOT…

Spring Task 定时任务框架

Spring Task Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 定位:定时任务框架 作用:定时自动执行某段Java代码 Spring Task使用步骤 1). 导入maven坐标 spring-context(已存在&#xff…

如何在忘记密码的情况下恢复解锁 iPhone

您忘记了 iPhone 密码吗?Apple 官方通常建议将 iPhone 恢复至出厂设置以将其删除。这种修复很不方便,甚至可能比问题本身更麻烦。 如果您也经历过同样的情况,并且想知道忘记了 iPhone 密码并且不想恢复它该怎么办,我们的终极指南…

本项目基于Spring boot的AMQP模块,整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ

在业务逻辑的异步处理,系统解耦,分布式通信以及控制高并发的场景下,消息队列有着广泛的应用。本项目基于Spring的AMQP模块,整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ添加和读取消息的功能。并比较了两种模式&…