5 分钟跑通 V-JEPA:自监督视频表征学习新手实战指南
【免费下载链接】jepaPyTorch code and models for V-JEPA self-supervised learning from video.项目地址: https://gitcode.com/GitHub_Trending/je/jepa
V-JEPA(Video Joint Embedding Predictive Architecture)是 Meta 开源的视频自监督表征学习框架:不标注、不重建像素,只靠"看"视频帧就能学出可用的视觉特征。这篇指南带你完成环境安装、本地启动预训练、跑通 frozen 探针评测三步,并把真正影响行为的配置参数逐行讲清楚。
三步跑通 V-JEPA:克隆、安装、单卡起训
环境准备与安装
项目要求 Python ≥ 3.9,依赖在 requirements.txt 里,核心是 PyTorch 2.x、decord(视频解码)、submitit(分布式提交):
git clone https://gitcode.com/GitHub_Trending/je/jepa cd jepa conda create -n jepa python=3.9 pip conda activate jepa python setup.py install # 会按 requirements.txt 安装全部依赖仓库结构很克制,四个顶层目录各司其职(README 中的 Code Structure 一节):
app/ 唯一允许写训练循环的地方,入口在 app/main.py evals/ 冻结骨干的探针评测,入口在 evals/main.py src/ 数据集、模型、掩码、工具包 configs/ 唯一允许放配置文件的地方,pretrain/ 与 evals/ 分开放所有实验参数都通过 YAML 配置文件传入,没有命令行超参——这一点决定了你调参的方式是"改 YAML"而不是"加 --xxx"。
准备视频数据 CSV
V-JEPA 预训练是无监督的,数据侧只需要一个 CSV 索引文件,格式为"绝对路径 + 任意整数标签"(预训练阶段标签列会被直接忽略,填 0 即可):
/path/to/video1.mp4 0 /path/to/video2.mp4 0 /path/to/video3.mp4 0注意两点:路径必须是绝对路径;如果要跑有监督的视频分类评测(evals/video_classification_frozen/),则必须把这一列换成真实类别标签。
改配置并启动本地预训练
以最小的 configs/pretrain/vith16.yaml 为例,启动前只需改三处路径:
data: datasets: - /your_path/to/video_index.csv # 你上面准备的 CSV 索引 logging: folder: /your/absolute/path/logs # 日志与 checkpoint 目录,必须是存在的绝对路径然后在仓库根目录执行(官方示例,app/main.py 会为每张卡 spawn 一个进程):
python -m app.main \ --fname configs/pretrain/vith16.yaml \ --devices cuda:0 cuda:1 cuda:2跑起来后你会在logging.folder下看到params-pretrain.yaml(实际生效配置的回写)和逐步保存的 checkpoint。
一个诚实的提醒:官方在 README 中明确说明,本地单机的作用是调试代码与数据管线;复现论文结果需要 16 节点 × 8 GPU 的分布式训练(nodes: 16, tasks_per_node: 8),那部分见文末"进阶"一节。
原理速览:为什么 V-JEPA 不用像素重建
用三句话说清核心机制:
- 从视频里随机挖掉若干时空块,剩下的区域叫 context,被挖掉的叫 target;
- 编码器只把 context 区域编码成特征,一个更小的 predictor 网络在潜在空间里预测被挖区域的特征;
- 损失算在特征空间(预测特征 vs. 目标编码器给出的真值特征),全程不接触像素重建、负样本或文本标注。
这就是 JEPA(Joint-Embedding Predictive Architecture)的思想落到视频上的版本:模型学到的是"视频接下来会发生什么"的表征级理解,而不是逐像素拟合。掩码的生成逻辑在 src/masks/,模型定义在 src/models/。
预训练配置逐行拆解:data、mask、model、optimization
下面按 configs/pretrain/vith16.yaml 拆四组真正影响行为的参数。
data 段:决定模型"看到什么"
data: num_frames: 16 # 每个片段取 16 帧 tubelet_size: 2 # 时序管片大小:每 2 帧合并成一个 patch sampling_rate: 4 # 帧采样间隔 crop_size: 224 # 空间裁剪分辨率 patch_size: 16 # 空间 patch 大小 batch_size: 24 # 每卡 batch size,显存不够时优先调它 filter_short_videos: false # 是否过滤过短视频16 帧 ÷ tubelet 2 = 8 个时序位置,空间 224 ÷ 16 = 14×14,即每个视频约 1568 个 token。
mask 段:决定"挖掉多少"
默认是两级掩码(对应data.mask_type: multiblock3d,实现在 src/masks/multiblock3d.py):
mask: - num_blocks: 8 # 挖 8 个小块 spatial_scale: [0.15, 0.15] # 每块空间占比约 15%(细粒度) temporal_scale: [1.0, 1.0] # 覆盖全部时间(整段都要预测) - num_blocks: 2 # 再挖 2 个大块 spatial_scale: [0.7, 0.7] # 每块空间占比 70%(粗粒度)细块 + 大块的双尺度设计,让模型同时学局部纹理和整段运动。想换另一种策略(随机时间管状掩码),把data.mask_type改成random_tube即可,对应实现是 src/masks/random_tube.py。
model 段:决定"多大多小"
model: model_name: vit_huge # 骨干规格,可选 vit_tiny~vit_gigantic pred_depth: 12 # predictor 层数 pred_embed_dim: 384 # predictor 隐层宽度(比骨干窄,省算力) use_mask_tokens: true # 用 2 个可学习 mask token 作为预测输入骨干选项在 src/models/vision_transformer.py 中定义(vit_tiny到vit_gigantic),predictor 在 src/models/predictor.py。改model_name就能换骨干规模,是显存紧张时最直接的开关。
optimization 与 meta 段:调度与精度
optimization: epochs: 300 # 训练轮数 warmup: 40 # 学习率线性预热轮数 lr: 0.000625 # 峰值学习率 clip_grad: 10.0 # 梯度裁剪阈值 ema: [0.998, 1.0] # 双 EMA 的衰减率区间 meta: use_sdpa: true # 使用 PyTorch 缩放点积注意力,省显存 dtype: bfloat16 # 混合精度;A100 及以上推荐,老卡改 float32实战场景:冻结骨干 + 轻量探针评测
V-JEPA 落地时的标准姿势是:骨干完全冻结,只训一个 attentive probe。这比"端到端微调"便宜一个数量级,且能直接复用官方 checkpoint。
场景一:Kinetics-400 视频分类
- 下载官方 pretrained checkpoint(
vith16.pth.tar,README 的 MODEL ZOO 一节有链接)放到本地目录; - 准备 K400 训练/验证的 CSV 索引(这次标签列必须写真实类别);
- 修改 configs/evals/vith16_k400_16x8x3.yaml 中的
data.dataset_train、data.dataset_val和pretrain.folder; - 本地起评测:
python -m evals.main \ --fname configs/evals/vith16_k400_16x8x3.yaml \ --devices cuda:0 cuda:1配置里eval_name: video_classification_frozen指定了用 evals/video_classification_frozen/eval.py;frames_per_clip: 16, num_segments: 8, num_views_per_segment: 3即 16 帧 × 8 段 × 3 视图的评测协议,这也是文件名后缀16x8x3的来历。
场景二:换骨干 / 换分辨率,收益有多大
下面这张表直接来自 README 的 MODEL ZOO(frozen 骨干 + attentive probe 的 top-1 accuracy,单位 %),可以当作"改造前 vs 改造后"的选型参考:
| 数据集 | ViT-L 224 | ViT-H 224 | ViT-H 384 |
|---|---|---|---|
| K400(16x8x3) | 80.8 | 82.0 | 81.9 |
| SSv2(16x2x3) | 69.5 | 71.4 | 72.2 |
| ImageNet-1K | 74.8 | 75.9 | 77.4 |
| Places205 | 60.3 | 61.7 | 62.8 |
| iNat21 | 67.8 | 67.9 | 72.6 |
结论很清晰:分类密集、语义细的任务(SSv2、iNat21)对分辨率更敏感,224→384 能拿到 0.8~4.7 个点;动作分类(K400)上换 ViT-H 反而略低于 384 版,选型要看任务。对应的五个数据集评测配置都在 configs/evals/ 下,各有一个vith16_*.yaml,改pretrain.checkpoint路径即可复用。
常见问题速查
| 现象 | 原因 | 解决方式 |
|---|---|---|
启动即报params-pretrain.yaml写失败 | logging.folder不存在或不是绝对路径(app/main.py 启动时就写这个文件) | 先手动创建目录,改为绝对路径;README 明确要求启动前更新配置内所有路径 |
| 视频加载崩溃 / 解出空帧 | decord 不支持该编码,或视频被截断损坏 | 换 mp4 等通用容器格式;把data.filter_short_videos设为true过滤异常样本 |
| 训练 OOM | 默认batch_size: 24× 16 帧 × 224 分辨率占用较高 | 先降data.batch_size,再考虑降model_name或crop_size |
bfloat16相关报错 | 老 GPU(Ampere 之前)对 bf16 支持不全 | 把meta.dtype改为float32(app/vjepa/train.py 中会自动关闭混合精度) |
| 跑有监督评测时标签全是 0 | CSV 标签列沿用预训练的占位 0 | 按 README 要求,把标签列替换为真实类别标签 |
| 本地跑和论文数字对不上 | 官方复现依赖 16 节点 × 8 GPU 分布式,本地版仅用于调试 | 接受本地只验证管线;复现数字走 SLURM 分布式(见进阶) |
进阶:分布式提交与掩码策略扩展
- SLURM 三步起分布式训练:入口是 app/main_distributed.py(基于 submitit),
--folder指定 stdout/stderr 落盘目录,--partition指定队列;评测同理用 evals/main_distributed.py。 - 加掩码变体:
mask段是列表,追加一条num_blocks+spatial_scale组合即可增加一个尺度;每个字段语义见 src/masks/multiblock3d.py 中_MaskGenerator的参数(如max_temporal_keep控制 context 可保留的最大时间比例)。 - 换骨干规模:
model.model_name支持vit_tiny / vit_small / vit_base / vit_large / vit_huge / vit_giant / vit_gigantic,配套配置参照 configs/pretrain/ 下三份 YAML 的写法。
官方三个 pretrained checkpoint(ViT-L 224、ViT-H 224、ViT-H 384,均训于 90K iterations、VideoMix2M)及全部探针 checkpoint 的下载地址都列在 README 的 MODEL ZOO 一节,配合上面的评测配置可以直接复现表中数字。
【免费下载链接】jepaPyTorch code and models for V-JEPA self-supervised learning from video.项目地址: https://gitcode.com/GitHub_Trending/je/jepa
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考