1. 搭建VLA与世界模型联合训练的基础框架
任务目标
搭建一个最小可运行的VLA(视觉-语言-动作)与世界模型联合训练框架。框架包含:一个接收图像和语言指令并输出动作的VLA策略网络、一个预测下一时刻图像特征的世界模型,以及一个交替更新两组参数的联合训练循环。通过本案例,你将得到一个可直接扩展的骨架代码,并验证前向传播、损失计算和参数更新链路完整可用。
环境依赖
需要 Python 3.9+、PyTorch 2.0+、torchvision。无需额外数据集,使用随机张量模拟输入。
核心实现
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import models
# ---------- 1. VLA策略网络 ----------
class VLA_Policy(nn.Module):
"""输入: 图像(3,64,64) + 语言指令(seq_len, 32) -> 输出: 连续动作(4,)"""
def __init__(self, lang_dim=32, action_dim=4):
super().__init__()
# 视觉编码器: 使用预训练ResNet18的conv层(冻结)
resnet = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
self.vision_encoder = nn.Sequential(*list(resnet.children())[:-2])
for p in self.vision_encoder.parameters():
p.requires_grad = False
# 语言编码器: 简单LSTM
self.lang_lstm = nn.LSTM(lang_dim, 128, batch_first=True)
# 动作头: 融合视觉+语言特征
self.fusion = nn.Sequential(
nn.Linear(512 + 128, 256),
nn.ReLU(),
nn.Linear(256, action_dim)
)
def forward(self, image, lang_seq):
# image: (B,3,64,64), lang_seq: (B,T,32)
vis_feat = self.vision_encoder(image) # (B,512,2,2)
vis_feat = vis_feat.mean(dim=[2,3]) # (B,512)
_, (h_n, _) = self.lang_lstm(lang_seq) # h_n: (1,B,128)
lang_feat = h_n.squeeze(0) # (B,128)
fused = torch.cat([vis_feat, lang_feat], dim=1) # (B,640)
action = self.fusion(fused) # (B,4)
return action
# ---------- 2. 世界模型 ----------
class WorldModel(nn.Module):
"""输入: 当前视觉特征 + 动作 -> 输出: 预测的下一时刻视觉特征"""
def __init__(self, vis_dim=512, action_dim=4, hidden_dim=256):
super().__init__()
self.fc = nn.Sequential(
nn.Linear(vis_dim + action_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, vis_dim)
)
def forward(self, vis_feat, action):
# vis_feat: (B,512), action: (B,4)
x = torch.cat([vis_feat, action], dim=1) # (B,516)
next_vis_feat = self.fc(x) # (B,512)
return next_vis_feat
# ---------- 3. 联合训练循环 ----------
def joint_training_step(policy, world_model, opt_p, opt_w,
image, lang_seq, action_target, next_image):
# 1) 前向: VLA输出动作
pred_action = policy(image, lang_seq) # (B,4)
# 2) 前向: 世界模型预测下一视觉特征
with torch.no_grad():
vis_feat = policy.vision_encoder(image).mean(dim=[2,3]) # (B,512)
next_vis_feat_target = policy.vision_encoder(next_image).mean(dim=[2,3])
pred_next_vis_feat = world_model(vis_feat, pred_action.detach())
# 3) 计算损失
loss_action = F.mse_loss(pred_action, action_target)
loss_wm = F.mse_loss(pred_next_vis_feat, next_vis_feat_target)
# 4) 更新VLA策略(仅动作损失)
opt_p.zero_grad()
loss_action.backward()
opt_p.step()
# 5) 更新世界模型(仅世界模型损失)
opt_w.zero_grad()
loss_wm.backward()
opt_w.step()
return loss_action.item(), loss_wm.item()
# ---------- 4. 最小验证入口 ----------
if __name__ == "__main__":
torch.manual_seed(42)
B, T = 4, 8
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
policy = VLA_Policy().to(device)
world_model = WorldModel().to(device)
opt_p = optim.Adam(policy.fusion.parameters(), lr=1e-4) # 只训练融合层
opt_w = optim.Adam(world_model.parameters(), lr=1e-3)
# 模拟输入
image = torch.randn(B, 3, 64, 64).to(device)
next_image = torch.randn(B, 3, 64, 64).to(device)
lang_seq = torch.randn(B, T, 32).to(device)
action_target = torch.randn(B, 4).to(device)
# 执行3步训练
for step in range(3):
la, lw = joint_training_step(policy, world_model, opt_p, opt_w,
image, lang_seq, action_target, next_image)
print(f"Step {step+1}: action_loss={la:.4f}, wm_loss={lw:.4f}")
# 验证前向输出形状
with torch.no_grad():
act = policy(image, lang_seq)
vf = policy.vision_encoder(image).mean(dim=[2,3])
nvf = world_model(vf, act)
print(f"Action shape: {act.shape}, Next vis feat shape: {nvf.shape}")
assert act.shape == (B, 4), "动作输出维度错误"
assert nvf.shape == (B, 512), "世界模型输出维度错误"
print("✓ 前向传播与训练循环验证通过")
运行方式
将上述代码保存为 vla_wm_joint.py,在终端执行:
python vla_wm_joint.py
验证方法与通过标准
- 运行成功标志:程序无异常退出,打印3行训练损失(数值会因随机初始化而变化),并输出
✓ 前向传播与训练循环验证通过。 - 损失下降观察:由于输入为随机噪声且仅训练3步,损失不要求严格下降;若你增加训练步数(如50步),可观察到
action_loss和wm_loss呈下降趋势,说明两个网络均在学习。 - 形状断言:代码末尾的
assert语句确保动作输出维度为(B,4)、世界模型输出维度为(B,512),这是框架正确性的基本保证。
关键说明
- 视觉编码器使用冻结的ResNet18,仅训练融合层和世界模型,以最小化计算开销。若需端到端微调,将
requires_grad改为True并将视觉编码器参数加入opt_p即可。 - 世界模型预测的是视觉特征而非原始像素,这是VLA联合训练中的常见设计,可降低预测难度并加速收敛。
- 本框架刻意省略了数据加载器、真实环境交互和奖励计算,聚焦于联合训练的核心参数更新逻辑。接入真实数据时,只需替换
image/lang_seq/action_target/next_image的来源。