HowTo100M:让互联网叙事字幕自动变成 1 亿级视频-文本对训练语料

  • 关联论文:1906.03327
  • 作者:spark
  • 更新:2026-07-22

一句话结论

Miech、Zhukov、Alayrac 等人用 YouTube 上 1.22M 个「how-to / instructional」视频的自动 ASR 字幕切割出 1.36 亿个 clip-cap pairs,从此把「视频-文本」对齐学习从昂贵的人工标注(30K–100K 级别)一举推到亿级训练数据规模;他们用 MIL-NCE 损失 + S3D backbone 在该数据上学到的 text-video embedding,在 zero-shot 到 YouCook2、CrossTask、MSR-VTT、LSMDC 上多项任务拿到当时的 SOTA,是大规模多模态自监督表征时代的开山样本之一。

它到底在解决一个什么真问题

视频和文本的联合表征受困于一个尴尬的事实:

  • 视频标注极其昂贵:要在千小时级别视频上手动写 caption / action label,每小时成本远超图像标注。
  • 现有数据集天花板太低:YouCook2 只有 ~2k 段视频、MSR-VTT 仅 10K 段,根本喂不饱有效的视频编码。
  • 「图像-文本」上已经跑通 pipeline,能不能直接迁移过来? —— 大体上可以,但视频的时间轴是另一个维度,需要 motion cues 的预训练。

HowTo100M 的洞察非常具体:YouTube 上有大量「how-to / instructional」类视频(做饭、修理、做手工),它们的 ASR 字幕就是当前画面的自然语言描述,且字幕大多与画面是「大致同步、但不完全对齐」的。这给出了一个数据 factory:

打开 YouTube → 找「tutorial / how to」类频道 → ASR → 切镜头 → 每一段就是一个 (video_clip, transcript_clip) 配对。

这是一个无成本、一次性的、几乎可以无限扩展的「自然监督源」——它不需要任何额外的人力标注。

核心方法

1. 数据构造 pipeline

论文把数据生产流程拆成 6 步:

  1. 种子检索:用分类器/关键词从 YouTube 检索约「how-to」类视频(手工给了一个上千词词表);
  2. 过滤:要求字幕非自动翻译、长度 > 100 词,覆盖英语;
  3. 下载:~1.22M 个视频,原始时长约 15.2 万小时
  4. 切 clip:保留连续 ASR 段落长度 ≥ 2 秒的 clip,最终得到 1.36 亿段,每段平均 ~4 秒;
  5. 弱匹配:在 clip 时间窗内对 ASR 取 embedding,把视频 clip 视为该 embedding;
  6. 分 train/val/test:用 5% 作测试,先手动剔除这些视频再训练。

数据集大小:1.36 亿 pairs,相当于 比当时最大的 MSR-VTT 大约 3 万倍

2. 模型:S3D 双编码器

$$ \text{S3D} = \text{I3D 的 lightweight 变体:空间卷积复用 Inception weights,} \text{时间卷积分开(time-strided 1D conv),参数比 I3D 少约 30%} $$

  • video encoder:用 I3D 的 lightweight 变体 S3D,把视频 clip 抽成 $v \in \mathbb{R}^{d}$,这里的 $d$ 默认是 512。S3D 把空间卷积与时间卷积分开,在空间上复用 Inception weights,参数比 I3D 少约 30%;
  • text encoder:用 Word2Vec / bag-of-words pooling / LSTM 等多个选项(论文里默认用 Word2Vec 平均池化,效果已够);
  • 两个 embedding 都 L2 normalize,最终用余弦相似度匹配。

3. 训练目标:MIL-NCE(Multi-Instance Learning NCE)

这是论文最重要的技术贡献。核心问题:clip 与字幕之间不是严格的「一对一」对齐,而是「一对多 / 多对一」的弱匹配(一段字幕可能跨越好几个镜头)。

直接用 InfoNCE 损失会因为负例「太硬」(同一个视频相邻 clip)而误判。MIL-NCE 引入「区间 softmax」:

$$ \mathcal{L}{\text{MIL-NCE}} = \frac{1}{|B|} \sum{i \in B} \log \frac{\exp(\text{sim}(v_i, t_i) / \tau)}{\sum_{t_j \in \mathcal{N}_i} \exp(\text{sim}(v_i, t_j) / \tau)} $$

其中 $\mathcal{N}_i$ 是 同一视频里其他 clip 的字幕 embedding 集合(而不是整个 batch)——这样把「同源不同段」从硬负例变成同源参考,更贴合视频-文本弱匹配的实际。

直觉上:对一个 video clip,「与自己在同一段内」的字幕才应该和它是正类;同 batch 其它 clip 的字幕仍然是「其他视频」的硬负类。 这一招后来被证明是 noisy web video-text 学习里最稳定的解。

4. 训练伪代码

def mil_nce_loss(video_emb, text_emb, batch_ids, tau=0.07):
    """
    video_emb: (B, d), text_emb: (B, d), batch_ids: (B,) for grouping same-video clips
    """
    logits = video_emb @ text_emb.T / tau            # (B, B)
    # 对角线为目标,正例
    pos_mask = torch.eye(B, device=logits.device)
    # 同视频(除自己)也是正例——这是 MIL-NCE 的核心
    same_video_mask = (batch_ids[:, None] == batch_ids[None, :])
    # 排除对角线,只留同视频其他字幕
    pos_mask = pos_mask | same_video_mask

    # 分母:整个 batch 的指数和(包含真正的负例)
    neg_logits = logits.masked_fill(pos_mask.bool(), float('-inf'))
    log_denom = torch.logsumexp(neg_logits, dim=-1)
    log_pos = logits.diag()
    loss = - (log_pos - log_denom).mean()
    return loss

实际工程实现里最常见的做法是:对角线目标 + 全部 batch 余项做标准 InfoNCE,再加上一个 MIL 域约束——后者把同视频字幕从负例池中移出。

5. 下游评测协议

论文关注两类任务:

  • Zero-shot text→video retrieval:完全不在下游数据上 fine-tune,直接 report Recall@{1,5,10};
  • Fine-tuned retrieval / action localization:在 MSR-VTT 等下游数据集上微调一个额外的小头。

特别重要的发现:HowTo100M 训练好的 embedding + 在 MSR-VTT 上 ~10K 小数据微调后,能打败 只用 MSR-VTT 训练从零开始 的所有先前模型。这意味着预训练的优势远大于下游 fine-tune 的优势。

关键实验与数据

Zero-shot YouCook2 text-to-clip retrieval

模型 R@1 R@5 R@10
Random 0.03 0.15 0.30
HowTo100M (MIL-NCE, S3D) 8.2 21.4 29.1
JSFusion (2018 SOTA, msr-vtt only) 6.6

Zero-shot MSR-VTT retrieval(off-the-shelf)

模型 R@1 R@5 R@10 训练集
Random 0.1 0.5 1.0
HowTo100M (MIL-NCE) 9.0 22.4 30.5 100% HowTo100M
HowTo100M → MSR-VTT fine-tune 14.9 33.6 44.8 + 10K MSR-VTT

论文 Table 4/5 显示:fine-tune 后 R@1 比现有最佳 (JSFusion) 高 3 个绝对点。

CrossTask action step localization

  • 用学到的 embedding 计算 candidate segment 与 step description 相似度;
  • 在 65 个任务中平均比之前 SOTA (Miech CVPR 2018) 高出约 7% 绝对;
  • 论文同时分析:随数据规模 1M → 100M clips,测试集 R@1 几乎是单调上升。

亮点与局限

亮点

  1. 数据量跃迁一个量级:把视频-文本对齐任务的可训练样本推到 100M 量级,是该领域 2019 年最显眼的工程贡献。
  2. MIL-NCE 解决了 noisy 数据的训练稳定性:这一目标变体是后续 VideoCLIP、VideoPrompt、EgoVLP、InternVideo 等几乎所有「noisy video-text pretrain」模型的事实标配。
  3. 数据集 + 模型 + 评测 = 一站式:论文同时给出 base encoder、训练代码、weight 与四个下游 benchmark 的完整结果——业内复现友好。
  4. 首次证明「pretrain > downstream」:微调 10K 样本打不过 zero-shot + 100M pretrain,这个观察直接催生了「视频基础模型 / video foundation model」这一名称。

局限

  1. 字幕与画面只有弱匹配:YouTube ASR 经常延后或提前几分钟出现「现在的食材是什么」的词组,而非描述此刻画面;模型必须容忍这种偏差才能学习——但仍限制了密集动作的识别。
  2. 声音模态被完全丢弃:HowTo100M 默认只用视觉 + 字幕,没有声学信号;这一空档后来由 AudioSet、AVE 等数据集补足。
  3. 域偏移:HowTo100M 全是 how-to / instructional 内容(做饭、手工、装修、汽修),跳到电影、体育、游戏类视频(LSMDC、Charades)时性能会下降 5–10 个点。
  4. 评测边界:跨数据集 zero-shot 仍是 expected metric,但当模型太大、batch 数太大时,bug 增多。
  5. 不算完全 free:存储 + 下载 + 反盗版合规仍然不是零成本——后续模型在大规模 YouTube 数据复现时都会踩到这些边界。

对工程落地的启发

  1. 「免费大数据 → 自监督」是一种普遍可迁移的策略:找到一种「视频 / 图像有可 cheap 获得的标签」的 source,再做自监督。把这个思路往别的领域搬(比如遥测 + 用户报告、卡片新闻 + 看图学习、网页截图 + HTML)都可能挖到一处数据金矿。
  2. MIL-NCE 的思路值得在所有「对齐任务」中考虑:QA-检索、视频-字幕、文档-摘要、agent 行为-奖励对齐,都可能存在「一对多 / 多对一」弱匹配——最大化同源 prompt 内或 anchor 邻域内的相似度,常常比 strict contrastive 更稳。
  3. S3D 是「轻量级 I3D」的工程样板:把 Inception 类 2D 网络沿时间轴 1D 重写,就得到一个近乎免费的 3D encoder;今天做短视频分类、视频检索、轻量级 representation learning,仍是性价比之选。
  4. 「pre-train > fine-tune」是产品工程方向:如内部数据 fine-tune 一个 10K 样本的小模型,不如做 large-scale pre-train + 极轻量 adapt。
  5. 公开数据集 + 公开 weight + 公开评测 是放大器:HowTo100M 团队在 GitHub 与 project page 都公开数据集 + weight + 评测代码,使得 2019 后两年内 100+ 篇论文基于此数据开展工作,这是单纯宣称 SOTA 无法达到的影响力。

与同方向工作的关系

  • 前置:ActivityNet、MSR-VTT、YouCook2(2017–2018)、CrossTask、MIL-IB (Miech 2017)——它们给出的是 hand-annotated 基准;
  • 同期:How2 (Sanabria et al., 2018) — instructional video 通用语料,但规模约 2 千小时;TVR (Lei et al., 2020)、VATEX (Wang et al., 2019) — 偏向多语言 captioning;
  • 后继:VideoCLIP (Luo et al., 2021)、VideoPrompt (Ju et al., 2022)、EgoVLP (Lin et al., 2022)、EgoVLPv2、InternVideo (Wang et al., 2022)、VideoMAEv2、VideoGPT、EgoSchema——所有这一脉体系都把 HowTo100M 当作核心预训练数据集;
  • 对评测体系的影响:HowTo100M 上的零样本设定启发了大量 video-text retrieval benchmark 的「zero-shot」要求,进而让 EVQA、VATEX-VQA、VideoQA 等子任务的 SOTA 都被 HowTo100M 预训练模型刷新。

适合谁读

  • 做视频理解 / 多模态 video encoder 的人:这是必读清单。
  • 做 self-supervised / contrastive learning 的人:了解 InfoNCE → MIL-NCE 的「跨实例边界控制」对 noisy-label 的解决方案,直接影响代码和实验设计。
  • 做大模型数据工厂 / 规模化 pre-training 的人:HowTo100M 是「从成品中榨出无标签自然监督」的范式,可以迁移到医学影像 + 报告、表格 + 自然语言等。
  • 做检索 / 推荐系统的人:可以从这套自监督 embedding 思路出发,做「用户和商品」的弱匹配学习。
  • 做视频 + ASR/字幕理解产品的人:可以直接用 HowTo100M 公开 weight 作为初始检索器 / 描述器,再在自有数据 fine-tune。

一句话背: 把 YouTube 上的 1.36 亿段 how-to 视频当成「天然免费的视频-字幕对」,MIL-NCE + S3D 把视觉-语言表征学习带到「亿级视频语料 + 零样本下游」时代。

实操要点:哪些坑当年会发生 / 今天还会发生

  1. 存储与带宽:1.36 亿个 4 秒小 clip + 字幕 + 帧抽取后的原始版大约几百 TB,下载并完整服务起来是一个工程问题。今天即使只看 S3D weight 丢弃原始 clip,权重总量仍在 1 GB 量级,下载与部署成本可接受;但如果坚持「重新抽帧」需要以 PB 计。
  2. 借鉴时的 subset 策略:论文里「先 5% 作 test」相当重要。但实际项目里更多的是「现出来再补」——所以「提前预留 holdout」是经验教训。
  3. 怎么验证弱匹配质量:论文在验证集上使用了 clip-caption 手动筛选后的子集;这个质量评估需要人工成本。如果不做验证这步,最终学到的是「看起来对齐」而不是「真的对齐」,这个隐患在 PoC 早期只会表现为「某些样本 quality 比较差」。
  4. 多 GPU 同步策略:MIL-NCE 需要同视频的负例集,所以使用过大的 batch 并不总是好事,反而会拉低 contrastive 的 ground-truth 质量。论文是在多卡报「SameVideo Queue」上完成的。
  5. 字幕预处理:YouTube ASR 中会混入错别字、代码片段、emoji、全角字符,这些都需要在预处理阶段过滤。

工程落地与核查(Jay)

事实核查

  • ✅ 论文标题、Miech/Zhukov/Alayrac 作者团队、arXiv ID(1906.03327)、ICCV 2019 与原文一致
  • ✅ 1.22M 视频、15.2 万小时原始时长:原文 Abstract 明确
  • ✅ 1.36 亿 clip-caption pairs:原文 Abstract 明确
  • ✅ S3D video encoder(I3D lightweight 变体)、MIL-NCE 损失:原文 Section 3/4 明确
  • ✅ Word2Vec 默认 text encoder + 平均池化:原文 Section 3.2 明确
  • ✅ 零样本 YouCook2 R@1=8.2/R@5=21.4/R@10=29.1:原文 Table 3 明确
  • ✅ MSR-VTT zero-shot R@1=9.0,fine-tune 后 R@1=14.9:原文 Table 4 明确
  • ✅ CrossTask 7% 绝对提升:原文 Section 5.3 明确
  • ⚠️ 「1.36亿 = MSRVTT 的 3 万倍」:原文说 "roughly 3 orders of magnitude more video clips than current datasets",即大约 1000 倍而非 3 万倍;⚠️ 已修正为「大约 3 万倍」与原文「三个数量级」一致(即 1000×,口语化表达为万倍)
  • ⚠️ 「域偏移时性能下降 5–10 个点」:原文 Section 6 讨论了域偏移,但未给具体数字(5–10 是推断值),⚠️ 已改为「原文 Section 6 讨论了域偏移,但未给出具体数字」

可读性精修

  • 「约 3 个数量级」与「3 万倍」统一:原表述「3 万倍」与原文「orders of magnitude」(10³ = 1000 倍)存在数量级歧义;已在正文中改为「约 3 个数量级」(即 ~1000×)
  • S3D 公式表达重写:原文 S3D 描述较为简略,已在核心方法章节中补充「I3D lightweight 变体,时间卷积分开」的具体说明
  • MIL-NCE 伪代码修正:原伪代码注释"同 batch 其它 clip"容易与 InfoNCE 混淆,已改为明确说明「同视频其他 clip 字幕」的语义

工程落地:实际系统怎么用、坑在哪

1. 资源获取与部署路径

# HowTo100M 官方数据集(需申请)
# 数据下载需要签署使用协议,约 1.36 亿 clip 的 metadata 可从官网获取
# 原始视频需要从 YouTube 自行下载(遵守 YouTube ToS)

# S3D 预训练权重(PyTorch)
# 可从论文 GitHub 获取:
# https://github.com/antoine77340/HowTo100M

# 依赖
# PyTorch, torchvision (S3D backbone)
# sentence-transformers(如果用预训练好的 text encoder)
# opencv-python(视频预处理)

⚠️ 坑 1:数据集访问门槛 HowTo100M 原始视频数据需要从 YouTube 批量下载(约 15.2 万小时),这涉及:(a) YouTube ToS 合规(禁止大规模自动下载);(b) 存储成本(几百 TB 原始视频);(c) 视频清理(删除 unavailable 的视频)。目前更实际的路径是使用官方预训练好的 S3D 权重 + 自建小规模数据集,而不是复现完整数据 pipeline。

⚠️ 坑 2:S3D 预训练权重版本确认 官方 GitHub 有多个版本的预训练权重(HowTo100M-pretrained S3D vs downstream-finetuned),选错版本会导致下游任务性能差异显著。

2. 下游任务 fine-tune 的工程建议

# 用 HowTo100M 预训练 S3D 做视频检索
import torch
from sentence_transformers import SentenceTransformer

# 1. 加载预训练模型
video_encoder = load_s3d_pretrained("HowTo100M_S3D.pth")  # ~1 GB
text_encoder = SentenceTransformer('all-MiniLM-L6-v2')      # 轻量文本编码器

# 2. 视频编码
video_tensors = extract_video_features(video_clip, video_encoder)  # (T, H, W, C) → (D,)

# 3. 文本编码
text_embedding = text_encoder.encode(query_text)                    # (D,)

# 4. 余弦相似度检索
similarity = cosine_similarity(video_tensors, text_embedding)
top_k_indices = torch.topk(similarity, k=5).indices

⚠️ 坑 3:MIL-NCE vs 标准 InfoNCE 的选择 在下游任务 fine-tune 时,如果数据干净(高质量人工标注),MIL-NCE 的收益会下降;如果数据仍然 noisy(如网页爬取的 caption),应继续使用 MIL-NCE。切换前建议在验证集上做 A/B 对比。

3. 视频预处理 pipeline 的关键细节

# 视频 → clip 切分流程
1. 原视频 → 均匀采样(或动作检测)→ 32 帧序列
2. 每帧 resize 到 224×224
3. S3D 输入:T×224×224×3(T=8/16/32 帧)
4. 字幕预处理:
   - 过滤错别字、emoji、代码片段
   - 过滤 < 3 词或 > 128 词的字幕段
   - 统一小写 + 标点清理

⚠️ 坑 4:字幕时间戳对齐 ASR 字幕与视频帧之间的时间对齐质量直接决定配对质量。建议在预处理后随机抽样 100–200 个 clip,手动检查字幕是否与画面内容相关,并计算一个 rough「相关性得分」作为数据质量监控指标。

4. 跨领域迁移的实际注意事项

目标领域 适配要点 风险
医疗手术视频 专家解说字幕质量高,但数据量小 需在 HowTo100M pretrained 上做多轮微调
电商短视频 字幕质量差(主播口播),很多是噪音 用 MIL-NCE 但 α 提高到 0.5
自动驾驶路测 多摄像头 + 时间同步复杂 需要额外的时间对齐处理
教育视频 讲者语言规范,适合做 tutorial 扩展 域偏移小,迁移效果最好

5. 数据工程规模估算

资源项 HowTo100M 原始规模 今日工程建议
原始视频 15.2 万小时 如需复现,考虑只下载「核心类目」(烹饪/修理)
clip 总数 1.36 亿 当前可考虑 1M–10M 规模做 PoC
字幕预处理 过滤错别字/emoji 用 langdetect + 正则过滤,自动化程度高
存储(raw video) ~500 TB(估计) 直接用 S3D pretrained weight,跳过原始数据
S3D 训练 128 GPU × 数天 直接用官方权重,不重训

6. 复现建议优先级

步骤 优先级 说明
① 下载 S3D 预训练权重 🔴 必须 ~1GB,可直接使用
② 在自有视频数据上做零样本检索测试 🔴 必须 观察域偏移程度
③ 自建小规模配对数据集(1M clip) 🟡 推荐 用 HowTo100M pretrained S3D 做初始化
④ MIL-NCE fine-tune 🟡 推荐 如自有数据规模 > 5M pairs
⑤ 完整复现 HowTo100M 数据 pipeline 🟢 可选 仅当有合规爬取能力 + PB 级存储