自然语言处理和信息检索中的许多任务都涉及句子的成对比较——例如,句子相似性检测、释义识别、问答蕴涵和文本蕴涵。
最准确的句子比较方法是所谓的cross-encoding,它在逐对的基础上将句子相互映射。然而,训练cross-encoders 器需要带标注的训练数据,收集这些数据是劳动成本很高。
我们如何为句子对任务训练完全无监督的模型,从而消除对数据标注的需求呢?
在今年的学习表示国际会议 ( ICLR ) 上,作者展示了一种无监督的句子对模型,我们称之为trans-encoder,它在句子相似度上比现有技术提高了 5%基准:
- paper:https://arxiv.org/pdf/2109.13059v3.pdf
- code :https://github.com/amzn/trans-encoder
两个编码器的故事
今天,句子对任务基本上有两种范式:cross-encoders 和 bi-encoders。两者之间的选择归结为计算效率和性能之间的标准权衡。
cross-encoders。在cross-encoders 中,将两个序列连接起来并一次性发送到句子对模型,该模型通常构建在基于 Transformer 的语言模型(如BERT或RoBERTa )之上。Transformer 的注意力头可以直接建模一个序列的哪些元素与另一个序列的哪些元素相关,从而能够计算准确的分类/相关性分数。
然而,cross-encoders 需要为每对输入句子计算一个新的编码,从而导致高计算开销。因此,cross-encoders 对于信息检索和聚类等涉及大量成对句子比较的任务是不切实际的。此外,将预训练语言模型 (PLM) 转换为cross-encoders 总是需要对带标注的数据进行微调。
bi-encoders。相比之下,在bi-encoders 中,每个句子都被单独编码并映射到一个公共嵌入空间,在那里可以测量它们之间的距离。由于编码的句子可以被缓存和重用,bi-encoders 效率更高,并且bi-encoders 的输出可以现成的用作下游任务的句子嵌入。
也就是说,众所周知,在监督学习中,bi-encoders 的性能不如cross-encoders,因为它们没有明确地模拟句子之间的交互。
Trans-Encoder:两全其美
在我们的 ICLR 论文中,我们询问是否可以利用cross-encoders 和 bi-encoders的优势以无监督的方式引导一个准确的句子对模型。
Trans-Encoder——建立在以下直觉之上:作为起点,我们可以使用bi-encoders 表示来微调 cross-encoders。凭借其更强大的句间建模,cross-encoders 应该从 PLM 中提取更多的知识,而不是bi-encoders 可以给定相同的输入数据。反过来,更强大的cross-encoders 可以将其知识提炼回bi-encoders ,从而提高计算更实用模型的准确性。我们可以重复这个循环,从cross-encoders 和 bi-encoders 迭代地引导。
具体来说,训练一个trans-encoder的过程如下:
步骤 1. 将 PLM 转换为有效的bi-encoder。 为了将现有的 PLM 转换为bi-encoder,我们利用了一个简单的对比调整程序。给定一个句子,我们使用两个不同的 PLM 对其进行两次编码。由于 dropout(一种标准技术,其中在每次通过训练数据期间随机丢弃一小部分神经网络节点,以防止出现瓶颈),两个 PLM 将产生略有不同的编码。
然后训练 bi-encoder 以最大化两个几乎相同的编码的相似性。这一步使 PLM进行更好的encoding。详细信息可以在之前的工作Mirror-BERT和SimCSE中找到(《文本匹配——【EMNLP 2021】SimCSE》)。
步骤 2. 自蒸馏:bi-encoder 到 cross-encoder。从第一步获得相当好的 bi-encoder 后,我们用它来创建 cross-encoder 的训练数据。具体来说,我们用 bi-encoder 计算的成对相似度分数标记句子对,并将它们用作构建在新 PLM 之上的 cross-encoder 的训练目标。
步骤 3. 自蒸馏:cross-encoder 到 bi-encoder。 下一步自然是将 cross-encoder 获得的额外知识提炼回 bi-encoder 形式,这对下游任务更有用。更重要的是,更好的 bi-encoder 可以产生更多的自标记数据来调整 cross-encoder。通过这种方式,我们可以重复第二步和第三步,不断优化编码器性能。
基准:句子相似度的最新技术
作者在七个句子文本相似性 (STS) 基准上对转编码器进行了实验。观察到在所有数据集上对以前的无监督句子对模型的显着提升。
损失函数的选择
令人惊讶的是,学生 bi-encoder 有时在“cross-encoder 到 bi-encoder”阶段优于其教师 cross-encoder。
作者认为这与观察到的“ cross-encoder 更容易过拟合”有关。由于 cross-encoder 是强大的函数逼近器,它们很容易过度拟合 bi-encoder 给出的伪分数并失去泛化能力,最终得到比 bi-encoder 更低的分数。这也是作者为 cross-encoder 和 bi-encoder 双蒸馏选择不同损失函数的原因。
损失函数的选择:保持师生差异是关键。直观地说,MSE 允许更准确的蒸馏,因为它会惩罚实例级别上预测分数和标签之间的任何数值差异。然而,在实践中,我们发现使用 MSE 进行 bi-to-cross 蒸馏会加剧 cross-encoder 的过拟合问题:cross-encoder 凭借其强大的句对建模能力,完全过拟合连接句对之间的映射和伪分数。这种消除模型预测和伪标签之间的差异会损害泛化,并且迭代学习周期无法继续(因为学生模型的预测分数将与教师模型相同)。因此,作者将 BCE 损失用于bi-encoder 向 cross-encoder,因为与 MSE 相比,BCE 是一个更宽容的损失函数。BCE 本质上是 MSE 的温度锐化版本,它更能容忍数值差异。这可以完全防止交叉编码器 cross-encoder 过度拟合伪标签。而与 cross-encoder 向 bi-encoder 蒸馏不存在类似的问题,两个输入序列分别编码,模型不容易过度拟合标签。
在设计模型时,我们对损失函数配置进行了全面的实验,发现在选择 cross-encoder 向 bi-encoder 和 bi-encoder 向 cross-encoder 蒸馏的学习目标时需要谨慎。如上所述,选择 MSE 进行 bi-to-cross 蒸馏会导致对伪分数的严重过拟合,而选择 BCE 进行 cross-to-bi 蒸馏无法使模型收敛。 因此,作者分别使用 BCE 和 MSE 进行 bi-to-cross 和 cross-to-bi 蒸馏的配置成为唯一可行的解决方案。