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 步:
- 种子检索:用分类器/关键词从 YouTube 检索约「how-to」类视频(手工给了一个上千词词表);
- 过滤:要求字幕非自动翻译、长度 > 100 词,覆盖英语;
- 下载:~1.22M 个视频,原始时长约 15.2 万小时;
- 切 clip:保留连续 ASR 段落长度 ≥ 2 秒的 clip,最终得到 1.36 亿段,每段平均 ~4 秒;
- 弱匹配:在 clip 时间窗内对 ASR 取 embedding,把视频 clip 视为该 embedding;
- 分 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 几乎是单调上升。
亮点与局限
亮点
- 数据量跃迁一个量级:把视频-文本对齐任务的可训练样本推到 100M 量级,是该领域 2019 年最显眼的工程贡献。
- MIL-NCE 解决了 noisy 数据的训练稳定性:这一目标变体是后续 VideoCLIP、VideoPrompt、EgoVLP、InternVideo 等几乎所有「noisy video-text pretrain」模型的事实标配。
- 数据集 + 模型 + 评测 = 一站式:论文同时给出 base encoder、训练代码、weight 与四个下游 benchmark 的完整结果——业内复现友好。
- 首次证明「pretrain > downstream」:微调 10K 样本打不过 zero-shot + 100M pretrain,这个观察直接催生了「视频基础模型 / video foundation model」这一名称。
局限
- 字幕与画面只有弱匹配:YouTube ASR 经常延后或提前几分钟出现「现在的食材是什么」的词组,而非描述此刻画面;模型必须容忍这种偏差才能学习——但仍限制了密集动作的识别。
- 声音模态被完全丢弃:HowTo100M 默认只用视觉 + 字幕,没有声学信号;这一空档后来由 AudioSet、AVE 等数据集补足。
- 域偏移:HowTo100M 全是 how-to / instructional 内容(做饭、手工、装修、汽修),跳到电影、体育、游戏类视频(LSMDC、Charades)时性能会下降 5–10 个点。
- 评测边界:跨数据集 zero-shot 仍是 expected metric,但当模型太大、batch 数太大时,bug 增多。
- 不算完全 free:存储 + 下载 + 反盗版合规仍然不是零成本——后续模型在大规模 YouTube 数据复现时都会踩到这些边界。
对工程落地的启发
- 「免费大数据 → 自监督」是一种普遍可迁移的策略:找到一种「视频 / 图像有可 cheap 获得的标签」的 source,再做自监督。把这个思路往别的领域搬(比如遥测 + 用户报告、卡片新闻 + 看图学习、网页截图 + HTML)都可能挖到一处数据金矿。
- MIL-NCE 的思路值得在所有「对齐任务」中考虑:QA-检索、视频-字幕、文档-摘要、agent 行为-奖励对齐,都可能存在「一对多 / 多对一」弱匹配——最大化同源 prompt 内或 anchor 邻域内的相似度,常常比 strict contrastive 更稳。
- S3D 是「轻量级 I3D」的工程样板:把 Inception 类 2D 网络沿时间轴 1D 重写,就得到一个近乎免费的 3D encoder;今天做短视频分类、视频检索、轻量级 representation learning,仍是性价比之选。
- 「pre-train > fine-tune」是产品工程方向:如内部数据 fine-tune 一个 10K 样本的小模型,不如做 large-scale pre-train + 极轻量 adapt。
- 公开数据集 + 公开 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.36 亿个 4 秒小 clip + 字幕 + 帧抽取后的原始版大约几百 TB,下载并完整服务起来是一个工程问题。今天即使只看 S3D weight 丢弃原始 clip,权重总量仍在 1 GB 量级,下载与部署成本可接受;但如果坚持「重新抽帧」需要以 PB 计。
- 借鉴时的 subset 策略:论文里「先 5% 作 test」相当重要。但实际项目里更多的是「现出来再补」——所以「提前预留 holdout」是经验教训。
- 怎么验证弱匹配质量:论文在验证集上使用了 clip-caption 手动筛选后的子集;这个质量评估需要人工成本。如果不做验证这步,最终学到的是「看起来对齐」而不是「真的对齐」,这个隐患在 PoC 早期只会表现为「某些样本 quality 比较差」。
- 多 GPU 同步策略:MIL-NCE 需要同视频的负例集,所以使用过大的 batch 并不总是好事,反而会拉低 contrastive 的 ground-truth 质量。论文是在多卡报「SameVideo Queue」上完成的。
- 字幕预处理: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 级存储 |