强化学习笔记:原理、算法、调参一条龙
本文是一篇强化学习笔记,主要涵盖以下内容:1) 数学基础部分介绍了马尔可夫性质、概率质量函数、期望值和方差等概念;2) 强化学习基础概念部分详细讲解了Agent、action、Environment、reward和State等核心要素;3) 值函数方法部分深入分析了状态价值函数和动作价值函数,包括它们的定义、关系以及贝尔曼方程的推导过程。文章还提供了多个优质学习资源的链接,适合有一定基础的读者梳理
强化学习笔记:原理、算法、调参一条龙[含程序]
持续更新中-但由于字数受限,后续文章内容在下面参考资料4的链接进行更新
1: 数学基础
2: 强化学习常见算法
3: 强化学习调参技巧
参考资料
1. 视频-王树森-建议看一下,通俗易懂
2. 笔记-王树森-建议看一下,通俗易懂
3. 超级好的文章-必看!!建议先去看着个文章,再来这边梳理一下!!这个文章思路特别好,给这个博主多点赞,太良心了!!!
4. 后续更新的网页
文章目录
- 强化学习笔记:原理、算法、调参一条龙[含程序]
- 前言
- 一、基础
- 二、常见强化学习方法
- 总结
前言
先去看上面链接强烈安利必看的文章,原文作者写的特别好,本文章主要用来梳理和牢记知识点的!!!
本文章适合有一定基础知识的公式主要来自上面大佬的博客和王树森大佬的书,本文的内容【公式和图】主要是来自参考资料
一、基础
概念
强化学习的模型:
- Agent:智能体,就是我们要训练的模型
- action(简记为a):动作
- Environment:即环境,它是提供reward的某个对象
- reward(简记为r):这个奖励是强化学习的核心
- State(简介为s):可以理解成环境的状态
总的而言,Agent依据策略决策从而执行动作action,然后通过感知环境Environment从而获取环境的状态state,进而,最后得到奖励reward(以便下次再到相同状态时能采取更优的动作),然后再继续按此流程“依据策略执行动作-感知状态–得到奖励”循环进行
1.0. 马尔可夫
马尔可夫性质: 当且仅当某时刻的状态只取决于上一时刻的状态时,一个随机过程被称为具有马尔可夫性质P(St+1|St)=P(St+1|S1,⋯,St),当然了,虽说当前状态只看上一个状态,但上一个状态其实包含了更上一个状态的信息,所以不能说当下与历史是无关的
MRP:在马尔可夫过程的基础上加入奖励函数R和折扣因子γ,就可以得到马尔可夫奖励过程
MDP增加一个来自外界的刺激比如智能体的动作,就得到了马尔可夫决策过程(MDP),有了策略、价值函数和模型3个组成部分后,就形成了一个马尔可夫决策过程
1.0. 概率质量函数
描述随机变量在各个取值上的概率分布的数学函数
- 对于任意实数x,概率密度函数f(x)都是非负的: f ( x ) ≥ 0 f ( x ) ≥ 0 f(x)≥0
- 整个实数轴上的概率密度函数的积分等于1:
- 概率密度函数并不直接给出具体的概率值,而是在某个取值范围内的概率密度。概率密度函数的图形在某个区间上的曲线下方的面积表示该区间内的概率。
1.1. 离散型随机变量 概率质量函数–PMF
它给出了随机变量每个可能取值的概率
1.2. 连续型随机变量 概率质量函数–PDF
它表示在某一点附近的概率密度,而实际概率则是通过对概率密度函数进行积分得到
1.3. 期望值
表示随机变量的乎均值,反映了分布的中心位置
线性性质: 对于常数a和b以及随机变量X、Y,有E(aX+bY)=aE(X)+bE(Y)
独立性质: 如果X和Y是相互独立的随机变量,则E(XY)=E(X)E(Y)
1.4. 方差
随机变量取值的分散程度,即分布的宽窄程度。
1.5. 值函数方法
通过求解一个状态或者状态下某个动作的估值为手段,从而寻找最佳的价值函数,找到价值函数后,再提取最佳策略:比如Q-learning、DQN等,适合离散的环境下,比如围棋和某些游戏领域
1.5.1. 奖励
我们把t时刻的回报return叫做Ut,return这样定义的把t时刻的奖励全都累计加起来,一直加到游戏结束时的最后一个奖励,下面这个是非折扣回报

可用G表示当下即时奖励和所有持久奖励等一切奖励的加权和(考虑到一般越往后某个状态给的回报率越低,也即奖励因子或折扣因子越小,用γ表示),从而有 
1.5.2. 状态价值函数
一个状态的期望回报就称之为这个状态的价值,所有状态的价值则组成了所谓的价值函数,用公式表达为
前半部分表示当前状态得到的即时奖励
后半部分表示当前状态得到的所有持久奖励,可以根据从状态s出发的转移概率得到
状态价值函数的形式2:进一步得到贝尔曼方程
ps:推导过程
1.5.3. 动作价值函数
对当前状态s依据策略π执行动作a得到的期望回报

因此主要取决于:当前状态s;依据策略π;执行动作a
怎么样才能排除掉策略 π 的影响:
最优动作价值函数,意思就是有很多种策略函数π \piπ 可供选择,而我们选择最好的策略函数
进一步:马尔可夫决策的贝尔曼方程
ps:推导
1.5.4. 动作价值函数与状态价值函数的关系
状态值函数 𝑉(𝑠_𝑡)等于在当前策略 𝜋 下,所有可能动作的动作值的期望

ps:简化推导
这边可以简化记忆:状态价值函数是对动作价值函数对动作求期望,这时候消掉了动作,只剩下状态S了
1.5.5. 总结:贝尔曼方程
1.5.5.1 状态价值函数

形式2:
1.5.5.2 动作价值函数

特殊情况:
这时候就是贝尔曼最优方程的价值函数
1.6. 策略优化方法
通过参数化的策略函数来寻找最优的策略。常见的方法包括策略梯度方法 :一般先进行策略评估,即对当前已经搜索到的策略函数进行估值,得到估值后,进行策略改进,不断重复这两步直至策略收敛
适合连续动作的场景,比如机器人控制领域以及Actor-Critic(一般被翻译为演员-评论家算法),Actor学习参数化的策略即策略函数,Critic学习值函数用来评估状态-动作对,不过,Actor-Critic本质上是属于基于策略的算法,毕竟算法的目标是优化一个带参数的策略[实际用到PPO算法时,会计算一个策略损失],只是会额外学习价值函数[相应的,运用PPO算法时,也会计算一个价值损失],从而帮助策略函数更好的学习
1.7. 表格求解法
1.7.1 动态规划
动态规划,其核心思想在于复杂问题的最优解划分为多个小问题的最优解的求解问题,就像递归一样,且子问题的最优解会被储存起来重复利用


相当于当知道奖励函数和状态转换函数时,便可以根据下一个状态的价值来更新当前状态的价值,意味着可以把计算下一个可能状态的价值当成一个子问题,而把计算当前状态的价值看做当前问题,这不刚好就可以用DP来求解了
流程:
# ===== 初始化 =====
V = np.zeros(n_states) # 状态价值函数
policy = np.ones((n_states, n_actions)) / n_actions # 初始为均匀随机策略
iteration = 0
while True:
# ---------- 1. 策略评估 ----------
while True:
delta = 0
for s in range(n_states):
if s in [0, 15]: # 跳过终止状态
continue
v = V[s]
V[s] = sum([policy[s, a] *
sum([1 * (r + gamma * V[s_next])
for s_next, r in [step(s, a)]])
for a in range(n_actions)])
delta = max(delta, abs(v - V[s]))
if delta < theta:
break
# ---------- 2. 策略改进 ----------
policy_stable = True
for s in range(n_states):
if s in [0, 15]:
continue
old_action = np.argmax(policy[s])
# 贪心更新策略
q_values = np.zeros(n_actions)
for a in range(n_actions):
s_next, r = step(s, a)
q_values[a] = r + gamma * V[s_next]
new_action = np.argmax(q_values)
# one-hot 更新
policy[s] = np.eye(n_actions)[new_action]
if old_action != new_action:
policy_stable = False
1.7.2 蒙特卡洛法-MC
通过大量的随机样本来估算或近似真实值
我们也可以用蒙特卡洛方法来估计一个策略在一个马尔可夫决策过程中的状态价值。考虑到一个状态的价值是它的期望回报,那么如果我们用策略在MDP上采样很多条序列,然后计算从这个状态出发的回报再求其期望是否就可以了?
1.7.3 时序差分法TD及与DP、MC的区别


V(St) ← V(St) + α[Gt − V(St)] 的含义是新的估计等于原来的估计,加上实际回报和估计回报之间的差距(误差)乘以一个学习率
时序差分(TD)
TD与DP一致的是,时序差分方法也无需等待交互的最终结果,而可以基于下一个时刻的收益 R t + 1 R_{t+1} Rt+1和估计值 V ( S t + 1 ) V(S_{t+1}) V(St+1)就可以更新当前状态的价值函数
TD与DP不一致的是,TD俗称无模型的RL算法,不需要像DP事先知道环境的奖励函数和状态转移函数(和MC一样,可以直接从与环境互动的经验中学习策略,事实上,很多现实环境中,其MDP的状态转移概率无从得知)
- MC的做法相当于一条道走到黑 没走个10公里不回头
- DP相当于所有道比如10条道 每条道都走个1公里 不错过任何一条可能成为最好道的可能,最后10条道都走完1公里后才返回汇报/反馈
- TD则相当于先选一条道走个1公里即返回汇报/反馈,之后再走下一条道的1公里

1.8. RL的分类


基于模型的强化学习【也就是知道转移概率P和奖励R:就不需要实际执行动作收集这些数据】
可以简单的使用动态规划求解,任务可定义为预测和控制,预测的目的是评估当前策略的好坏,即求解状态价值函数,控制的目的则是寻找最优策略和V∗(s)
无模型的强化学习[动作价值函数比状态价值函数更容易被评估]:
基于价值的强化学习,其会学习并贪婪的选择值最大的动作,即a=argmaxaQ(s,a),最经典的便是off-policy模式的Q-learning和on-policy模式的SARSA,一般得到的是确定性策略
基于策略的强化学习,其对策略进行进行建模 π ( s , a ) \pi (s,a) π(s,a)并优化,一般得到的是随机性策略,下文第四部分会重点介绍
目标策略:我们最终想学出来的最优策略【目标策略就是用于更新 价值公式中“下一步动作选择方式”的策略】,也就是你希望机器人、智能体最后能“照着它行动”的策略,用来指导学习
你在玩游戏,你心里有一套“理想打法”——你认为最优的动作选择方式。比如「看到怪 → 立刻开大招」。
行为策略:当前智能体在环境中“实际执行动作”的策略,用来采样经验(产生数据)
你现在实际在玩的策略,可能会“试试别的路子”或“随机试探”。比如「有时开大招,有时试试闪现看看效果」。
二、常见强化学习方法
2.1.价值学习
特点:
- 通过价值函数(通常是状态值函数或动作值函数)来 评估动作或状态的好坏。
- 通常使用贝尔曼方程来更新价值函数。
- 通过最优值函数来选择最优动作。
- 通常更为稳定,对样本效率的要求较低。
- 在有限状态、离散动作的问题中表现良好。
缺点:对于连续动作空间和高维状态空间的处理可能不够灵活。可能会收敛到局部最优解,特别是在非线性问题上。
2.1.1 TD与Sarsa
2.1.1.1 TD(0)与Sarsa(0)
用类似TD(0)控制的思路寻找最优的动作价值函数并提取出最优策略,便被称作Sarsa(0)算法,它将原本时序差分方法更新V的过程,变成了更新Q
2.1.1.2 TD(n)与Sarsa(n)
多步一更新:
推导:回顾下回报公式的定义,即为(根据前几项可以看出: γ \gamma γ的上标加t+1即为R的下标,反过来,当最后一项R的下标T确定后,自然便可以得出 γ \gamma γ的上标为T -t -1:
G t = R t + 1 + γ R t + 2 + γ 2 R t + 3 + ⋯ + γ T − t − 1 R T G_t = R_{t+1} + \gamma R_{t+2} + \gamma ^2 R_{t+3}+\cdots + \gamma ^{T-t-1}R_T Gt=Rt+1+γRt+2+γ2Rt+3+⋯+γT−t−1RT
2.1.2 Q-learning
2.1.2.1 同策略与异策略

同策略:行动遵循的行动策略与被评估的目标策略是同一个策略,如Sarsa
异策略: 行动遵循的行动策略和被评估的目标策略是不同的策略,如Q-learning,通常是经过重要性采样实现的,但是并不是用了重要性采样就是异策略,如PPO
2.1.2.2 Sarsa算法与Q-learning更新规则的对比

Sarsa(0)算法的更新规则:
Q ( S t , A t ) ← Q ( S t , A t ) + α [ R t + 1 + γ Q ( S t + 1 , A t + 1 ) − Q ( S t , A t ) ] Q(S_t,A_t) \leftarrow Q(S_t,A_t) + \alpha [R_{t+1} + \gamma Q(S_{t+1},A_{t+1}) - Q(S_t,A_t)] Q(St,At)←Q(St,At)+α[Rt+1+γQ(St+1,At+1)−Q(St,At)]
目标策略=行为策略
目标值 target: R t + 1 + γ Q ( S t + 1 , A t + 1 ) R_{t+1} + \gamma Q(S_{t+1},A_{t+1}) Rt+1+γQ(St+1,At+1)下一个动作 A t + 1 A_{t+1} At+1是你真实执行的动作,是当前策略π选出来的动作
流程:
- 采样当前状态与动作观测到当前状态 ( s t ) ( s_t ) (st),根据当前策略采样动作:
a t ∼ π n o w ( ⋅ ∣ s t ) a_t \sim \pi_{\mathrm{now}}(\cdot \mid s_t) at∼πnow(⋅∣st)
价值网络计算 Q 值:
q ^ t = q n o w ( s t , a t , w n o w ) \widehat{q}_t = q_{\mathrm{now}}(s_t, a_t,w_{now}) q t=qnow(st,at,wnow)- 环境交互,获得新状态与奖励
执行动作 ( a t ) ( a_t ) (at),环境反馈奖励 ( r t ) ( r_t ) (rt) 与下一个状态 ( s t + 1 ) ( s_{t+1} ) (st+1)。- 采样下一个动作(由当前策略产生)
a ~ t + 1 ∼ π n o w ( ⋅ ∣ s t + 1 ) \tilde{a}_{t+1} \sim \pi_{\mathrm{now}}(\cdot \mid s_{t+1}) a~t+1∼πnow(⋅∣st+1)注意:
这里的 a ~ t + 1 \tilde{a}_{t+1} a~t+1是假想动作,并不真正执行:仅用于估计目标 Q 值。
对应 Q 取值:
q ^ t + 1 = q n o w ( s t + 1 , a ~ t + 1 ; w n o w ) \widehat{q}_{t+1} = q_{\mathrm{now}}(s_{t+1}, \tilde{a}_{t+1};w_{now}) q t+1=qnow(st+1,a~t+1;wnow)
- 计算 TD 目标与 TD 误差
TD 目标:
y ^ t = r t + γ ⋅ q ^ t + 1 \widehat{y}_t = r_t + \gamma \cdot \widehat{q}_{t+1} y t=rt+γ⋅q t+1
TD 误差:
δ t = q ^ t − y ^ t \delta_t = \widehat{q}_t - \widehat{y}_t δt=q t−y t- 对价值网络q 做反向传播,计算 q关于 w 的梯度 ∇ w q ( s t , a t , w n o w ) ∇ _w q_(s_t, a_t,w_{now}) ∇wq(st,at,wnow)更新价值网络参数

使用任意策略改进算法(如 ε-greedy、softmax 等)更新
Q-learning算法的更新规则:
Q ( S t , A t ) = Q ( S t , A t ) + α [ R t + 1 + γ max a ′ Q ( S t + 1 , a ′ ) − Q ( S t , A t ) ] Q\left(S_{t}, A_{t}\right) = Q\left(S_{t}, A_{t}\right)+\alpha\left[R_{t+1}+\gamma \max _{a'} Q\left(S_{t+1}, a'\right)-Q\left(S_{t}, A_{t}\right)\right] Q(St,At)=Q(St,At)+α[Rt+1+γmaxa′Q(St+1,a′)−Q(St,At)]
目标策略: π \pi π直接在Q表格上使用贪心策略
π ( s t + 1 ) = arg max a ′ ∼ Q ( s t + 1 , a ′ ) \pi\left(s_{t+1}\right) = \underset{a^{\prime}}{\arg \max}\sim Q\left(s_{t+1}, a^{\prime}\right) π(st+1)=a′argmax∼Q(st+1,a′)
行为策略 : μ \mu μ可以是一个随机的策略,,但我们采取 ε − \varepsilon- ε−贪心策略,让行为策略不至于是完全随机的,它是基于Q表格逐渐改进的你执行的动作 a 来自行为策略,(通常是 ε-greedy,有探索成分)
但更新时取的 m a x a ′ Q ( s ′ , a ′ ) max_{a'} Q(s', a') maxa′Q(s′,a′) 来自 目标策略(完全贪心)
使用确定性策略选出的新动作只用于动作价值函数,而不会被真正执行,当动作价值函数更新后,得到新状态,并基于新状态由 ε − \varepsilon- ε−贪心策略选择得到执行行动,这意味着行动策略与目标策略不属于同一个策略
目标值 target:
R t + 1 + γ Q ( S t + 1 , A ′ ) = R t + 1 + γ Q ( S t + 1 , arg max Q ( S t + 1 , a ′ ) ) = R t + 1 + γ max a ′ Q ( S t + 1 , a ′ ) \begin{aligned} R_{t+1}+\gamma Q\left(S_{t+1}, A^{\prime}\right) &=R_{t+1}+\gamma Q\left(S_{t+1},\arg \max ~Q\left(S_{t+1}, a^{\prime}\right)\right) \\ &=R_{t+1}+\gamma \max _{a^{\prime}} Q\left(S_{t+1}, a^{\prime}\right) \end{aligned} Rt+1+γQ(St+1,A′)=Rt+1+γQ(St+1,argmax Q(St+1,a′))=Rt+1+γa′maxQ(St+1,a′)
流程:收集经验与更新表格 Q ~ ~ \tilde{Q} Q~可以同时进行,每当智能体执行一次动作,我们可以用经验回放做几次更新
- 收集训练数据
- 经验回放数组中抽取一个四元组,记作 ( s j , a j , r j , s j + 1 ) (s_j,a_j,r_j,s_{j+1}) (sj,aj,rj,sj+1)
- 把表格 Q ~ n o w \tilde{Q}_\mathrm{now} Q~now中第 ( s j , a j ) (s_j,a_j) (sj,aj)位置上的元素记作: q j = Q ~ n o w ( s j , a j ) q_{j}\:=\:\widetilde Q_{\mathrm{now}}(s_{j},a_{j}) qj=Q now(sj,aj).
- 把表格 Q ~ n o w \tilde{Q}_\mathrm{now} Q~now中第 s j + 1 s_{j+1} sj+1行的最大值记作
- 计算 TD 目标和 TD 误差
6.更新表格
常用策略:
- ∈-greedy策略
2.1.3 DQN
我们希望知道 Q ⋆ Q ⋆ Q⋆,因为它就像是先知一般,可以预见未来,在t时刻就预见t到n时刻之间的累计奖励的期望。在实践中我们不知道Q ⋆ ,近似学习“先知”Q ⋆最有效的办法是深度Q网络记作Q(s,a;w)

其中的 w 表示神经网络中的参数。首先随机初始化w ,随后用“经验”去学习w
用DQN玩游戏:agent每次采取的action是使得Q函数取最大的那个动作,一直玩下去。
在编程实现的时候,TensorFlow 和PyTorch 可以对 DQN 输出向量的一个元素 关于变量 w 自动求梯度
2.1.3.1 把TD算法用到DQN
智能体在环境中观察当前状态 𝑠 𝑡 𝑠_𝑡 st,并按照策略去执行动作 𝑎 𝑡 𝑎_𝑡 at:如ε-greedy,选择动作
def select_action(state, eps): if random.random() < eps: return random.randrange(ACTION_DIM) # 探索 else: # unsqueeze 是为了带 batch 维度 state_v = torch.tensor(state,dtype=torch.float32).unsqueeze(0) q_values = policy_net(state_v) # shape: [1, ACTION_DIM] # dim=1 表示在每一行(即每个样本的动作维度)上取最大值索引 # .item() 把这个单元素 Tensor 变成普通的 Python 整数 return q_values.argmax(dim=1).item() # 利用使用神经网络预测当前价值:根据当前状态获得每个动作价值,我们可以选取根据我们策略执行动作的对应Q,qt=Q(st,at;wt)
q_values = policy_net(s_batch) # shape (B, ACTION_DIM) # .gather(1, a_batch) 表示只取出每个样本执行的动作对应的 Q 值 q_s_a = q_values.gather(1, a_batch) # shape (B,1)执行动作,环境反馈新状态 𝑠 𝑡 + 1 𝑠_{𝑡+1} st+1和奖励 r 𝑡 r_𝑡 rt
s_next, r, done, _ = env.step(a) replay.push(s, a, r, s_next, done)根据 Bellman 方程计算新的目标值 y t = r t + γ ⋅ m a x a Q ( s t + 1 , a ; w t ) y_t=r_t+γ⋅max_aQ(s_{t+1},a;w_t) yt=rt+γ⋅maxaQ(st+1,a;wt):目标值不需要梯度
with torch.no_grad(): q_next = target_net(s_next_batch) # shape (B, A) # PyTorch 的 .max(dim, keepdim) 会返回两个结果 # 1️⃣ [0] → 最大值 # 2️⃣ [1] → 最大值的索引 # dim=1:沿着动作维度(即每一行)取最大值 # keepdim=True:保持原来的维度(方便后续拼接计算) max_q_next = q_next.max(1, keepdim=True)[0] # shape (B,1) y = r_batch + GAMMA * max_q_next
- 计算损失函数,并对当前 Q 函数对参数的梯度 d t d_t dt:自动计算梯度
loss = nn.MSELoss()(q_s_a, y) optimizer.zero_grad() loss.backward() #PyTorch 会自动构建计算图并计算梯度 # optimizer.step() # 就完成参数更新
- 使用 TD 误差更新参数 w t + 1 = w t − α ( q t − y t ) d t w_{t+1}=w_t−α(q_t−y_t)d_t wt+1=wt−α(qt−yt)dt:更新权重
optimizer.step()
2.2.策略学习
特点:
- 直接学习最优策略,而不是通过价值函数间接得到。 直接优化策略参数以最大化累积奖励。
- 策略通常表示为一个参数化的概率分布,例如高斯分布。
- 在连续动作空间和高维状态空间中表现良好,适用于非确定性策略。
- 可以处理高度非线性和连续动作空间。
- 收敛性更好,特别适用于大规模、高维度的问题。
缺点:训练通常更为计算密集。对样本效率要求较高。
策略梯度的核心:
参数为 θ \theta θ的策略 π θ \pi_{\theta} πθ接受状态s,输出动作概率分布,在动作概率分布中采样动作,执行动作(形成运动轨迹 τ \tau τ),得到奖励r,跳到下一个状态
在这样的步骤下,可以使用策略 π \pi π收集一批样本,然后使用梯度下降算法学习这些样本,不过当策略 π \pi π的参数更新后,这些样本不能继续被使用,还要重新使用策略 π \pi π与环境互动收集数据
2.2.1 策略评价
评价策略的好坏:状态价值函数、动作价值函数,说白了,评估策略(包括状态、动作)的价值,就是看其因此得到的期望奖励
2.2.1.1 策略评价的目标函数
虑到期望的定义,由于每一个轨迹 τ \tau τ 都有其对应的发生概率,对所有 τ \tau τ出现的概率与对应的奖励进行加权最后求和,即可得期望值:
R ˉ θ = ∑ τ R ( τ ) p θ ( τ ) = E τ ∼ p θ ( τ ) [ R ( τ ) ] \bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=\mathbb{E}_{\tau \sim p_{\theta}(\tau)}[R(\tau)] Rˉθ=∑τR(τ)pθ(τ)=Eτ∼pθ(τ)[R(τ)]
可以计算某一条轨迹 τ \tau τ发生的概率为『轨迹 τ \tau τ来源于在特定的环境状态下采取特定动作的序列,而特定的状态、特定的动作又分别采样自智能体的动作概率分布 p θ ( a t ∣ s t ) p_{\theta }(a_{t}|s_{t}) pθ(at∣st)、状态的转换概率分布 p ( s t + 1 ∣ s t , a t ) 』 p(s_{t+1}|s_t,a_t)』 p(st+1∣st,at)』
p θ ( τ ) = p ( s 1 ) p θ ( a 1 ∣ s 1 ) p ( s 2 ∣ s 1 , a 1 ) p θ ( a 2 ∣ s 2 ) p ( s 3 ∣ s 2 , a 2 ) ⋯ = p ( s 1 ) ∏ t = 1 T p θ ( a t ∣ s t ) p ( s t + 1 ∣ s t , a t ) \begin{aligned} p_{\theta}(\tau) &=p\left(s_{1}\right) p_{\theta}\left(a_{1} | s_{1}\right) p\left(s_{2} | s_{1}, a_{1}\right) p_{\theta}\left(a_{2} | s_{2}\right) p\left(s_{3} | s_{2}, a_{2}\right) \cdots \\ & =p\left(s_{1}\right) \prod_{t=1}^{T} p_{\theta}\left(a_{t} | s_{t}\right) p\left(s_{t+1} | s_{t}, a_{t}\right) \end{aligned} pθ(τ)=p(s1)pθ(a1∣s1)p(s2∣s1,a1)pθ(a2∣s2)p(s3∣s2,a2)⋯=p(s1)t=1∏Tpθ(at∣st)p(st+1∣st,at)
2.2.1.2 策略梯度更新
想让奖励越大越好,可以使用梯度上升来最大化期望奖励
表示期望的梯度等于对数概率梯度的期望乘以原始函数
主要利用
- ∇ f ( x ) = f ( x ) ∇ log f ( x ) \nabla f(x)=f(x)\nabla \log f(x) ∇f(x)=f(x)∇logf(x)
首先,对函数f(x)取对数得:
log f ( x ) \log f(x) logf(x)
对上式求导数得:
d d x log f ( x ) = 1 f ( x ) d d x \frac{d}{dx}\log f(x) = \frac{1}{f(x)}\frac{d}{dx} dxdlogf(x)=f(x)1dxd
将等式两边同乘以f(x),得到:
f ( x ) d d x log f ( x ) = d d x f(x) \frac{d}{dx} \log f(x) = \frac{d}{dx} f(x)dxdlogf(x)=dxd
这个等式表明,我们可以用 ∇ log f ( x ) \nabla \log f(x) ∇logf(x)来表示 ∇ f ( x ) \nabla f(x) ∇f(x),即: ∇ f ( x ) = f ( x ) ∇ log f ( x ) \nabla f(x)=f(x)\nabla \log f(x) ∇f(x)=f(x)∇logf(x)
- 期望的定义 E [ X ] = ∑ i p i x i E[X] = \sum_{i}^{}p_ix_i E[X]=∑ipixi
2.2.1.3 策略评价问题–策略更新梯度期望无法计算
问题1:
期望值 E τ ∼ p θ ( τ ) [ R ( τ ) ∇ log p θ ( τ ) ] \mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] Eτ∼pθ(τ)[R(τ)∇logpθ(τ)]无法计算
💡思路💡:使用MC来近似求期望:
可以采样N条轨迹 τ \tau τ并计算每一条轨迹的值,再把每一条轨迹的值加起来除以N取平均,即 ( τ n (\tau^{n} (τn上标n代表第n条轨迹,而 a t n 、 s t n a_{t}^{n}、s_{t}^{n} atn、stn则分别代表第n条轨迹里时刻t的动作、状态)
E τ ∼ p θ ( τ ) [ R ( τ ) ∇ log p θ ( τ ) ] ≈ 1 N ∑ n = 1 N R ( τ n ) ∇ log p θ ( τ n ) = 1 N ∑ n = 1 N ∑ t = 1 T n R ( τ n ) ∇ log p θ ( a t n ∣ s t n ) \begin{aligned} \mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\ &=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) \end{aligned} Eτ∼pθ(τ)[R(τ)∇logpθ(τ)]≈N1n=1∑NR(τn)∇logpθ(τn)=N1n=1∑Nt=1∑TnR(τn)∇logpθ(atn∣stn)
即:
∇ R ˉ θ = 1 N ∑ n = 1 N ∑ t = 1 T n R ( τ n ) ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right) ∇Rˉθ=N1∑n=1N∑t=1TnR(τn)∇logpθ(atn∣stn)
更新:
θ ← θ + η ∇ R ˉ θ \theta \leftarrow \theta+\eta \nabla \bar{R}_{\theta} θ←θ+η∇Rˉθ
其中学习率 η \eta η(类似步长、距离的含义),学习率的调整可用 Adam、RMSProp等方法调整
和一般分类问题的区别所在:梯度前面乘一个权重 R ( τ n ) R\left(\tau^{n}\right) R(τn)
REINFORCE算法-高方差+更详细不稳定+无法利用自举
流程:
用策略网络控制智能体从头开始玩一局游戏,得到一条轨迹:收集 (s, a, r, s’) 并存入 buffer
计算所有的回报:从 buffer 采样 batch 更新 Q 网络
回报:
G t = R ( τ ) = ∑ k = t n γ k − t ⋅ r k , ∀ t = 1 , ⋯ , n . G_{t}=R(τ)\:=\:\sum_{k=t}^{n}\gamma^{k-t}\cdot r_{k},\quad\forall\:t=1,\cdots,n. Gt=R(τ)=k=t∑nγk−t⋅rk,∀t=1,⋯,n.for r in reversed(rewards): # 逆序 r_n, r_{n-1}, ..., r_1 G = r + self.gamma * G # G becomes current G_t returns.insert(0, G) # 在头部插入,最终 returns = [G1, G2, ..., Gn] # returns: Python list 长度 n,每个元素是标量 # 转成 tensor,shape [n] returns = torch.tensor(returns, dtype=torch.float32) # 可选:标准化 returns(通常能减小方差,稳定训练) if normalize_returns: returns = (returns - returns.mean()) / (returns.std() + 1e-8)
- 用 { ( s t , a t ) } t = 1 n \{(s_t,a_t)\}_{t=1}^n {(st,at)}t=1n作为数据,做反向传播计算:用 TD 目标更新 Q 网络
∇ θ l n π ( a t ∣ s t ; θ n o w ) , ∀ t = 1 , ⋯ , n . ∇_θlnπ(a_t∣s_t;θ_now),∀t=1,⋯,n. ∇θlnπ(at∣st;θnow),∀t=1,⋯,n.
构造 loss:
实际代码中,我们要最小化损失函数(loss),因为 PyTorch 是做 梯度下降,所以加上负号,所以 PyTorch 中通常写成
这样在 loss.backward() 时就实现了梯度上升# 计算 logπ(a_t|s_t) # 构造 loss = -sum G_t * logπ for s, a, Gt in zip(states, actions, returns): # unsqueeze(0) 在最前面加一个 batch 维度 s_t = torch.FloatTensor(s).unsqueeze(0) # [1, s_dim] # policy(s_t) 输出的是每个动作的概率,输出形状 [1, a_dim] # .squeeze(0) 去掉 batch 维度,变成 [a_dim] probs = self.policy(s_t).squeeze(0) # [a_dim] # Categorical 表示离散分布 dist = torch.distributions.Categorical(probs) # 计算选中动作的 log 概率 logp = dist.log_prob(torch.tensor(a)) # scalar tensor loss = loss + (- logp * Gt)
- 做随机梯度上升更新策略网络参数:定期更新 target 网络,
self.optimizer.zero_grad() # Step 4️⃣:反向传播更新参数 θ,这个相当于∇θloss loss.backward() self.optimizer.step()
2.2.1.4 策略评价问题–花大量来采样数据
问题2:
策略梯度是一个会花很多时间来采样数据的算法,其大多数时间都在采样数据。
因为 E τ ∼ p θ ( τ ) \mathbb{E}_{\tau \sim p_{\theta}(\tau)} Eτ∼pθ(τ)是对策略 π θ \pi_{\theta} πθ采样的轨迹 τ \tau τ求期望,一旦更新了参数,从 θ \theta θ 变成 θ ′ \theta' θ′,在对应状态s下采取动作的概率 p θ ( τ ) p_\theta(\tau) pθ(τ)就不对了,之前采样的数据也不能用了。
💡思路💡:使用重要性采样:
用另外一个策略 π θ ′ \pi_{\theta'} πθ′与环境交互,用 θ ′ \theta' θ′采样的数据去训练 θ \theta θ:
我们可以多次使用 θ ′ \theta' θ′采样到的数据,可以多次执行梯度上升,可以多次更新参数 θ \theta θ, 都只需要用 θ ′ \theta' θ′采样到的同一批数据
需在 R ( τ ) ∇ log p θ ( τ ) R(\tau) \nabla \log p_{\theta}(\tau) R(τ)∇logpθ(τ)的基础上补上一个重要性权重: p θ ( τ ) p θ ′ ( τ ) \frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)} pθ′(τ)pθ(τ)
这个重要性权重针对某一个轨迹 τ \tau τ用 θ \theta θ算出来的概率除以这个轨迹 τ \tau τ用 θ ′ \theta^{'} θ′算出来的概率
加上重要性权重之后,可得
∇ R ˉ θ = E τ ∼ p θ ′ ( τ ) [ p θ ( τ ) p θ ′ ( τ ) R ( τ ) ∇ log p θ ( τ ) ] \nabla \bar{R}_{\theta}=\mathbb{E}_{\tau \sim p_{\theta^{\prime}(\tau)}}\left[\frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)} R(\tau) \nabla \log p_{\theta}(\tau)\right] ∇Rˉθ=Eτ∼pθ′(τ)[pθ′(τ)pθ(τ)R(τ)∇logpθ(τ)]
2.2.1.5 策略评价问题–避免奖励总为正增加
问题3:
实际在做策略梯度的时候,并不是给整个轨迹 τ \tau τ都一样的分数,而是每一个状态-动作的对会分开来计算,但通过蒙特卡洛方法进行随机抽样的时候,可能会出问题,比如在采样一条轨迹时可能会出现
- 所有动作均为正奖励
- 出现比较大的方差【重要性采样时,采样的分布与当前分布之间也可能会出现比较大的方差】
对于第1个问题,举个例子: 比如在某一一个状态,可以执行的动作有a、b、c,但我们可能只采样到动作b或者只采样到动作c,没有采样到动作a
- 但不管采样情况如何,现在所有动作的奖励都是正的,所以采取a、b、 c的概率都应该要提高
- 可实际最终b、c的概率按预期提高了,但因为a没有被采样到,所以a的概率反而下降了
- 然而问题是a不一定是一个不好的动作,它只是没有被采样到
💡思路💡:在之前梯度计算的公式基础上加一个基准线b:
此b指的baseline,非上面例子中的b,这个所谓的基准线b可以是任意函数,只要不依赖于动作a即可
∇ R ˉ θ ≈ 1 N ∑ n = 1 N ∑ t = 1 T n ( R ( τ n ) − b ) ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(R\left(\tau^{n}\right)-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) ∇Rˉθ≈N1∑n=1N∑t=1Tn(R(τn)−b)∇logpθ(atn∣stn)
理解:
没引入基线之前我们对目标函数求梯度是这个式子”
引入基线之后我们对目标函数求梯度是这个式子
是可以通过数学证明引入基线并不改变目标函数的梯度的,所以说我们接下来的推导都是基于第二个式子进行的
b到底该如何取值?
- 使用轨迹上的奖励均值,即 b = 1 T ∑ t = 0 T R t ( τ ) b = \frac{1}{T}\sum_{t=0}^{T}R_t(\tau ) b=T1∑t=0TRt(τ)
从而使得 R ( τ ) − b R(\tau)-b R(τ)−b有正有负
当大于平均值b时,为正,则增加该动作的概率
当小于平均值b时, 为负,则降低该动作的概率
如此,对于每条轨迹,平均而言,较好的50%的动作将得到奖励,避免所有奖励均为正或均为负,同时,也减少估计方差- 还可以是状态价值函数
我们经常选用方案2:
其中 R ( τ ) − b R(\tau)-b R(τ)−b 一般被定义为优势函数 A θ ( s t , a t ) A^{\theta}(s_t,a_t) Aθ(st,at)
优势函数:不断鼓励并探索高于平均预期回报的动作从而指导策略更新,是对一个动作在平均意义上比其他动作好多少的度量
注意事项:
1. A π ( s , a ) = Q π ( s , a ) − V π ( s ) A_\pi (s,a) = Q_\pi (s,a) - V_\pi (s) Aπ(s,a)=Qπ(s,a)−Vπ(s):
该动作相对于特定状态下其他可用动作的执行情况来选择,而不是根据该动作的绝对值。通俗来说就是要估测的是在状态s采取动作a是好的还是不好正的(即大于0),意味着在状态 s采取动作 a获得的回报比在状态 s 采取其他可能的动作获得的平均回报要好,要增加概率;同理负的(即小于0),要减少概率
此外,通常我们只学习状态价值函数, V π ( s ) V_\pi (s) Vπ(s)「比如通过时序差分法估计」,然后通过 V π ( s ) V_\pi (s) Vπ(s)与奖励的结合来估计 Q π Q_\pi Qπ,即 Q π = R + γ V π ( s t + 1 ) Q_\pi = R+ \gamma V_{\pi }(s_{t+1}) Qπ=R+γVπ(st+1)得到动作价值函数
进一步得到:
A π ( s , a ) = Q π ( s , a ) − V π ( s ) = R + γ V π ( s t + 1 ) − V π ( s ) A_\pi (s,a) = Q_\pi (s,a) - V_\pi (s) = R + \gamma V_{\pi }(s_{t+1}) - V_\pi (s) Aπ(s,a)=Qπ(s,a)−Vπ(s)=R+γVπ(st+1)−Vπ(s)
- E ( s t , a t ) ∼ π θ [ A θ ( s t , a t ) ∇ log p θ ( a t n ∣ s t n ) ] \mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta}}\left[A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] E(st,at)∼πθ[Aθ(st,at)∇logpθ(atn∣stn)]
最终在更新梯度的时候,『我们用演员 θ \theta θ去采样出 s t s_{t} st跟 a t a_{t} at,采样出状态跟动作的对 ( s t , a t ) (s_{t},a_{t}) (st,at),计算这个状态跟动作对的优势 A θ ( s t , a t ) A^{\theta }(s_{t},a_{t}) Aθ(st,at)』
结合重要性采样
A θ ( s t , a t ) A^{\theta}(s_t,a_t) Aθ(st,at)是演员 θ \theta θ与环境交互的时候计算出来的,基于重要性采样的原则,当从 θ \theta θ
换到 θ ′ \theta' θ′ 的时候,就需要在E ( s t , a t ) ∼ π θ [ A θ ( s t , a t ) ∇ log p θ ( a t n ∣ s t n ) ] \mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta}}\left[A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] E(st,at)∼πθ[Aθ(st,at)∇logpθ(atn∣stn)]
基础上, A θ ( s t , a t ) A^{\theta}(s_t,a_t) Aθ(st,at)变换成 A θ ′ ( s t , a t ) A^{\theta'}(s_t,a_t) Aθ′(st,at),一变换便得加个重要性权重(即把 s t 、 a t s_{t}、a_{t} st、at用 θ \theta θ采样出来的概率除掉
s t 、 a t s_{t}、a_{t} st、at用 θ ′ \theta^{'} θ′采样出来的概率)E ( s t , a t ) ∼ π θ ′ [ p θ ( s t , a t ) p θ ′ ( s t , a t ) A θ ′ ( s t , a t ) ∇ log p θ ( a t n ∣ s t n ) ] \mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(s_{t}, a_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}, a_{t}\right)} A^{\theta'}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] E(st,at)∼πθ′[pθ′(st,at)pθ(st,at)Aθ′(st,at)∇logpθ(atn∣stn)]
拆解 p θ ( s t , a t ) p_{\theta}(s_{t}, a_{t}) pθ(st,at)和 p θ ′ ( s t p_{\theta'}(s_{t} pθ′(st, a t ) a_{t}) at)
p θ ( s t , a t ) = p θ ( a t ∣ s t ) p θ ( s t ) p θ ′ ( s t , a t ) = p θ ′ ( a t ∣ s t ) p θ ′ ( s t ) \begin{aligned} p_{\theta}\left(s_{t}, a_{t}\right)&=p_{\theta}\left(a_{t}|s_{t}\right) p_{\theta}(s_t) \\ p_{\theta'}\left(s_{t}, a_{t}\right)&=p_{\theta'}\left(a_{t}|s_{t}\right) p_{\theta'}(s_t) \end{aligned} pθ(st,at)pθ′(st,at)=pθ(at∣st)pθ(st)=pθ′(at∣st)pθ′(st)
可得
E ( s t , a t ) ∼ π θ ′ [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) p θ ( s t ) p θ ′ ( s t ) A θ ′ ( s t , a t ) ∇ log p θ ( a t n ∣ s t n ) ] \mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} \frac{p_{\theta}\left(s_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)pθ′(st)pθ(st)Aθ′(st,at)∇logpθ(atn∣stn)]
这里需要做一件事情,假设模型是 θ \theta θ的时候,我们看到 s t s_{t} st的概率,跟模型是 θ ′ \theta^{'} θ′的时候,看到 s t s_{t} st的概率是差不多的,即 p θ ( s t ) = p θ ′ ( s t ) p_{\theta}(s_t)=p_{\theta'}(s_t) pθ(st)=pθ′(st)。
为什么可以这样假设呢?一种直观的解释就是 p θ ( s t ) p_{\theta}(s_t) pθ(st)很难算,这一项有一个参数 θ \theta θ,需要拿 θ \theta θ去跟环境做互动,算 s t s_{t} st出现的概率。 尤其是如果输入是图片的话,同样的 s t s_{t} st根本就不会出现第二次。我们根本没有办法估这一项,所以就直接无视这个问题
但是 p θ ( a t ∣ s t ) p_{\theta}(a_t|s_t) pθ(at∣st)是很好算,我们有 θ \theta θ这个参数,它就是个网络。我们就把 s t s_{t} st带进去, s t s_{t} st就是游戏画面。 我们有个策略的网络,输入状态 s t s_{t} st,它会输出每一个 a t a_{t} at的概率。所以,我们只要知道 θ \theta θ和 θ ′ \theta' θ′的参数就可以算 p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} pθ′(at∣st)pθ(at∣st)所以,基于这个假设,实际上在更新参数的时候,我们就是按照下式来更新参数:
E ( s t , a t ) ∼ π θ ′ [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) ∇ log p θ ( a t n ∣ s t n ) ] \mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)Aθ′(st,at)∇logpθ(atn∣stn)]
即:最终可以从梯度 ∇ f ( x ) = f ( x ) ∇ log f ( x ) \nabla f(x)=f(x) \nabla \log f(x) ∇f(x)=f(x)∇logf(x)来反推目标函数,,当使用重要性采样的时候,要去优化的目标函数如下式所示,把它记 J θ ′ ( θ ) J^{\theta^{\prime}}(\theta) Jθ′(θ)
J θ ′ ( θ ) = E ( s t , a t ) ∼ π θ ′ [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) ] J^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right] Jθ′(θ)=E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)Aθ′(st,at)]
2.2.1.6 策略评价问题–两个分布相差大
问题4:
两个分布相差大
p、q,当不能从p里面很好的采样数据,而能从 q里面很好的采样数据时,基于重要性采样的原则,虽然我们可以把 p换成任何的 q,但是在实现上,p和 q的差距不能太大,差距太大
这个成立:
但是下面俩个方差不同:
1.
2.3.
💡思路💡:使用信任区域策略优化TRPO:
- 解决重要性采样中两个分布差距太大的问题
- 一个是解决策略梯度算法中步长难以确定的问题
思路:
在这个基础上再加上KL散度约束KL散度:相对熵,而相对熵 = 交叉熵 - shannon熵,其衡量的是两个数据分布p和q之间的差异
左半边是一组原始输入的概率分布曲线p(x),与之并列的是重构值的概率分布曲线q(x),下图右半边则显示了两条曲线之间的差异KL散度的公式
- 概率:定义概率分布为p(x)或q(x)
- 信息:对p(x)取对数,加符号得正值 I ( p ) I(p) I(p) = -logp(x)
- 熵:熵是信息的平均,直观上,Shannon熵是信息在同一分布下的平均,概率越高,包含的信息越小,因为事件越来越确定;相反,概率越低,包含的信息越多,因为事件具有很大的不确定性
- 交叉熵:即指p(x)对I(q)平均
- KL散度 = 交叉熵 - shannon熵
最前面加个负号,再结合Jensen不等式
2.2.1.7 策略评价问题–计算量太大了
问题5:
把 KL 散度约束当作一个额外的约束,没有放在目标里面,导致TRPO很难计算,总之因为信任域的计算量太大了,PPO算法是针对TRPO计算量的大的问题提出来的
利用 New Policy 和 Old Policy 的比例,限制了 New Policy 的更新幅度,让策略梯度对稍微大点的 Step size 不那么敏感
💡思路💡:使用PPO:
PPO算法有两个主要的变种:
- 近端策略优化惩罚(PPO-penalty):用上了KL散度约束
流程:
- 目标函数: J θ ′ ( θ ) = E ( s t , a t ) ∼ π θ ′ [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) ] J^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} \mid s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} \mid s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right] Jθ′(θ)=E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)Aθ′(st,at)]
- 初始化一个策略的参数 θ \theta θ,用前一个训练的迭代得到的actor的参数 θ \theta θ’与环境交互,采样到大量状态-动作对, 根据 θ ′ \theta ' θ′交互的结果,估测 A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)
- 加入约束:为了 p θ ( a t ∣ s t ) p_{\theta}\left(a_{t} | s_{t}\right) pθ(at∣st)不能与 p θ ′ ( a t ∣ s t ) p_{\theta'}\left(a_{t} | s_{t}\right) pθ′(at∣st)相差太多,这个约束就好像正则化的项一样,是 θ \theta θ与 θ ′ \theta' θ′输出动作的 KL散度,用于衡量 θ \theta θ 与 θ ′ \theta' θ′ 的相似程度
J P P O θ ′ ( θ ) = J θ ′ ( θ ) − β K L ( θ , θ ′ ) \\J_{\mathrm{PPO}}^{\theta^{\prime}}(\theta)=J^{\theta^{\prime}}(\theta)-\beta \mathrm{KL}\left(\theta, \theta^{\prime}\right) JPPOθ′(θ)=Jθ′(θ)−βKL(θ,θ′)
也就是
J P P O θ ′ ( θ ) = E ( s t , a t ) ∼ π θ ′ [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) ] − β K L ( θ , θ ′ ) J_{\mathrm{PPO}}^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} \mid s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} \mid s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right]-\beta \mathrm{KL}\left(\theta, \theta^{\prime}\right) JPPOθ′(θ)=E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)Aθ′(st,at)]−βKL(θ,θ′)
β \beta β是可以动态调整的,故称之为自适应KL惩罚(adaptive KL penalty)动态调整流程:
- 设一个可以接受的 KL 散度的最大值 K L m a x KL_{max} KLmax和最小值 K L m i n KL_{min} KLmin
K L m a x KL_{max} KLmax:为了防止 θ \theta θ与 θ ′ \theta' θ′差距过大(即学习率/步长过大),也就代表后面惩罚的项 β K L ( θ , θ ′ ) \beta \mathrm{KL}(\theta ,\theta ') βKL(θ,θ′)惩罚效果太弱,这时候 β \beta β要增大
K L m i n KL_{min} KLmin:意味着 θ \theta θ与 θ ′ \theta' θ′差距过小,也就代表后面这一项 β K L ( θ , θ ′ ) \beta \mathrm{KL}(\theta ,\theta ') βKL(θ,θ′)的惩罚效果太强了,我们怕它只优化后一项,使 θ \theta θ与 θ ′ \theta' θ′一样,这时候 β \beta β要减小
- 近端策略优化裁剪(PPO-clip)
目标函数里面没有 KL 散度,但和KL散度约束所要做的事情本质上是一样的,都是为了让两个分布之间的差距不致过大,但裁剪算法相对好实现
其要最大化的目标函数为
J P P O 2 θ ′ ( θ ) ≈ ∑ ( s t , a t ) min ( p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) , c l i p ( p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) , 1 − ε , 1 + ε ) A θ ′ ( s t , a t ) ) \begin{aligned} J_{\mathrm{PPO2}}^{\theta'}(\theta) \approx \sum_{\left(s_{t}, a_{t}\right)} \min &\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta'}\left(a_{t} | s_{t}\right)} A^{\theta'}\left(s_{t}, a_{t}\right),{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta'}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right) A^{\theta'}\left(s_{t}, a_{t}\right)\right) \end{aligned} JPPO2θ′(θ)≈(st,at)∑min(pθ′(at∣st)pθ(at∣st)Aθ′(st,at),clip(pθ′(at∣st)pθ(at∣st),1−ε,1+ε)Aθ′(st,at))理解:
在min这个大括号里有两部分,最终对比两部分那部分更小,就取哪部分的值,这么做的本质目标就是为了让 p θ ( a t ∣ s t ) 和 p θ ′ ( a t ∣ s t ) p_{\theta }(a_{t}|s_{t})和p_{\theta'}(a_{t}|s_{t}) pθ(at∣st)和pθ′(at∣st)可以尽可能接近,不致差距太大。
- clip括号里的部分:使得 p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)其值最小不小于 ( 1 − ε ) (1- \varepsilon) (1−ε),最大不大于 ( 1 + ε ) (1+\varepsilon) (1+ε)
- A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at):大于0,则说明这是好动作,需要增大,小于0,则说明该动作不是好动作,需要减小
- 例子:见红线
A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)大于0, p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)大于 ( 1 + ε ) (1+\varepsilon) (1+ε),min= A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)x ( 1 + ε ) (1+\varepsilon) (1+ε)
A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)大于0, p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)小于 ( 1 − ε ) (1-\varepsilon) (1−ε),min= A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)x p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)
A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)小于0, p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)大于 ( 1 + ε ) (1+\varepsilon) (1+ε),min= A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)x p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)
A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)小于0, p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) \frac{p_{\theta }(a_{t}|s_{t})}{p_{\theta'}(a_{t}|s_{t})} pθ′(at∣st)pθ(at∣st)小于 ( 1 − ε ) (1-\varepsilon) (1−ε),min= A θ ′ ( s t , a t ) A^{\theta '}(s_t,a_t) Aθ′(st,at)x小于 ( 1 − ε ) (1-\varepsilon) (1−ε)
2.2.1.8 策略评价问题–自举+高估
在强化学习中,“自举”的意思是“用一个估算去更新同类的估算”,类似于“自己把自己给举起来”。
自举的好处是方差小,收敛比较快,坏处是有偏差
用价值网络自己做出的估计去更新价值网络自己
例子:
以TD算法来看
- 损失函数
2. 理解
蒙特卡洛和自举的对比
蒙特卡洛方法 用真实采样的总回报 𝑢𝑡作为目标,是对
Font metrics not found for font: .的无偏估计,但方差大。自举方法(TD) 用自己的估计更新自己,方差小但有偏。
| 方法 | 目标 | 性质 | 方差 | 偏差 | 收敛速度 |
|---|---|---|---|---|---|
| 蒙特卡洛 (Monte Carlo) | ( u t = ∑ k = t n γ k − t r k ) ( u_t = \sum_{k=t}^n \gamma^{k-t} r_k ) (ut=∑k=tnγk−trk) | 无偏 | 高 | 无偏 | 慢 |
| 自举 (Bootstrapping, TD) | ( y ^ t = r t + γ q ( s t + 1 , a t + 1 ; w ) ) ( \widehat{y}_t = r_t + \gamma q(s_{t+1}, a_{t+1}; w) ) (y t=rt+γq(st+1,at+1;w)) | 有偏 | 低 | 有偏 | 快 |

策略评价问题–高估
Q 学习算法有一个缺陷:用 Q 学习训练出的 DQN 会高估真实的价值,而且高估通常是非均匀的。
- 产生高估的原因有两个
- 第一,自举导致偏差的传播
- 第二,最大化导致 TD 目标高估真实价值。
TD 算法属于“自举”,即用 DQN 的估计值去更新 DQN 自己。自举会导致偏差的传播。
即使 DQN 是真实价值 Q ⋆ 的无偏估计,只要 DQN 不恒等于 Q ⋆,TD 目标就会高估真实价值。TD 目标是高估,而Q学习算法鼓励 DQN 预测接近 TD 目标,因此DQN 会出现高估
- 产生高估的危害
如果高估是均匀的,则高估没有危害;如果高估非均匀,就会有危害。高估本身不是问题, 只要所有动作价值被同等高估,如果 DQN 有非均匀的高估,那么用 DQN 做出的决策是不可靠的
💡思路💡:切断自举:
原始的 Q学习算法用 DQN 计算 y ^ \widehat{y} y
,然后拿 y ^ \hat{y} y^更新 DQN 自己, 造成自举,可以改用目标网络计算 y ^ \widehat{y} y ,这样就避免了用 DQN 的估计更新 DQN 自己,降低自举造成的危害。然而这种方法不能完全避免自举,原因是目标网络的参数仍然与 DQN 相关。
双 Q 学习算法
double DQN, 缩写 DDQN
对比
- 原始的 Q 学习算法选择和求值都用目标网络:
- 双 Q 学习,第一步的选择用 DQN, 第二步的求值用目标网络
为什么双 Q 学习可以缓解最大化造成的高估呢?
双 Q 学习得到的 TD 目标更小,双 Q学习缓解了高估
流程
设当前 DQN(在线网络)参数为 w n o w \boldsymbol{w}_{\mathrm{now}} wnow,目标网络参数为 w n o w − \boldsymbol{w}_{\mathrm{now}}^{-} wnow−。
从经验回放池随机取出一个样本四元组 ( s j , a j , r j , s j + 1 ) (s_j, a_j, r_j, s_{j+1}) (sj,aj,rj,sj+1),每次按下面步骤更新一次在线网络与目标网络。
- 在线网络前向得到当前 Q 值
q ^ j = Q ( s j , a j ; w n o w ) \widehat{q}_j = Q(s_j, a_j; \boldsymbol{w}_{\mathrm{now}}) q j=Q(sj,aj;wnow)q_values = policy_net(s) # shape [B, A] q_j =q_values.gather(1, a) # shape [B, 1]
- 用在线网络选择下步的贪婪动作(argmax) a ⋆ = arg max a ∈ A Q ( s j + 1 , a ; w n o w ) a^\star = \arg\max_{a\in\mathcal{A}} Q(s_{j+1}, a; \boldsymbol{w}_{\mathrm{now}}) a⋆=arga∈AmaxQ(sj+1,a;wnow)
with torch.no_grad(): q_next_online = policy_net(s_next) # [B, A] a_star = q_next_online.argmax(dim=1, keepdim=True) # [B,1] 动作索引
- 用目标网络估计该动作的 Q 值
q ^ j + 1 = Q ( s j + 1 , a ⋆ ; w n o w − ) \widehat{q}_{j+1} = Q(s_{j+1}, a^\star; \boldsymbol{w}_{\mathrm{now}}^{-}) q j+1=Q(sj+1,a⋆;wnow−)
(注意:评估使用目标网络,这就是 Double DQN
把选择与评估分离的要点)with torch.no_grad(): q_next_online = policy_net(s_next) # [B, A] a_star = q_next_online.argmax(dim=1, keepdim=True) # [B,1] 动作索引 # 3) q_hat_{j+1} = Q(s_{j+1}, a*; w_now^- ) 用目标网络评估 q_next_target = target_net(s_next) # [B, A] q_j1 = q_next_target.gather(1, a_star) # [B,1]
- 计算 TD 目标与 TD 误差
TD 目标: y ~ j = r j + γ q ^ j + 1 \tilde{y}_j = r_j + \gamma \widehat{q}_{j+1} y~j=rj+γq j+1 TD 误差:
δ j = q ^ j − y ~ j \delta_j = \widehat{q}_j - \tilde{y}_j δj=q j−y~jwith torch.no_grad(): q_next_online = policy_net(s_next) # [B, A] a_star = q_next_online.argmax(dim=1, keepdim=True) # [B,1] 动作索引 # 3) q_hat_{j+1} = Q(s_{j+1}, a*; w_now^- ) 用目标网络评估 q_next_target = target_net(s_next) # [B, A] q_j1 = q_next_target.gather(1, a_star) # [B,1] # 4) 计算 TD 目标 y_tilde = r + gamma * q_j1 * (1 - done) y_tilde = r + gamma * q_j1 * (1.0 - done) # [B,1]
- 对在线网络做反向传播得到梯度
计算关于 w n o w \boldsymbol{w}_{\mathrm{now}} wnow 的梯度 ∇ w Q ( s j , a j ; w n o w ) \nabla_{\boldsymbol{w}} Q(s_j, a_j; \boldsymbol{w}_{\mathrm{now}}) ∇wQ(sj,aj;wnow)
:实际用 PyTorch 的loss.backward()自动计算with torch.no_grad(): q_next_online = policy_net(s_next) # [B, A] a_star = q_next_online.argmax(dim=1, keepdim=True) # [B,1] 动作索引 # 3) q_hat_{j+1} = Q(s_{j+1}, a*; w_now^- ) 用目标网络评估 q_next_target = target_net(s_next) # [B, A] q_j1 = q_next_target.gather(1, a_star) # [B,1] # 4) 计算 TD 目标 y_tilde = r + gamma * q_j1 * (1 - done) y_tilde = r + gamma * q_j1 * (1.0 - done) # [B,1] # 5) 构造损失 L = 0.5 * (q_j - y_tilde)^2 (或者用 MSELoss)+反向传播更新在线网络参数 # 细节!!!! # NOTE:如果我们 不加 .detach(),PyTorch 会认为 y_tilde 也需要参与反向传播(因为它是通过 target_net 计算出来的),这会导致梯度从目标网络流回去,使得目标网络也被更新(这违反了算法设计) loss =nn.MSELoss()(q_j, y_tilde.detach()) optimizer.zero_grad() loss.backward() # optimizer.step()
- 用梯度下降更新在线网络参数
理论形式(单步梯度形式):
w ∗ new ← w ∗ n o w − α , δ j , ∇ w Q ( s j , a j ; w n o w ) \boldsymbol{w}*{\text{new}} \leftarrow \boldsymbol{w}*{\mathrm{now}} - \alpha ,\delta_j ,\nabla_{\boldsymbol{w}} Q(s_j, a_j; \boldsymbol{w}_{\mathrm{now}}) w∗new←w∗now−α,δj,∇wQ(sj,aj;wnow) 实践中通常把上式等价地通过最小二乘损失优化实现(MSE):
L ( w ) = 1 2 ( Q ( s j , a j ; w ) − y ~ j ) 2 \mathcal{L}(\boldsymbol{w}) = \tfrac{1}{2}\big(Q(s_j,a_j;\boldsymbol{w}) - \tilde{y}_j\big)^2 L(w)=21(Q(sj,aj;w)−y~j)2
然后optimizer.step()。optimizer.step()
- 软更新目标网络参数(Polyak / EMA)
设 τ ∈ ( 0 , 1 ) \tau\in(0,1) τ∈(0,1),做加权平均更新目标网络: w new − ← τ w new + ( 1 − τ ) w n o w − \boldsymbol{w}_{\text{new}}^{-} \leftarrow \tau\boldsymbol{w}_{\text{new}} + (1-\tau)\boldsymbol{w}_{\mathrm{now}}^{-} wnew−←τwnew+(1−τ)wnow−(当 τ = 1 \tau=1 τ=1 时相当于直接替换;常用较小 τ \tau τ 如 0.001 做平滑更新。)
for param_new, param_target in zip(policy_net.parameters(), target_net.parameters()): param_target.data.copy_(tau * param_new.data + (1.0 - tau) * param_target.data)
2.2.1.9 价值学习高级技巧-经验回放
经验回放的意思是把智能体与环境交互的记录 (即经验) 储存到一个数组里,事后反复利用这些经验训练智能体。需要人为指定数组的大小 (记作 b)。数组中只保留最近b条数据;通常设置 b为 1 0 5 ∼ 1 0 6 10^5\sim10^6 105∼106
经验回放
- 在实践中,要等回放数组中有足够多的四元组时,才开始做经验回放
- 经验回放的一个好处在于打破序列的相关性+重复利用收集到的经验
- 经验回放数组里的数据全都是用行为策略控制智能体收集到的
- 经验回放数组中的经验通常是过时的行为策略收集的,而我们真正想要学的目标策略不同于过时的行为策略
样本数量是指智能体从环境中获取的奖励 r 的数量,更新次数是从经验回放数组里取出一个或多个四元组,用它对参数w 做更新,通常来说,样本数量更重要, 因为在实际应用中收集经验比较困难
优先经验回放
它比普通的经验回放效果更好:既能让收敛更快,也能让收敛时的平均回报更高。优先经验回放给每个四元组一个权重,然后根据权重做非均匀随机抽样,如果 DQN 对 ( s j , a j ) (s_j,a_j) (sj,aj) 的价值判断不准确,即 Q ( s j , a j ; w ) Q(s_j,a_j;\boldsymbol{w}) Q(sj,aj;w)离 Q ⋆ ( s j , a j ) Q_\star(s_j,a_j) Q⋆(sj,aj)Q较远,则四元组 ( s j , a j , r j , s j + 1 ) (s_j,a_j,r_j,s_{j+1}) (sj,aj,rj,sj+1)应当有较高的权重
设想你用强化学习训练一辆无人车。经验回放数组中的样本绝大多数都是车辆正常行驶的情形,只有极少数样本是意外情况,比如旁边车辆强行变道、行人横穿马路、警察封路要求绕行。数组中的样本的重要性显然是不同的。绝大多数的样本都是车辆正常行驶,而且正常行驶的情形很容易处理,出错的可能性非常小。意外情况的样本非常少,但是又极其重要,处理不好就会车毁人亡。所以意外情况的样本应当有更高的权重,受到更多关注。这两种样本不应该同等对待。
如何抽样
如果 TD 误差的绝对值 ∣ δ j ∣ ∣δ_j∣ ∣δj∣大,说明 DQN 对 ( s j , a j ) (s_j,a_j) (sj,aj) 的价值判断不准确,则四元组 ( s j , a j , r j , s j + 1 ) (s_j,a_j,r_j,s_{j+1}) (sj,aj,rj,sj+1)应当有较高的权重
两种方法设置抽样概率
- p j ∝ ∣ δ j ∣ + ϵ p_j∝∣δ_j∣+ϵ pj∝∣δj∣+ϵ
此处的ϵ是个很小的数,防止抽样概率接近零,用于保证所有样本都以非零的概率被抽到
- p j p_j pj∝ 1 / r a n k ( j ) 1/rank(j) 1/rank(j)
此处的 r a n k ( j ) rank(j) rank(j)是 ∣ δ j ∣ ∣δ_j∣ ∣δj∣的序号,大的 ∣ δ j ∣ ∣δ_j∣ ∣δj∣序号小,小的 ∣ δ j ∣ ∣δ_j∣ ∣δj∣序号大,原理一样都是 ∣ δ j ∣ ∣δ_j∣ ∣δj∣大的样本的抽到的概率大
问题1:不同的样本有不同的抽样概率,这样会导致 DQN 的预测有偏差
解决方法: 应该相应调整学习率,抵消掉不同抽样概率造成的偏差
TD 算法用“随机梯度下降”来更新参数 w n e w ← w n o w − α ⋅ g w_{new}← w_{now}−α⋅g wnew←wnow−α⋅g此处的α是学习率,g 是损失函数关于w 的梯度。如果用均匀抽样,那么所有样本有相同的学习率 α \alpha α。如果做非均匀抽样的话,应该根据抽样概率来调整学习率 α \alpha α。如果一条样本被抽样的概率大,那么它的学习率就应该比较小,可以这样设置学习率,其中 b是经验回放数组中样本的总数,β∈(0,1) 是个需要调的超参数【(论文里建议一开始让β比较小,最终增长到 1):β=0:没有修正,完全按优先抽样,β=1:完全修正成均匀抽样(无偏差)】
均匀抽样是一种特例,即所有抽样概率都相等
问题2:样本抽样概率大,学习率小,如当β=1时,如果抽样概率 p j p_j pj变大 10 倍,则学习率 α j \alpha_j αj减小 10 倍。岂不是抵消了吗,那么优先经验回放有什么意义呢?
“概率高 → 更新更频繁(抽样次数多)”,
但 每次抽样都是一次新的、独立的随机梯度估计。
这与“重复使用同一个样本多次”完全不同!
2.2.1.10 价值学习高级技巧-对决网络
在传统 DQN 中,神经网络直接学习:Q(s,a;,w)——即状态 s 下每个动作 a 的价值。
问题是:有些状态下,动作几乎没差别,比如:
小车停在坡底,不论左移右移,状态都差不多。
那在这种状态下,网络还要对每个动作都输出一个 Q 值,学习效率很低。
🧠能不能把状态的“整体好坏”和动作的“相对好坏”分开?
拆分思想:状态价值 + 优势函数
- 状态价值函数 V(s): 表示当前状态本身的价值。
- 优势函数 D(s, a)(有时也写成 A(s,a)): 表示在这个状态下,不同动作之间的相对差异。
于是直觉上:Q(s,a) = V(s) + D(s,a)
问题:这样写不唯一
假设我把 ( V(s) ) 加 10,同时把所有 ( D(s,a) ) 减 10,
那 ( Q(s,a) ) 的值一点没变。这叫做可加不确定性,会导致网络训练时不稳定,难以收敛。
解决:中心化(去除偏移)
让 ( D(s,a) ) 的“平均”或“最大值”为 0。这样 ( D ) 只表示“相对差距”,不会整体漂移。
有两种常见写法:
- 方法 1(论文中最常见):
Q ( s , a ) = V ( s ) + D ( s , a ) − 1 ∣ A ∣ ∑ a ′ D ( s , a ′ ) Q(s,a) = V(s) + D(s,a) - \frac{1}{|\mathcal{A}|}\sum_{a'}D(s,a') Q(s,a)=V(s)+D(s,a)−∣A∣1∑a′D(s,a′)
即让 D 的平均值为 0。- 方法 2(部分实现中):
Q ( s , a ) = V ( s ) + D ( s , a ) − max a ′ D ( s , a ′ ) Q(s,a) = V(s) + D(s,a) - \max_{a'}D(s,a') Q(s,a)=V(s)+D(s,a)−maxa′D(s,a′)
即让 D 的最大值为 0。
无论哪种方式,目的相同:
让 ( D(s,a) ) 只表示相对优势,而不是绝对偏移。
现在你得到的 Q 网络是:
Q ( s , a ; w ) = V ( s ; w V ) + D ( s , a ; w D ) − max a ′ D ( s , a ′ ; w D ) Q(s,a;w) = V(s;w^V) + D(s,a;w^D) - \max_{a'}D(s,a';w^D) Q(s,a;w)=V(s;wV)+D(s,a;wD)−maxa′D(s,a′;wD)
或者
Q ( s , a ; w ) = V ( s ; w V ) + D ( s , a ; w D ) − m e a n a ′ D ( s , a ′ ; w D ) Q(s,a;w) = V(s;w^V) + D(s,a;w^D) - mean_{a'}D(s,a';w^D) Q(s,a;w)=V(s;wV)+D(s,a;wD)−meana′D(s,a′;wD)

可以让两个神经网络 V ( s ; w V ) , D ( s , a ; w D ) V(s;w^V) , D(s,a;w^D) V(s;wV),D(s,a;wD)共享部分卷积层;这些卷积层把输入的状态s映射成特征向量,特征向量是“优势头”与“状态价值头”的输入。优势头输出一个向量,向量的维度是动作空间的大小|A|, 向量每个元素对应一个动作。
2.2.1.11 价值学习高级技巧-噪声网络
在普通 DQN 里,网络参数是固定确定的(训练过程中虽然会更新,但每次 forward 时不随机):Q(s,a; w)此时策略是确定的,因此我们还需要外部加一个 ε-greedy 来让智能体偶尔探索。
噪声 DQN 的想法:
“既然我每次选动作都要加随机性,不如让这种随机性直接来源于网络参数本身的扰动。”
于是,定义带噪声的参数:
w = μ + σ ∘ ξ w = \mu + \sigma \circ \xi w=μ+σ∘ξ
其中:
- ( μ \mu μ ):参数的均值,可训练;
- ( σ \sigma σ ):参数的标准差,可训练;
- ( ξ ∼ N ( 0 , 1 ) \xi \sim \mathcal{N}(0,1) ξ∼N(0,1) ):每次 forward 都随机采样;
- “∘”表示逐元素相乘。
这样,每次输入相同状态 s ,因为噪声不同,输出的 Q 值也略不同 ⇒策略自然就会“探索”,而不再需要 ε-greedy。
处理
1️⃣ 如果参数是向量:
w i = μ i + σ i ξ i w_i = \mu_i + \sigma_i \xi_i wi=μi+σiξi
2️⃣ 如果参数是矩阵:
w i j = μ i j + σ i j ξ i j w_{ij} = \mu_{ij} + \sigma_{ij} \xi_{ij} wij=μij+σijξij
每个元素独立地加噪声。
嵌入到神经网络中的层结构
标准全连接层(无噪声): z = R e L U ( W x + b ) z = \mathrm{ReLU}(Wx + b) z=ReLU(Wx+b) 其中 ( W,b ) 是确定参数。
现在替换为带噪声参数: z = R e L U ( ( W μ + W σ ∘ W ξ ) x + ( b μ + b σ ∘ b ξ ) ) z = \mathrm{ReLU}\Big((W^{\mu} + W^{\sigma} \circ W^{\xi})x + (b^{\mu} + b^{\sigma} \circ b^{\xi})\Big) z=ReLU((Wμ+Wσ∘Wξ)x+(bμ+bσ∘bξ))
公式中 W μ , W σ , b μ , b σ W^{\mu}, W^{\sigma},b^{\mu},b^{\sigma} Wμ,Wσ,bμ,bσ此时每次 forward 时都随机生成
W ξ , b ξ W^{\xi}, b^{\xi} Wξ,bξ ,网络输出带有随机性。 这种随机性来源于结构本身,而不是外部 ε。噪声 DQN 的 Q 网络定义
原始 DQN:Q(s,a; w)
带噪声 DQN: Q ~ ( s , a , ξ ; μ , σ ) = Q ( s , a ; μ + σ ∘ ξ ) \tilde{Q}(s,a,\xi; \mu, \sigma) = Q(s,a; \mu + \sigma \circ \xi) Q~(s,a,ξ;μ,σ)=Q(s,a;μ+σ∘ξ)
反向传播梯度推导
定义损失函数: L = 1 2 ( Q target − Q ( s , a ; μ , σ , ξ ) ) 2 L = \frac{1}{2}(Q_{\text{target}} - Q(s,a; \mu,\sigma,\xi))^2 L=21(Qtarget−Q(s,a;μ,σ,ξ))2
我们要求的是对参数 ( μ , σ \mu,\sigma μ,σ ) 的梯度。
利用链式法则(chain rule):
∂ L ∂ μ = ∂ L ∂ z ⋅ ∂ z ∂ μ , ∂ L ∂ σ = ∂ L ∂ z ⋅ ∂ z ∂ σ \frac{\partial L}{\partial \mu} = \frac{\partial L}{\partial z} \cdot \frac{\partial z}{\partial \mu}, \quad \frac{\partial L}{\partial \sigma} = \frac{\partial L}{\partial z} \cdot \frac{\partial z}{\partial \sigma} ∂μ∂L=∂z∂L⋅∂μ∂z,∂σ∂L=∂z∂L⋅∂σ∂z
而:
z = ( W μ + W σ ∘ W ξ ) x + ( b μ + b σ ∘ b ξ ) z = (W^{\mu} + W^{\sigma} \circ W^{\xi})x + (b^{\mu} + b^{\sigma} \circ b^{\xi}) z=(Wμ+Wσ∘Wξ)x+(bμ+bσ∘bξ)
所以:
∂ z ∂ W μ = x , ∂ z ∂ W σ = ( W ξ ∘ x ) \frac{\partial z}{\partial W^{\mu}} = x, \quad \frac{\partial z}{\partial W^{\sigma}} = (W^{\xi} \circ x) ∂Wμ∂z=x,∂Wσ∂z=(Wξ∘x)
反向传播时,计算完 ( ∂ L ∂ z ) (\frac{\partial L}{\partial z}) (∂z∂L),梯度可以顺利传回 ( μ , σ ) (\mu,\sigma) (μ,σ)。
更新规则:
μ ← μ − α μ ∂ L ∂ μ , σ ← σ − α σ ∂ L ∂ σ \mu \leftarrow \mu - \alpha_\mu \frac{\partial L}{\partial \mu}, \quad \sigma \leftarrow \sigma - \alpha_\sigma \frac{\partial L}{\partial \sigma} μ←μ−αμ∂μ∂L,σ←σ−ασ∂σ∂L
总结
提示:这里对文章进行总结:
更多推荐






























3. 










2. 理解





所有评论(0)