基于词库构建一个向量,向量的每一维对应词库中的一个词,当向量值为1时,表示对应维度的词出现在句子中,反之则则值为0。
例如:
词库:你,我,他,喜欢,吃,苹果
句子:他/喜欢/吃/苹果 (/表示分词)
句子向量:[0,0,1,1,1,1]
**意义:**保留句子中词出现与否的信息。
**用途:**即使是最低级普通的方法,也可以作为一种快速实现baseline的方法去做一些简单的文本分类任务。
如果是用于将句子表示为向量,与one-hot的区别就是将每个维度的值(0,1)替换为词的tf-idf值,tf-idf的计算公式如下:
T F − I D F = T F ∗ l o g D d + 1 TF-IDF = TF*log \frac{D}{d+1} TF−IDF=TF∗logd+1D
TF表示词i在文档(这里文档就是句子)中的词频(可根据文档总词数进行标准化,去除文档长度的影响),D表示文档总数,d表示包含词i的文档数
**意义:**词频越高表示该词对文档约重要,词同时出现在很多的文档中表示该词重要性降低。
**用途:**用作筛选重点词、特征表示、信息检索
bm25用来衡量查询与文档之间的相关系,本质上是对tf-idf的改进,其的完整公式如下:
S c o r e ( Q , D ) = ∑ i n W i ⋅ R ( q i , D ) Score(Q,D)=\sum_{i}^{n}W_{i}\cdot R(q_{i}, D) Score(Q,D)=i∑nWi⋅R(qi,D)
Q和D分别表示查询和文档对应的文本,其中 W i W_{i} Wi表示查询Q中第i个词的权重,用IDF表示,(推理见:idf)。
S c o r e ( Q , D ) = ∑ i n l o g N − n ( q i ) + 0.5 n ( q i ) + 0.5 ⋅ R ( q i , D ) Score(Q,D)=\sum_{i}^{n}log\frac{N-n(q_{i})+0.5}{n(q_{i})+0.5} \cdot R(q_{i}, D) Score(Q,D)=i∑nlogn(qi)+0.5N−n(qi)+0.5⋅R(qi,D)
其中 R ( q i , D ) R(q_{i},D) R(qi,D)表示词i与文档之间相关性,在tf-idf中用词频来表示这一项。BM25中对这一项做了修改:
R ( q i , D ) = f i ⋅ ( k 1 + 1 ) f i + K ⋅ q f i ⋅ ( k 2 + 1 ) q f i + k 2 R(q_{i},D)=\frac{f_{i}\cdot (k_{1}+1)}{f_{i}+K} \cdot \frac{qf_{i}\cdot (k_{2}+1)}{qf_{i}+k_{2}} R(qi,D)=fi+Kfi⋅(k1+1)⋅qfi+k2qfi⋅(k2+1)
由两个因子的乘积表示, f i 、 q f i f_{i}、qf_{i} fi、qfi分别表示词i在文档和查询中的词频, k 1 、 k 2 、 K k_{1}、k_{2}、K k1、k2、K为超参。
得到:
R ( q i , D ) = f i ⋅ ( k 1 + 1 ) f i + K K = k 1 ( 1 − b + b ⋅ d l a v g ( d l ) ) R(q_{i},D)=\frac{f_{i}\cdot (k_{1}+1)}{f_{i}+K} \\ K =k_{1}(1-b+b\cdot \frac{dl}{avg(dl)}) R(qi,D)=fi+Kfi⋅(k1+1)K=k1(1−b+b⋅avg(dl)dl)
这一项与tf-idf中的词频不同的是:
最后:
S c o r e ( Q , D ) = ∑ i n l o g N − n ( q i ) + 0.5 n ( q i ) + 0.5 ⋅ f i ⋅ ( k 1 + 1 ) f i + k 1 ( 1 − b + b ⋅ d l a v g ( d l ) ) Score(Q,D)=\sum_{i}^{n}log\frac{N-n(q_{i})+0.5}{n(q_{i})+0.5} \cdot \frac{f_{i}\cdot (k_{1}+1)}{f_{i}+k_{1}(1-b+b\cdot \frac{dl}{avg(dl)})} Score(Q,D)=i∑nlogn(qi)+0.5N−n(qi)+0.5⋅fi+k1(1−b+b⋅avg(dl)dl)fi⋅(k1+1)
b常取0.75, k 1 、 k 2 k_{1}、k_{2} k1、k2常取1.2~2
与TF-IDF的区别:
限制词频上限,词频理论上是无线增长的,而BM25中 f i ⋅ ( k 1 + 1 ) f i + K \frac{f_{i}\cdot (k_{1}+1)}{f_{i}+K} fi+Kfi⋅(k1+1)上限为 k 1 + 1 k_{1}+1 k1+1。
考虑文档长度对词i与文档之间相关性的影响。直观上,当文档越短,随着词i的词频增加,词i与文档之间的相关性应该快速收敛到上限,反之,收敛速度慢。正如 f i ⋅ ( k 1 + 1 ) f i + k 1 ( 1 − b + b ⋅ d l a v g ( d l ) ) \frac{f_{i}\cdot (k_{1}+1)}{f_{i}+k_{1}(1-b+b\cdot \frac{dl}{avg(dl)})} fi+k1(1−b+b⋅avg(dl)dl)fi⋅(k1+1)中参数b控制的,当b=0时不考虑文档长度对收敛速度的影响。
BERT刚出世的时候横扫各大榜单,但是用bert来进行句子嵌入效果缺很差。
语义相似度与bert预训练之间的联系
MLM可以简化为对给定上文 c c c对token x x x的条件概率进行建模:
其中 h c , w x h_c, w_x hc,wx分别表示 c , x c,x c,x的嵌入表示。其中 h c T w x h_c^Tw_x hcTwx可以分解为如下形式:
PMI衡量二者之间的相关性,表示 c , x c,x c,x共现相对于二者独立出现的频繁程度。共现的统计是一个典型的处理语义的工具。那么可以看出MLM的预训练过程中上下文与token之间的语义关系有被涉及到并加强。因此通过token作为中间枢纽(出现同一个token的上下文),上下文与上下文(也可以看成句子与句子之间)的语义关系也涉及并加强。那么为什么bert embedding效果不好呢。
为什么bert embedding效果不好?
bert的embedding空间被验证是各向异性的。
**什么是各向异性:**bert-flow论文中提到词嵌入在向量空间中占据一个狭窄的圆锥体。在物理学上的含义是“物质的全部或部分化学、物理等性质随着方向的改变而有所变化,在不同的方向上呈现出差异的性质”。
各项异性的缺陷:向量空间不均匀。任意取两个点之间的相似度都比较高。语义表征的能力退化严重。
为什么BERT embedding 空间出现各向异性:感性的理解,从bert的训练目标看,给定上下文表示正样本表示会被推向接近上下文的地方,而负样本表示会远离上下文。对上下文来看,大多数token都是负样本且被推远。对单个上下文看,推远的方向可能有很多。但对很多上下文而言,他们共同的负方向会呈现聚集状态。最终向量空间的二维表示如下:
此外bert-flow作者观察到bert的embedding空间有两个现象
embedding空间对词频是有偏的,高频词距离原点近,低频词距离原点远。
直观上来讲,我们希望embedding产生的相似度是与语义相关。但如果embedding空间的分割是按词频统计来,那么空间下表示的相似度将没有意义。(从上下文与token的内积分解公式也可以得出结论)
低频词分布十分稀疏。如上表所示,随着词频越来越稀疏,其与最近邻的距离在变大。
稀疏带来的问题是:
低频词的语义空间周围存在很多“空洞”,很难去定义其语义。当我们利用平均池化去得到句向量时,平均池化是一个保凸运算,而“空洞”违背了嵌入空间的凸性
直观上看,只有呈现一定的局部聚集的状态,这些片空间才可以去定义其语义。而稀疏的情况导致,低频词的表示没有意义。
基于bert应用于句子对打分这类任务上存在两个问题:
通过微调的bert去做句子对的计分非常慢,需要多次推理,例如从5000w个句子库中找出于输入句子最相似的需要5000w次推理(V100GPU,60h/its),这里一次完整的推理是指一次完成的前向传播过程,比两个向量计算一次余弦相似度显然跟花时间。
注意:
如果直接输入句子对到bert中,属于交互式,如下所示,两个句子直接很早就进行特征交互。因此无法通过离线的方式节省查询集合里的所有句子对应的计算量(整个前向过程是与输入句子耦合在一起的)
直接利用bert去获得cls token做为句子表示、或者利用meanpooling去做句子表示效果差,不能反映两个句子之间的语义相似度:
比如文本语义相似度任务:
利用该embedding去用于LR这样的模型微调时(与bert论文用于下游任务的方式一致),效果蛮好,例如在SentEval基准下的一系列任务:
论文给出如下解释:语义匹配对embedding向量的所有维度一视同仁,但是LR训练后是允许embedding向量某些维度对分类结果产生不同的影响。
SBERT实际上设计了一种bert微调方式,基于SNLI和STS这样的语料进行微调。例如下图,句子对分类任务用如下结构的微调方式。
注意:
这是一个孪生网络的结构,这样的结构在得到embedding之前两边是分离的,没有任何特征交叉,因此假设如下场景:需要在5000w条句子中多次查询与查询句子最相似的,此时不需要每次新的查询都需要去计算5000w句子的embedding,5000w句子的embedding可以离线计算好。因此这种方式会有性能上的提升。
提升性能的额外角度:由于在孪生网络两边的句子在embedding之前都没有特征交互,所以bert部分涉及的计算量也是偏少的(粗略感知,从原来的O(N+M)^2 变成O(M ^2+N ^2)),而且可以利用ANN方法做进一步加速
SNLI是句子对的语义关系推理的数据集,关系包括(矛盾,蕴含,中立)三种情况;STS是语义文本相似度任务。
SNLI
STS
|u-v|这样的特征构建在分类任务训练上有很大的提升。
CoSENT提出了在对bert基于文本匹配的标注数据进行有监督训练,用于获取通用embedding的场景下,如果采用余弦相似度作为优化目标则效果很差。
**原因:**如果在分类任务中利用cos定义了一个回归类型的损失函数。这样的转变倾向于告诉模型:相似的句子对需要得到接近与1的cos值,而不相似的句子对需要得到接近与-1的cos。这与相似的定义是不符的。两个句子除非完全一模一样,则cos为1,其余相似的句子不应该让其完全与1相等,反之即使是两个语义不一样的句子,又有可能存在一定的“相似”,其值不应该完全为0。那么应该如何定义其cos值,就是一个很难处理的问题(并不是所有的数据集都可以标注句子对的相似度值)。原因似乎是通过回归损失我们间接的给了模型一个错误的优化方向。
**变化:**引入如下损失,设计的初衷是让对于任意的正样本对和负样本对,都有正样本对cos值大于负样本对cos值,这里直接避免了上述问题。
与sbert相比:引用原本分析原因。1、sbert在损失上的设计需要初始模型下 ∣ u − v ∣ |u-v| ∣u−v∣有一定的聚类倾向。这潜在的引入了风险。2、训练与预测阶段不一致,预测阶段毕竟还是利用cos值。而CoSENT在设计上避免了这两个问题。
BERT在有监督的情况下可以在下游任务中有不错的表现,但是bert导出的原生的句子表征被证明质量很低。直接上实验图:
左图为bert embedding在STS任务上的结果,即使是被标注为完全不相关的句子对,bert embedding也会得到很高相似度(相似度值分布于0.6~1.0)。
**方案:**ConSENT提出的解决方案是对比学习+bert,二者结合达成“来自同一个句子的数据增强样本之间相似(正样本),同时与其他句子(负样本,同一个batch内)保持距离”的目标。以一次前向传播过程介绍方案:
从数据中获取一个batch=N的句子样本。
选取两个数据增强的方法,分别对每个句子进行扩展,得到2N个扩展后的样本。数据增强的方案有四种:给句子embedding矩阵加噪、打乱token顺序、随机在token维度(0.15)或者feature维度(0.2)切除、 给句子embedding矩阵做dropout。实验表明,shuffle+feature cutoff组合效果最佳
2N个“句子”输入到bert中,针对每个“句子”,对bert的output做平均池化得到对应的表征向量
计算损失:损失函数的目的是方案中提到的目标。
其中$r_{i},r_{j}属于正样本对,r_{i},r_{k} (k\neq j) 属于负样本。一个 b a t c h 中的每个样本只有一个正样本(由同一个句子经过两个 a u g m e n t a t i o n 方案得到), b a t c h 中的其他样本都可以作为负样本。 属于负样本。一个batch中的每个样本只有一个正样本(由同一个句子经过两个augmentation方案得到),batch中的其他样本都可以作为负样本。 属于负样本。一个batch中的每个样本只有一个正样本(由同一个句子经过两个augmentation方案得到),batch中的其他样本都可以作为负样本。\tau$属于温度系数(0.1)
这里同样使用了cos相似度的计算方式,并作为损失函数,并没有带来效果差的问题。我们观察损失可以发现,对比学习本身并不关注相似度的绝对值,因此不会面临“强制要求相似的分值趋向于1,不想死的分值趋向于-1”这样不合理的情况。
整体流程如下:
除了上面描述的整个自监督的流程,论文中还提到了如何去整合监督信息,利用有标注的数据。以NLI的句子分类(3分类,矛盾,蕴含,中立)任务举例:
在最后实验过程中,取ConSETN最后两层输出的平均池化。作者还分析了自监督下,模型对样本量的需求,发现在STS任务中只需要1000条样本即可达到与有监督相同的结果。
BERT embedding为什么差
bert的词表征空间是各向异性的,高频词之间聚集,低频词稀疏。在经过平均池化后高频词主导embedding的表征,导致没有区分度。论文用实验去验证这一点:通过去除高频词,观察随着去除高频词的数量变化,bert embedding在STS任务上的效果。发现随着去除高频词,句子表征逐渐有了区分度。结果如下:
a simple contrastive sentence embedding framework
SimCSE内容很简单,基于预训练语言模型利用对比学习,句子embedding的方案,分为无监督和有监督两种
无监督SimCSE
以一次前向传播过程来描述一下SimCSE无监督训练过程:
给定一个batch的数据,包含n个句子
对每个句子 x i x_{i} xi有 x i + = x i x_{i}^{+}=x_{i} xi+=xi,对 x i + , x i x_{i}^{+},x_{i} xi+,xi分别通过bert或者其他预训练模型编码得到对应的向量,再分别对向量进行不同的dropout mask 得到 h i + , h i h_{i}^{+},h_{i} hi+,hi。这是一对正样本。
计算如下损失
学习的目标就是标准的对比学习的思想,让正样本在空间上靠近,同时分离负样本。这里负样本就是batch内其他句子对应的dropout mask
有监督SimCSE
以NLI数据集(一个句子对分类任务,类别分为蕴含、中立、矛盾)上的一次前向传播过程来描述SimCSE有监督训练过程:
将原本的样本 ( s 1 , s 2 , l a b e l ) (s_{1}, s_{2},label) (s1,s2,label)转为 ( s 1 , s 1 + , s 1 − ) (s_{1},s_{1}^+, s_{1}^{-}) (s1,s1+,s1−)的格式, s 1 + s_{1}^+ s1+表示 s 1 s_{1} s1的正样本(与 s 1 s_1 s1的label为蕴含的句子), s 1 − s_1^- s1−为 s 1 s_1 s1的强负样本(label为矛盾的句子,加入强负样本相对于仅仅用batch内其他样本作为负样本在效果上有比较明显的提升,见下表)。NLI支持构建这样的三元组,因为每个句子都包含一个与之对应关系为蕴含、矛盾、中立的句子。所以不是所有数据集都能满足这样的转变
对每个三元组样本计算如下损失
与无监督相比,分母中加入了强负样本和batch内其他样本的负样本(这里貌似每个样本的负样本数量也变多了,假设与无监督使用相同的batchsize。在实验部分,实验表明这里单单考虑强负样本并没有改善效果),正样本来自标注。
Alignment and uniformity
对比损失可以分解为Alignment和uniformity两点,其中:
Alignment表示相似的点距离接近。
uniformity表示空间中点的均匀性,均匀意味着跟多的信息量,从熵的角度看,均匀分布的信息量是最多的。
《RetroMAE: Pre-Training Retrieval-oriented Language Models Via Masked Auto-Encoder》
Dense retrieval:将query和doc向量化,接着可以通过ANN等方法高效的查找与query相关的文档。向量化的方法对检索的质量至关重要。
面向检索的预训练语言模型:bert等预训练模型的预训练任务多是token级别的,并没有很好的句子或者段落级别的表征能力。见PRE-TRAINING TASKS FOR EMBEDDING-BASED LARGE-SCALE RETRIEVAL,如下图所示:,MLM下模型的召回偏弱。因此需要训练面向检索的预训练语言模型。
下图中涉及到三个段落级别的预训练任务,分别是:
两条改进的技术路线:对比学习和MAE
MAE
**方案:**本文设计的预训练方案如下图所示
encoding:给定句子X,以相对较低的比例(15~30%)随机mask一些token,使用一个bert结构的编码器对mask之后的句子进行编码,取cls向量作为句子的embedding,如下图A
decoding:针对句子 X X X以较高的比例(50~70%)mask一些token,然后拼接上encoding阶段得到的句子embedding。利用一个一层的tranformer进行解码,如图B。可以发现,这里更高的mask比例以及一层的网络设计,其目的是为了逼迫encoding阶段产生质量高的句子表示
作者进一步优化了第二步的decoding任务。如图C
利用RetroMAE训练预训练模型
BGE 针对中文、英文分别构建了多达120M、232M的样本对数据,借助负采样扩增与难负样例挖掘进一步提升对比学习的难度,实现了多达65K的负样本规模,增强了语义向量的判别能力
借鉴 Instruction Tuning的思想,采取了非对称的指令添加方式,在问题端添加场景描述, 提升语义向量在多任务场景下的通用能力
效果展示: