【自用-学习记录】强化学习
学习资料:
1、李宏毅强化学习
视频链接:https://www.bilibili.com/video/BV1jiqoB1EPi?spm_id_from=333.788.videopod.episodes&vd_source=c87e83a3ffcd7880aa0b0bc420d3a334&p=5
2、DPO:
五道口纳什。
视频链接:https://www.bilibili.com/video/BV1pM4m1U75K/?spm_id_from=333.1391.0.0&vd_source=c87e83a3ffcd7880aa0b0bc420d3a334
3、GAE,PPO代码:
东川路第一可爱猫猫虫
视频链接:https://www.bilibili.com/video/BV1KxSTBpEiW?spm_id_from=333.788.videopod.sections&vd_source=c87e83a3ffcd7880aa0b0bc420d3a334
对应代码:https://github.com/DLR-RM/stable-baselines3
4、KL散度的蒙特卡洛估计:
http://joschu.net/blog/kl-approx.html
李宏毅课程学习+网络学习
RL的三要素:reward(即时奖励)与value(长期奖励),actor,environment
分类:
- Actor
- Critic
- Actor-Critic
Actor- based模型: Policy Gradient
从玩游戏出发,一条轨迹
τ
=
{
s
1
,
a
1
,
r
1
,
s
2
,
a
2
,
r
2
,
⋯
,
s
T
,
a
T
,
r
T
}
\tau=\{s_1,a_1,r_1,s_2,a_2,r_2,\cdots,s_T,a_T, r_T\}
τ={s1,a1,r1,s2,a2,r2,⋯,sT,aT,rT}
actor模型是一个NN,负责玩游戏,判断面对每个状态
s
s
s的下一步动作是什么,actor可以看成是有限的下一步动作的分类器,如
π
θ
(
s
)
\pi_{\theta}(s)
πθ(s),执行T步后奖励
R
=
∑
t
=
1
T
r
t
R=\sum_{t=1}^Tr_t
R=∑t=1Trt。
显然 玩游戏的目的是为了最大化所有可能情况的奖励之和
=
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
=
E
τ
∼
π
θ
R
(
τ
)
=\sum_{\tau}R(\tau)P(\tau|\theta)=\mathbb{E}_{\tau\sim\pi_{\theta}}R(\tau)
=∑τR(τ)P(τ∣θ)=Eτ∼πθR(τ)。
参考监督学习,最小化loss可以用梯度下降,同理最大化奖励可以用梯度上升。问题转为了怎么求所有情况奖励之和的梯度。
定义
R
θ
ˉ
=
E
τ
∼
π
θ
R
(
τ
)
\bar{R_{\theta}}=\mathbb{E}_{\tau\sim\pi_{\theta}}R(\tau)
Rθˉ=Eτ∼πθR(τ)表示每次采样的轨迹的总奖励的期望值,可以衡量actor的好坏。
我们需要求
∇
R
θ
ˉ
\nabla\bar{R_{\theta}}
∇Rθˉ 推导如下
∇
R
θ
ˉ
=
∇
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
=
∑
τ
R
(
τ
)
∇
P
(
τ
∣
θ
)
\begin{array}{rl} \nabla\bar{R_{\theta}} =& \nabla\sum_{\tau}R(\tau)P(\tau|\theta) \\ =& \sum_{\tau}R(\tau) \nabla P(\tau|\theta) \end{array}
∇Rθˉ==∇∑τR(τ)P(τ∣θ)∑τR(τ)∇P(τ∣θ)
注意,根据已有知识
∇
log
f
(
x
)
=
1
f
(
x
)
∇
f
(
x
)
\nabla \log f(x)=\dfrac{1}{f(x)}\nabla f(x)
∇logf(x)=f(x)1∇f(x) ,所以把f(x)换成P得到:
∇
P
(
τ
∣
θ
)
=
P
(
τ
∣
θ
)
∇
log
P
(
τ
∣
θ
)
\nabla P(\tau|\theta) = P(\tau|\theta)\nabla \log P(\tau|\theta)
∇P(τ∣θ)=P(τ∣θ)∇logP(τ∣θ)
继续推导
∇
R
θ
ˉ
=
∑
τ
R
(
τ
)
∇
P
(
τ
∣
θ
)
=
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
∇
log
P
(
τ
∣
θ
)
=
E
τ
R
(
τ
)
∇
log
P
(
τ
∣
θ
)
≈
1
N
∑
n
=
1
N
R
(
τ
n
)
∇
log
P
(
τ
n
∣
θ
)
=
1
N
∑
n
=
1
N
R
(
τ
n
)
∇
log
[
P
(
s
1
n
)
P
(
a
1
n
∣
s
1
n
,
θ
)
P
(
r
1
n
,
s
2
n
∣
s
1
n
,
a
1
n
)
⋯
P
(
a
T
n
∣
s
T
n
,
θ
)
P
(
r
T
n
,
s
T
+
1
n
∣
s
T
n
,
a
T
n
)
]
=
1
N
∑
n
=
1
N
R
(
τ
n
)
[
∇
log
P
(
s
1
n
)
+
∑
t
=
1
T
n
∇
log
P
(
a
t
n
∣
s
t
n
,
θ
)
+
∑
t
=
1
T
n
∇
log
P
(
r
t
n
,
s
t
+
1
n
∣
s
t
n
,
a
t
n
)
]
\begin{array}{rl} \nabla\bar{R_{\theta}} =& \sum_{\tau}R(\tau) \nabla P(\tau|\theta) \\ =& \sum_{\tau}R(\tau) P(\tau|\theta)\nabla \log P(\tau|\theta) \\ =& \mathbb{E}_{\tau}R(\tau) \nabla \log P(\tau|\theta)\\ \approx & \dfrac{1}{N}\sum_{n=1}^N R(\tau^n) \nabla \log P(\tau^n|\theta) \\ =& \dfrac{1}{N}\sum_{n=1}^N R(\tau^n) \nabla \log \left[ P(s_1^n) P(a_1^n|s_1^n,\theta)P(r_1^n,s_2^n|s_1^n,a_1^n) \cdots P(a_T^n|s_T^n,\theta)P(r_T^n,s_{T+1}^n|s_T^n,a_T^n) \right]\\ =&\dfrac{1}{N}\sum_{n=1}^N R(\tau^n) \left[ \nabla \log P(s_1^n)+ \sum_{t=1}^{T^n}\nabla \log P(a_t^n|s_t^n,\theta)+ \sum_{t=1}^{T^n}\nabla \log P(r_t^n,s_{t+1}^n|s_t^n,a_t^n) \right] \end{array}
∇Rθˉ===≈==∑τR(τ)∇P(τ∣θ)∑τR(τ)P(τ∣θ)∇logP(τ∣θ)EτR(τ)∇logP(τ∣θ)N1∑n=1NR(τn)∇logP(τn∣θ)N1∑n=1NR(τn)∇log[P(s1n)P(a1n∣s1n,θ)P(r1n,s2n∣s1n,a1n)⋯P(aTn∣sTn,θ)P(rTn,sT+1n∣sTn,aTn)]N1∑n=1NR(τn)[∇logP(s1n)+∑t=1Tn∇logP(atn∣stn,θ)+∑t=1Tn∇logP(rtn,st+1n∣stn,atn)]
注意 我们是对actor的参数
θ
\theta
θ求梯度,而初始状态
s
1
s_1
s1不是actor可控的、是环境决定的,给定状态和动作后的奖励、下一个动作也是环境决定的。所以去掉和
θ
\theta
θ无关的项后继续推导
∇
R
θ
ˉ
=
1
N
∑
n
=
1
N
R
(
τ
n
)
[
∇
log
P
(
s
1
n
)
+
∑
t
=
1
T
n
∇
log
P
(
a
t
n
∣
s
t
n
,
θ
)
+
∑
t
=
1
T
n
∇
log
P
(
r
t
n
,
s
t
+
1
n
∣
s
t
n
,
a
t
n
)
]
=
1
N
∑
n
=
1
N
R
(
τ
n
)
∑
t
=
1
T
n
∇
log
P
(
a
t
n
∣
s
t
n
,
θ
)
=
1
N
∑
t
=
1
T
n
∑
n
=
1
N
R
(
τ
n
)
∇
log
P
(
a
t
n
∣
s
t
n
,
θ
)
\begin{array}{rl} \nabla\bar{R_{\theta}} =&\dfrac{1}{N}\sum_{n=1}^N R(\tau^n) \left[ \nabla \log P(s_1^n)+ \sum_{t=1}^{T^n}\nabla \log P(a_t^n|s_t^n,\theta)+ \sum_{t=1}^{T^n}\nabla \log P(r_t^n,s_{t+1}^n|s_t^n,a_t^n) \right]\\ =&\dfrac{1}{N}\sum_{n=1}^N R(\tau^n) \sum_{t=1}^{T^n}\nabla \log P(a_t^n|s_t^n,\theta)\\ =&\dfrac{1}{N}\sum_{t=1}^{T^n}\sum_{n=1}^N R(\tau^n) \nabla \log P(a_t^n|s_t^n,\theta)\\ \end{array}
∇Rθˉ===N1∑n=1NR(τn)[∇logP(s1n)+∑t=1Tn∇logP(atn∣stn,θ)+∑t=1Tn∇logP(rtn,st+1n∣stn,atn)]N1∑n=1NR(τn)∑t=1Tn∇logP(atn∣stn,θ)N1∑t=1Tn∑n=1NR(τn)∇logP(atn∣stn,θ)
而
∇
log
P
(
a
t
n
∣
s
t
n
,
θ
)
\nabla \log P(a_t^n|s_t^n,\theta)
∇logP(atn∣stn,θ)就是正常的分类器的梯度。
训练过程就是
- 采样N条轨迹,计算梯度
- 更新模型参数,然后转回1
存在的问题:
奖励都是正数,各个操作都被鼓励了。理想情况下,虽然每个操作都被鼓励了,但是因为奖励值是不一样的,鼓励的程度不同,仍然可以使得学到倾向于去做高奖励的动作。
但是实际情况下,我们的公式中是通过采样来近似期望的,采样过程可能会漏掉一些操作,由于其他被采样的操作都被鼓励的,对比下漏掉的操作就被排斥了,而漏掉的操作有可能是高奖励的操作。所以这里会出现问题。
解决办法:
为奖励值设置一个baseline值,
R
(
τ
)
new
=
R
(
τ
)
−
baseline
R(\tau)_{\text{new}} = R(\tau)-\text{baseline}
R(τ)new=R(τ)−baseline,从而使得奖励有高有低。
baseline是期望的奖励值(相当于中等水平的奖励),鼓励做超过期望的操作轨迹,排斥做低于期望的操作轨迹。
Critic-based模型:DQN和Q-Learning
Actor-based模型学习的是Actor,学面对某个状态下应该做哪个下一步操作。
而Critic-based模型学习的是Value,
V
π
(
s
)
V^{\pi}(s)
Vπ(s)表示actor为
π
\pi
π时的状态价值,是从状态
s
s
s到操作轨迹结束的奖励之和 的期望,即状态
s
s
s的长期累积期望奖励。
我们可以用
G
(
t
)
G(t)
G(t)表示从时刻t开始的累积奖励。
实际上,考虑到不同时刻的奖励的重要性不同,G(t)是累积折扣奖励
G
t
=
r
t
+
1
+
γ
r
t
+
2
+
γ
2
r
t
+
3
+
⋯
G_t=r_{t+1}+\gamma r_{t+2}+\gamma^2r_{t+3} +\cdots
Gt=rt+1+γrt+2+γ2rt+3+⋯
学习value函数
怎么学习V函数?有两种方法:
- 蒙特卡洛 Monte Carlo, MC。
- 时序差分
蒙特卡洛求解V:
V
π
(
s
)
=
E
[
G
t
∣
S
t
=
s
]
V^{\pi}(s)=\mathbb{E}\left[G_t|S_t=s\right]
Vπ(s)=E[Gt∣St=s],即状态s下的期望奖励=任意时刻t并且状态为s下的累积奖励 的期望
实际操作就是,采样N条操作轨迹,对每个轨迹从最后一步开始逆向遍历计算G(t)并把G值加入到对应s的桶里,最后每个s的桶里取G值平均,得到
V
π
(
s
)
V^{\pi}(s)
Vπ(s)
但是存在一个问题:一条轨迹里可能出现多次同一个状态s
所以有两种方案:
1、First-Visit MC:一条轨迹里逆向遍历,每个状态只考虑第一次遇到时的贡献
2、Every-Visit MC:逆向遍历,每次遇到都算贡献
逆向遍历是因为
G
t
G_t
Gt有递推关系:
G
t
=
r
t
+
1
+
γ
G
t
+
1
G_t=r_{t+1}+\gamma G_{t+1}
Gt=rt+1+γGt+1
这样N条长度为T的轨迹,处理完的复杂度就是
O
(
N
T
)
O(NT)
O(NT)。
如果正向遍历,每条轨迹的每一步都要统计一遍到最后的累积折扣奖励,复杂度就是
O
(
N
T
2
)
O(NT^2)
O(NT2)
此外还有一个问题,如果轨迹特别大的时候也不方便,所以拿到一个新G值后可以增量更新均值:
N
bucket
(
s
)
=
N
bucket
(
s
)
+
1
V
bucket
(
s
)
=
V
bucket
(
s
)
+
1
N
bucket
(
s
)
[
G
−
V
bucket
(
s
)
]
\begin{array}{rl} N_{\text{bucket}}(s)=&N_{\text{bucket}}(s)+1\\ V_{\text{bucket}}(s)=&V_{\text{bucket}}(s)+\dfrac{1}{N_{\text{bucket}}(s)}\left[G - V_{\text{bucket}}(s)\right] \end{array}
Nbucket(s)=Vbucket(s)=Nbucket(s)+1Vbucket(s)+Nbucket(s)1[G−Vbucket(s)]
EasyR1代码阅读
学习资料:
1、官方代码:
https://github.com/hiyouga/EasyR1
2、代码走读:
https://zhuanlan.zhihu.com/p/1921972845669492319
config配置:https://verl.readthedocs.io/en/latest/examples/config.html#ppo-trainer-yaml-for-rl-fsdp-backend
代码运行入口:EasyR1/examples/xxx.sh
参考配置文件:EasyR1/examples/config.yaml
配置文件
配置文件分为4个部分:
1、data
rollout_batch_size:等价verl的data.train_batch_size
mini_rollout_batch_size:等价verl的data.gen_batch_size
运行过程
1、执行入口:EasyR1/verl/trainer/main.py
- 读取了默认PPO的配置+cli参数。
- 初始化Ray分布式框架,ray运行了自定义类Runner,运行PPO任务。
- 类Runner中:
- 读取文本分词器tokenizer和多模态处理器processor
- 分配资源
- 定义Reward
- 读取训练集和验证集
- 构建Trainer
- 开始训练
2、训练:EasyR1/verl/trainer/ray_trainer.py
- 验证函数:def _validate(self) -> dict[str, Any]
其他学习记录
学习2-系列
学习1
强化学习,需要agent不断地在环境中进行交互实验,通过环境给予的反馈(奖励)来不断优化(状态-行为)的对应关系,目标一般是追求最大回报
强化学习四要素:
- 策略(policy):给定状态(环境状态+智能体状态),策略能判断下一个行为是什么。策略本身可以是具体的映射也可以是随机的分布。
- 奖励(reward):在每个时间步骤内,环境返回的标量值即为奖励,能表征在某一步智能体的表现如何。
- 价值(value):与奖励的即时性不同,价值函数是对长期收益的衡量。它可以评估状态的好坏。价值函数的计算需要对状态之间的转移进行分析
- 环境/模型(model):并非所有的强化学习系统都需要有一个模型,因此会有基于模型(Model-based)、不基于模型(Model-free)两种不同的方法,不基于模型的方法主要是通过对策略和价值函数分析进行学习。模型可以预测环境下一步的表现(即,状态和奖励)。
基于策略和价值的分类,分为三类:
基于价值的方法(Value Based):没有策略但是有价值函数
基于策略的方法(Policy Based):有策略但是没有价值函数
参与评价方法(Actor Critic):既有策略也有价值函数
基于环境的分类,分为两类:
无模型的方法(Model Free):有策略和价值函数,没有模型
基于模型的方法(Model Based):有策略和价值函数,也有模型
探索(Exploration)和利用(Exploitation)
一方面,为了从环境中获取尽可能多的知识,我们要让agent进行探索。
另一方面,为了获得较大的奖励,我们要让agent对已知的信息加以利用。
鱼与熊掌不可兼得,我们不可能同时把探索和利用都做到最优,因此,强化学习问题中存在的一个重要挑战即是如何权衡探索-利用之间的关系。
更多推荐


所有评论(0)