首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【RL Latest Tech】分层强化学习:MAXQ分解算法

【RL Latest Tech】分层强化学习:MAXQ分解算法

作者头像
不去幼儿园
发布2024-12-03 13:34:40
发布2024-12-03 13:34:40
8580
举报
文章被收录于专栏:强化学习专栏强化学习专栏

📢本篇文章是博主强化学习RL领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏: 【强化学习】(23)---《分层强化学习:MAXQ分解算法》

分层强化学习:MAXQ分解算法

MAXQ分解是一种用于分层强化学习(Hierarchical Reinforcement Learning, HRL)的算法,由Thomas G. Dietterich提出。该算法通过将复杂的任务分解成更小的子任务来简化问题,并利用这些子任务来构建更复杂的策略。


1. MAXQ分解算法的核心思想

MAXQ分解的主要思想是将一个复杂的Markov决策过程(MDP)分解成一系列嵌套的子MDP,以便更容易解决。MAXQ算法引入了一种分层的结构,将原始任务逐步分解为多个子任务,从而形成一个任务树(task hierarchy),并通过各个子任务的求解来最终解决整个任务。


2. 任务层次结构(Task Hierarchy)

在MAXQ分解算法中,任务被组织成一个分层结构,其中每一个节点都是一个子任务。任务层次结构的关键特征包括:

  1. 根任务(Root Task):这是整个任务的顶层,即原始的MDP问题。
  2. 子任务(Subtasks):根任务可以分解成一系列子任务,每个子任务又可以进一步分解成更小的子任务,直到最底层为不可再分的原子动作(Primitive Actions)。
  3. 子任务的目标:每个子任务都有一个特定的目标(Goal),即在某个状态下完成该子任务。

任务树中的每个子任务对应一个子MDP,包含其状态、动作和奖励结构。子任务的动作可以是原子动作(如“向前移动一步”),也可以是其他子任务(递归地分解)。


3. MAXQ值函数分解

MAXQ算法的核心是将值函数(Value Function)分解成一系列子任务的值函数。这种分解被称为“MAXQ值函数分解”,包括以下两个部分:

  • Completion Function

:表示在给定状态 s 下,执行子任务 a 的完成过程中所累积的期望奖励。

  • Q函数

:描述了在给定状态 s 下,不同子任务 a 的选择带来的期望回报。

公式表示为:

其中,

表示在状态 s 选择动作(子任务) a 的值。

4. MAXQ学习过程

MAXQ分解的学习过程是通过策略梯度或Q-learning等强化学习算法来进行的。学习过程包括以下几个步骤:

  1. 策略学习:对于每个子任务,学习其最优策略,使得完成该子任务的期望奖励最大化。
  2. 值函数更新:通过子任务的执行和奖励反馈来更新对应的值函数

和完成函数

  1. 分层执行:在执行过程中,首先选择顶层任务,然后递归地选择各个子任务,直到执行到原子动作。

[Python] MAXQ分解算法实现

CartPole 环境中使用 MAXQ 分解算法的 Python 实现。MAXQ 分解是分层强化学习的一种方法,它通过将任务分解为多个子任务,从而减少问题的复杂性,达到更高效的学习效果。具体来说,MAXQ 会将任务分解成多个层次的子任务,智能体会根据不同的子任务学习不同的策略。

🔥若是下面代码复现困难或者有问题,欢迎评论区留言;需要以整个项目形式的代码,请在评论区留下您的邮箱📌,以便于及时分享给您(私信难以及时回复)。

主要步骤:
  1. 设置 CartPole 环境。
  2. 定义 MAXQ 分解结构,将任务分解为子任务。
  3. 在各个子任务中分别学习Q值。
  4. 通过递归结构自上而下地选择动作,并利用低层策略解决高层问题。
  5. 通过Q值更新来优化分层结构中的各个任务。
训练代码实现:
代码语言:javascript
复制
"""《MAXQ分解算法实现》
    时间:2024.10.03
    环境:CartPole 
    作者:不去幼儿园
"""
import gym
import numpy as np
import random

# 定义超参数
GAMMA = 0.99
LEARNING_RATE = 0.1
EPSILON_DECAY = 0.995
MIN_EPSILON = 0.1
NUM_EPISODES = 500

# 定义 MAXQ 子任务节点
class MAXQNode:
    def __init__(self, num_actions, is_primitive=False):
        self.num_actions = num_actions
        self.is_primitive = is_primitive  # 是否为原子任务
        self.q_values = {}  # Q 值字典,(state, action) -> Q 值

    def get_q(self, state, action):
        state = tuple(state)  # 将 state 转换为元组
        if (state, action) not in self.q_values:
            self.q_values[(state, action)] = 0.0  # 初始化 Q 值
        return self.q_values[(state, action)]

    def set_q(self, state, action, value):
        state = tuple(state)  # 将 state 转换为元组
        self.q_values[(state, action)] = value

# 创建 MAXQ 分解的顶层任务
class MAXQTask:
    def __init__(self, num_actions):
        self.num_actions = num_actions
        self.subtasks = []
        self.root = MAXQNode(num_actions)  # 顶层任务节点

    def add_subtask(self, subtask):
        self.subtasks.append(subtask)

# 定义智能体
class MAXQAgent:
    def __init__(self, env):
        self.env = env
        self.epsilon = 1.0
        self.maxq_root = MAXQTask(env.action_space.n)  # CartPole 的动作数为 2

        # 添加子任务
        self.pickup_subtask = MAXQNode(env.action_space.n, is_primitive=True)  # 装载任务
        self.dropoff_subtask = MAXQNode(env.action_space.n, is_primitive=True)  # 卸载任务
        self.navigate_subtask = MAXQNode(env.action_space.n)  # 导航任务

        # 将子任务添加到根节点
        self.maxq_root.add_subtask(self.pickup_subtask)
        self.maxq_root.add_subtask(self.dropoff_subtask)
        self.maxq_root.add_subtask(self.navigate_subtask)

    def select_action(self, state, subtask, epsilon):
        # ε-贪婪策略选择动作
        if random.random() < epsilon:
            return self.env.action_space.sample()  # 探索
        else:
            q_values = [subtask.get_q(state, action) for action in range(subtask.num_actions)]
            return np.argmax(q_values)  # 利用当前策略

    def update_q(self, state, subtask, action, reward, next_state):
        # 确保传入的是 MAXQNode 而不是 MAXQTask
        if not isinstance(subtask, MAXQNode):
            subtask = subtask.root  # 传入的是 MAXQTask,则使用其根节点
        next_q_values = [subtask.get_q(next_state, a) for a in range(subtask.num_actions)]
        max_next_q = max(next_q_values)

        # Q 值更新
        current_q = subtask.get_q(state, action)
        new_q = current_q + LEARNING_RATE * (reward + GAMMA * max_next_q - current_q)
        subtask.set_q(state, action, new_q)

    def train(self, num_episodes):
        for episode in range(num_episodes):
            state,_ = self.env.reset()
            done = False
            total_reward = 0

            while not done:
                # 确保传递的是 MAXQNode
                action = self.select_action(state, self.maxq_root.root, self.epsilon)
                next_state, reward, done, _, __ = self.env.step(action)

                # 这里传递的是 MAXQNode,而不是 MAXQTask
                self.update_q(state, self.maxq_root.root, action, reward, next_state)
                state = next_state
                total_reward += reward

            # 逐渐减少 epsilon 以减少探索
            self.epsilon = max(MIN_EPSILON, self.epsilon * EPSILON_DECAY)
            print(f"Episode {episode + 1}: Total Reward: {total_reward}")

# 创建 CartPole 环境并训练智能体
env = gym.make('CartPole-v1')
agent = MAXQAgent(env)
agent.train(NUM_EPISODES)
env.close()
测试代码实现:
代码语言:javascript
复制
import gym
import torch

# 测试 MAXQ 智能体并显示动画
def test_maxq_agent(agent, env, num_episodes=5):
    for episode in range(num_episodes):
        state, _ = env.reset()
        done = False
        total_reward = 0
        env.render()  # 初始化渲染

        while not done:
            env.render()  # 显示动画
            action = agent.select_action(state, agent.maxq_root.root, epsilon=0.0)  # 使用已学策略选择动作
            next_state, reward, done, _, __ = env.step(action)
            state = next_state
            total_reward += reward

        print(f"测试 Episode {episode + 1}: Total Reward: {total_reward}")
    env.close()

# 创建环境并调用测试函数
env = gym.make('CartPole-v1', render_mode='human')
test_maxq_agent(agent, env)

[Notice] 注意事项

主要思路:
  1. MAXQNode 类定义了一个子任务。每个子任务都可以拥有自己的 Q 值,并且可以是一个原子任务或复合任务。
  2. MAXQTask 是根任务,它管理多个子任务。
  3. MAXQAgent 使用 MAXQ 分解结构来训练智能体。每个状态下会通过 MAXQ 的结构选择动作,并递归调用子任务的策略。
代码解读:
  • MAXQ 分解:任务被分解为多个层次的子任务。在这里,假设有两个子任务:保持平衡和终止任务。终止任务是一个原子任务,即在某些条件下智能体选择终止,而不是继续执行其他任务。
  • Q 值更新:基于每个子任务的动作和状态,更新对应的 Q 值。
运行提示:

此代码将 MAXQ 分解方法应用于 CartPole 环境。该方法通过分层强化学习的方式来解决问题。您可以通过调整超参数(如 LEARNING_RATEGAMMA)来进一步优化结果。

优化建议:
  1. 增加训练回合数:Taxi Domain 是一个复杂环境,可能需要较长的训练时间来收敛。
  2. 调节 ε-greedy 策略:可以加快 ε 的衰减速度,以减少后期训练中的探索。
  3. 优化子任务分解:可以进一步细化任务分解,增加中间子任务以加快训练过程。

由于博文主要为了介绍相关算法的原理应用的方法,缺乏对于实际效果的关注,算法可能在上述环境中的效果不佳,一是算法不适配上述环境,二是算法未调参和优化,三是等。上述代码用于了解和学习算法足够了,但若是想直接将上面代码应用于实际项目中,还需要进行修改。


5. 优点与挑战

优点
  • 分解问题复杂度:通过将复杂的任务分解成子任务,减少了原问题的复杂度。
  • 复用子任务:相同的子任务可以被多个父任务复用,从而提高学习效率。
  • 减少探索空间:分层结构使得每个子任务只需探索自己相关的状态空间,减小了整体的搜索空间。
挑战
  • 任务分解:如何将复杂的任务合理地分解成子任务仍然是一个挑战性问题。
  • 子任务依赖:在某些情况下,不同子任务之间可能存在复杂的依赖关系,处理这些依赖关系需要更加复杂的策略设计。

6. MAXQ的应用场景

MAXQ分解算法适用于需要分解和递归解决的问题,如:

  • 多阶段决策过程,例如机器人路径规划、复杂游戏策略。
  • 任务中存在天然的分解结构,或者通过人工设计可以合理分解的任务。

7.总结

MAXQ算法提供了一种分层强化学习的方法,可以显著简化复杂任务的求解过程,并利用层次结构来提高学习的效率和策略的可解释性。

参考文献: Hierarchical Reinforcement Learning with the MAXQ Value Function Decomposition

文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分层强化学习:MAXQ分解算法
    • 1. MAXQ分解算法的核心思想
    • 2. 任务层次结构(Task Hierarchy)
    • 3. MAXQ值函数分解
    • 4. MAXQ学习过程
    • [Python] MAXQ分解算法实现
      • 主要步骤:
      • 训练代码实现:
      • 测试代码实现:
    • [Notice] 注意事项
      • 主要思路:
      • 代码解读:
      • 运行提示:
      • 优化建议:
    • 5. 优点与挑战
      • 优点
      • 挑战
    • 6. MAXQ的应用场景
    • 7.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档