强化学习:Policy Gradients 学习笔记
一、Policy Gradients 是什么?
1.1 算法定义
Policy Gradient Softmax是一种基于策略的强化学习算法,使用参数化的策略函数 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(a∣s)(通常建模为Softmax分布),通过梯度上升直接优化策略参数 θ \theta θ。其核心创新点在于:
- 策略参数化:用神经网络表示策略 π θ ( a ∣ s ) = exp ( z θ ( s , a ) ) ∑ a ′ exp ( z θ ( s , a ′ ) ) \pi_\theta(a|s) = \frac{\exp(z_\theta(s,a))}{\sum_{a'}\exp(z_\theta(s,a'))} πθ(a∣s)=∑a′exp(zθ(s,a′))exp(zθ(s,a)),其中 z θ ( s , a ) z_\theta(s,a) zθ(s,a) 是动作偏好函数。
- 梯度上升优化:通过计算策略梯度 ∇ θ J ( θ ) ≈ E π [ ∇ θ log π θ ( a ∣ s ) ⋅ R t ] \nabla_\theta J(\theta) \approx \mathbb{E}_\pi\left[\nabla_\theta \log\pi_\theta(a|s) \cdot R_t\right] ∇θJ(θ)≈Eπ[∇θlogπθ(a∣s)⋅Rt],直接最大化累积奖励 J ( θ ) = E τ ∼ π θ [ R ( τ ) ] J(\theta) = \mathbb{E}_{\tau\sim\pi_\theta}[R(\tau)] J(θ)=Eτ∼πθ[R(τ)]。
公式 1:目标函数
- J ( θ ) = E τ ∼ π θ [ R ( τ ) ] J(\theta) = \mathbb{E}_{\tau \sim \pi_{\theta}}[R(\tau)] J(θ)=Eτ∼πθ[R(τ)]
符号 | 含义 |
---|---|
J ( θ J(\theta J(θ) | 目标函数:策略 ( \pi_{\theta} ) 的期望累积奖励(需最大化) |
θ \theta θ | 策略参数:神经网络的权重 |
τ \tau τ | 轨迹(Trajectory):一个完整的状态-动作序列 ( s 0 , a 0 , s 1 , a 1 , … , s T ) (s_0,a_0,s_1,a_1,\dots,s_T) (s0,a0,s1,a1,…,sT) |
R ( τ ) R(\tau) R(τ) | 累积奖励:轨迹 ( \tau ) 的总奖励(通常为折扣奖励和 ∑ t = 0 T γ t r t \sum_{t=0}^T \gamma^t r_t ∑t=0Tγtrt) |
E τ ∼ π θ \mathbb{E}_{\tau \sim \pi_{\theta}} Eτ∼πθ | 期望:在策略 π θ \pi_{\theta} πθ下所有可能轨迹的期望值 |
公式 2:策略梯度
- ∇ θ J ( θ ) ≈ E π [ ∇ θ log π θ ( a ∣ s ) ⋅ R t ] \nabla_{\theta} J(\theta) \approx \mathbb{E}_{\pi} [\nabla_{\theta} \log \pi_{\theta}(a|s) \cdot R_t] ∇θJ(θ)≈Eπ[∇θlogπθ(a∣s)⋅Rt]
符号 | 含义 |
---|---|
∇ θ J ( θ ) \nabla_{\theta} J(\theta) ∇θJ(θ) | 目标函数的梯度:参数空间中最速上升方向 |
∇ θ log π θ ( a ∣ s ) \nabla_{\theta} \log \pi_{\theta}(a|s) ∇θlogπθ(a∣s) | Score Function:策略对数概率关于参数 ( \theta ) 的梯度 |
R t R_t Rt | 累积奖励:从时刻 t t t 开始的未来累积奖励( R t = ∑ k = t T γ k − t r k R_t = \sum_{k=t}^T \gamma^{k-t} r_k Rt=∑k=tTγk−trk) |
E π \mathbb{E}_{\pi} Eπ | 期望:在策略 π θ \pi_{\theta} πθ下状态-动作对的期望 |
1.2 核心概念
- 不同于传统方法:不学习价值函数(如Q值),直接学习策略(动作选择规则)
- 神经网络输出:动作的概率分布(而非动作价值)
动作概率 = π(a|s; θ) # θ是神经网络参数
1.3 与基于值的方法对比
特性 | 基于值的方法(如DQN) | Policy Gradients |
---|---|---|
输出 | 动作价值(Q值) | 动作概率 |
动作选择 | 选择最高Q值的动作 | 按概率分布采样动作 |
动作空间 | 适合离散动作 | 适合连续动作(如转向角度) |
策略类型 | 确定性策略 | 随机性策略(更灵活) |
二、核心思想:奖励驱动的学习🎯
2.1 基本机制
2.2 直观理解
- 好动作:获得正奖励 → 增加选择概率(下次更可能选)
- 坏动作:获得负奖励 → 减少选择概率(下次更少选)
就像训练宠物:做对给零食(强化行为),做错说"No"(弱化行为)
三、算法实现:
3.1 算法流程(伪代码)
初始化神经网络参数 θ
for 每个回合 do收集轨迹 {s₁,a₁,r₂,s₂,a₂,...,r_T}for 每个时间步 t do计算累积奖励 Gₜ = Σ γᵏ⁻ᵗ rₖ (k从t到T)更新参数:θ ← θ + α ∇θ logπ(aₜ|sₜ) Gₜend
end
3.2 关键组件
- logπ(aₜ|sₜ):动作概率的对数(“惊讶度”)
- 概率小 → 对数大(更惊讶)
- 概率大 → 对数小(不惊讶)
- Gₜ:累积折扣奖励
- α:学习率
3.3 算法步骤
-
初始化:
- 策略网络 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(a∣s)(通常为Softmax输出层);
- 优化器(如Adam);
- 设置参数:学习率 α \alpha α,折扣因子 γ \gamma γ。
-
对于每个episode:
- 初始化状态 s 1 s_1 s1,轨迹 τ = { } \tau = \{\} τ={};
- 对于每个时间步 t t t:
- 根据当前策略 π θ ( a ∣ s t ) \pi_\theta(a|s_t) πθ(a∣st) 采样动作 a t a_t at;
- 执行动作 a t a_t at,获得奖励 r t r_t rt 和下一状态 s t + 1 s_{t+1} st+1;
- 将 ( s t , a t , r t ) (s_t,a_t,r_t) (st,at,rt) 添加到轨迹 τ \tau τ 中;
- 计算累积回报:
对于每个时间步 t t t,计算从 t t t 开始的累积折扣回报 R t = ∑ k = t T γ k − t r k R_t = \sum_{k=t}^T \gamma^{k-t} r_k Rt=∑k=tTγk−trk; - 计算损失并更新策略:
损失函数: L ( θ ) = − 1 T ∑ t = 0 T log π θ ( a t ∣ s t ) ⋅ R t \mathcal{L}(\theta) = -\frac{1}{T}\sum_{t=0}^T \log\pi_\theta(a_t|s_t) \cdot R_t L(θ)=−T1∑t=0Tlogπθ(at∣st)⋅Rt;
通过梯度上升更新参数: θ ← θ + α ∇ θ L ( θ ) \theta \leftarrow \theta + \alpha \nabla_\theta \mathcal{L}(\theta) θ←θ+α∇θL(θ)。
四、神经网络架构🧠
4.1 网络结构
4.2 TensorFlow 实现
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95):self.n_actions = n_actionsself.n_features = n_featuresself.lr = learning_rateself.gamma = reward_decay# 存储回合数据self.ep_obs = [] # 状态self.ep_as = [] # 动作self.ep_rs = [] # 奖励self._build_net()self.sess = tf.Session()self.sess.run(tf.global_variables_initializer())def _build_net(self):# 输入层self.tf_obs = tf.placeholder(tf.float32, [None, self.n_features])self.tf_acts = tf.placeholder(tf.int32, [None])self.tf_vt = tf.placeholder(tf.float32, [None]) # 折扣奖励# 隐藏层layer = tf.layers.dense(inputs=self.tf_obs,units=10,activation=tf.nn.tanh)# 输出层all_act = tf.layers.dense(inputs=layer,units=self.n_actions,activation=None)# 动作概率self.all_act_prob = tf.nn.softmax(all_act)# 损失函数:-log(prob)*vtneg_log_prob = tf.reduce_sum(-tf.log(self.all_act_prob)*tf.one_hot(self.tf_acts, self.n_actions), axis=1)loss = tf.reduce_mean(neg_log_prob * self.tf_vt)# 优化器self.train_op = tf.train.AdamOptimizer(self.lr).minimize(loss)
五、训练流程详解🔧
5.1 主训练循环
env = gym.make('CartPole-v0')
RL = PolicyGradient(n_actions=env.action_space.n,n_features=env.observation_space.shape[0],learning_rate=0.02,reward_decay=0.99)for i_episode in range(3000):observation = env.reset()while True:# 1. 选择动作(基于概率)action = RL.choose_action(observation)# 2. 执行动作observation_, reward, done, info = env.step(action)# 3. 存储数据RL.store_transition(observation, action, reward)if done:# 4. 计算折扣奖励vt = RL.learn()breakobservation = observation_
5.2 关键方法实现
def choose_action(self, observation):prob_weights = self.sess.run(self.all_act_prob, feed_dict={self.tf_obs: observation[np.newaxis, :]})# 按概率选择动作action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel())return actiondef store_transition(self, s, a, r):self.ep_obs.append(s)self.ep_as.append(a)self.ep_rs.append(r)def learn(self):# 计算折扣奖励discounted_ep_rs = self._discount_and_norm_rewards()# 训练网络self.sess.run(self.train_op, feed_dict={self.tf_obs: np.vstack(self.ep_obs),self.tf_acts: np.array(self.ep_as),self.tf_vt: discounted_ep_rs,})# 清空回合数据self.ep_obs, self.ep_as, self.ep_rs = [], [], []return discounted_ep_rs
六、损失函数深度解析📊
6.1 损失函数:
- l o s s = − l o g ( π ( a ∣ s ) ) × G loss = -log(π(a|s)) \times G loss=−log(π(a∣s))×G
- − l o g ( π ( a ∣ s ) ) -log(π(a|s)) −log(π(a∣s)):动作概率的对数的负值
- 概率小 → 值大(“惊讶”)
- 概率大 → 值小(“不惊讶”)
- G G G:累积奖励
- 正奖励 → 增加动作概率
- 负奖励 → 减少动作概率
6.2 物理意义
场景 | 动作概率 | 奖励 | 更新效果 |
---|---|---|---|
好动作但概率低 | 小 → -log大 | +50 | 大幅提升概率 |
好动作概率高 | 大 → -log小 | +50 | 小幅提升概率 |
坏动作概率高 | 大 → -log小 | -100 | 大幅降低概率 |
坏动作概率低 | 小 → -log大 | -100 | 小幅降低概率 |
七、优缺点分析⚖️
7.1 核心优势
优势 | 说明 |
---|---|
连续动作空间 | 直接输出连续值(如转速0-100%) |
随机策略 | 天然支持概率性决策 |
简单高效 | 无需复杂价值函数估计 |
探索能力 | 内置随机性,无需ε-greedy |
7.2 主要挑战
挑战 | 解决方案 |
---|---|
高方差 | 使用基线(如Actor-Critic) |
样本效率低 | 结合经验回放(如PPO) |
回合制更新 | 使用TD误差进行单步更新 |
八、实际应用技巧💡
8.1 奖励处理技巧
def _discount_and_norm_rewards(self):discounted_rs = np.zeros_like(self.ep_rs)running_add = 0# 反向计算折扣奖励for t in reversed(range(len(self.ep_rs))):running_add = running_add * self.gamma + self.ep_rs[t]discounted_rs[t] = running_add# 标准化奖励(重要!)discounted_rs -= np.mean(discounted_rs)discounted_rs /= np.std(discounted_rs)return discounted_rs
8.2 超参数设置建议
params = {'learning_rate': 0.01, # 通常比 DQN 大'gamma': 0.99, # 折扣因子'hidden_units': 20, # 隐藏层神经元数'entropy_coef': 0.01, # 探索鼓励因子
}
九、扩展知识
9.1 算法演进
算法 | 创新点 | 优势 |
---|---|---|
REINFORCE | 基础PG算法 | 简单直观 |
Actor-Critic | 添加价值函数 | 降低方差 |
PPO | 限制策略更新幅度 | 稳定训练 |
TRPO | 理论保证的优化 | 可靠收敛 |
9.2 常见问题解答
Q:为什么用 − l o g ( π ) -log(π) −log(π) 而不是 − π -π −π?
A: − l o g ( π ) -log(π) −log(π) 在概率接近0时梯度大,能更快调整低概率动作,类似交叉熵损失。
Q:如何平衡探索与利用?
A:神经网络初始输出均匀概率,训练中自动调整,也可添加熵正则化项鼓励探索。
Q:是否支持在线更新?
A:基础REINFORCE需要完整回合,但Actor-Critic变种支持单步更新。
总结:Policy Gradients 让强化学习从"评价动作"转向"直接生成动作",特别适合连续控制问题。就像学习骑自行车 - 不是计算每个动作的价值,而是直接训练肌肉记忆!🚴♂️
好的,我们用简单易懂的方式向初学者介绍一下 Policy Gradient(策略梯度):
十、直观理解
想象一下你在训练一个玩游戏的智能体。它需要决定在屏幕上看到不同画面(状态)时,是选择“跳”、“射击”还是“向左跑”(动作)。最终目标是尽可能多地得分(获得奖励)。
- 传统方法(Value-Based): 很多早期方法(如 Q-Learning)是让 智能体 学习一个“价值表”或“价值函数”。这个函数告诉 智能体:“在某个状态下,选择某个动作,未来大概能得多少分”。智能体 学会这个表后,每次都选“未来得分最高”的那个动作。
- Policy Gradient 方法(策略梯度): 它走了一条更直接的路!它直接学习并优化一个策略本身。
- 策略是什么? 策略就是一个“决策指南”。它告诉 智能体:“在某个状态下,选择每个动作的概率分别是多少”。
- 优化什么? 它有一个包含参数的函数(比如神经网络),这个函数直接输出动作的概率分布(例如:跳:70%,射击:20%,左移:10%)。Policy Gradient 的目标就是调整这个函数的参数,使得智能体执行动作后获得的总奖励(回报)的期望值最大化。
🌐 怎么优化?
- 试错: 智能体用当前的策略玩一回合游戏。它会根据策略的概率分布随机选择动作。
- 记录: 记下它看到的状态、它选择的动作、以及它因为这个动作(和后续动作)得到的奖励。
- 评估好坏: 计算这回合游戏得到的总奖励(或者更精确地说,从选择动作那一刻起获得的“回报”)。
- 调整策略:
- 关键点: 如果一个动作(在某个状态下)带来了高回报,我们就提高策略在未来遇到类似状态时选择这个动作的概率。
- 如果一个动作带来了低回报(或惩罚),我们就降低策略选择它的概率。
- 数学工具(梯度): 这个“提高”或“降低”概率的过程,在数学上是通过计算一个“梯度”来实现的。这个梯度指明了“为了增加期望回报,策略参数应该朝哪个方向(增大还是减小)调整”。然后我们用类似爬山的“梯度上升”方法来更新策略参数。
🌐 为什么叫“梯度”?
因为它使用了微积分中的“梯度”概念。目标是最大化期望回报 J(θ)
(其中 θ
是策略函数的参数)。策略梯度定理告诉我们,这个目标的梯度 ∇J(θ)
可以通过智能体与环境交互的经验来估计。更新规则就是:θ = θ + α * ∇J(θ)
(α
是学习率)。