自监督视觉:SimCLR、DINO、MAE


文档摘要

自监督视觉:SimCLR、DINO、MAE 本节摘要:标签是监督视觉的瓶颈。自监督预训练把它拿掉——从一亿张无标签图里学视觉特征,再在一万张带标签图上微调。本节追踪三大家族:对比学习(SimCLR,拉近正对、推开负样本,需大批)、师生蒸馏(DINO,学生预测教师输出、教师是学生的 EMA、靠居中+锐化防塌缩)、掩码重建(MAE,掩 75% patch 重建像素)。从零实现 InfoNCE 损失,讲清为什么批 512 行而批 32 不行、为什么 MAE 的 75% 掩码率不是随便定的(图像 patch 熵低,BERT 的 15% 不够)。读完本节,你能用 DINOv2/MAE 检查点做线性探测与零样本检索。 对应原课程:Phase 4 · Lesson 17 · (原英文 )。

自监督视觉:SimCLR、DINO、MAE

本节摘要:标签是监督视觉的瓶颈。自监督预训练把它拿掉——从一亿张无标签图里学视觉特征,再在一万张带标签图上微调。本节追踪三大家族:对比学习(SimCLR,拉近正对、推开负样本,需大批)、师生蒸馏(DINO,学生预测教师输出、教师是学生的 EMA、靠居中+锐化防塌缩)、掩码重建(MAE,掩 75% patch 重建像素)。从零实现 InfoNCE 损失,讲清为什么批 512 行而批 32 不行、为什么 MAE 的 75% 掩码率不是随便定的(图像 patch 熵低,BERT 的 15% 不够)。读完本节,你能用 DINOv2/MAE 检查点做线性探测与零样本检索。

对应原课程:Phase 4 · Lesson 17 · self-supervised-vision(原英文 phases/04-computer-vision/17-self-supervised-vision/docs/en.md)。

学习目标

阅读完本节,你应当能够:

  1. 追踪三大自监督家族——对比(SimCLR)、师生(DINO)、掩码重建(MAE)——并说出各自优化什么。
  2. 从零实现 InfoNCE 损失,解释为什么批 512 行而批 32 不行。
  3. 解释为什么 MAE 的 75% 掩码率不是随便定的,以及它与 BERT 文本的 15% 有何不同。
  4. 用 DINOv2 或 MAE 的 ImageNet 检查点做线性探测与零样本检索。

一、问题与直觉

监督式 ImageNet 有 130 万张标注图,标注成本估计 1000 万美元。医疗和工业数据集更小、更贵。每个视觉团队都在问:能否在廉价无标签数据(YouTube 帧、网页爬取、监控、卫星扫掠)上预训练,再在小的带标签集上微调?

自监督学习就是答案。在 LAION 或 JFT 上训的现代自监督 ViT,微调后达到或超过监督式 ImageNet 精度,且比监督预训练迁移到下游任务(检测、分割、深度)更好。DINOv2(Meta,2023)和 MAE(Meta,2022)是当前可迁移视觉特征的生产默认。

概念上的转变是:前置任务(模型被训去做的事)不必是下游任务。要紧的是它逼模型学到有用特征。预测灰度图的颜色、旋转图片再让模型分类旋转角度、掩 patch 重建——都奏效过。能 scale 的三种是对比学习、师生蒸馏、掩码重建。

三大家族

对比学习(SimCLR)

取一张图,套两次随机增强,得到两个视图。都过同一个编码器加一个投影头。最小化这样一个损失:「这两个嵌入应该接近」「这个嵌入应该远离批里所有其他图的嵌入」。

每批 2N 个视图里正对 (z_i, z_j) 的损失: L_ij = -log( exp(sim(z_i, z_j) / tau) / sum_{k in batch \ {i}} exp(sim(z_i, z_k) / tau) ) sim = 余弦相似度 tau = 温度(0.1 是标准)

这就是 InfoNCE 损失。它要求每个正对有许多负样本,所以批大小要紧——SimCLR 要 512~8192。MoCo 引入过去批的动量队列,把负样本数与批大小解耦。

师生(DINO)

两个同架构网络:学生和教师。教师是学生权重的指数移动平均(EMA)。两者都看图像的增强视图。学生的输出被训去匹配教师的——没有显式负样本。

loss = CE( student_output(view_1), teacher_output(view_2) ) + CE( student_output(view_2), teacher_output(view_1) ) teacher_weights = m * teacher_weights + (1 - m) * student_weights (m ≈ 0.996)

为什么不塌缩成「预测常数」:教师输出被居中(减去每维均值)和锐化(除以小温度)。居中防止某一维主导;锐化防止输出塌缩成均匀分布。

DINOv2 把 DINO 在 1.42 亿张精选图上 scale 上去,得到的特征是当前零样本视觉检索和密集预测的 SOTA。

掩码重建(MAE)

掩掉 ViT 输入 75% 的 patch,只把可见的 25% 过编码器。一个小解码器接收编码器输出加上被掩位置上的掩码 token,被训去重建被掩 patch 的像素。

编码器: 可见 25% patch -> 特征 解码器: 特征 + 被掩位置的掩码 token -> 重建像素 损失: 仅在被掩 patch 上的重建像素与原像素 MSE

让 MAE 跑通的关键设计:

  • 75% 掩码率——高。逼编码器学语义特征;只重建 25% 近乎平凡(相邻像素高度相关,CNN 就能搞定)。
  • 非对称编码器/解码器——大 ViT 编码器只看可见 patch;小解码器(8 层、512 维)负责重建。比朴素 BEiT 快 3 倍。
  • 像素空间重建目标——比 BEiT 的 token 化目标更简单,在 ViT 上效果更好。

预训练后丢掉解码器,编码器就是特征提取器。

为什么是 75% 而非 15%

BERT 掩 15% token,MAE 掩 75%。差别在信息密度。

  • 自然语言每 token 熵高。预测 15% token 仍难,因为每个被掩位置有许多合理填法。
  • 图像 patch 熵低——未掩邻域常几乎决定被掩 patch 的像素。要让预测需要语义理解,就得激进地掩。

75% 高到简单空间外推解不了,编码器必须表示图像内容。

线性探测评估

自监督预训练后,标准评估是线性探测:冻结编码器,在上面训一个单层线性分类器,用 ImageNet 标签,报 top-1 准确率。

  • SimCLR ResNet-50:~71%(2020)
  • DINO ViT-S/16:~77%(2021)
  • MAE ViT-L/16:~76%(2022)
  • DINOv2 ViT-g/14:~86%(2023)

线性探测是特征质量的纯度量;微调通常再加 2~5 个点,但混入了头重训的效应。

二、从零实现

步骤 1:双视图增强流水线

import torch import torchvision.transforms as T two_view_train = lambda: T.Compose([ T.RandomResizedCrop(96, scale=(0.2, 1.0)), T.RandomHorizontalFlip(), T.ColorJitter(0.4, 0.4, 0.4, 0.1), T.RandomGrayscale(p=0.2), T.ToTensor(), ]) class TwoViewDataset(torch.utils.data.Dataset): def __init__(self, base): self.base = base self.aug = two_view_train() def __len__(self): return len(self.base) def __getitem__(self, i): img, _ = self.base[i] v1 = self.aug(img) v2 = self.aug(img) return v1, v2

每个 __getitem__ 返回同一张图的两个增强视图,不需要标签。

步骤 2:InfoNCE 损失

import torch.nn.functional as F def info_nce(z1, z2, tau=0.1): """ z1, z2: (N, D) L2 归一化的配对视图嵌入 """ N, D = z1.shape z = torch.cat([z1, z2], dim=0) # (2N, D) sim = z @ z.T / tau # (2N, 2N) mask = torch.eye(2 * N, dtype=torch.bool, device=z.device) sim = sim.masked_fill(mask, float("-inf")) targets = torch.cat([torch.arange(N, 2 * N), torch.arange(0, N)]).to(z.device) return F.cross_entropy(sim, targets)

调用前先 L2 归一化嵌入。tau=0.1 是 SimCLR 默认;更低让损失更尖锐,需要更多负样本。

步骤 3:InfoNCE 健全性检查

z1 = F.normalize(torch.randn(16, 32), dim=-1) z2 = z1.clone() loss_same = info_nce(z1, z2, tau=0.1).item() z2_random = F.normalize(torch.randn(16, 32), dim=-1) loss_random = info_nce(z1, z2_random, tau=0.1).item() print(f"配对相同时的 InfoNCE: {loss_same:.3f}") print(f"随机配对时的 InfoNCE: {loss_random:.3f}")

相同配对应给低损失(大批低温下接近 0)。随机配对应给 log(2N−1),16 对时约 log(31) ≈ 3.4。

步骤 4:MAE 风格掩码

def random_mask_indices(num_patches, mask_ratio=0.75, seed=0): g = torch.Generator().manual_seed(seed) n_keep = int(num_patches * (1 - mask_ratio)) perm = torch.randperm(num_patches, generator=g) visible = perm[:n_keep] masked = perm[n_keep:] return visible.sort().values, masked.sort().values num_patches = 196 visible, masked = random_mask_indices(num_patches, mask_ratio=0.75) print(f"可见: {len(visible)} / {num_patches}") print(f"掩码: {len(masked)} / {num_patches}")

简单、快、对给定种子确定性。真实 MAE 实现会批处理并保留每样本掩码。

三、框架对比

DINOv2 是 2026 年的生产标准:

import torch from transformers import AutoImageProcessor, AutoModel processor = AutoImageProcessor.from_pretrained("facebook/dinov2-base") model = AutoModel.from_pretrained("facebook/dinov2-base") model.eval() # 零样本检索的每图嵌入 with torch.no_grad(): inputs = processor(images=[pil_image], return_tensors="pt") outputs = model(**inputs) embedding = outputs.last_hidden_state[:, 0] # CLS token

得到的 768 维嵌入是现代图像检索、密集对应、零样本迁移流水线的主干。下游任务微调往往只需一个线性头。

图文嵌入用 SigLIP 或 OpenCLIP;MAE 风格微调用 timm 仓库的各种 MAE 检查点。

四、可复用产物

本节产出两个可复用文件(位于原课程 outputs/):

  • prompt-ssl-pretraining-picker.md:一个提示词——给定数据集大小、算力、下游任务,在 SimCLR / MAE / DINOv2 之间挑。
  • skill-linear-probe-runner.md:一个技能——为任意冻结编码器 + 带标签数据集写出线性探测评估。

五、练习

  1. (简单) 验证:对良好对齐的嵌入,降低温度 InfoNCE 下降;对随机嵌入,降低温度 InfoNCE 上升。画出 tau in [0.05, 0.1, 0.2, 0.5] 对损失的图。
  2. (中等) 实现 DINO 风格的居中缓冲。证明没有居中时,学生几个 epoch 内就塌缩成常数向量。
  3. (困难) 在 CIFAR-100 上用第 10 节的 TinyUNet 作主干训 MAE。报告 10、50、200 epoch 的线性探测精度。证明 MAE 预训练的线性探测打败同一 1000 图子集上从头监督的线性探测。

本节要点回顾

  1. 标签是瓶颈——自监督在廉价无标签数据上预训练,再小标签集微调;DINOv2/MAE 是生产默认。
  2. 前置任务不必是下游任务——只要逼模型学有用特征;旋转预测、灰度上色、patch 重建都奏效过。
  3. 对比学习(SimCLR)——双视图、InfoNCE、拉近正对推开负样本;要大批(512~8192),MoCo 用动量队列解耦。
  4. 师生(DINO)——学生预测教师、教师是 EMA、无显式负样本;靠居中(防维主导)+锐化(防均匀塌缩)防崩。
  5. 掩码重建(MAE)——掩 75%、编码器只看可见 25%、小解码器重建像素;非对称设计快 3 倍。
  6. 75% vs 15% 是信息密度——图像 patch 熵低、邻域几乎决定像素,必须激进掩才逼出语义;文本 token 熵高,15% 就够。
  7. 线性探测是特征质量纯度量——冻结编码器+单层线性头;DINOv2-g/14 达 86%。
  8. DINOv2 是 2026 生产标准——768 维 CLS 嵌入是检索/密集对应/零样本迁移的主干,微调常只需线性头。

下一节进入 CLIP 与开放词表——用图文对比学习让模型零样本认出训练时没见过的类别。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U