最近在做毕设需要用强化学习来做控制,对强化学习的知识点做一下总结。
高斯策略
高斯策略属于强化学习中的基于策略优化的分支(Policy Optimization),尤其是策略梯度方法(Policy Gradient Methods) 的一部分。这一分支专注于通过优化策略的参数来直接提升策略的性能,而不需要显式地学习一个价值函数。
高斯策略在强化学习中的位置
强化学习可以按照以下几个主要分支分类:
-
基于价值函数的方法(Value-Based Methods)
- 如Q-Learning、深度Q网络(DQN)。
- 这些方法学习状态-动作值函数 ( Q(s, a) ),然后通过选择最大值的动作来构建策略。
-
基于策略的方法(Policy-Based Methods)
- 直接对策略进行建模并优化。
- 高斯策略属于这一类方法,特别是策略梯度方法(Policy Gradient Methods),因为它通过优化概率分布(高斯分布)来学习策略。
-
基于策略与价值的混合方法(Actor-Critic Methods)
- 同时学习策略(Actor)和价值函数(Critic),如A3C、DDPG等。
- 虽然高斯策略本身是策略梯度的一部分,但它也经常在这些方法中作为Actor的策略模型使用。
高斯策略与策略梯度的关系
高斯策略是一种经典的连续动作空间中的策略表示形式,其主要特点是将策略建模为一个概率分布(通常是高斯分布):
πθ(a∣s)=N(μθ(s),Σθ(s)) \pi_{\theta}(a|s) = \mathcal{N}(\mu_{\theta}(s), \Sigma_{\theta}(s)) πθ(a∣s)=N(μθ(s),Σθ(s))
- 均值 μθ(s)\mu_{\theta}(s)μθ(s) 和 协方差 Σθ(s)\Sigma_{\theta}(s)Σθ(s) 是需要学习的策略参数。
- 通过最大化期望累计奖励 J(θ)=Eπθ[R]J(\theta) = \mathbb{E}_{\pi_{\theta}}[R]J(θ)=Eπθ[R]来优化策略。
策略梯度方法的核心公式:
通过策略梯度定理,我们可以计算梯度并优化策略参数:
∇θJ(θ)=Eπθ[∇θlogπθ(a∣s)Qπ(s,a)] \nabla_{\theta} J(\theta) = \mathbb{E}_{\pi_{\theta}} \left[ \nabla_{\theta} \log \pi_{\theta}(a|s) Q^{\pi}(s, a) \right] ∇θJ(θ)=Eπθ[∇θlogπθ(a∣s)Qπ(s,a)]
其中:
- logπθ(a∣s)\log \pi_{\theta}(a|s)logπθ(a∣s)是高斯分布的对数似然。
- Qπ(s,a)Q^{\pi}(s, a)Qπ(s,a) 是状态-动作值函数,用于评估策略的表现。
高斯策略在连续动作空间中的广泛应用,得益于高斯分布的可微性和灵活性,适合通过梯度优化调整策略。
高斯策略适用的场景
- 适用场景:
- 机器人控制:如臂式机器人轨迹规划。
- 无人机导航:优化无人机通过动态障碍的策略(如论文中提到的任务)。
- 自动驾驶:优化车辆在连续状态和动作空间中的驾驶策略。
高斯策略的实际应用:Policy Gradient vs Actor-Critic
-
纯策略梯度方法(如REINFORCE):
高斯策略直接使用策略梯度定理更新参数,但容易出现高方差问题。 -
Actor-Critic方法:
高斯策略作为Actor,由Critic(价值函数)提供更稳定的梯度信号,常见于:- 深度确定性策略梯度(DDPG)
- 近端策略优化(PPO)
- 信任区域策略优化(TRPO)
总结
高斯策略属于强化学习的基于策略优化的分支,具体归类为策略梯度方法。它特别适合解决连续动作空间中的任务,并在机器人控制、无人机飞行等领域得到广泛应用。结合其他强化学习算法(如Actor-Critic),高斯策略还能实现更稳定和高效的策略优化。
看一个GPT给的代码,理解高斯策略优化
import time
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import gym
# =========== 1. 创建 Pendulum 环境 ===========
env = gym.make("Pendulum-v1", render_mode="human")
# =========== 2. 定义高斯策略网络 ===========
class GaussianPolicy(nn.Module):
def __init__(self, state_dim, action_dim):
super(GaussianPolicy, self).__init__()
self.fc = nn.Sequential(
nn.Linear(state_dim, 64),
nn.ReLU(),
nn.Linear(64, action_dim)
)
self.log_std = nn.Parameter(torch.zeros(action_dim))
def forward(self, state):
"""
state: [batch_size, state_dim] (例如 [1, 3])
返回:
mean: [batch_size, action_dim]
std: [action_dim] (可广播为 [batch_size, action_dim])
"""
mean = self.fc(state)
std = torch.exp(self.log_std)
return mean, std #前向传播输出的是均值和方差(动作的)
# =========== 3. 初始化策略、优化器 ===========
state_dim = env.observation_space.shape[0] # 3 for Pendulum
action_dim = env.action_space.shape[0] # 1 扭矩
policy = GaussianPolicy(state_dim, action_dim) # model
optimizer = optim.Adam(policy.parameters(), lr=0.01) # 用adam优化器,优化model的参数
# =========== 4. 策略梯度训练 (REINFORCE) ===========
def train(policy, env, episodes=300, gamma=0.99, render=False):
for episode in range(episodes):
state, _ = env.reset()
log_probs = []
rewards = []
total_reward = 0
while True:
# (A) 将状态转换为 [1, state_dim] 的张量
state_t = torch.tensor(state, dtype=torch.float32).unsqueeze(0)
# (B) 前向传播:获取动作分布
mean, std = policy(state_t) # input: current state ; output: mean and std of action
dist = torch.distributions.Normal(mean, std) # 知道均值和方差,就可以直到action的高斯分布了。
# (C) 采样动作,并计算 log_prob
action = dist.sample() # shape: (1, 1) 对动作空间采样
log_prob = dist.log_prob(action).sum(dim=-1) # 计算action的对数概率,为了策略梯度
# (D) 裁剪动作并与环境交互
action_env = action.detach().numpy()[0]
action_env = np.clip(action_env,
env.action_space.low[0],
env.action_space.high[0])
# 执行动作
next_state, reward, terminated, truncated, info = env.step(action_env)
# (E) 保存 log_prob & reward
log_probs.append(log_prob)
rewards.append(reward)
total_reward += reward
state = next_state
if terminated or truncated:
break
# ========== 回合结束:计算回报并更新策略 ==========
returns = []
G = 0
for r in reversed(rewards): # 存放每个时间步的折扣累计奖励
G = r + gamma * G
returns.insert(0, G)
returns = torch.tensor(returns, dtype=torch.float32)
# 标准化回报
returns = (returns - returns.mean()) / (returns.std() + 1e-9)
# REINFORCE 损失
loss = 0
# 对每个时间步的 (log_prob, return) 求和,前面加负号是因为要最大化期望回报,相当于最小化负的期望回报。
for log_p, R in zip(log_probs, returns):
loss -= log_p * R
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印训练进度
if (episode + 1) % 50 == 0:
print(f"Episode {
episode+1}/{
episodes}, Total Reward: {
total_reward:.2f}")
env.close()
# =========== 5. 运行训练并渲染 ===========
if __name__ == "__main__":
train(policy, env, episodes=300, render=True)
代码解析
在这行代码里:
dist = torch.distributions.Normal(mean, std)
我们使用了 PyTorch 提供的 概率分布模块(torch.distributions
)来构建一个高斯(正态)分布对象。以下是这句代码背后的原理与作用:
1. 为什么要构建 torch.distributions.Normal(mean, std)
-
表示连续动作策略
在连续动作空间(如倒立摆),我们经常用高斯分布 (\mathcal{N}(\mu, \sigma^2)) 来表示“策略”,其中:- μ\muμ(mean):动作的均值
- σ\sigmaσ(std):动作的标准差
-
进行动作采样
有了这个Normal(mean, std)
对象,就可以用action = dist.sample()
来采样一个连续值的动作
action
,从而在不同状态下能产生随机探索的效果。 -
计算对数概率(log_prob)
在策略梯度强化学习里,需要用对数概率 logπ(a∣s)\log \pi(a|s)logπ(a∣s) 来进行梯度更新。
这个dist
对象提供了dist.log_prob(action)
,可以直接得到对数似然,方便我们实现 REINFORCE、PPO 等算法的损失函数。
3. 原理:高斯分布中的参数
一个一维高斯(正态)分布通常由两个参数决定:
X∼N(μ,σ2) X \sim \mathcal{N}(\mu, \sigma^2) X∼N(μ,σ2)
- μ\muμ(mean):分布的均值。
- σ\sigmaσ(std):分布的标准差。
**分布的概率密度函数(PDF)**为:
p(x)=12π σexp(−(x−μ)22σ2). p(x) = \frac{1}{\sqrt{2 \pi} \, \sigma} \exp\left( -\frac{(x - \mu)^2}{2 \sigma^2} \right). p(x)=2πσ1exp(−2σ2(x−μ)2).
在代码中,mean
和 s