This repository contains my personal learning notes.
- Not tutorials
- Not guaranteed to be correct
- Updated continuously as my understanding evolves
在完成SAC作业时写下的笔记 许多内容是在理解过程中记录的,后续可能会进行修改
学习过程流水线:
- 创建分布时,Independent与Normal
- 为什么要将log_prob在最后一维相加
- TransformedDistribution的作用
- critic网络label获取:
- 根据采样数据中下一时刻状态获取当前策略下一时刻动作
- 使用target critic 获得下一时刻Q-value
- 下一时刻Q-value的backup strategy(Double-Q swap, mean, clip)
- 增加entropy_bonus
- 期望符号去哪了
- double Q loss
- actor 网络更新:
- 熵正则部分,梯度打开了
- 优势函数 * 对数概率 部份梯度关闭了,为什么,反向的时候只从熵正则部分对actor 网络进行参数更新
- 上面的问题理解了,但是有点绕,前一项的梯度没有关闭,只是将action当常量,该项的梯度是同过ation分布的log_prob部分传递的
- actor 重参数化 loss = -q(s,重参数化样本) 重参数化样本 = .rsample() (z = mean() + std * ε)
- target critic更新策略
中断时重启点:
-
作业文档里找 critic 网络 添加熵正则的公式
-
为什么公式里都是用期望,在实际update时没有期望
-
是均方差loss本身是在求样本的期望,所以等价了?
-
double 网络 loss
-
num_actor_samples 是什么意思,一个obs采样多个action?
-
重参数化
-
使用自己的语言和理解描述sac算法
回忆soft-actor-critic 算法流程:
SAC是off-policy RL,replay buffer里的数据来自旧策略,(以前一直以为off-policy 就是当前要更新的动作策略与生成训练数据的使用的策略不是同一个策略,
在完成这个作业时才发现,SAC里actor网络更新时使用动是当前策略中采样的,但是状态来自replay buffer)
- 运行当前策略,生成一批数据加入到replay buffer里 (状态,动作,收益,下一个状态,轨迹是否结束)
- 从replay buffer中采样一批数据D,在(当前策略+过去策略)中随机采样
- critic网络训练:
- 根据下一时刻状态s_t+1,运行actor网络采样一个动作a_t+1 ,这里动作来自当前策略
- 使用target_critic网络计算q(s_t+1,a_t+1),
- 如果使用的双Q网络,可以选择1.交换两者的q_t+1结果 2.求两个q_t+1的均值 3.两个q_t+1选最小值
- 计算entropy bonus,下一时刻动作的概率似然,-log[pi(a_t+1)] 熵应该是它的期望值,这里是使用的采样样本
- 计算target Q-value = r(st,at) + discount * (轨迹是否终止) * (q(s_t+1,a_t+1)-temperature * -log[pi(a_t+1)])
- 使用critic网络估计q(s_t,a_t)与 target Q-value 进行均方差得到loss,反向梯度更新critic网络
- actor网络训练:
- 根据当前时刻状态s_t,运行actor网络采样新动作a1_t
- 使用critic网络估计q(s_t,a1_t),做为策略梯度的权重
- 计算当前actor网络a_t的负对数似然然后乘以q(s_t,a1_t),做为loss的第一项
- 计算entropy bonus,同样根据当前时刻状态s_t,运行actor网络采样新动作a2_t,计算该动作的负对数似然乘以temperature,做为loss的第二项
- 两项相减得到最终的loss,更新actor模型梯度
复习昨天关于SAC的部分(发现以问自己问题的形式来学习高效且有趣)
- 训练critic网络目的是希望能对当前策略产生的(状态,动作)能带来的未来累积收益进行估计
- 那对应的groundtruth就得是当前针对策略的Q-function,记为target_Q_valule
- target_Q_valule在SAC算法中的计算方法是:
- target_Q_valule = r(s_t,a_t) + discount * Q(s_t+1, a_t+1)
- 这里的s_t, a_t, s_t+1, a_t+1,还有Q(...)都指什么?
- Q-function的贝尔曼公式一步展开后应该是:
- 当前状态动作的收益 + 下一时刻状态的value-funtion的期望,
- 而value-funtion又等于该状态下所有动作的Q-function的期望,
- target_Q_valule(groundtruth)为什么能使用的单个轨迹来计算Q_value ?
- 为什么target_Q_value能作为当前策略的Q-value ?
- 计算target_Q_value时使用的Q与要训练的Q为什么不是同一个?
- 为什么使用double-Q?
- 为什么在target_Q_value上也加了熵?
- 在这个算法中熵正则的目的是为了增加动作的探索空间,
- 为什么在critic网络这部分也加而且是加在了groundtruth上?
- wait a minute ,让我思考下,嗯,
- 这里下一时刻的动作是从当前策略里采样出来的,它的Q_value是衡量未来收益,
- 它的熵是表示这个动作概率意义?比如这个动作的Q指很大,但熵很小(在动作空间分布成簇状),
- 或者这个动作Q很大同时熵也很大(在动作空间分布很散),
- 那对训练critic有什么帮助呢?
- 这样组合不就让训练出来的critic网络输出的结果不单纯是估计未来收益了,还包括了熵的信息,
- 这样合理么?目标就不单一了呢
- 均方差loss 或 L2真是个好东西,发现在很多地方用到了它预测的是均值/期望,无偏估计特性,
- 比如在NCSN的Denoising score matching
- actor网络训练部分其实就是on-policy的吧
- 损失函数里有优势函数加权的策略梯度项和熵正则项,
- 作业代码里这两项里求log_prob时用的动作都是来自当前策略,
- 但为什么是不同的动作,不理解,极大的不理解?
- 作业代码里:torch.mean(self.entropy(action_distribution))
- 这里算熵的时候传了策略的分布,而不是采样好的动作
关键点:
- SAC 的 critic 学的是 soft Q
- Bellman target 是 Monte Carlo + bootstrapping 的无偏回归
- actorloss 里使用解析熵(Gaussian),直接用 distribution,不依赖具体 sampled action,是“对分布的期望”;而 target_Q_value 需要的是“期望里的一个样本”,手动进行负对数似然计算 ,而不是解析熵
SAC的论文还没看
今日完成:
- cs224r lecture9 收尾,lecture10补全,
- 这两节课换了讲师,课堂内容有点散,吸收率低了很多,没有想记录的知识点
- 看了篇4D World Model论文,没看完,因为涉及到3DGS的内容,不懂,
- 让chatgpt给讲了下,竟然没有很枯燥,比这篇论文有趣
NeoVerse: Enhancing 4D World Model with in-the-wild Monocular Videos
- pose-free, 不需要依赖相机位姿,这点很有吸引力,看到还要用相机位姿的就头大,这样数据简单了
- 4D是啥?3D物体/场景+时间维度?
- 既能重建也能生成
DPO
- 使用人类偏好数据对来调整模型输出
- 不用训练一个真实reward模型
- kl约束新旧策略
- 本质上还是对比学习,有监督学习
GRPO
- PPO的简化版(训练目标相同,重要性采样+裁剪)
- 去掉PPO的critic部分,不用训练value-function模型
- 那优势函数怎么求?
- 优势函数目的是衡量采取当前动作比平均动作好多少或差多少
- GRPO使用同一prompt采样多个样本,用这个多个样本的收益来模拟平均收益,即组内归一化(group-relative)
- 优势函数=(单个样本收益-减均值)/标准差
FlowMatching
- 拟合一个确定性ODE速度场
- 加噪不是扩散,而是插值采样
- 从x0加噪到xt,在�扩散模型中,xt服从在给定x0的条件概率分布,从这个分布中使用重参数化采样一个xt,同一个x0同一个t得到的xt可能是不同的,是有随机性在的;
- flowmatching中是在数据分布和高斯噪声分布之间做插值采样,给定x0和噪声端x1,中间状态xt是确定的,随机性来自对噪声的采样
- 推理阶段,标准DDPM扩散模型依然是一个条件分布p(xt-1|xt),即使固定初始噪声xT,每次得到的路径也是不同的,因为每一步都要重新采样噪声,(ps:DDIM可以做成确定性的);flowmatch,从同一个初始噪声出发,解ODE,路径是唯一的,轨迹是完全确定的
问:
- flowmatching有什么优势
- flowmatching又付出了什么代价
Flow-GRPO
- 好了,flow的优势在rl面前成了劣势,flow是确定性生成,而rl一大亮点是它通过探索更多的空间动作来寻找更优策略
- online rl需要高效采样数据,flow要multi-step才能生成一个完整的样本
- 在看具体的算法前,先脑海里思考下,如何在flow-matching训练过程中加入grpo?
- 网络输出的是向量场,根据向量场怎么得到似然函数/概率密度p(x_t-1)|x_t,t,c)?
- 论文看完了,这个概率分布是一长串公式推导
- ODE找一个等价的SDE
- 去看看代码
- 看train_wan2_1.py x_t-1部分怎么跟论文公式对不上??
- 仔细核对了,一样的,做了同类项提取
- x_t+Δt∣x_t∼N(μ(x_t,t)Δt,(σ_t)**2ΔtI)--> 概率密度是多维高斯分布
Flow-GRPO 代码部分
- 每个prompt生成m个样本轨迹,每个轨迹包含timesteps(比如20步)个中间状态/动作,每个轨迹各个时刻都是使用该轨迹最终解码的视频来计算reward,进而得到优势函数值,一个轨迹中的每个动作优势函数值相同
- 在单步grpo更新时,优势函数是按照timestep来取值的,但是reward确实是针对一个轨迹(video)来计算的,没找到在哪里对优势函数处理成timestep维度的?
- 从后面mask部分的代码注释,似乎每个timestep的优势函数值还不一样?哪里没对齐呢?
- 对数似然 和 kl? 应该每个时刻都有一个对应的计算值
- 找到了,在这行代码中发生了广播samples["rewards"]["avg"] = samples["rewards"]["avg"].unsqueeze(-1) - config.sample.kl_reward*samples["kl"]
SuperFlow 论文(只看了个开头)
- 针对两个问题:
- 每个prompt都对应m个样本轨迹,忽略不同prompt样本方差,比如有的prompt生成的m个样本,reward都一样,方差小,梯度几乎为0
- 奖励是轨迹层级的,而不是timestep层级的
Flow-GRPO算法流程回忆:
Flow-GRPO
- 论文实验部分
- kl-rewards 对reward hacking的影响
- train-timesteps直接决定训练的速度,太少会影响模型的效果,最佳timesteps(一个轨迹的长度)
- 噪音level控制了探索空间和生成多样性,过大的噪声同样影响生成效果
- groupsize对效果的影响,太小优势函数不准确(方差大)
- 应用到视频领域面临的问题
- 视频一致性,物理规律如何评估
- reward hacking因素更多
- 训练规模更大,如何更高效的训练
SuperFlow 论文
- 在 prompt 维度上,通过 KL-自适应遗忘的 Beta tracker,在线估计稳定的平均 reward 作为 baseline;
- 在时间维度上,根据噪声强度/时间步的重要性,将终态 reward 相对于 baseline 的偏差,重分配为各 denoising step 的 step-wise advantage
- 对每个prompt维护一个KL自适应遗忘的reward均值估计
- 将最终状态reward相对于上述均值估计的偏差,根据噪声(时间步)幅度的权重函数,进行step-wise advantage分配
CS224R lecture11
- model-based rl
- dynamic model 训练 ,输入当前时刻状态动作,输出下一时刻状态
- planning
- gradient-based planning
- Random Shooting
- Cross Entropy Method
DQN
- off-policy
- epsilon-greedy strategy
- 问:在代码中如何实现argmax_a(q(s,a)),如何遍历全部的动作,找到让q(s,a)最大的a呢?
- 答:DQN适用离散场景,可以直接使用下标来表示动作
- 作业代码中给出的critic网络输入只有状态,没有动作,输出是在所有动作上的q(s,a)
- 每一千步更新一次target_critic
- Double-DQN:
- 运行一次critic模型,选择q值最大的动作a下标,假设是k(第k个动作在critic模型下未来收益最大)
- 再运行一次target_critic模型,选择动作k的q值做为target
- vs DQN
- 运行taget_critic模型,输出的是所有动作的q,直接选择最大的那个q做为target
- 先做的SAC的作业,里面也有double-Q,原来跟这里完全不是一回事啊
AWAC
- offline RL
- critic 部分跟DQN里的部分相似,target部分将求最大该成根据动作概率分布求q(s,a)的期望(比DQN中多了actor部分,可以输出动作分布)
- actor网络是离散动作空间,输出logits,返回分布分布distributions.Categorical(logits=logits)
- 离散动作空间,也就限定了所有可能的动作,actor网络输出的动作就不会有超出数据集外的动作出现,这里就不用考虑OOD如何处理的问题
- 优势函数权重计算:
- actor网络输入当前状态s_t,输出动作分布
- critic网络输入当前状态s_t,输出所有动作的q(s_t,a)
- 过滤出样本动作a_t的q(s_t,a_t)
- 根据动作概率和q(s_t,a),求value(s_t),即所有动作的q(s_t,a)的期望
- 计算样本动作a_t的优势函数
- 根据动作分布计算样本动作a_t的对数似然
- loss = 优势函数 * 对数似然 (根据优势函数的权重来调整样本动作的概率),学习高Q的动作
- critic网络的训练依赖的actor
IQL(未完待续)
- 对AWAC进行改造
- actor不再参与critic网络学习
- critic部分增加value-critic
RMSNorm
- 对每个token向量进行归一化,这里是选择均方根而不L2 norm,
- L2 norm是把向量映射成模长为1的向量,每个维度的取值会受到向量维度的影响,维度越大每个维度的值会越小,数值不稳定
- RMSNorm是将向量映射到半径固定的球体表面,每个维度的取值与向量维度解耦,数值稳定
- 用在attn的Q,K上,attn中Q、K 用于打分(score),对数值尺度极端敏感,进行RMSNorm后,不同token的Q,K向量尺度对齐
- 进行RMSNorm后,把所有token向量缩放到 L2 范数 ≈ √d,每个 token 的 Q、K 的模长几乎相同,所有token向量都被映射到一个半径固定(≈√d)的高维球面附近
ROPE
- 目的是两个位置的向量,通过各种绝对位置编码后的向量内积能表示成相对位置的函数
- ...
wan2.1 model
- 时间调制+block调制+self-attn模块调制+ffn模块调制,cross-attn没有调制,只负责条件引入,与时间无关(时间是噪声相关的,条件是噪声无关的,不管当前是高噪声还是低噪声,引入的条件都是一致的)
- i2v是,图像条件token与文本条件token是拼接到一起送入cross-attn模块的,在这里把两个条件分开,各自独立进行cross-attn后,相加
- ...
flash-attn
- 通过减少I/O的次数,提高效率
- 每次完成一个完整的局部操作(分块计算)
- 通过online softmax来对齐全局计算结果
- ...
开了新坑,cs336的作业
IQL
- 模仿数据集中比baseline(平均)好的动作;AWAC是模仿高Q的动作
- 引入了value网络来估计baseline
- 训练value网络时使用不平衡loss,当value网络预测的v(s)低于样本的Q(s,a)时,按正常L2 loss的化,会让value往增加v(s)的方向更新(也就是让v(s),接近Q(s,a)),但在expectile regression,前面的权重小(小于0.5),极端情况比如权重接近与0,那就是模型对这中情况惩罚力度极小,有点默许这种低估的情况,(模型放水了)
- 如果value网络的预测v(s)高于样本Q(s,a)时,前面的权重大(大于0.5),模型对这中高估反感,对惩罚网络降低v(s)的预测,让它不要给高预测
- 训练的结果就是vaule模型偏向与给出较低的v(s)预测,也就是baseline是偏低的
- 在计算优势函数时,A = Q - V,这里的V如果低于真实的数据平均水平的话,那就是说数据集中本来之前不太好的动作,在这种V低估的情况下也有可能 被认为是高于平均水平的好动
- 上面这句话,chatgpt非常不认可,经过一番讨论,最终的理解为:
- 当τ=1时,模型模仿Q值最高的样本进行学;τ=0时模型会对所有的样本进行学习
- 当τ=0.5时模型Q对高于均值的样本进行学习,但是Q本身会有高估计问题,会是均值也高估计,所以模型还是被高Q样本影响大
- 如果τ 稍微低于0.5的话会对这种情况进行修正,将value修正到略微低于均值的稳定点
- 注意 value网络中Q(s,a)来自online critic而不是target critic,target_critic只是在DQN中用来训练critic网络时的label来源,在IQL算法没有target_critic
CQL
- Conservative Q-Learning
- 为了防止OOD动作上的高估值,显示打压不在数据集中的高Q的动作
- 作业中提供的是离散动作场景,正则项计算部分,可以直接通过critic输出所有动作的Q,计算所有动作的logsumexp
- logsumexp 与 max Q(s,a) 与 softmax
model-based (进行中) - 训练动力学模型
更正错误点:
前面理解AWAC时作业给的是离散动作空间
当时的理解是“
- 离散动作空间,也就限定了所有可能的动作,actor网络输出的动作就不会有超出数据集外的动作出现,这里就不用考虑OOD如何处理的问题” 这里是不对的,可以通过下标的方式获取到所有的动作,不等于这些动作都在数据集里出现过,依然会有OOD的情况
截止到目前已经看了模仿学习、策略梯度、actor-critic、PPO、SAC、DQN、IQL、CQL、model-base rl有9个算法了,感觉能理解了一些,知道它们是什么、怎么做,知道相关的算法背景,知道自己知道什么,也隐约知道自己不知道什么,但是还缺一个Aha moment!预计还得进行几次深度思考才能把它们串起来
- 保留任一帧的高频细节
- 能将20s的视频压缩到5k tokens
- 训练了一个历史帧压缩编码器
- 利用这个编码器提取历史帧特征做为视频生成模型的条件
- 对历史帧进行随机mask,剩余的干净帧做为扩散模型重构的目标
- 历史编码器提取的历史帧做为条件,然后利用标准的flowmaching方式来进行任意历史帧重构
今天主要复习flash attention
向Claude Sonnet 4.5进行傻瓜式提问
问题汇总(一字未改)
-
在脚本中 cu_seqlens_q=torch.cat([q_lens.new_zeros([1]), q_lens]).cumsum(0, dtype=torch.int32).to(q.device, non_blocking=True) 这两行是在做什么?
-
在代码中 b, lq, lk, out_dtype = q.size(0), q.size(1), k.size(1), q.dtype,这里 lq = q.size(1),batchsize 中每个样本的序列长度都是一样的 lq 是么?
-
在使用 flash_attention 时需要考虑什么?容易犯什么错误?
-
在代码的第 82,83 行 q = q.to(v.dtype), k = k.to(v.dtype),这里的 q,k 还没有放到显存上么?是在调用 flash_attn_varlen_func 函数内将它们放置在显存里的么?
-
重新问一次,就是当前数据都在显存 HBM 上,在函数 flash_attn_varlen_func 中会逐块将它们搬运到 SRAM 中进行 kernel 计算是么?
-
seqused_q 这个起什么作用?window_size 是做什么用的?
-
flash2 和 flash3 的区别是什么?
-
cu_seqlens_q 中 non_blocking 为什么只在这两个变量中有异步传输,异步传输的对象是谁?什么是异步传输,是块和块进行异步传输么?比如 q 的块 0 传输到 SRAM kernel 的块 0,q 的块 1 异步传输到 SRAM kernel 的块 1?
-
window_size 在 flash 内部是如何实现的?
-
为什么 flash-atten3 速度更快,是因为 kernel 内部计算时使用 fp8 精度计算么?还有其他原因么?
-
flash-attn 有什么缺点或不足?
-
作为算法工程师,而非 AI infra 岗,关于 flash-attention 必须要掌握的内容具体是哪些,如何检测是否已经高质量的掌握了?
-
前面提到,长序列(L > 2048)时显存爆炸,这里是只HBM爆炸还是SRAM爆炸
-
scores = Q @ K.T # [B, num_heads, L, L] ← 存储在 HBM! 这句话中,在标准的attention计算中,Q和K的矩阵乘法不是在SRAM里进行的么?而SRAM的容量比HBM还要小,不应该是SRAM里先发生爆炸么
-
意思是在 Q @ K.T 计算时是分块计算的,每块计算完成就将部分的score结果传回HBM,所以在整个过程中只有HBM上是存放完整的score矩阵是么?
-
计算softmax的时候因为要全局信息,在标准attention中,要将scores全部读入SRAM么,不然的话,标准attention中没有online softmax策略,这里怎么处理呢
-
怎么记得前面讲的flash-attention2是两次扫描,flash-attention3是单次扫描
- 它确实说的2中是两次扫描,还不承认
