NLP: SBERT介绍及sentence-transformers库的使用

1. Sentence-BERT

  Sentence-BERT(简写SBERT)模型是BERT模型最有趣的变体之一,通过扩展预训练的BERT模型来获得固定长度的句子特征,主要用于句子对分类、计算两个句子之间的相似度任务。

1.1 计算句子特征

  SBERT模型同样是将句子标记送入预训练的BERT模型来获取句子特征的,但这里并不使用 R [ C L S ] R_{[CLS]} R[CLS]作为最终的句子特征。在SBERT中,通过汇聚所有标记的特征来计算整个句子的特征。具体的汇聚方法有两种:平均汇聚和最大汇聚。

  • 平均汇聚:使用平均汇聚来获取句子特征。这种方法得到的句子的特征将包含所有词语(Token)的意义。
  • 最大汇聚:使用最大汇聚来获取句子特征。这种方法得到的句子的特征将仅包含重要词语(Token)的意义。
    在这里插入图片描述

1.2 SBERT架构

  SBERT模型使用二元组网络架构来执行以一对句子作为输入的任务,并使用三元组网络架构来实现三元组损失函数。

1.2.1 使用二元组网络架构的SBERT模型

  SBERT通过二元组网络(两个共享同样权重的相同网络)架构对执行句子对任务的预训练的BERT模型进行微调。句子对任务具体包括以下两种:

  • 句子对分类任务: 判断句子对是否相似。相似则返回1,不相似则返回0。其SBERT模型架构为:
    在这里插入图片描述
  • 句子对回归任务:计算两个给定句子之间的语义相似度。其对应的SBERT架构为:在这里插入图片描述
1.2.2 使用三元组网络架构的SBERT模型

  三元组网络架构的SBERT模型的任务计算出一个特征,使锚定句和正向句之间的相似度高,锚定句和负向句之间的相似度低。其架构如下:
在这里插入图片描述

2. 计算文本相似度

2.1 bi-encoder VS cross-encoder

  bi-encoder和cross-encoder是语义匹配、文本相似度、信息检索场景下下常用的两种模型架构。这两者都基于深度学习模型(如BERT等)进行编码和比较文本之间的相似度,但它们在计算方式、效率和适用场景上有显著的区别。

2.1.1 bi-encoder

  bi-encoder是一种独立编码方式,即输入的两个文本会被分别编码为独立的向量,然后通过计算这两个向量的相似度来判断文本之间的关系。使用bi-encoder方式计算文本相似度的案例如下:

from sentence_transformers import SentenceTransformer
#加载预训练的sentence transformer模型
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences=["这个商品挺好用的","这个商品一点也不好用"]
embeddings=model.encode(sentences)
similarity=model.similarity(embeddings[0],embeddings[1])
print(similarity) #0.5868
2.1.2 cross-encoder

  cross-encoder是一种联合编码方式,即将两个文本拼接在一起作为模型的输入,模型会通过对两个文本的联合表示来直接输出一个相似度分数。这种方式可以更好地捕捉两个文本之间的复杂交互信息,因此在诸如问答匹配、精确文本相似度计算等需要细粒度判断的任务上表现更好。具体使用方式如下:

from sentence_transformers.cross_encoder import CrossEncoder
model=CrossEncoder("cross-encoder/stsb-distilroberta-base")
query="这个产品挺好用的"
corpus=["这个产品很好",
        "这个产品的设计有很大问题",
        "这个产品不好用"]
ranks=model.rank(query,corpus)
for rank in ranks:
    print(f"{rank['score']:.2f}\t{corpus[rank['corpus_id']]}")

3 微调SBERT

  接下来我们使用STSB数据集对SBERT模型进行微调。具体代码如下

from datasets import load_dataset
from sentence_transformers import losses
from sentence_transformers import (
    SentenceTransformer,
    SentenceTransformerTrainingArguments,
    SentenceTransformerTrainer,
)
from sentence_transformers.training_args import SentenceTransformerTrainingArguments
from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator,SimilarityFunction
from datasets import load_dataset

train = load_dataset("sentence-transformers/stsb",split='train')
dev = load_dataset("sentence-transformers/stsb",split='validation')
test= load_dataset("sentence-transformers/stsb",split='test')

model=SentenceTransformer('FacebookAI/xlm-roberta-base')

loss=losses.CoSENTLoss(model=model)

args=SentenceTransformerTrainingArguments(output_dir='models/model1',
                                          num_train_epochs=1,
                                          per_device_train_batch_size=16,
                                          per_device_eval_batch_size=16,
                                          warmup_ratio=0.1,
                                          eval_strategy='steps',
                                          eval_steps=100,
                                          save_strategy='steps',
                                          save_total_limit=2,
                                          bf16=False,)

dev_evaluator=EmbeddingSimilarityEvaluator(
    sentences1=dev['sentence1'],
    sentences2=dev['sentence2'],
    scores=dev['score'],
    main_similarity=SimilarityFunction.COSINE,
    name='dev-evaluator')

dev_evaluator(model)

trainer=SentenceTransformerTrainer(model=model,
                                   args=args,
                                   train_dataset=train,
                                   eval_dataset=dev,
                                   loss=loss,
                                   evaluator=dev_evaluator)   
trainer.train()                        

test_evaluator=EmbeddingSimilarityEvaluator(
    sentences1=test['sentence1'],
    sentences2=test['sentence2'],
    scores=test['score'],
    main_similarity=SimilarityFunction.COSINE,
    name='test-evaluator')
test_evaluator(model)
model.save_pretrained('models/model1')

关于上述代码,需要说明以下几点:

  • 训练和评估SBERT的数据类型必须是datasets.Datasetdatasets.DatasetDict
  • 数据集的格式必须和损失函数、评估器相匹配。如果损失函数需要标签字段,那么数据集必须有“label”或“score”字段;其他名称非“label”或“score”的字段将自动归属于Inputs字段。所以在进行后续步骤时,必须将数据集中的无法标签删除,同时要保证数据集中的字段顺序与对应损失函数中要求的顺序一致。
  • 需要根据具体的任务以及数据集的形式选择合适的损失函数,没有哪种损失函数可以解决所有的问题。SBERT提供的损失函数列表如下:
    https://www.sbert.net/docs/sentence_transformer/loss_overview.html
  • 微调后的模型可以和其他预训练的模型一样使用,比如计算文本相似度,这里不再赘述。

参考资料

  1. BERT基础教程: Transformer大模型实战
  2. https://baijiahao.baidu.com/s?id=1801193891938395467
  3. https://www.sbert.net
Sentence-transformers是一种基于深度学习的工具,用于将自然语言句子转换为向量表示。以下是该工具的帮助文档: 1. 安装 要安装Sentence-transformers,请使用以下命令: pip install sentence-transformers 2. 使用 使用Sentence-transformers很简单。只需导入相应的模型和tokenizer,并将文本传递给模型即可。以下是一个示例: from sentence_transformers import SentenceTransformer, util model = SentenceTransformer('bert-base-nli-mean-tokens') sentences = ['This is an example sentence', 'Each sentence is converted to a vector'] sentence_embeddings = model.encode(sentences) 3. 模型 Sentence-transformers包括许多不同的模型,包括基于BERT、RoBERTa和DistilBERT的模型。您可以使用以下命令查看所有可用的模型: from sentence_transformers import SentenceTransformer models = SentenceTransformer.models print(models) 4. 相似度计算 Sentence-transformers还包括一些实用程序函数,可用于计算句子之间的相似度。以下是一个示例: from sentence_transformers import SentenceTransformer, util model = SentenceTransformer('bert-base-nli-mean-tokens') sentences = ['This is an example sentence', 'Each sentence is converted to a vector', 'Sentence embeddings are useful for many NLP tasks'] sentence_embeddings = model.encode(sentences) # 计算第一句话和第二句话之间的余弦相似度 cosine_scores = util.pytorch_cos_sim(sentence_embeddings[0], sentence_embeddings[1]) print(cosine_scores) 5. 参考文献 如果您想了解有关Sentence-transformers的更多信息,请参阅以下文献: - Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence embeddings using siamese BERT-networks. arXiv preprint arXiv:1908.10084. - Devlin, J., Chang, M. W., Lee, K., & Toutanova, K. (2019). BERT: Pre-training of deep bidirectional transformers for language understanding. arXiv preprint arXiv:1810.04805.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值