📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏: 【强化学习】(29)---《隐空间分层强化学习(HRL-LS )算法》
隐空间分层强化学习,Hierarchical Reinforcement Learning with Latent Space (HRL-LS) 是一种分层强化学习(Hierarchical Reinforcement Learning, HRL)算法,旨在通过在隐空间(Latent Space)中进行策略优化,来处理高维复杂任务中的长期依赖问题。该算法提出了一种新的框架,能够同时利用分层结构和潜在变量模型,来提高在复杂环境中的学习效率。
上图展示了一个高级策略的例子,根据期望的观察产生目标,在这个任务中对应于四足机器人所有关节的位置和方向(包括根的位置)。低级策略直接控制智能体(粉色),并因将其躯干和每个肢体的位置和方向与目标(蓝色矩形,提高能见度)相匹配而获得奖励。高级策略和低级策略之间通过隐空间来映射,通过这种方式,两层策略可以执行涉及一系列运动和交互的复杂任务;例如,推开一个方块到达目标(绿色)。
HRL-LS的核心思想是引入隐空间来表征复杂任务的潜在结构。通过将高维的状态空间投射到低维的隐空间中,算法可以简化复杂任务的表示,并在不同的抽象层次上进行策略学习。这种方法利用了分层强化学习的优势,将复杂任务分解为多个较小的子任务,从而提高学习效率,同时通过隐空间进一步减少学习的难度。
HRL-LS 的分层结构包含以下两层:
HRL-LS的整体架构基于两层策略学习机制,并结合了潜在变量模型来简化高维环境中的状态表示。
投射到低维隐空间
中。
,作为当前时间步的子目标。
,在原始状态空间中选择具体的动作
。
HRL-LS的核心公式包括高层策略的隐空间转换和低层策略的目标导向动作选择。
通过编码器
,高层策略将原始状态
映射到低维隐空间
:
在隐空间中,高层策略生成子目标
,并将其传递给低层策略。高层策略的目标是最大化长期期望回报,公式为:
其中:
是高层策略的隐空间目标值函数。
是高层策略选择的子目标。
是全局奖励,
是折扣因子。
低层策略通过解码器
将隐向量
解码为子目标,并在原始状态空间中选择动作:
低层策略的目标是通过动作来逐步实现高层设定的子目标
。
低层策略使用Q-learning来优化其策略,更新公式为:
其中:
是低层策略的 Q 值函数。
是低层策略的内在奖励,用于衡量低层策略在当前时间步是否实现高层目标。
和其他分层强化学习方法类似,HRL-LS 使用了内在奖励机制。低层策略通过内在奖励来评估是否成功接近高层目标。
内在奖励的计算方式为:
其中:
是当前状态
和高层策略设定的子目标
之间的距离。
HRL-LS 的学习过程包括高层策略和低层策略的分层学习机制:
Hierarchical Reinforcement Learning with Latent Space (HRL-LS) 是一种分层强化学习算法,使用潜在空间(Latent Space)进行高效的状态表示和动作选择。这个算法通常包括两层:
通过利用潜在空间,HRL-LS 可以有效降低原始高维状态空间的复杂性,同时保持层次化策略的结构。
🔥若是下面代码复现困难或者有问题,欢迎评论区留言;需要以整个项目形式的代码,请在评论区留下您的邮箱📌,以便于及时分享给您(私信难以及时回复)。
"""《HRL-LS算法实现》
时间:2024.10.13
环境:CartPole
作者:不去幼儿园
"""
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import random
# 超参数
GAMMA = 0.99
LEARNING_RATE = 0.001
EPSILON_DECAY = 0.995
MIN_EPSILON = 0.1
NUM_EPISODES = 500
LATENT_DIM = 2 # 潜在空间维度
HIGH_LEVEL_UPDATE_FREQUENCY = 10 # 高层更新频率
LOW_LEVEL_UPDATE_FREQUENCY = 1 # 低层更新频率
# Encoder 网络,将状态映射到潜在空间
class Encoder(nn.Module):
def __init__(self, state_dim, latent_dim):
super(Encoder, self).__init__()
self.fc1 = nn.Linear(state_dim, 128)
self.fc2 = nn.Linear(128, latent_dim)
def forward(self, state):
x = torch.relu(self.fc1(state))
latent = self.fc2(x)
return latent
# Decoder 网络,将潜在空间中的目标解码为实际目标
class Decoder(nn.Module):
def __init__(self, latent_dim, state_dim):
super(Decoder, self).__init__()
self.fc1 = nn.Linear(latent_dim, 128)
self.fc2 = nn.Linear(128, state_dim)
def forward(self, latent_goal):
x = torch.relu(self.fc1(latent_goal))
goal = self.fc2(x)
return goal
# Actor-Critic 网络
class ActorCritic(nn.Module):
def __init__(self, input_dim, action_dim):
super(ActorCritic, self).__init__()
self.actor = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, action_dim),
nn.Softmax(dim=-1)
)
self.critic = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, 1)
)
def forward(self, input):
action_probs = self.actor(input)
state_value = self.critic(input)
return action_probs, state_value
# Hierarchical Reinforcement Learning with Latent Space 智能体
class HRLLSAgent:
def __init__(self, state_dim, action_dim, latent_dim):
self.encoder = Encoder(state_dim, latent_dim) # 编码器
self.decoder = Decoder(latent_dim, state_dim) # 解码器
self.high_level_net = ActorCritic(latent_dim, latent_dim) # 高层策略在潜在空间中操作
self.low_level_net = ActorCritic(state_dim + state_dim, action_dim) # 低层策略根据目标执行动作
self.high_level_optimizer = optim.Adam(self.high_level_net.parameters(), lr=LEARNING_RATE)
self.low_level_optimizer = optim.Adam(self.low_level_net.parameters(), lr=LEARNING_RATE)
self.epsilon = 1.0
def encode_state(self, state):
state = torch.FloatTensor(state).unsqueeze(0)
latent_state = self.encoder(state)
return latent_state
def decode_goal(self, latent_goal):
# 检查 latent_goal 的大小是否为 LATENT_DIM
if latent_goal.numel() != LATENT_DIM: # `numel()` 返回张量中元素的总数
raise ValueError(f"Invalid shape for latent_goal: {latent_goal.size()}, expected size: {LATENT_DIM}")
# 调整 latent_goal 的形状为 (1, LATENT_DIM)
latent_goal = latent_goal.view(1, LATENT_DIM)
return self.decoder(latent_goal)
def select_high_level_goal(self, latent_state, epsilon):
if random.random() < epsilon:
return torch.randn(1, LATENT_DIM) # 随机选择潜在空间目标,确保大小正确
else:
action_probs, _ = self.high_level_net(latent_state)
goal_index = torch.argmax(action_probs).unsqueeze(0) # 找到目标索引
# 将目标索引扩展到潜在空间维度,确保形状为 [1, LATENT_DIM]
latent_goal = torch.zeros(1, LATENT_DIM)
latent_goal[0, goal_index] = 1.0 # 将目标索引位置设置为 1,其他为 0
return latent_goal
def select_low_level_action(self, state, goal, epsilon):
state_goal = torch.cat((torch.FloatTensor(state).unsqueeze(0), goal), dim=-1)
if random.random() < epsilon:
return random.choice([0, 1]) # 随机选择动作
else:
action_probs, _ = self.low_level_net(state_goal)
return torch.argmax(action_probs).item()
def update_high_level(self, latent_state, latent_goal, reward, next_latent_state):
_, state_value = self.high_level_net(latent_state)
_, next_state_value = self.high_level_net(next_latent_state)
next_state_value = next_state_value.detach()
target_value = reward + GAMMA * next_state_value
loss_critic = nn.functional.mse_loss(state_value, target_value)
# 获取动作概率
action_probs, _ = self.high_level_net(latent_state)
# 确保 latent_goal 在动作空间的范围内
latent_goal = latent_goal.clamp(0, action_probs.size(1) - 1)
# 计算 log_prob,避免索引超出范围
log_prob = torch.log(action_probs[0, latent_goal.long()])
advantage = target_value - state_value
loss_actor = -log_prob * advantage
loss = (loss_critic + loss_actor).mean()
self.high_level_optimizer.zero_grad()
loss.backward(retain_graph=True) # 保持计算图
self.high_level_optimizer.step()
def update_low_level(self, state, goal, action, reward, next_state):
state_goal = torch.cat((torch.FloatTensor(state).unsqueeze(0), goal), dim=-1)
next_state_goal = torch.cat((torch.FloatTensor(next_state).unsqueeze(0), goal), dim=-1)
_, state_value = self.low_level_net(state_goal)
_, next_state_value = self.low_level_net(next_state_goal)
next_state_value = next_state_value.detach()
target_value = reward + GAMMA * next_state_value
loss_critic = nn.functional.mse_loss(state_value, target_value)
action_probs, _ = self.low_level_net(state_goal)
log_prob = torch.log(action_probs[0, action])
advantage = target_value - state_value
loss_actor = -log_prob * advantage
loss = loss_critic + loss_actor
self.low_level_optimizer.zero_grad()
loss.backward(retain_graph=True) # 保留计算图
self.low_level_optimizer.step()
def train(self, env, num_episodes):
for episode in range(num_episodes):
state, _ = env.reset() # 修改后的reset返回值
latent_state = self.encode_state(state) # 将状态映射到潜在空间
latent_goal = self.select_high_level_goal(latent_state, self.epsilon) # 高层选择潜在空间目标
goal = self.decode_goal(latent_goal) # 解码为实际空间中的目标
done = False
episode_reward = 0
steps = 0
while not done:
steps += 1
action = self.select_low_level_action(state, goal, self.epsilon) # 低层选择动作
next_state, reward, done, _, _ = env.step(action) # 修改后的step返回值
# 更新低层
self.update_low_level(state, goal, action, reward, next_state)
# 更新高层目标
if steps % HIGH_LEVEL_UPDATE_FREQUENCY == 0:
next_latent_state = self.encode_state(next_state)
new_latent_goal = self.select_high_level_goal(next_latent_state, self.epsilon)
self.update_high_level(latent_state, latent_goal, reward, next_latent_state)
latent_goal = new_latent_goal
goal = self.decode_goal(latent_goal)
state = next_state
episode_reward += reward
self.epsilon = max(MIN_EPSILON, self.epsilon * EPSILON_DECAY)
print(f"Episode {episode + 1}: Total Reward: {episode_reward}")
# 测试 Hierarchical Reinforcement Learning with Latent Space 智能体并显示动画
def test_hrlls_agent(agent, env, num_episodes=5):
for episode in range(num_episodes):
state, _ = env.reset() # 修改后的reset返回值
latent_state = agent.encode_state(state) # 将状态映射到潜在空间
latent_goal = agent.select_high_level_goal(latent_state, epsilon=0.0) # 高层选择潜在空间目标
goal = agent.decode_goal(latent_goal) # 解码为实际目标
done = False
total_reward = 0
env.render()
while not done:
env.render()
action = agent.select_low_level_action(state, goal, epsilon=0.0) # 低层选择动作
next_state, reward, done, _, _ = env.step(action) # 修改后的step返回值
state = next_state
total_reward += reward
print(f"Episode {episode + 1}: Total Reward: {total_reward}")
# 运行测试
if __name__ == "__main__":
env = gym.make('CartPole-v1')
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
agent = HRLLSAgent(state_dim, action_dim, LATENT_DIM)
agent.train(env, NUM_EPISODES)
env = gym.make('CartPole-v1', render_mode="human")
test_hrlls_agent(agent, env)
上述代码创建一个简单的 HRL-LS 框架,并在 CartPole 环境中进行训练。代码结构:
由于博文主要为了介绍相关算法的原理和应用的方法,缺乏对于实际效果的关注,算法可能在上述环境中的效果不佳,一是算法不适配上述环境,二是算法未调参和优化,三是等等。上述代码用于了解和学习算法足够了,但若是想直接将上面代码应用于实际项目中,还需要进行修改。
HRL-LS 适用于需要处理高维状态空间和长期依赖任务的场景,如:
Hierarchical Reinforcement Learning with Latent Space (HRL-LS) 的相关研究可以追溯到一些结合分层强化学习和潜在空间表征的论文。然而,这类特定的算法(HRL-LS)并没有一个标准的名称在主流文献中广泛流传。通常,这类方法在强化学习领域中被用来处理高维任务和长期依赖性任务。相关的方法通常会结合以下领域:
可供参考论文:
该论文提出了一种基于数据高效的分层强化学习方法,使用潜在空间来分解高维任务,类似于 HRL-LS 的想法。
🔥想了解更多分层强化学习的文章,请查看文章: 【RL Latest Tech】分层强化学习(Hierarchical RL)
文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者