机场国际到达口,你攥着一张朋友去年发的照片,等着接阿伟。人流涌出来,有的低头看手机,有的拖着行李箱,还有的戴着口罩。你不能挨个问“你是阿伟吗”,也没时间用尺子量每个人和照片像不像。你真正做的是——飞快地扫一眼所有人,选出“最像照片”的那个人。注意,是“相对最像”,不是“绝对像”。如果每个人都长得像照片呢?那也要挑一个最接近的;如果所有人都不太像呢?也得选出相对最像的那一个。这种“在候选者中做比较”的思路,正是对比学习的核心心法,也是 InfoNCE 损失函数的工作方式。 这篇文章我们就用“机场接人”这条故事线,把 InfoNCE 拆开看:先看怎么定义要找的人(正样本)和要避开的人(负样本);再看用什么尺子量“像不像”(相似度度量);接着看如何把“最像”变成数学公式(InfoNCE);然后认识一个关键的调节旋钮——温度系数;最后聊一聊这套方法的优点与隐藏的坑。
InfoNCE 是 SimCLR、MoCo、CLIP 等主流预训练模型的核心损失函数。掌握它的原理,你就拿到了看懂大量对比学习论文的钥匙公式,也能在自监督任务里亲手搭出高效的特征学习流程。
可视化演示
展示正负样本对构建与嵌入空间拉近推远、温度系数对softmax分布的调节效果、InfoNCE损失计算全流程,通过模式切换理解对比学习核心机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
正负样本对:嵌入空间拉近推远 查询样本通过数据增强生成正样本对,在嵌入空间中被拉近 Batch内其他样本作为负样本,在嵌入空间中被推远 L = -log[exp(sim(q,k⁺)/τ) / Σexp(sim(q,kᵢ)/τ)] InfoNCE通过对比正负样本相似度学习高质量表征
样本对构建
接人之前,你手里有两样东西:一张目标照片(锚点),以及一批从出站口涌出来的旅客(候选样本)。要找的人叫阿伟,他是正样本;其他旅客是负样本。但问题来了——这张照片是阿伟三年前拍的,头发、穿搭都变了,光靠这一张照片根本不够。怎么办?聪明做法是:把照片做几个“变体”——调亮度、裁剪局部、镜像翻转,相当于同时拿着好几张不同角度的阿伟照片去认。这就是数据增强的直觉。
在对比学习中,没有人工标签,正样本必须“自己造”。对同一张图片施加不同的随机增强(随机裁剪、翻转、颜色抖动),得到两个视图,它们就是一对正样本;同一批次里其他图片的视图,自动成为负样本。模型的任务被设计成:在众多候选里,把同一张图的两个视图认出来。
这个设计迫使网络学会“即使外观变化,本质不变”的特征。比如一张猫的照片,无论被裁剪成头还是尾巴、颜色偏蓝还是偏黄,模型都要认出它们是同一只猫。
1. 锚点样本:$x_i$ 是要被查询的基准样本,相当于机场里你正在寻找的目标人物。
2. 正样本对:$(x_i, x_i^+)$ 表示锚点和它的增强视图,它们语义相同,是你想拉近的一对。
3. 负样本对:$(x_i, x_j^-)$ 表示锚点和批次里其他样本,它们语义不同,是你想推远的一对。
4. 不相交条件:$i \neq j$ 强调负样本不能是锚点自己,否则就没有对比意义了。
所以,照片不只是用来“看”的,还要靠“变体照片”制造训练信号。正样本给模型指明方向,负样本给模型施加压力,两者共同替代码写出了一场“认人训练”。
相似度度量
你扫过出站口每一个人时,心里其实在快速比对“这个人和照片里的五官、脸型像不像”。这不是一个非黑即白的判断,而是一个连续的分数。有人像七分,有人像三分。在神经网络里,我们也需要这样一把能量出“像不像”的尺子。
神经网络无法直接比较两张图片的像素,它会把每个样本压缩成一个向量(特征)。真正被比较的,是这些向量的方向是否一致。于是,余弦相似度登场了:它计算两个向量夹角的余弦值。夹角越小,方向越一致,相似度越高。更妙的是,把特征向量归一化到长度 1 之后,余弦相似度就简化为点积,计算速度更快,数值也更稳定。
在实现时,我们会把一个 batch 所有样本的特征两两点积,得到一张“相似度矩阵”。矩阵第 i 行第 j 列,就是第 i 个样本和第 j 个样本有多像。InfoNCE 的所有计算,都建立在这张矩阵之上。
1. 点积:$u^\top v$ 把两个向量对应位置相乘再求和,结果既和方向有关,也和长度有关。
2. 向量范数:$\|u\|_2$ 是向量的欧几里得长度,用来把长度影响“归一化”掉。
3. 整体比值:除以两个长度后,结果只由夹角决定,取值范围在 $[-1, 1]$,这就是余弦相似度。
这把“尺子”还有个好处:它的输出天然适合做后续的 softmax。你不需要关心特征的绝对大小,只要关心“谁和谁方向更一致”,这正好贴合机场接人时“相对比较”的直觉。
InfoNCE公式
你把出站口所有人按“和照片的相似度”排成一排,然后问自己:阿伟站在队伍里的可能性有多大?如果阿伟排在最前面,你会很安心;如果阿伟被淹没在人群中,你会很焦虑。机器学习里有一个工具专门做这件事——softmax。它把一组相似度分数变成一组和为 1 的概率,分数高的自然获得更高的概率。
InfoNCE 做的正是这件事:把锚点和正样本的相似度作为分子,把所有候选样本(包括正样本和全部负样本)的相似度之和作为分母,得到一个“正样本被选中”的概率。然后取负对数,概率越高损失越低。模型训练的目标,就是让这个概率尽量接近 1。
公式里还有一层互信息的视角:InfoNCE 可以被理解为互信息的一个下界估计,所以它也常被用于“最大化输入与特征之间的共享信息”。这就像你每成功认出一次阿伟,你对“阿伟长什么样”的把握就更强一些——你从一堆混乱的视觉信息里,提取出了关于阿伟的关键信息。
1. 编码特征:$z_i$ 是样本 $x_i$ 经过编码器后得到的特征向量,可以理解为神经网络对图片的“数字化描述”。
2. 相似度除以温度:$\operatorname{sim}(z_i, z_i^+)/\tau$ 将原始相似度按温度系数缩放,温度的作用会在下一节展开。
3. 分子:$\exp(\cdot)$ 对正样本相似度做指数放大,相当于给“最像的人”加权重。
4. 分母:$\sum_{j=1}^{N}$ 累加所有样本的指数相似度,构成完整的概率归一化。
5. 负对数:$-\log$ 把概率转换为损失,概率越接近 1,损失越接近 0。
这个公式本质上就是一个加了温度的 softmax 交叉熵。它把“机场接人”的概率模型写成了可微分的数学形式,让梯度下降能一步步优化模型的“认人能力”。
温度系数
如果你特别信任那张照片,看到九分像的人才肯认,你会调低温度;如果照片是十年前拍的,你愿意给七分像的人也发一张“嫌疑卡”,你会调高温度。温度系数 $\tau$ 就是这个“严格程度”旋钮。
温度系数出现在 softmax 的分母中。$\tau$ 很小时,相似度差异被指数放大,概率分布变得尖锐——几乎只有最像的那个人能得到高概率;$\tau$ 很大时,所有指数都接近相等,概率分布变得平滑——每个人得到的概率差不多,模型失去分辨力。这就像调“锐度”:太尖容易过拟合噪音,太平则学不到细节。
经典实验里,SimCLR 等模型把温度设为 0.07。这个值不是拍脑袋决定的:它让模型既能专注地惩罚“最难缠的负样本”,又不会因为只盯着一个样本而震荡。工程师调参时,$\tau$ 往往比学习率更敏感。
1. 相似度分数:$s_i$ 表示锚点与第 $i$ 个候选样本的相似度。
2. 除以温度:$\tau$ 在分母上。$\tau$ 小则 $s_i/\tau$ 差距巨大,$\tau$ 大则差距被压缩。
3. 指数化:$\exp(s_i/\tau)$ 将缩放后的分数转为非负的权重,放大“胜者”的优势。
4. 归一化:除以所有指数之和,得到第 $i$ 个样本被选中的概率。
温度太高,满眼都是嫌疑人;温度太低,稍微有点不像就错杀。找到一个合适的 $\tau$,才能在人群中又稳又准地锁定阿伟。
优化原理
每次认错人,你都会下意识地调整自己的“判断标准”:那个和阿伟长得很像的路人甲,下次要降低他的权重;真正的阿伟,下次要多给他几分。训练 InfoNCE 的过程,就是不断重复这个调整。
梯度下降把损失函数的“不满”传递回每个样本的相似度。正样本的相似度不够高时,梯度会给它一个“推力”,把它往上抬;负样本的相似度过高时,梯度会给它一个“压力”,把它往下压。关键在于,这个力的大小不是均匀的:某个负样本如果和正样本几乎一样像,它就会分走大量概率,从而收到最强的反向压力——这就是困难负样本被重点惩罚的机制。
用数学表达,InfoNCE 对正样本相似度 $s_i^+$ 的梯度是负的(拉近),对负样本相似度 $s_j^-$ 的梯度是正的(推远)。温度越小,这个梯度信号越强。最终,所有正样本被拉向锚点附近,所有负样本被推离,特征空间里同类聚成一团,异类彼此远离。
1. 概率符号:$p_i^+$ 是正样本被 softmax 选中的概率,$p_j^-$ 是第 $j$ 个负样本的概率。
2. 正样本梯度:$-(1-p_i^+)/\tau$:当正样本概率低时,这个负梯度绝对值很大,把它强烈拉高。
3. 负样本梯度:$p_j^-/\tau$:负样本概率越高,正梯度越大,把它强烈压下。
4. 温度放大:$\frac{1}{\tau}$ 表示温度越小时,梯度整体越敏感,训练越“较真”。
一拉一推,正是对比学习名字的由来。模型不是去背“阿伟长什么样”,而是在一次又一次的“拉近正样本、推远负样本”中,提炼出真正有用的视觉特征。
优点与局限
机场接人这套方法有不少好处:你不需要给每个出站旅客建立档案,不用提前标注“这是谁”,只要凭一张照片就能练习认人。这正是自监督学习的魅力——InfoNCE 能在完全没有人工标注的数据上,训练出高质量的特征提取器。
它还有个很强的扩展性:不只适用于图像。文本、语音、视频、图文对,只要能构造出“正样本对”,就能用 InfoNCE 对齐。CLIP 把图片和文本各自编码,再用 InfoNCE 让语义一致的图文互相靠近,就是典型例子。
但它的软肋同样明显:负样本的“质”和“量”都很关键。一个批次只有 $B$ 个样本时,每个锚点只有 $B-1$ 个负样本。batch 太小,负样本不足,对比不充分;batch 太大,显存吃不消。更麻烦的是,如果负样本全是八竿子打不着的简单样本,模型很快就“躺平”;而困难负样本虽然最能训练模型,数量过多又容易引入噪音。工程上往往需要难例挖掘来配合。
1. 批次大小:$B$ 是一个训练批次中的样本总数,相当于同时出现在你面前的旅客数量。
2. 负样本数量:$B-1$:锚点自己不能当负样本,所以候选负样本数减一。
3. 含义:batch 越大,负样本越多,对比越充分,但对显存和工程的要求也越高。
InfoNCE 像一把能打开无标注数据大门的钥匙,但你需要准备好足够大的“旅客量”和合理的人群构成。钥匙虽好,也得配一把合适的锁。
AI 应用场景
自监督视觉模型预训练
阶段:预训练 / 表示学习
解决的问题:传统图像任务依赖大量人工标注,成本高、周期长,且难以覆盖长尾场景。InfoNCE 让模型在无标注图片上,通过“同图增强为正、跨图为负”的方式学习通用视觉特征。
具体案例:SimCLR 在 ImageNet 上先用 InfoNCE 做自监督预训练,之后仅用 1%~10% 的标注数据微调,就能达到接近全监督训练的效果。这在医疗影像等标注稀缺的领域尤其有吸引力。
多模态图文对齐(CLIP)
阶段:多模态融合 / 对齐
解决的问题:图片和文本之间没有天然标签,需要把“语义一致的图文对”拉近、把“语义不一致的图文对”推远。InfoNCE 天然适合这种配对对比任务。
具体案例:CLIP 用 InfoNCE 同时训练图像编码器和文本编码器,实现“以文搜图”“以图搜文”。做零样本分类时,只需要把类别名写成句子,再匹配图像特征即可。
推荐系统用户表征学习
阶段:召回 / 用户画像
解决的问题:用户行为日志没有显式标签,传统协同过滤依赖物品共现,难以捕捉深层兴趣。
具体案例:把同一用户相邻会话中点击的物品视为正样本,把随机采样到的无关物品视为负样本,用 InfoNCE 学习用户向量和物品向量的相似度,在召回阶段快速筛选候选集。
Python 演示
import numpy as np def normalize(x, axis=-1): return x / (np.linalg.norm(x, axis=axis, keepdims=True) + 1e-12) def info_nce_loss(feats, tau=0.07): # feats: [N, D], row i and row i^1 are a positive pair n = feats.shape[0] sim = np.dot(feats, feats.T) / tau labels = np.arange(n) ^ 1 exp_sim = np.exp(sim - sim.max(axis=1, keepdims=True)) probs = exp_sim / exp_sim.sum(axis=1, keepdims=True) return -np.mean(np.log(probs[np.arange(n), labels] + 1e-12)) def numeric_grad(fn, x, eps=1e-3): x = x.copy() grad = np.zeros_like(x) for idx in np.ndindex(x.shape): orig = x[idx] x[idx] = orig + eps fp = fn(x) x[idx] = orig - eps fm = fn(x) x[idx] = orig grad[idx] = (fp - fm) / (2 * eps) return grad np.random.seed(42)n, d = 8, 16feats = normalize(np.random.randn(n, d)) for step in range(30): loss = info_nce_loss(feats) if step % 5 == 0: print("step %2d loss %.4f" % (step, loss)) grad = numeric_grad(lambda z: info_nce_loss(normalize(z)), feats) feats -= 0.1 * grad feats = normalize(feats)print("final loss %.4f" % info_nce_loss(feats))
def info_nce_loss(feats, tau=0.07):定义 InfoNCE 损失函数,tau是温度系数。labels = np.arange(n) ^ 1让第 0 和第 1 个样本互为“两张增强视图”,即正样本对。sim = np.dot(feats, feats.T) / tau一次性算出所有样本两两之间的相似度矩阵,再除以温度。probs = exp_sim / exp_sim.sum(axis=1, keepdims=True)对每一行做 softmax,把相似度变成概率。numeric_grad(lambda z: info_nce_loss(normalize(z)), feats)用数值梯度模拟反向传播,得到每个特征位置的更新方向。feats -= 0.1 * grad沿梯度反方向更新特征,让损失下降,正样本对逐渐靠近。
常见误区
误区温度系数只是把数值缩放一下,设大一点能让训练更顺滑,直接设成 1 就行。
正解温度系数是“认人的严格程度”。设太大,相当于每个人都有嫌疑,模型学不到细粒度差别;设太小,稍微有点不像就毫不留情,训练会剧烈摆动。经典实验里的 τ=0.07 是经过大量调参得到的经验值,工程中需要针对下游任务重新调。
为何常见:τ 在公式里只是简简单单除一下,看起来无关轻重,但它控制的是 softmax 分布的锐度和梯度尺度,所以特别容易被低估。
误区以为特征相似度超过某个值就是正样本,低于某个值就是负样本,于是想定一个 0.8 这样的阈值。
正解InfoNCE 从不做绝对判断,它只关心“正样本在这个批次里是不是排第一”。即使所有相似度都低,只要正样本比所有负样本高,损失就低;反之,即使所有相似度都高,正样本不是最高的,损失照样高。对比学习要的是排序,而不是阈值。
为何常见:分类任务习惯用阈值做决策,但对比学习设计的是“候选集里挑目标”的任务,和分类的决策模式完全不同。
误区既然分母要累加负样本,那就把 batch size 调到显卡上限,负样本多多益善。
正解负样本数量确实重要,但“质量”更重要。如果负样本全是完全不相关的简单样本,损失很快降到很低,模型却没学到精细特征。真正给梯度“上课”的是那些长得像正样本、但实际不是的困难负样本;没有它们,对比学习容易走入捷径。
为何常见:公式里分母是求和,很容易让人以为项数越多越精确,忽略了每个负样本对梯度的贡献极不均衡。
误区看到训练曲线里 InfoNCE loss 不断下降甚至接近零,就认为特征质量已经非常好,可以部署了。
正解loss 低只能说明模型在当前这批负样本里挑出了正样本,可能只是记住了颜色、纹理、边框等表面线索,并没有真正理解语义。评估特征要去看下游任务(分类、检索)或 KNN、线性探测,才能看到真实水平。
为何常见:训练 loss 是最直观的反馈,容易让人产生“loss 降低等于学到东西”的错觉;但对比学习里 loss 与特征质量并不是严格的等价关系。
面试题
Q1. InfoNCE 通过哪些样本对来学习表征?
- A.任意两张不同图片作为正对
- B.负样本对来提供主要监督
- C.正样本对与负样本对共同对比← 正确答案
- D.只用正样本对进行监督学习
答案:C。InfoNCE 做的是“机场接人”式的对比:正样本对和负样本对同时上场,目标是让正样本的相对相似度在全体候选中胜出。A 错在“任意”,B 错在只用负样本,D 错在只用正样本;只有 C 准确描述了这一机制。
Q2. 温度系数 τ 非常小时,softmax 概率分布会出现哪种变化?
- A.分布平滑且梯度稳定
- B.分布几乎完全均匀化
- C.分布更尖锐也更敏感← 正确答案
- D.分布完全不受温度影响
答案:C。τ 很小时,相似度差异被指数放大,softmax 分布变得尖锐,近似“只认最像的人”。A 和 B 是 τ 很大时的表现,D 不可能。调小 τ 等于把认人标准调到极度严格,对困难负样本高度敏感。
Q3. 自监督对比学习中,正样本对通常如何构造?
- A.同一张图两种不同增强视图← 正确答案
- B.两张语义完全相同的图片
- C.同一个批次里的任意邻接图
- D.从数据集随机抽取的样本对
答案:A。自监督没有标签,正样本只能靠数据增强构造。对同一张图做裁剪、翻转、颜色扰动得到两个视图,它们就是一对正样本。B 提到的“语义完全相同图片”难以定义;C 和 D 描述的其实是负样本思路。
Q4. InfoNCE 损失优化的核心目标是?
- A.让所有样本相似度都趋近于零
- B.让正样本的相对相似度最大← 正确答案
- C.让负样本的相似度绝对最小
- D.让损失值降到最低就可以
答案:B。InfoNCE 的核心是让正样本在全体候选中的归一化概率最高,也就是“相对相似度最大”。A 与目标相反;C 只压负样本,忽略了正样本的相对位置;D 是训练结果而不是目标本身。
Q5. 关于温度系数 τ 的作用,下列说法正确的是?
- A.较小会让分布更加尖锐← 正确答案
- B.较大时分布平滑且梯度稳← 正确答案
- C.τ 设为零时损失依然有效
- D.经典实现常取 0.07 附近← 正确答案
答案:ABD。τ 小会让 softmax 更尖锐,τ 大则平滑且梯度更均匀。τ=0 会除零,所以 C 错。SimCLR 等经典实现常用 τ=0.07,所以 D 对。这个“严格程度旋钮”是训练是否稳定的关键超参。
Q6. InfoNCE 分母中的求和主要包含哪些项?
- A.正样本和所有负样本相似度← 正确答案
- B.仅包含正样本的相似度项
- C.只累加负样本的相似度项
- D.包含特征向量的 L2 范数
答案:A。分母要包含正样本和所有负样本的相似度指数和,才能构成完整的概率归一化。B 少了负样本,C 少了正样本,D 把范数与相似度混为一谈。
Q7. 为什么 InfoNCE 对批次大小比较敏感?
- A.批次大可提供更多负样本← 正确答案
- B.大批次增强样本多样性更高← 正确答案
- C.批次大小决定正样本标签
- D.小批次导致损失方差较大← 正确答案
答案:ABD。batch 大,负样本多,对比更充分;批次内增强样本也更丰富;batch 小会让损失估计方差增大,训练不稳定。C 错误,正样本由增强配对决定,和批次大小无关。
Q8. 当某个负样本与正样本极其相似时,InfoNCE 会产生什么梯度信号?
- A.该负样本收到更强的推远梯度← 正确答案
- B.该负样本不参与梯度更新
- C.正样本梯度变为零并停止
- D.模型损失直接降为零且不变
答案:A。负样本与正样本很像时,它会在 softmax 中分走很大概率,损失主要“归咎”于它,梯度会给它更大的推力把它推远。B 和 C 违背了推远机制;D 不可能,正样本概率仍会影响损失。
Q9. InfoNCE 中 log 运算的核心作用是?
- A.为了使训练曲线更平滑
- B.抵消指数并保持数值稳定← 正确答案
- C.让损失值永远保持为正数
- D.把相似度变成概率分布
答案:B。log 让交叉熵与 softmax 中的 exp 互相抵消,既避免指数运算数值溢出,也让优化更稳定。A 是表面感受;D 是 softmax 做的事;C 是附带效果,不是核心原因。
Q10. 若去掉 InfoNCE 分母中所有负样本项,模型会发生什么?
- A.模型更快收敛并得到优质特征
- B.特征分布可能崩溃到同一常数← 正确答案
- C.所有特征在球面上均匀分布
- D.模型完全不能进行梯度更新
答案:B。去掉所有负样本后,目标变成“最大化正样本相似度”,最简单的解是所有特征变成同一个常数向量,模型彻底退化塌缩。这不是更好收敛,而是学到零信息。A 和 C 都是理想化幻想;D 不对,正样本项仍然提供梯度。