建立于2025-11-27,继承自MVIG
ACTION CHUNKING WITH TRANSFORMERS
这个东西很重要
A. Action Chunking and Temporal Ensemble
Temporal ensembling(时间融合) 问题:
- 每k步才更新一次,会让机器人“隔几步突然变个方向”,动作变得断断续续、不平滑 怎么办?
- 改成:每一步都预测一“整段”动作(chunk),让这些动作块重叠,每一时刻可能有多个预测,那就用加权平均法融合一下,动作会更平滑
- 加权策略是“越新越重、越老越轻”,保证动作“随时对当前外部观察敏感”
感觉这个东西看起来和ICS1五级流水线比较像
关于读论文
- 比方说这个ACT是个很复杂的东西
- 让ai解读一下
- 我先看A的解读,然后去看原文
CVAE这个东西,在CS231n笔记l13里面提到过vae,此外,2025课程花了2节课时间讲生成模型,但是主要是
Lecture 13: Generative Models 1
Variational Autoencoders
Generative Adversarial Network
Autoregressive Models
可以看看
我觉得具体内容的批注还是在zotero里面进行比较好,对于更抽象层面的笔记可以写入ob。此外,可以研究一下ob和zotero的结合,我觉得可能会比较有意思 参见Obsidian折腾日志
B. Modeling human data
CVAE 的总损失 L = 重建误差(Lreconst)+ β × KL 距离(LKL)
- 重建误差:模型输出的动作和人演示的动作差得有多远。这个要求模型必须“还原得像”。
- KL 距离(KL 散度):要求编码器输出的 z 分布,要接近标准高斯分布 N(0, I)(就是均值为0,协方差为单位阵的正态分布),别乱跑。
β 的具体作用
- β 前面乘的是 KL 正则,也就是限制 z 不能带太多“专属私货” 的开关。
- β 越大,相当于告诉模型:“z 不许特别跑偏,离 N(0,I) 太远你就吃大罚!”
- 这样,模型会更强烈地克制自己“往 z 里塞更多信息”,不敢有太复杂的花样。
C. Implementing ACT
CVAE Encoder(左边)
- 只要“全看一遍输入”→ 得出一个z分布
- 结构用bert-like transformer encoder最合适
- 不需要生成序列,不需要逐步输出
CVAE Decoder/Policy(右边)
- 要干两件事:
- 全局融合上下文(各种图像+关节+z) ——靠transformer encoder
- 序列化地生成动作块(一个k*14序列) ——靠transformer decoder自回归一帧一帧地产生
- 必须包含encoder(输入特征混合)和decoder(动作序列生成)两个transformer部分
(99 封私信 / 82 条消息) 读懂BERT,看这一篇就够了 - 知乎 bert可以看看这个
17点33分 妈的,终于看到V. EXPERIMENTS了,不容易
https://shuiyuan.sjtu.edu.cn/t/topic/436157/4 终于做出这个一直很想做的工具,我把它叫做 VibeReading。它是专门为阅读学术论文而设计的,不是那种简单的“对照翻译”或“Chat with PDF”工具,而是更像一个会陪你一起读论文、不断指给你关键内容的“AI学长”。
消融实验
本节要做“消融实验”,也就是把 ACT 里的“关键设计(动作分块、时间加权、CVAE)”逐个拆掉或替换,看看哪个对表现最关键,以及加一个用户实验说明高频控制的重要性。目标是让你看明白:ACT里的每一个模块,都是不是简单叠加,而是确实对解决难题有巨大贡献
- L1 loss(或叫重建损失)定义为“预测输出和真实动作每一帧的数据绝对值差的总和/平均”。
- 这种只能“死记硬背”、“平均取中间值”,而不能泛化到有人类风格变化/多解的情况。
1. 50Hz是什么意思?
- Hz = 赫兹 = 次/秒
- 在本论文和机器人操控场景里,“50Hz”= 每秒刷新(发送新控制命令)50次。
- 也就是每隔 1/50 秒(= 20毫秒)一次,系统会:
- 读取传感器/相机/状态
- 把最新状态输入到控制/动作神经网络
- 让神经网络算出新的动作(比如下一个关节角度)
- 把这个动作指令下发给机器人
2. 和采样频率的关系
- 和采样频率其实很接近。
- 采样频率通常指“每秒采集环境状态/观察数据的次数”。
- 控制频率指“每秒对机器人更新动作命令的次数”。
- 论文里的“50Hz”往往同时代表感知→决策→执行这一整套循环的刷新频率(事实上它就是控制系统的“刷新频率”)。
这里的50Hz控制频率在论文实验中主要是指“人为操作采集数据阶段”的操作刷新频率,即人类操作者通过远程遥控(teleoperation)机器人时,系统每秒会将新的人类控制输入(比如操纵杆/按钮等动作指令)刷新并执行50次。
2025-11-29 14点52分 看到了ACKNOWLEDGEMENT,真是不容易
A sample of z is obtained using reparameterization, a standard way to allow back-propagating through the sampling process so the encoder and decoder can be jointly optimized
- 上文说:encoder 会输出一个 分布 来表示风格变量 z
- 比如:均值 μ(一个向量),方差 σ²(一个向量)
- 表示:z ~ N(μ, σ²I),也就是一个高斯分布
- 我们想从这个分布里“抽一个 z”,然后交给 decoder 去预测动作序列。
问题:
- 这一步“抽 z(sampling)”是一个随机操作。
- 神经网络训练需要“从输出算损失,再把梯度往前传回每一层”,叫 back-propagation(反向传播)。
- 但普通的“随机采样”是不可导的,梯度没法顺畅地传回去给 encoder 学习。
换句话说:
如果我们只是简单写 z = sample_from_gaussian(μ, σ),那 z 这一步“掐断了链路”,encoder 那些参数就不知道自己哪里做得好/不好,无法被更新好。
2. reparameterization 是什么鬼?
reparameterization(重参数化技巧) 就是想办法把:
“从一个分布里抽样(随机 z)”
改写成:
“从一个固定简单分布抽样一个 ε,再用一个可导的公式算出 z”
通常我们这样写:
- 先从标准正态分布中采样:
ε ~ N(0, I) (均值为0,方差为1的高斯) - 然后用 encoder 输出的 μ 和 σ 来算 z:
z = μ + σ ⊙ ε
(⊙ 表示按元素相乘)
这样一来:
- “随机性”集中在 ε 上(ε 和网络参数无关,只是外部噪声)
- μ 和 σ 通过一个完全可导的公式“搬运” ε,生成 z
- 因为 z 是 μ, σ 的光滑函数(加减乘),所以:
- 损失 L 对 z 的导数 → 可以通过链式法则传到 μ 和 σ
- 于是 encoder 网络就能得到梯度,继续学习。
这整个改写的过程就叫 reparameterization trick。
4. 用生活类比讲一下
想象你在教一个学生(encoder + decoder)画画:
- 你先让学生根据风格参数(μ, σ)想象一个“风格随机数 z”
- 再用 z 来画画(decoder 输出画作)
- 然后你看画作评分(loss),要告诉学生哪里画得不好
如果“z 是硬抽的,没有可导关系”,那相当于:
- 学生脑子“随机冒出一个点子 z”
- 你只知道画坏了,但不知道是“脑子生成风格参数的那部分”问题,还是“画画技术(decoder)有问题”,没法细分反馈。
reparameterization做法相当于:
- 告诉学生:
- 先从“公共灵感池”里随便抽一个 ε(大家都能抽到,和个人无关)
- 再用你自己的参数 μ, σ 进行“可导的加工”得到 z
- 这样当画差时,你就能追着 μ, σ 和画技两个部分都给具体反馈(反向传播),两部分都会改进。
5. 一句话极简总结
reparameterization 就是把“随机抽 z”改写成“z = μ + σ·ε”这种可导的形式,让随机性通过 ε 承担,而 μ、σ 仍然可以接受梯度,从而 encoder 和 decoder 能一起被优化。
在 Step 3 里,CVAE decoder(也就是策略网络)的做法是:
先用 ResNet18 把每个摄像头的图像变成带有空间位置信息的特征序列,再把四个摄像头的特征序列连起来,加上当前关节状态和风格变量 z,一起送入 Transformer Encoder,得到对当前观测+状态+风格的高层表示;然后 Transformer Decoder 把这些表示作为 keys/values,用固定位置编码作为 queries,通过 cross-attention 逐步预测出整个动作序列。
The “queries” are fixed sinusoidal embeddings for the first layer.
这句话的意思是:
在解码器的第一层里,为了预测第1步、第2步、第3步……这些动作,他们不是用“前一步动作”当输入,而是给每个时间步一个固定的、只表示“我是第几步”的位置向量(正弦位置编码),把这些当作 queries。
也就是说:
每个要预测的动作时间步都有一个“我在第 t 步”的标签,这个标签就是一个固定的正弦向量,用来问:“在当前观察和状态下,我这第 t 步应该干什么?”
下面超细致地拆开。
1. 先搞清楚:queries / keys / values 是谁在干嘛?
在 Transformer 的 注意力机制(attention) 里:
-
keys(K)和 values(V):
你可以想象是“知识库”里的内容:- keys:用来判断“这个位置和我现在的问题相关不相关?”
- values:真正存的信息,被根据相关性加权平均后给当前步使用。
-
queries(Q):
就像“提问的人”带着一个问题向量去问:“我现在要预测第 t 步动作,我该关心哪些输入信息?”
在本模型里:
- Encoder 输出:当作 keys & values(机器人当前看到的图像特征 + 关节 + z 的理解)
- Decoder:每个时间步都生成一个 query,去从这些 keys / values 里“取信息”,然后输出这个时间步的动作。
2. 一般情况下,queries 可以怎么来?
常见两种做法(你不用都记,只是帮你区分这篇论文在做什么):
-
自回归方式:
- 第 t 步的 query 用“前 t−1 步已经预测出的动作”再做个投影得到。
- 就像语言模型那样:“我已经说了前面这些词,现在我要说下一个词”。
-
位置编码方式(这篇论文用的):
- 不依赖前面的输出,而是直接给每个时间步一个“固定的位置信号”,表示“现在是第1步”、“第2步”、“第3步”。
- 然后靠 cross-attention 从 Encoder 里取必要信息。
这篇论文明确说:
The “queries” are fixed sinusoidal embeddings for the first layer.
也就是:
Decoder 第一层的 query,不是来自前一步预测,而是来自“固定的正弦位置编码”。
3. 什么是 fixed sinusoidal embeddings?
我们分拆成两个词:
3.1 sinusoidal(正弦)位置编码
- 常见于 Transformer(比如原始 Transformer 论文),用 sin 和 cos 函数给每个“位置 index”生成一个向量。
- 举个概念上的例子(不必记公式):
- 对于位置 1,我们用不同频率的 sin(1)、cos(1)、sin(1/10000)… 拼成一个向量
- 对于位置 2,用 sin(2)、cos(2)、sin(2/10000)… 拼成另一个向量
- 这样一来:
- 不同位置有不同向量
- 模型可以从这些向量中“感知顺序”:哪个是前、哪个是后,谁距离谁近
所以:
正弦位置嵌入 = 一种用 sin/cos 函数生成“带顺序意义”的向量的方法。
3.2 fixed(固定的)
- “固定”的意思是:这些向量不靠训练学出来,而是用公式直接算。
- 所以网络不会改变它们,只是使用它们。
- 每次训练/测试时,对于第1步、第2步 … 的向量始终相同。
4. 把它们当 queries 是什么意思?
我们假设要预测未来 k 步动作:
t = 1, 2, ..., k
对于每个 t:
- 用“正弦位置编码公式”生成一个向量 PE(t)
- 这个向量就是这一时间步的 query(第一层的输入)
于是:
- 第1步的 query:一个固定的“我是第1步”的向量
- 第2步的 query:一个固定的“我是第2步”的向量
- …
- 第k步的 query:一个固定的“我是第k步”的向量
这些 query 不含任何动作内容,只告诉模型两件事:
- “我现在代表第 t 个动作槽位”
- “我需要从 Encoder 提供的图像+关节+z 信息中,取出对第 t 步最有用的东西”
接着 Decoder 会用这些 query 通过 cross-attention 去读 Encoder 的 keys / values,然后输出每步动作向量。
5. 为什么要这样设计?
几点直观原因(不需要你全都背下来,只是帮助理解逻辑):
-
让动作序列的每一步有独立的“时间位置身份”
- 第1步和第10步虽然都在同一个观察下预测,但它们的“使命”不一样:
- 第1步可能是“先伸手”
- 第10步可能是“拔出来”
- query 里加入“我是第 t 步”的位置信息,可以帮模型区分每一步的角色。
- 第1步和第10步虽然都在同一个观察下预测,但它们的“使命”不一样:
-
不用依赖之前是否预测正确
- 如果 query 来自前一步动作,那么一旦前面预测有误,后面会层层传染(error accumulation)。
- 用固定位置编码做第一层 query,可以减少这种连锁错误的影响,让每一步都直接依据 Encoder 的“观察理解”来决定。
-
结构简单、易训练
- 因为 query 是固定的,不需要额外学这些向量,它只负责“占位”和表明“第几步”。
6. 再用一个生活比喻说明
假设你是老师(Decoder),你有一本说明书(Encoder 输出的理解:当前图像+状态+风格z)。
你要写下一个“做菜步骤清单” 1~k 步。
你这样做:
-
你先写一个空白步骤格子:“步骤1:_____”
- 这个“步骤1”的标题就是 query1(固定模板)
- 然后你根据说明书里的内容(keys/values)来填:这一步要干啥
-
然后你写“步骤2:_____”
- 这个“步骤2”的标题就是 query2(另一个固定模板)
- 再次去说明书里查:第二步应该做什么动作
-
…
每个“步骤标题”本身没有内容,只说明“这是第几步”,真正的内容从说明书(Encoder 输出)里查出来。
这里的“步骤标题模板”就是 fixed sinusoidal embeddings,
把它作为 query,就是让它充当“第 t 步动作的提问者”。
7. 一句话压缩总结
“The ‘queries’ are fixed sinusoidal embeddings for the first layer.” 的意思是:
在解码器预测动作序列的第一层中,针对将要输出的每一个时间步,他们不给它任何前一步动作信息,而是只给它一个固定的、只编码“我是第几步”的正弦位置向量,这个向量就作为这个时间步在 cross-attention 里向 Encoder 提问的 query。
Fig. 11: Detail architecture of Action Chunking with Transformers (ACT).
这个图很有必要看看
图里画的 Weight matrix (512) → [CLS] (512),可以理解成:
-
他们没有把
[CLS]当成“一个固定常数向量”,
而是当成一个 可学习的参数向量。 -
这个参数向量本质上就是一个大小为
512的权重向量(或者是一个 1×512 的权重矩阵), 在训练过程中和模型其它参数一起更新。 -
画成 “Weight matrix (512)” →
[CLS] (512),只是为了说明:“这个
[CLS]不是输入数据算出来的,而是模型里直接存着的一块参数,维度 512。”
所以:
- 为什么是由
Weight matrix (512)得到?
因为[CLS]向量本身就是一个 learnable weight,用一个 512 维的权重矩阵/向量来表示;
每次前向传播时,直接把这块权重取出来(或者用一个很简单的线性层)当作[CLS]token 的嵌入。
所以这个token不是一个单纯的标记符,而是一个复杂矩阵
step 3
Sinusoidal Position Embedding(正弦位置编码)是 Transformer 里常用的一种 位置编码方式,用来告诉模型“序列中第几个元素”。
- 左边 encoder 部分:
ResNet 特征 + Sinusoidal PosEmb→ 告诉 encoder 每个图像 patch / 时间帧在序列中的位置。 - 右边 decoder 部分:
position embeddings (fixed)→ 给每个要预测的动作时间步一个独特的位置向量,作为解码器输入 token。
图里的 position embeddings (fixed) 是什么?
在这张图里,decoder 下面那一排彩色小方块标的 position embeddings (fixed) 表示:
- 解码器输入端有一串长度为
T的向量(T= 要预测的 action 的时间步数)。 - 第
t个向量只编码“这是第 t 个时间步”,不包含具体动作信息。 - 这些向量是 固定不学习的(fixed),通常就是 正弦位置编码(sinusoidal position embedding)。
换句话说:
decoder 的输入 token = “时间步 query”,每个 query 仅由一个固定的位置向量表示。
就是那个固定的Q
15点52分 2025-11-29 不错,差不多看完了。