预训练句子表征——【EMNLP 2021】SimCSE

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1. 介绍

SimCSE(Simple Contrastive Learning of Sentence Embeddings)是一种简单在没有监督训练数据的情况下训练句子向量的对比学习方法。

这个方法是对同一个句子进行两次编码。由于在 Transformer 模型中使用了 dropout,两个句子表征的位置将略有不同。这两个表征之间的距离将被最小化,而同一批中其他句子的其他表征的距离将被最大化(它们作为反例): 在这里插入图片描述

  • 目标函数 Multiple Negatives Ranking Loss:

在这里插入图片描述 其中,z和z' 是两个不同的dropout随机掩码。 h i z i , h i z i h_i^{z_i},h_i^{z'_i} 是相同句子 x i x_i 输入相同编码器,但使用两个不同的dropout随机掩码而得到的向量。

2. 实验效果

在这里插入图片描述 发现效果会比我之前介绍的CT要好

3. 实现

sentence_transformers已经把SimCSE已经封装成pip包,完整的训练流程例子可以参考《Sentence-BERT》。我们在此基础上只用修改loss就能轻松的训练SimCSE了:

from sentence_transformers import SentenceTransformer, InputExample
from sentence_transformers import models, losses
from torch.utils.data import DataLoader

# ……

train_loss = losses.MultipleNegativesRankingLoss(model)

# 训练模型
model.fit(
    train_objectives=[(train_dataloader, train_loss)],
    epochs=1,
    show_progress_bar=True
)
复制代码

4. 有监督的训练

SimCSE也可以用于有监督的数据上训练。我们构造的有监督数据形式为 ( x i , x i + , x i ) (x_i,x_i^+,x_i^-) 。简单来说,就是在训练时不只是把 x i x_i^- 视为负例,且把同batch其他句子的正负例都视为句子i的负例: 在这里插入图片描述 目标函数为: 在这里插入图片描述 实验效果: 在这里插入图片描述

Why does it work?

知乎上有同学提问《为什么SimCSE的效果这么好呢?》

如题,为何通过两次dropout、"自己预测自己"的这种方法效果会这么好呢?通过dropout添加噪声不会改变原来句子的语义吗?

作者在论文中也尝试做了解答: 在这里插入图片描述

Table3 中尝试不同的dropout rate,并观察所有变体的表现都低于默认值Transformers 的 dropout rate p = 0.1。可以发现,当 p增加时,的确可能会添加过多的“噪声不会改变原来句子的语义”,导致表现变差。

此外,我们发现两个极端情况特别有趣: “no dropout”(p = 0)和“fixed 0.1”(使用默认值 dropout p = 0.1,但该对的 dropout 掩码相同)

在这两种情况下,结果对的embedding完全相同,它导致性能急剧下降。我们在训练期间每 10 步检查一次这些模型的checkpoints,并可视化对齐和均匀性(alignment and uniformity) 在这里插入图片描述

Alignment:positive pairs Feature 之间的对齐性(紧密性)。相似的样本具有相似的特征

Uniformity:特征在归一化后在超平面上的均匀性。保留最大信息

这两个指标与对比学习的目标非常一致:正实例应该保持接近,随机实例的嵌入应该分散在超球面上。 在这里插入图片描述 如上图所示,清楚地表明,从预训练的checkpoint开始,所有 模型大大提高了均匀性。

然而两个特殊变体的对齐性也急剧下降,而无监督 SimCSE 保持稳定对齐性,这要归功于 dropout 的使用噪音。

它还表明,从预训练的checkpoint开始是至关重要的,因为它提供了良好的初始对齐性。最后,“删除一个词”改善了对齐方式但获得了较小的增益在均匀性指标上,最终表现不如无监督 SimCSE。

猜你喜欢

转载自juejin.im/post/7085185477275287582