【强化学习】Soft Actor
【强化学习】Soft Actor
一、Soft Actor-Critic (SAC) 算法详解
Soft Actor-Critic(SAC) 是一种最先进的强化学习算法,属于 Actor-Critic 方法的变体。它特别适合处理 连续动作空间,并通过引入最大熵(Maximum Entropy)强化学习的思想,解决了许多传统算法中的稳定性和探索问题。
二、SAC 背景与核心思想
1. 强化学习的挑战
- 探索与利用的平衡:传统算法在初期探索新策略与后期利用已有最优策略之间难以达到平衡。
- 不稳定性:在连续动作空间中,训练通常会出现发散或收敛缓慢的问题。
- 样本效率:强化学习中,数据采集成本高,如何有效利用经验池中的数据是关键。
SAC 引入了以下核心思想来应对这些问题:
- 最大熵强化学习:在最大化累计奖励的同时,最大化策略的随机性(熵),以鼓励探索。
- 双 Q 网络:缓解 Q 值过估计的问题。
- 目标网络:使用目标网络稳定 Q 值计算。
2. 最大熵强化学习的目标
传统强化学习的目标是最大化期望累计奖励:
而 SAC 则通过添加一个 熵项,在奖励中加入策略随机性的权重,目标变为:
其中:
,表示策略的熵,鼓励策略更随机化;
:熵系数,控制熵和奖励之间的平衡。
效果:
- 更好的探索:熵的最大化使策略更加多样化。
- 更稳定的学习:避免陷入次优策略。
三、SAC 算法流程
SAC 使用了 Actor-Critic 框架,结合策略梯度和 Q 函数更新。以下是算法的关键步骤:
初始化:
- 初始化两组 Q 网络
,用于计算 Q 值。
- 初始化策略网络
和值函数网络
。
- 创建目标值函数网络
,并设置其参数为
的初始值。
每一回合循环:
- 采样动作:
- 根据策略网络
\pi_\phi 采样动作
a \sim \pi(a|s) 。
- 执行动作,记录
(s, a, r, s', \text{done}) 到经验池中。
- 更新 Q 网络:
- 使用 TD 目标更新 Q 值:
y = r + \gamma (1 - \text{done}) \cdot V_{\psi'}(s') - 最小化以下损失函数:
J_Q = \mathbb{E} \left[ \left( Q_{\theta_i}(s, a) - y \right)^2 \right] \quad (i = 1, 2) - 更新值函数网络:
- 值函数
V_\psi 的目标是逼近以下值:
y_V = \mathbb{E}{a \sim \pi} \left[ \min{i=1,2} Q_{\theta_i}(s, a) - \alpha \log \pi_\phi(a|s) \right] - 最小化值函数损失:
J_V = \mathbb{E} \left[ \left( V_\psi(s) - y_V \right)^2 \right] - 更新策略网络:
- 策略网络的目标是最大化奖励和熵,最小化以下损失:
J_\pi = \mathbb{E} \left[ \alpha \log \pi_\phi(a|s) - \min_{i=1,2} Q_{\theta_i}(s, a) \right] - 更新目标值函数网络:
- 使用软更新规则:
\psi' \gets \tau \psi + (1 - \tau) \psi'
四、公式推导
1. Q 值更新
Q 值通过 Bellman 方程更新,目标是最小化 TD 误差:
损失函数为:
2. 值函数更新
值函数估计策略的长期价值,目标值为:
损失函数为:
. 策略网络更新
策略网络的目标是最大化奖励和熵,等价于最小化:
4. 目标值函数更新
目标值函数使用软更新规则:
其中
控制更新步长。
[Python] Soft Actor-Critic算法实现
以下是PyTorch中Soft Actor-Critic (SAC)算法的完整实现:
1.参数设置
代码语言:javascript代码运行次数:0运行复制"""《SAC, Soft Actor-Critic算法》
时间:2024.12
作者:不去幼儿园
"""
import torch # 引入 PyTorch 库,用于构建和训练深度学习模型
import as nn # PyTorch 的神经网络模块
import as optim # PyTorch 的优化模块,用于更新模型参数
import numpy as np # umPy 库,用于高效的数值计算
import gym # OpenAI Gym 库,用于创建和交互强化学习环境
import random # Python 的随机模块,用于随机抽样
from collecti import deque # Python 的双端队列模块,用于构建经验回放缓冲区
# 超参数设置
GAMMA = 0.99 # 折扣因子,用于计算未来奖励
TAU = 0.005 # 软更新目标网络的参数
ALPHA = 0.2 # 熵正则化系数,鼓励探索
LR = 0.001 # 学习率,用于优化器
BATCH_SIZE = 256 # 每次训练的样本数量
MEMORY_CAPACITY = 100000 # 经验回放缓冲区的最大容量
2.策略网络
代码语言:javascript代码运行次数:0运行复制# 策略网络(用于生成随机的策略动作)
class Policyetwork(nn.Module):
def __init__(self, state_dim, action_dim, max_action):
super(Policyetwork, self).__init__()
self.fc1 = nn.Linear(state_dim, 256) # 第一层全连接层,输入状态维度
self.fc2 = nn.Linear(256, 256) # 第二层全连接层
= nn.Linear(256, action_dim) # 输出动作均值
self.log_std = nn.Linear(256, action_dim) # 输出动作的对数标准差
_action = max_action # 动作的最大值,用于缩放
def forward(self, state):
x = torch.relu(self.fc1(state)) # 激活第一层
x = torch.relu(self.fc2(x)) # 激活第二层
mean = (x) # 计算动作均值
log_std = self.log_std(x).clamp(-20, 2) # 将对数标准差限制在合理范围内
std = (log_std) # 通过对数标准差计算标准差
return mean, std # 返回均值和标准差
def sample(self, state):
mean, std = self.forward(state) # 获取动作分布的均值和标准差
normal = torch.(mean, std) # 正态分布
x_t = normal.rsample() # 使用重参数化技巧采样
y_t = (x_t) # 使用 Tanh 将动作限制在 [-1, 1]
action = y_t * _action # 缩放动作到最大值范围
log_prob = normal.log_prob(x_t) # 计算动作的对数概率
log_prob -= torch.log(1 - y_t.pow(2) + 1e-6) # Tanh 的修正项
log_prob = log_prob.sum(dim=-1, keepdim=True) # 对每个维度求和
return action, log_prob # 返回动作和对数概率
.Q 网络
代码语言:javascript代码运行次数:0运行复制# Q 网络(价值函数,用于评估状态-动作对的价值)
class Qetwork(nn.Module):
def __init__(self, state_dim, action_dim):
super(Qetwork, self).__init__()
self.fc1 = nn.Linear(state_dim + action_dim, 256) # 输入包括状态和动作
self.fc2 = nn.Linear(256, 256) # 第二层全连接层
self.fc = nn.Linear(256, 1) # 输出单一 Q 值
def forward(self, state, action):
x = ([state, action], dim=-1) # 将状态和动作连接起来作为输入
x = torch.relu(self.fc1(x)) # 激活第一层
x = torch.relu(self.fc2(x)) # 激活第二层
x = self.fc(x) # 输出 Q 值
return x # 返回 Q 值
4.经验回放缓冲区
代码语言:javascript代码运行次数:0运行复制# 经验回放缓冲区
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity) # 初始化一个具有固定最大容量的双端队列
def push(self, state, action, reward, next_state, done): # 存储经验
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size): # 随机采样
batch = random.sample(self.buffer, batch_size) # 随机选取 batch_size 个经验
states, acti, rewards, next_states, dones = zip(*batch) # 解压
return (np.array(states), np.array(acti), np.array(rewards),
np.array(next_states), np.array(dones))
def __len__(self): # 返回缓冲区当前大小
return len(self.buffer)
5.SAC 算法
代码语言:javascript代码运行次数:0运行复制# SAC 算法智能体
class SACAgent:
def __init__(self, state_dim, action_dim, max_action):
self.device = torch.device("cuda" if is_available() else "cpu") # 检查是否有 GPU
# 初始化网络
self.actor = Policyetwork(state_dim, action_dim, max_action).to(self.device) # 策略网络
self.q1 = Qetwork(state_dim, action_dim).to(self.device) # 第一个 Q 网络
self.q2 = Qetwork(state_dim, action_dim).to(self.device) # 第二个 Q 网络
# 初始化优化器
self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=LR) # 策略网络优化器
self.q1_optimizer = optim.Adam(self.q1.parameters(), lr=LR) # Q1 优化器
self.q2_optimizer = optim.Adam(self.q2.parameters(), lr=LR) # Q2 优化器
# 初始化经验回放缓冲区
self.replay_buffer = ReplayBuffer(MEMORY_CAPACITY)
_action = max_action # 最大动作值
def select_action(self, state): # 根据策略选择动作
state = torch.FloatTensor(state).to(self.device).unsqueeze(0) # 转换状态为张量
action, _ = self.actor.sample(state) # 从策略中采样动作
return ().detach().numpy()[0] # 转换为 umPy 格式返回
def train(self): # 训练智能体
if len(self.replay_buffer) < BATCH_SIZE: # 如果经验回放缓冲区不足,跳过训练
return
# 从回放缓冲区采样
states, acti, rewards, next_states, dones = self.replay_buffer.sample(BATCH_SIZE)
states = torch.FloatTensor(states).to(self.device)
acti = torch.FloatTensor(acti).to(self.device)
rewards = torch.FloatTensor(rewards).unsqueeze(1).to(self.device)
next_states = torch.FloatTensor(next_states).to(self.device)
dones = torch.FloatTensor(dones).unsqueeze(1).to(self.device)
# 更新 Q 网络
with _grad():
next_acti, log_probs = self.actor.sample(next_states) # 计算下一步的动作及其概率
target_q1 = self.q1(next_states, next_acti) # Q1 值
target_q2 = self.q2(next_states, next_acti) # Q2 值
target_q = (target_q1, target_q2) - ALPHA * log_probs # 使用最小值更新
q_target = rewards + GAMMA * (1 - dones) * target_q # 计算目标 Q 值
q1_loss = ((self.q1(states, acti) - q_target) ** 2).mean() # Q1 损失
q2_loss = ((self.q2(states, acti) - q_target) ** 2).mean() # Q2 损失
self.q1_optimizer.zero_grad() # 清空梯度
q1_loss.backward() # 反向传播
self.q1_optimizer.step() # 更新 Q1
self.q2_optimizer.zero_grad()
q2_loss.backward()
self.q2_optimizer.step()
# 更新策略网络
new_acti, log_probs = self.actor.sample(states)
q1_new = self.q1(states, new_acti)
q2_new = self.q2(states, new_acti)
q_new = (q1_new, q2_new)
actor_loss = (ALPHA * log_probs - q_new).mean() # 策略损失
self.actor_optimizer.zero_grad()
actor_loss.backward()
self.actor_optimizer.step()
def update_replay_buffer(self, state, action, reward, next_state, done):
self.replay_buffer.push(state, action, reward, next_state, done)
6.主函数循环
代码语言:javascript代码运行次数:0运行复制# 训练循环
env = ("Pendulum-v1") # 创建环境
state_dim = _space.shape[0] # 状态空间维度
action_dim = env.action_space.shape[0] # 动作空间维度
max_action = float(env.action_space.high[0]) # 最大动作值
agent = SACAgent(state_dim, action_dim, max_action) # 初始化智能体
num_episodes = 500 # 训练的总回合数
for episode in range(num_episodes):
state = env.reset() # 重置环境
episode_reward = 0 # 初始化总奖励
done = False
while not done:
action = agent.select_action(state) # 根据策略选择动作
next_state, reward, done, _ = env.step(action) # 执行动作
agent.update_replay_buffer(state, action, reward, next_state, done) # 更新经验
() # 训练智能体
state = next_state # 更新状态
episode_reward += reward # 累积奖励
print(f"Episode {episode}, Reward: {episode_reward}") # 打印回合奖励
[otice] 代码核心
(SAC, Soft Actor-Critic)算法是一种支持连续动作空间的强化学习算法。核心功能包括:
- 策略网络(Policy etwork):生成随机策略,用于采样动作。
- 价值网络(Q 网络):评估当前动作-状态对的价值。
- 经验回放缓冲区:存储并采样过往经验,提升训练稳定性。
- 训练循环:在环境中反复交互,学习最优策略。
# 环境配置
Python .11.5
torch 2.1.0
torchvision 0.16.0
gym 0.26.2
由于博文主要为了介绍相关算法的原理和应用的方法,缺乏对于实际效果的关注,算法可能在上述环境中的效果不佳或者无法运行,一是算法不适配上述环境,二是算法未调参和优化,三是没有呈现完整的代码,四是等等。上述代码用于了解和学习算法足够了,但若是想直接将上面代码应用于实际项目中,还需要进行修改。
五、 SAC 优势
- 样本效率高:使用离线经验池,充分利用历史数据。
- 探索能力强:通过最大化熵,鼓励更广泛的探索。
- 稳定性好:结合双 Q 网络和目标网络,降低训练波动。
- 适用于连续动作空间:支持复杂控制任务,如机器人控制。
参考文献:
[Haarnoja, Tuomas, et al. "Soft actor-critic: Off-policy maximum entropy deep reinforcement learning with a stochastic actor."发表于2018年,详细介绍了SAC算法的基本原理和应用1。
Haarnoja, Tuomas, et al. "Soft actor-critic algorithms and applicati." 同进一步探讨了SAC算法的损失函数和最大熵框架
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-01-07,如有侵权请联系 cloudcommunity@tencent 删除actor函数算法网络强化学习#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 17 条评论) |
本站网友 墙倒众人推 | 18分钟前 发表 |
a) \right] 更新目标值函数网络: 使用软更新规则: \psi' \gets \tau \psi + (1 - \tau) \psi'四 | |
本站网友 北京顺景温泉 | 0秒前 发表 |
用于评估状态-动作对的价值) class Qetwork(nn.Module) | |
本站网友 佘山月湖山庄 | 9分钟前 发表 |
Tuomas | |
本站网友 卢龙新闻 | 2分钟前 发表 |
用于优化器 BATCH_SIZE = 256 # 每次训练的样本数量 MEMORY_CAPACITY = 100000 # 经验回放缓冲区的最大容量2.策略网络代码语言:javascript代码运行次数:0运行复制# 策略网络(用于生成随机的策略动作) class Policyetwork(nn.Module) | |
本站网友 2013年黄金多少钱一克 | 11分钟前 发表 |
def __init__(self | |
本站网友 菜百黄金价格今天多少一克 | 14分钟前 发表 |
state_dim | |
本站网友 maphacker | 11分钟前 发表 |
a) \right] 更新目标值函数网络: 使用软更新规则: \psi' \gets \tau \psi + (1 - \tau) \psi'四 | |
本站网友 葛兰素史克制药公司 | 24分钟前 发表 |
r | |
本站网友 戴尔显卡驱动 | 15分钟前 发表 |
acti) - q_target) ** 2).mean() # Q1 损失 q2_loss = ((self.q2(states | |
本站网友 湾流g550 | 14分钟前 发表 |
它特别适合处理 连续动作空间 | |
本站网友 上海婚庆策划 | 7分钟前 发表 |
# 存储经验 self.buffer.append((state | |
本站网友 核桃分心木 | 16分钟前 发表 |
log_probs = self.actor.sample(next_states) # 计算下一步的动作及其概率 target_q1 = self.q1(next_states | |
本站网友 上海到台湾旅游 | 7分钟前 发表 |
next_state | |
本站网友 上清丸 | 6分钟前 发表 |
【强化学习】Soft Actor 一 | |
本站网友 公租房摇号结果 | 19分钟前 发表 |
a | |
本站网友 牛皮癣治疗方法 | 21分钟前 发表 |
用于评估状态-动作对的价值) class Qetwork(nn.Module) |