Embedding微调
主要思路是:
将文本映射到语义向量空间,也就是将文本转化为固定长度的向量表示。
计算两个文本向量之间的相似度,例如使用余弦相似度。
相似度高则表示两个文本在语义上相似,相似度低则表示语义不同。
这个任务的主要难点在于获得合适的文本向量表示,需要模型能够捕捉文本的语义信息,忽略词汇表面的差异,根据上下文判断语义是否相近。
常用的语义相似度任务数据集包括STS-B,SICK等。模型训练过程中需要大量语义相关的文本对构成监督数据,损失函数则常采用余弦相似度与标注相似度的差异作为优化目标。
其模型架构如下图所示:
数据格式
说到语义相似这个任务,其实有三种训练样本格式示例如下:
- Pair (句子对):每个样本包含一个正例句子对。用于学习区分正例和负例句子。
[{
'text': 'I love apples',
'positive_text': 'Apples are my favorite fruit'
},
{
'text': 'I play football',
'positive_text': 'Football is an exciting sport'
}]
- Triplet (三元组) :每个样本包含一个正例句子和一个负例句子。可以更明确地学习区分正负样本。
[{
'text': 'I love apples',
'positive_text': 'Apples are my favorite fruit',
'negative_text': 'Bananas are too soft'
},
{
'text': 'I play football',
'positive_text': 'Football is an exciting sport',
'negative_text': 'Basketball is also great'
}]
- Scored Pair (打分句子对):每个样本包含一对句子和它们的相似度分数。可以直接学习评估语义相似度。
[{
'text': 'I love apples',
'scored_text': 'Apples are my favorite fruit',
'score': 0.9
},
{
'text': 'I play football',
'scored_text': 'Football is an exciting sport',
'score': 0.8
}]
三者对比:
-
Pair:区分正负样本
-
Triplet:更明确的正负样本
-
Scored Pair:直接学习语义相似度
适用于不同的训练目标。
模型选择
目前的基础模型大多是基于Transformer Encoder的预训练语言模型,BERT, RoBERTa,Ernie等
向量化的方式
文本通过模型进行向量化的方式也有很多种不同的方式
cls:取最后一层的第一个token(CLS)作为句子向量
last_mean:对最后一层的所有token取平均pooling
first_last_mean:第一层和最后一层分别平均池化,再取平均
embedding_last_mean:embedding层和最后一层分别平均池化,再取平均
last_weighted: 最后一层按token位置加权平均池化
语义相似度损失函数
1.PairInBatchNegCoSentLoss:计算一个batch内每个句子与正例句子的余弦相似度,然后减去该句子与自身的相似度,再取log-sum-exp作为loss。
2.TripletInBatchNegCoSentLoss:在PairInBatchNegCoSentLoss的基础上,额外加入负例样本,计算句子与正负例的相似度差值。希望正例相似度–负例相似度的差值越大。
3.PairInBatchNegSoftmaxContrastLoss:将句子两两相似度矩阵进行softmax,并与句子本身的label计算交叉熵损失。
4.TripletInBatchNegSoftmaxContrastLoss: 在3的基础上加入负例样本。
5.PairInBatchNegSigmoidContrastLoss:将句子两两相似度矩阵进行sigmoid,高于对角线的部分取负对数作为loss。
6.TripletInBatchNegSigmoidContrastLoss:在5的基础上加入负例样本。
7.CoSentLoss:输入预测相似度矩阵和真实相似度矩阵,计算两者差值进行log-sum-exp作为loss。这个损失是苏神提出来的,将排序的逻辑引入到了对比损失中。
其实可以看出语义相似的损失函数——主要思路是构建句子之间的相似度矩阵,然后通过比较正例和负例的相似度,采用交叉熵、log-sum-exp等方式计算loss,优化模型的句子表示,使得正例相似度更高。
训练策略
1. FullParametersTraining:全参数微调,不进行任何修改,所有参数都参与训练。
2. BitFitTraining:只训练某些关键词参数,其他参数固定。通过keywords指定要训练的参数名。
3. PrefixTraining:只训练前缀tokens对应的embedding参数。通过additional_special_tokens指定前缀tokens,并只训练这些tokens的embedding。
这些策略可以平衡语料大小与模型大小,降低过拟合风险,帮助模型快速适应下游任务。通常先做全参数训练预热一下,再使用部分固定或前缀训练等策略微调到特定下游任务。
M3E微调实战部分
这里笔者就不实战BitFitTraining和PrefixTraining 这两种训练,只介绍一下如何进行全量微调。参考的是https://github.com/wangyuxinwhy/uniem/tree/main 的微调教程。