《VLA 系列》MemoryVLA | 感知-认知记忆库 | 长时序操作 | 论文与源码解析
机器人操作并不总是一个只看当前画面就能决策的 Markov 问题。按钮按下前后几乎没有视觉差异,物体被杯子遮住后当前位置不再可见,清理物体并计数还要求机器人记住已经完成了多少步。MemoryVLA 的核心判断是:VLA 不应把所有历史帧粗暴拼进视觉语言模型,而应维护一个可检索、可压缩、同时保留视觉细节与语义摘要的长期记忆。
- 核心结构:7B Prismatic VLM 将单帧图像与语言指令编码成 256 个感知 token 和 1 个认知 token,两者组成当前工作记忆。
- 长期记忆:感知-认知记忆库 PCMB 分别保存低层视觉细节和高层语义,当前 token 通过带时间位置编码的交叉注意力检索历史。
- 容量控制:记忆满后,只在时间相邻条目之间计算相似度,合并最相似的一对,避免长期执行时记忆无限增长。
- 动作生成:记忆增强后的认知与感知 token 条件化一个约 3 亿参数的 DiT 动作专家,用 10 步 DDIM 生成 16 步、7-DoF 连续动作块。
- 主要结果:MemoryVLA 在 SimplerEnv-Bridge、Fractal、LIBERO、Mikasa-Robo 上分别达到 71.9%、72.7%、96.5%、41.2%;12 个真机任务中,通用任务和长时序任务得分为 85% 与 83%。
论文:MemoryVLA: Perceptual-Cognitive Memory in Vision-Language-Action Models for Robotic Manipulation
项目主页:MemoryVLA Project
官方源码:shihao1895/MemoryVLA
模型与日志:Hugging Face Collection

图 1 的按钮任务给出了最直接的矛盾:当前帧只能告诉模型按钮现在在哪里,却不能告诉模型它是否已经按过。下方结果也说明收益主要集中在依赖历史的任务上,真机长时序任务相对 CogACT 提升 26 个百分点,明显高于通用任务的 9 个百分点。
1、MemoryVLA 要解决什么问题
主流 VLA 通常从当前观测 I t I_t It 和语言指令 L L L 直接预测动作。MemoryVLA 将控制问题写为:
A t = ( a t , … , a t + T − 1 ) = π ( I t , L , M t − 1 ) A_t=(a_t,\ldots,a_{t+T-1})=\pi(I_t,L,\mathcal{M}_{t-1}) At=(at,…,at+T−1)=π(It,L,Mt−1)
其中:
| 符号 | 含义 | 在模型中的作用 |
|---|---|---|
| I t I_t It | 时刻 t t t 的第三视角 RGB 图像 | 当前视觉观测,训练时通常为 224 × 224 224\times224 224×224 |
| L L L | 语言指令 | 规定任务目标 |
| M t − 1 \mathcal{M}_{t-1} Mt−1 | 执行到前一时刻积累的记忆库 | 提供当前画面中缺失的历史线索 |
| A t A_t At | 从当前时刻开始的动作块 | 默认包含 16 个连续动作 |
| a t a_t at | 单步 7-DoF 动作 | 三维平移、三维欧拉角旋转与二值夹爪状态 |
论文原式没有显式写出 M t − 1 \mathcal{M}_{t-1} Mt−1,但 MemoryVLA 的实际策略正是让当前观测先和记忆交互,再生成动作。这样做针对两类具体失败:
- 状态别名:两个视觉上相似的当前帧对应不同的正确动作,例如按钮已经按过或尚未按过。
- 信息被遮蔽:关键线索只在过去出现,例如球被杯子盖住前的位置。
直接拼接连续帧并不理想。一方面,视觉 token 数量随帧数增长,Transformer 自注意力成本按序列长度平方增长;另一方面,OpenVLA/Prismatic 的机器人预训练主要使用单帧输入,多帧拼接会改变其输入分布。MemoryVLA 因此保留单帧 VLM 接口,把历史建模放到一个轻量的外部记忆模块中。
2、总体架构:Cognition-Memory-Action

读图时可以沿着从左到右的三条数据流理解:当前图像产生感知 token,图像和指令共同经过 LLM 产生认知 token;两类 token 查询各自的历史记忆;融合结果同时进入 DiT 动作专家和记忆更新路径。
2.1、视觉语言认知模块
视觉侧并行使用 DINOv2 与 SigLIP,拼接两路 patch 特征。原始视觉 token 一路经投影器进入 LLaMA-7B,与指令 token 联合建模;另一路经 SE-bottleneck 压缩通道,保留更细粒度的视觉信息。
当前工作记忆为:
M w k = { p t ∈ R N p × d p , c t ∈ R 1 × d c } \mathcal{M}_{\mathrm{wk}}=\{p_t\in\mathbb{R}^{N_p\times d_p},\ c_t\in\mathbb{R}^{1\times d_c}\} Mwk={pt∈RNp×dp, ct∈R1×dc}
变量含义如下:
| 符号 | 含义 | 论文与代码中的形态 |
|---|---|---|
| p t p_t pt | 当前感知 token | N p = 256 N_p=256 Np=256,通道 d p = 256 d_p=256 dp=256 |
| c t c_t ct | 当前认知 token | 取 LLM 序列末端 EOS 位置,形状 1 × 4096 1\times4096 1×4096 |
| N p N_p Np | 感知 token 数 | 对应视觉 patch 数,代码要求可还原为方形空间网格 |
| d p d_p dp | 压缩后感知通道数 | 默认 256 |
| d c d_c dc | LLM 隐藏维度 | 默认 4096 |
这里的 cognitive token 不是模型生成的一段文字思维链,而是 EOS 位置的隐藏特征。它把当前视觉与指令压缩为一个高层语义向量;perceptual token 则保留抓取边界、物体位置和局部纹理等动作控制所需细节。
2.2、训练流与推理流
训练阶段按 episode 保持时间顺序。Bridge/Fractal 使用 stream dataloader,LIBERO/Mikasa 使用 group dataloader;每个 batch 或组内帧来自同一 episode 且按时间排序。模型为每一帧依次检索并更新记忆,再用未来 16 步真实动作监督扩散噪声预测。
推理阶段每个 episode 的第一帧显式清空两类记忆库并把时间计数归零。之后每次请求只传入当前图像和指令,模型内部记忆跨请求保留。动作专家从高斯噪声开始,以认知 token 提供任务语义,以感知 token 提供细节,执行 10 步 DDIM 采样,最后反归一化为机器人动作。
训练期和推理期的输入边界可以概括为:
| 阶段 | 输入 | 仅该阶段存在的信号 | 输出 |
|---|---|---|---|
| 训练 | 有序图像、语言、episode id、时间步、真实动作块 | 真实未来动作、扩散噪声时间 | 噪声预测损失 |
| 推理 | 当前图像、语言、episode 首帧标记 | 无真实未来动作 | 16 步连续动作块 |
3、PCMB:检索、融合与压缩

PCMB 不是一个混合大池,而是结构相同、参数独立的两条流:感知记忆保存 N p × d p N_p\times d_p Np×dp 的低层细节,认知记忆保存 1 × d c 1\times d_c 1×dc 的语义摘要。每个条目还带有 episode 内时间索引。
3.1、带时间位置编码的检索
对任一分支 x ∈ { p e r , c o g } x\in\{\mathrm{per},\mathrm{cog}\} x∈{per,cog},历史键和值写为:
K x = [ m 1 x + T E ( t 1 ) ; … ; m L x + T E ( t L ) ] , V x = [ m 1 x ; … ; m L x ] K^x=[m_1^x+\mathrm{TE}(t_1);\ldots;m_L^x+\mathrm{TE}(t_L)],\quad V^x=[m_1^x;\ldots;m_L^x] Kx=[m1x+TE(t1);…;mLx+TE(tL)],Vx=[m1x;…;mLx]
H ^ x = s o f t m a x ( q x ( K x ) ⊤ d x ) V x \hat H^x=\mathrm{softmax}\left(\frac{q^x(K^x)^\top}{\sqrt{d_x}}\right)V^x H^x=softmax(dxqx(Kx)⊤)Vx
| 符号 | 含义 | 实际作用 |
|---|---|---|
| q x q^x qx | 当前感知或认知 token | 查询当前决策需要的历史 |
| m i x m_i^x mix | 第 i i i 个历史记忆条目 | 感知流为一组视觉 token,认知流为单 token |
| t i t_i ti | 条目在 episode 中的时间索引 | 区分内容相似但先后顺序不同的记忆 |
| T E \mathrm{TE} TE | 正弦时间嵌入 | 只加到 key,不加到 value |
| L L L | 记忆容量 | 通常为 16,真机长时序任务为 256 |
| H ^ x \hat H^x H^x | 检索结果 | 与当前 token 形状一致,继续进入 FFN 与门控融合 |
实现中连续堆叠两层 cross-attention + FFN。感知历史在注意力前从 [ L , N p , d p ] [L,N_p,d_p] [L,Np,dp] 展平为 [ 1 , L N p , d p ] [1,LN_p,d_p] [1,LNp,dp],认知历史则是 [ 1 , L , d c ] [1,L,d_c] [1,L,dc],所以两类信息使用相同机制,但计算规模不同。
3.2、门控融合
论文把门控融合写成:
g x = σ ( M L P ( [ x ; H ^ x ] ) ) g^x=\sigma(\mathrm{MLP}([x;\hat H^x])) gx=σ(MLP([x;H^x]))
x ~ = g x ⊙ H ^ x + ( 1 − g x ) ⊙ x \tilde{x}=g^x\odot\hat H^x+(1-g^x)\odot x x~=gx⊙H^x+(1−gx)⊙x
其中 [ x ; H ^ x ] [x;\hat H^x] [x;H^x] 表示沿通道维拼接, σ \sigma σ 是 sigmoid, ⊙ \odot ⊙ 是逐元素乘法, x ~ \tilde{x} x~ 是送往动作专家的记忆增强特征。门控的意义不是固定相信历史,而是让模型按 token 和通道判断当前信息与历史信息各占多少。
消融结果也支持这一设计:SimplerEnv-Bridge 上,简单平均相加为 67.7%,门控融合为 71.9%。不过当前源码的权重方向与论文公式相反,具体差异在 6.8 节说明。
3.3、相邻条目合并
当条目数超过容量时,模型只比较时间上相邻的记忆:
i x ∗ = arg max i cos ( x ~ i , x ~ i + 1 ) , m i x ∗ x ← x ~ i x ∗ + x ~ i x ∗ + 1 2 i_x^*=\arg\max_i\cos(\tilde{x}_i,\tilde{x}_{i+1}),\quad m_{i_x^*}^x\leftarrow\frac{\tilde{x}_{i_x^*}+\tilde{x}_{i_x^*+1}}{2} ix∗=argimaxcos(x~i,x~i+1),mix∗x←2x~ix∗+x~ix∗+1
i x ∗ i_x^* ix∗ 是最相似相邻对的起点, cos \cos cos 是余弦相似度。合并后的条目保留较早条目的时间戳,并删除后一条。这样既不会跨越很长的时间距离合并两个偶然相似状态,也能不断压缩局部冗余。
这里需要把 Token Merge 理解为记忆条目合并策略,不是对 VLM 内部 token 做通用剪枝。它也不是永久知识库:记忆随 episode 重置,当前实现没有跨任务、跨 episode 保存经验。
4、记忆如何进入动作生成
MemoryVLA 使用 DiT-L 动作专家,默认 24 层、隐藏维度 1024、16 个注意力头,约 3 亿参数。它预测 16 个 7-DoF 动作,而不是离散动作 token。
正向加噪可以写成标准 DDPM 形式:
x s = α ˉ s A + 1 − α ˉ s ϵ , ϵ ∼ N ( 0 , I ) x_s=\sqrt{\bar\alpha_s}A+\sqrt{1-\bar\alpha_s}\,\epsilon,\quad \epsilon\sim\mathcal{N}(0,I) xs=αˉsA+1−αˉsϵ,ϵ∼N(0,I)
训练目标为:
L d i f f = E A , s , ϵ [ ∥ ϵ θ ( x s , s , c ~ , p ~ ) − ϵ ∥ 2 2 ] \mathcal{L}_{\mathrm{diff}}=\mathbb{E}_{A,s,\epsilon}\left[\left\|\epsilon_\theta(x_s,s,\tilde c,\tilde p)-\epsilon\right\|_2^2\right] Ldiff=EA,s,ϵ[∥ϵθ(xs,s,c~,p~)−ϵ∥22]
| 符号 | 含义 | 注意事项 |
|---|---|---|
| A A A | 真实 16 步动作块 | 每步 7 维,训练前已归一化 |
| s s s | 扩散内部噪声时间 | 代码从 100 个训练扩散步中随机采样,不是机器人真实时间 t t t |
| ϵ \epsilon ϵ | 高斯噪声 | 与动作块形状一致 |
| x s x_s xs | 第 s s s 个噪声层级的动作 | DiT 的动作输入 |
| c ~ \tilde c c~ | 记忆增强认知 token | 与扩散时间嵌入相加后作为条件 token |
| p ~ \tilde p p~ | 记忆增强感知 token | 通过每个 DiT block 的 perception attention 注入 |
| ϵ θ \epsilon_\theta ϵθ | 动作专家预测的噪声 | MSE 直接比较预测噪声与采样噪声 |
推理使用 10 步 DDIM,CFG scale 为 1.5。CFG 把有条件和无条件 batch 拼接后一次前向,最终按 ϵ u n c o n d + 1.5 ( ϵ c o n d − ϵ u n c o n d ) \epsilon_{\mathrm{uncond}}+1.5(\epsilon_{\mathrm{cond}}-\epsilon_{\mathrm{uncond}}) ϵuncond+1.5(ϵcond−ϵuncond) 放大条件方向。生成结果裁剪到 [ − 1 , 1 ] [-1,1] [−1,1],再用训练数据的 1% 与 99% 分位数反归一化;夹爪维度最后按 0.5 阈值二值化。
5、具体任务:为什么单帧真的不够

以 Change Food 为例,指令是把盘中的食物移走,再把另一种食物放入盘中。执行可以拆成四步:
- 第一帧看到玉米在盘中、胡萝卜在盘外,感知与认知 token 写入 PCMB。
- 机器人拿走玉米。当前画面随后只剩两个物体和一个空盘,单帧无法说明哪一个刚被拿走。
- 当前认知 token 查询历史,检索到玉米原先在盘内以及刚才从右向左移动的关键帧。
- 融合后的 token 条件化动作专家,生成移动到胡萝卜、抓取并放入盘中的动作块。
同样的逻辑覆盖 Clean Table & Count 中是否已经按过计数按钮、Guess Where 中方块被哪个杯子遮住等问题。MemoryVLA 的价值不在于让机器人回看所有帧,而在于当前状态发生歧义时检索少量决策相关历史。

图 6 给出的 attention 曲线很有代表性。Change Food 的当前帧出现歧义时,注意力峰值落在近期运动趋势和歧义出现前的决定性帧;Mikasa-Robo 的 Shell Game Touch 中,峰值落在杯子尚未盖住球的初始揭示帧。这说明记忆模块没有只偏好最近帧,也能跨较长间隔取回唯一有效线索。
6、源码解析:论文模块如何落到实现
6.1、版本与目录
本文讲解的是官方仓库 openvla-codebase 分支。该分支对应基于 OpenVLA/Prismatic 的 MemoryVLA。
与方法直接相关的目录如下:
MemoryVLA/
├── vla/
│ ├── memory_vla.py # 主模型、双记忆库、训练与推理
│ ├── load.py # checkpoint 加载
│ └── datasets/
│ └── rlds/ # RLDS 数据、时序采样与 OXE 配置
├── action_model/
│ ├── action_model.py # 扩散损失与 DDIM 构造
│ ├── models.py # DiT、认知/感知条件注入、CFG
│ └── gaussian_diffusion.py # DDPM/DDIM 采样实现
├── training/strategies/
│ └── base_strategy.py # 训练循环、反向传播、EMA
├── evaluation/
│ ├── libero/ # LIBERO 客户端与评测
│ └── simpler_env/ # Bridge/Fractal/Mikasa 评测
├── script/
│ ├── train/ # 各数据集训练配置
│ └── eval/ # benchmark 入口与结果汇总
├── train.py # 训练参数和模型装配入口
└── deploy.py # HTTP 推理服务与动作集成
论文概念与源码落点如下:
| 论文模块 | 源码文件/类/函数 | 实际作用 |
|---|---|---|
| 感知压缩 | vla/memory_vla.py / BottleneckSE |
把 DINOv2+SigLIP 特征压到 256 通道 |
| 认知 token | MemoryVLA.forward、predict_action |
取 LLM 最后有效位置或生成末端隐藏状态 |
| 记忆检索 | CogMemBank.process_batch / CrossTransformerBlock |
当前 token 对历史 token 做两层 cross-attention |
| 门控融合 | GateFusion.forward |
逐元素混合当前与检索特征 |
| 记忆压缩 | _consolidate_with_token_merge |
合并余弦相似度最高的相邻条目 |
| 扩散动作专家 | action_model/models.py / DiT |
认知条件 + 感知注意力生成噪声预测 |
| 训练损失 | ActionModel.loss |
随机加噪并计算噪声预测 MSE |
| 推理采样 | MemoryVLA.predict_action |
重置/更新记忆、CFG、DDIM/DDPM、反归一化 |
| 训练入口 | train.py、base_strategy.py |
构造 RLDS 数据、FSDP 训练与 checkpoint |
| benchmark | script/eval/*、evaluation/* |
LIBERO、SimplerEnv 与 Mikasa-Robo 评测 |
6.2、主模型如何初始化
下面的构造代码把论文的双流记忆与动作专家装配到同一个模型中:
# vla/memory_vla.py :: MemoryVLA.__init__
self.per_compr = BottleneckSE(
C_in=self.vision_dim,
C_mid=self.per_token_size * 2,
C_out=self.per_token_size,
)
self.cog_mem_bank = CogMemBank(token_size=self.cog_token_size, ...)
self.per_mem_bank = PerMemBank(token_size=self.per_token_size, ...)
self.action_model = ActionModel(
model_type=action_model_type,
token_size=token_size,
in_channels=action_dim,
future_action_window_size=future_action_window_size,
use_per_attn=True,
per_token_size=per_token_size,
)
vision_dim 是两路视觉 backbone 通道之和。BottleneckSE 输出 [ B , 256 , 256 ] [B,256,256] [B,256,256] 感知 token;认知记忆通道与 LLM 的 4096 维隐藏状态对齐。动作专家的 in_channels=7,future_action_window_size=15 表示包含当前动作在内共 16 步。
6.3、当前观测如何变成两类 token
# vla/memory_vla.py :: MemoryVLA.forward
last_hidden_state = output.hidden_states[-1]
last_hidden_state = last_hidden_state[:, num_patch:]
cumulative_sum = attention_mask.cumsum(dim=1)
last_true_indices = (
cumulative_sum == cumulative_sum.max(dim=1, keepdim=True)[0]
).float().argmax(dim=1)
cog_tokens = last_hidden_state.gather(
1, last_true_indices[:, None, None].expand(-1, 1, last_hidden_state.size(-1))
)
vision_feats = self.vlm.vision_feats
per_tokens = self.per_compr(vision_feats)
训练时,代码先排除视觉 patch 对应的 LLM 输出,再根据 attention_mask 找到每个样本最后一个有效 token,得到 [ B , 1 , 4096 ] [B,1,4096] [B,1,4096] 的认知特征。感知分支不从 LLM 隐藏状态回取,而是直接读取 VLM 前向时缓存的 vision_feats,因此保留了进入语言模型前的细节。
6.4、记忆检索与更新的数据流
# vla/memory_vla.py :: CogMemBank.process_batch
episode_mem = torch.stack(hist_feats).reshape(-1, D).unsqueeze(0)
pe = self.timestep_encoder(hist_timesteps).unsqueeze(0)
pe = pe.repeat_interleave(N, dim=1)
query = working_mem
for block in self.retrieval_blocks:
query = block(query, episode_mem + pe, episode_mem)
retrieved_episode_mem = query
fused_feats = self.gate_fusion_blocks(working_mem, retrieved_episode_mem)
self._memory_consolidate(eid, tokens[i], timestep_i)
输入 tokens 为 [ B , N , D ] [B,N,D] [B,N,D],代码按 batch 内样本顺序逐帧处理。历史被堆叠为 [ 1 , T N , D ] [1,TN,D] [1,TN,D],时间嵌入重复 N N N 次后只加到 key。两层检索后,输出仍为 [ 1 , N , D ] [1,N,D] [1,N,D],因此可以和当前 token 逐元素融合。默认最后一行写回 tokens[i],而不是 fused_feats,这正是源码与论文叙述的一处差异。
记忆保存时执行了明确的梯度隔离:
# vla/memory_vla.py :: CogMemBank._memory_consolidate
self.bank[episode_id].append((timestep, feat.detach().clone()))
while len(self.bank[episode_id]) > self.mem_length:
if self.consolidate_type == "fifo":
self.bank[episode_id] = self.bank[episode_id][-self.mem_length:]
elif self.consolidate_type == "tome":
self._consolidate_with_token_merge(episode_id)
detach().clone() 使后续帧不能沿记忆库反向传播到更早帧,避免跨长序列保存完整计算图。记忆检索和门控本身仍可从当前帧损失获得梯度,但历史特征在写入时已经停止梯度。
6.5、动作专家结构与损失
DiT-L 的规模在源码中是固定映射:
# action_model/action_model.py
def DiT_L(**kwargs):
return DiT(depth=24, hidden_size=1024, num_heads=16, **kwargs)
# action_model/models.py :: DiT.forward
x = self.x_embedder(x)
t = self.t_embedder(t)
z = self.z_embedder(z, self.training)
per_token = self.per_token_embedder(per_token)
c = t.unsqueeze(1) + z
x = torch.cat((c, x), dim=1) + self.positional_embedding
for block in self.blocks:
x = block(x, per_token)
return self.final_layer(x)[:, 1:, :]
动作与扩散时间先嵌入到 1024 维;认知 token z z z 与扩散时间相加后放在动作序列最前端。感知 token 没有直接拼进主序列,而是由每个 DiT block 的 perception attention 读取。最终去掉条件 token,只返回 16 个动作位置的噪声预测。
# action_model/action_model.py :: ActionModel.loss
noise = torch.randn_like(x)
timestep = torch.randint(
0, self.diffusion.num_timesteps, (x.size(0),), device=x.device
)
x_t = self.diffusion.q_sample(x, timestep, noise)
noise_pred = self.net(x_t, timestep, z, per_token=per_token)
assert noise_pred.shape == noise.shape == x.shape
loss = ((noise_pred - noise) ** 2).mean()
这段实现直接证明当前开源训练目标只有扩散噪声 MSE。VLM 的 output 虽然一并返回,但 MemoryVLA.forward 最终把 ActionModel.loss 作为训练 loss,训练循环只对它反向传播;代码没有额外叠加语言模型损失。
6.6、推理时的记忆生命周期与去噪循环
# vla/memory_vla.py :: MemoryVLA.predict_action
if episode_first_frame == 'True':
self.cog_mem_bank.reset()
self.per_mem_bank.reset()
self.cur_timestep = 0
cog_tokens = self.cog_mem_bank.process_batch(...)
per_tokens = self.per_mem_bank.process_batch(...)
noise = torch.randn(B, self.future_action_window_size + 1,
self.action_model.in_channels, device=cog_tokens.device)
self.action_model.create_ddim(ddim_step=num_ddim_steps)
samples = self.action_model.ddim_diffusion.ddim_sample_loop(
sample_fn, noise.shape, noise, model_kwargs=model_kwargs, eta=0.0, ...
)
episode_first_frame 是推理正确性的关键接口。客户端如果忘记在新 episode 第一帧传 True,前一任务的记忆会污染后一任务。训练期才存在的真实动作、episode id 和数据采样逻辑在推理时都被移除;保留下来的只有内部时间计数、两类记忆库和扩散动作专家。
6.7、数据、训练与评测入口
官方数据统一为 RLDS。README 提供处理后的 LIBERO、Bridge、Fractal 数据;自定义数据动作格式为 EEF Delta XYZ (3) + Roll-Pitch-Yaw (3) + Gripper (1)。训练入口为 train.py,官方脚本使用单节点 8 张 A100、每卡 batch 32、全局 batch 256、学习率 2 × 10 − 5 2\times10^{-5} 2×10−5。
LIBERO-100 配置的关键参数为:
torchrun --nproc_per_node=8 train.py \
--vla.data_mix libero_100_no_noops \
--vla.global_batch_size 256 \
--vla.learning_rate 2e-5 \
--vla.max_steps 40000 \
--repeated_diffusion_steps 4 \
--future_action_window_size 15 \
--action_model_type DiT-L \
--dataloader_type group
训练中每个真实动作块重复 4 次,并各自采样扩散时间和噪声,相当于为同一监督动作提供 4 个噪声层级。base_strategy.py 使用 FSDP/AMP,loss 除以梯度累积步数后反向传播,执行梯度裁剪、优化器与学习率调度器更新,并按间隔保存 checkpoint。
官方评测入口包括:
# LIBERO
bash script/eval/libero/eval_libero.sh
python script/eval/libero/extract_libero_results.py
# SimplerEnv-Bridge
bash script/eval/bridge/eval_bridge.sh
python script/eval/bridge/extract_bridge_results.py
# 真机推理服务
bash script/eval/real_world/deploy.sh
LIBERO 每个任务评 50 次;Bridge 每任务 24 次;Mikasa-Robo 每任务 100 次。仓库 README 和论文都提醒扩散策略的 checkpoint 表现会波动,SimplerEnv 按 2.5k step 间隔验证并报告最佳 checkpoint,不能只看训练 loss 选择模型。
6.8、论文与当前开源实现的差异和复现注意事项
| 项目 | 论文设定 | 当前 openvla-codebase 默认实现 |
影响 |
|---|---|---|---|
| 门控权重方向 | x ~ = g H ^ + ( 1 − g ) x \tilde{x}=g\hat H+(1-g)x x~=gH^+(1−g)x | GateFusion(x1=current, x2=retrieved) 返回 g x + ( 1 − g ) H ^ g x+(1-g)\hat H gx+(1−g)H^ |
两者都是可学习凸组合,但 g g g 的语义相反;读代码时不能照搬论文变量解释 |
| 写回记忆内容 | 正文描述融合后 p ~ , c ~ \tilde p,\tilde c p~,c~ 更新到 PCMB | update_fused=False,默认写回原始当前 token |
release 默认记忆不递归积累融合结果,可能更稳定,也与文字叙述不同 |
| 动作专家采样 | 论文实验固定 10 步 DDIM | 代码同时支持 DDIM 和 100 步 DDPM,predict_action 默认参数 use_ddim=False |
必须由部署配置显式启用 DDIM;deploy.py 的默认值为 True |
| 记忆长度 | 常规任务 16,真机长时序 256 | 类默认 16,由任务脚本覆盖 | 不能用默认值复现长时序真机结果 |
| 输入分辨率 | 大多数实验 224 × 224 224\times224 224×224;Mikasa 为 128 × 128 128\times128 128×128 | 通用部署预处理默认输出 224 × 224 224\times224 224×224 | Mikasa 需使用对应训练/评测配置,不能套用通用真机预处理 |
| 代码基线 | 论文主结果对应 MemoryVLA | 仓库还提供 MemoryVLA+ 与后续 MemoryVLA++ 信息 | 分支、checkpoint 与结果表必须配套,不能跨版本比较 |
另一个容易忽略的问题是 deploy.py 会把预处理后的图像保存为 resized_image.png,且注释要求用户按自己的相机与训练预处理修改裁切逻辑。真机部署时,是否完整保留夹爪和机器人作业区域往往比模型参数微调更先决定效果。
7、实验结果怎么读

论文覆盖 3 类机器人、6 个 benchmark、10 个 suite、150+ 任务与 500+ 变化。不同表格的数字不能脱离协议直接横比:Bridge 每任务 24 次,LIBERO 每任务 50 次,Mikasa 每任务 100 次;真机长时序任务使用 10-15 次试验和分步计分,不等同于二值成功率。
7.1、主结果
| 场景 | MemoryVLA | 最强对照与差值 | 评测口径要点 |
|---|---|---|---|
| SimplerEnv-Bridge | 71.9% | CogACT-Large 57.3%,+14.6 | 4 任务,每任务 24 次;最佳验证 checkpoint |
| SimplerEnv-Fractal | 72.7% | CogACT 68.1%,+4.6 | VM+VA,336 变化、2856 次试验 |
| LIBERO 5 suites | 96.5% | CogACT 93.2%,+3.3 | 130 任务,每任务 50 次 |
| Mikasa-Robo | 41.2% | PI-0 29.4%,+11.8 | 5 个记忆任务,每任务 100 episode |
| 真机通用任务 | 85 分 | CogACT 76 分,+9 | 6 任务,每任务 15-25 次 |
| 真机长时序任务 | 83 分 | CogACT 57 分,+26 | 6 任务,10-15 次,分步计分 |
MemoryVLA 在 LIBERO 上使用单个第三视角 RGB,不使用腕部相机和本体状态;表中的 π 0 \pi_0 π0 与 π 0 \pi_0 π0-FAST 使用了额外输入,因此论文没有把输入条件不同的数值描述为完全公平的同设置比较。更有说服力的是 Mikasa 和真机长时序任务:这些任务明确需要过去信息,MemoryVLA 的增益也最大。

7.2、消融说明了什么
感知记忆单独使用为 64.6%,认知记忆单独使用为 63.5%,二者结合达到 71.9%。这说明高层语义不能替代视觉细节,视觉历史也不能替代任务阶段判断。
其他关键消融为:
| 设计 | 对照 | 默认方案 | 结论 |
|---|---|---|---|
| 记忆长度 | 4: 67.7%,64: 67.7% | 16: 71.9% | 容量不是越大越好,应匹配 episode 长度 |
| 时间位置编码 | 无: 69.8% | 有: 71.9% | 历史内容之外,先后顺序也有价值 |
| 融合方式 | Add: 67.7% | Gate: 71.9% | 模型需要按状态选择当前与历史信息 |
| 压缩方式 | FIFO: 66.7% | Token Merge: 71.9% | 只保留最近帧会丢失早期关键线索 |
附录进一步显示,真机 Clean Table & Count 上记忆长度 64、256、512 分别为 78、84、81;LIBERO-Long-90 上 8、16、32 分别为 94.2、95.6、95.6。长任务需要更大容量,但超过任务所需范围后没有稳定收益。
7.3、鲁棒性与边界

真机 Pick Place Order 在背景、干扰物、光照、新容器和遮挡变化下保持 92%-100%,新物体为 89%;Clean Restaurant Table 各 OOD 设置为 86%-96%。但仿真附录显示相机视角变化更困难:Pick Coke Can 从 92.0% 降到 42.0%,Move Near 从 76.0% 降到 58.0%。这说明 PCMB 解决的是时间信息缺失,不会自动解决严重的视觉域偏移。
7.4、推理代价

效率表在 bfloat16、动作块长度 16、300 次运行下测量。RTX 4090 上延迟从 0.187 s 增到 0.194 s,约 3.7% 开销;吞吐从 85.6 Hz 降到 82.5 Hz;显存从 15.8 GB 增到 16.6 GB。H20 上延迟从 0.236 s 增到 0.246 s。这里的吞吐是一次前向生成 16 步动作块后的动作步等效吞吐,不应直接理解为每秒进行 82 次完整 VLM 推理。
8、方法价值、局限与工程判断
MemoryVLA 最有价值的设计不是仿照人脑的叙事,而是把单帧 VLM 兼容性、长时序状态、有限计算开销三个工程约束同时纳入结构:VLM 仍看单帧,历史在外部双流记忆中维护,记忆通过相邻合并保持有界。
适合的任务包括:
- 当前画面不能判断任务阶段的多步操作;
- 关键目标会被遮挡或移出视野;
- 需要记住完成次数、顺序或先前选择;
- 已有单帧 VLA 基线,希望以较小增量加入时间建模。
局限也很明确:
- 记忆是 episode 内短期/情景记忆,任务结束后清空,不具备跨 episode 的终身学习。
- 记忆条目通过均值合并,缺少显式重要性保护;罕见但关键的早期线索仍可能在长序列中被稀释。
- 训练依赖有序 episode 与正确时间索引,随机打乱帧会破坏方法前提。
- 论文以 imitation learning 为主,记忆检索正确与否没有独立监督,attention 可视化是行为证据,不等同于因果解释。
- 相机视角变化仍是明显短板,时间记忆无法替代视觉域适配。
- release 默认配置与论文文字存在门控权重、写回特征两处差异,严格复现应固定 branch、commit、checkpoint 与完整配置。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)