语义相似度、句向量生成超强模型之SBERT《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》

Sentence-BERT(SBERT)通过对预训练的BERT模型进行改进,使用孪生和三级网络结构,解决了语义相似度搜索和非监督任务中的挑战。SBERT在文本语义相似度等句子对的回归任务上表现优异,通过特定的训练策略和特征提取方法,有效提高了句向量的质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 前言

随着2018年底Bert的面世,NLP进入了预训练模型的时代。各大预训练模型如GPT-2,Robert,XLNet,Transformer-XL,Albert,T5等等层数不穷。但是几乎大部分的这些模型均不适合语义相似度搜索,也不适合非监督任务,比如聚类。而解决聚类和语义搜索的一种常见方法是将每个句子映射到一个向量空间,使得语义相似的句子很接近。说到这,可能有的人会尝试将整个句子输入预训练模型中,得到该句的句向量,然后作为句子的句向量表示。但是这样得到的句向量真的好吗?在论文《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》就指出了,这样得到的句向量不具有语义信息,也就是说,两个相似的句子,得到的句向量可能会有很大的差别。此外,不仅句向量表示的语义方面存在很大差别,而且,它要求两个句子都被输入到网络中,从而导致巨大开销:从10000个句子集合中找到最相似的sentence-pair需要进行大约5000万个推理计算(约65小时),因此,这种方案不太友好。

2 解决的问题

面对上述预训练模型在文本语义相似度等句子对的回归任务上的问题,本文提出了Sentence-BERT(SBERT),对预训练的BERT进行修改:使用孪生(Siamese)和三级(triplet)网络结构来获得语义上有意义的句子embedding,以此获得定长的sentence embedding,使用余弦相似度或Manhatten/Euclidean距离等进行比较找到语义相似的句子。通过这样的方法得到的SBERT模型,在文本语义相似度等句子对的回归任务上吊打BERT , RoBERTa 拿到sota。
那么接下来看下论文是怎么做的。

3 网络结构

在这里插入图片描述
其中左图是训练的模型,右图是训练好模型之后利用句向量计算2个句子之间的相似度。u,v分别表示输入的2个句子的向量表示,|u-v|表示取两个向量的绝对值,(u, v, |u-v|)表示将三个向量在-1维度进行拼接,因此得到的向量的维度为 3*d,d表示隐层维度。

4 训练

使用SNLI和NLI数据集对Bert和Roberta进行fine-tune,得到SBERT预训练模型。

  • Polling策略

    ① mean:将句子的所有token在token维度上计算平均,这样就可以得到768(base)/1024(large)维度向量;
    ② max:将句子的所有token在token维度上的最大那个值,即做max_over_time,这里多解释下max_over_time,就是比如x = torch.randn(2, 10, 20),就是取x.max(1);
    ③ CLS:就是原始Bert做分类的方法,取句子的第一个token的向量。
    作者发现,使用mean的效果最好,max最差。

  • loss函数

    ① 回归任务:softmax,均方差损失函数;
    ② 分类任务:softmax, 交叉熵损失函数;
    ③ Wikipedia section triplets dataset (Dor et al., 2018)(三句分类任务):这个数据集是一些书中的句子,每一条数据有三句话,其中两句来自同一个章节的句子,另外一句是这本书的另外一个章节。
    在这里插入图片描述
    其中 ε设为1,||a, b||表示a和b的距离。求该损失函数的目的就是使得,a和p的距离小于a和n的距离

  • Encoder之后特征提取策略
    - [在这里插入图片描述](https://img-blog.csdnimg.cn/20200509140943386.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkyMjkwMQ==,size_16,color_FFFFFF,t_70)
    最后发现使用(u, v, |u-v|)效果最好

  • 训练速度

    在CPU, InferSent比SBERT块65%,在GPU上,论文使用了Smart batching策略,即将长度差不多的句子放在一个Batch训练,用这种方法在CPU上提升了89%,在GPU上提上了48%。此外,速度比inferSent快5%,比Universal Sentence Encoder快55%。

  • 其他细节

    学习率:2e-5
    warmup:0.1
    batchsize:16
    优化器:Adam

5 结论

  • STS数据集

直接使用SBERT进行预测。

在这里插入图片描述
从表中可以看到,使用SBERT的效果远远好于BERT

注意:表格中的SBERT-NLI-base其实就是文章中的SBERT,意思是使用SNLI和NLI数据集对BERT进行fine-tune得到的预训练模型。

  • NLI + STSb两步训练

即使用STSb数据集对SBERT进行fine-tune
在这里插入图片描述
从表中可以看到,当使用了STSb数据对SBERT进行fine-tune(bert-base:88.33)后,比直接使用SBERT评测STSb(77.03)效果好得多

  • AFS(Argument Facet Similarity)数据集

该数据集包含gun control, gay marriage, and death penalty三个话题。论文使用了其中两个主题A,B作为训练数据,另外一个C主题数据作为测试。最后取平均分数。结果如下:
在这里插入图片描述
从表中可以看到,对比于Glove和tf-idf均有很大的提升,但是对于Bert,不论是10倍交叉验证还是正常评测,效果反而下降了。论文提到,这个是由于训练的主题数据太少,导致在得到没有见过的主题时,性能不如Bert。

  • Wikipedia section triplets dataset

在这里插入图片描述
从表中可以看到,对比于Dor et al论文的方法有很大的提升。

  • 句向量评测 SentEval

在这里插入图片描述
从表中可以看到,对比于Glove,BERT和Universal Sentence Encoder,SBERT在大部分词向量评测上也是sota。

总之,SBERT的方法可以很好的用于语义相似度和句子对分类和一些回归的任务上,均能取得不错的效果。

论文链接:https://arxiv.org/abs/1908.10084
本人相关项目:https://github.com/Lisennlp/two_sentences_classifier

### 回答1: Sentence-BERT是一种自然语言处理模型,可用于将句子转换为向量表示。下面是一个使用Python代码的示例,展示如何使用Sentence-BERT转换句子为向量。 首先,需要安装Sentence-BERT的Python包。可以使用以下命令安装: ``` pip install sentence-transformers ``` 然后,可以使用以下代码加载Sentence-BERT模型并将句子转换为向量: ```python from sentence_transformers import SentenceTransformer # 加载Sentence-BERT模型 model = SentenceTransformer('bert-base-nli-mean-tokens') # 定义句子列表 sentences = ['这是一个句子', '这是另一个句子'] # 将句子转换为向量 sentence_embeddings = model.encode(sentences) # 打印结果 print(sentence_embeddings) ``` 上述代码将输出一个形如`[array([...], dtype=float32), array([...], dtype=float32)]`的列表,其中每个数组都是对应句子的向量表示。 请注意,这是一个简化的示例,实际应用中还可能有更多的参数和配置。建议您参考Sentence-BERT的文档,了解更多信息。 ### 回答2: Sentence-BERT是一种预训练的BERT模型,专门用于生成文本句子的嵌入向量。使用Sentence-BERT来转换句子为向量的代码如下: 首先,需要安装相应的Python依赖库,包括transformers和torch等。 ```python from sentence_transformers import SentenceTransformer, util import torch # 加载Sentence-BERT模型 model = SentenceTransformer('bert-base-nli-mean-tokens') # 需要转换为向量的句子 sentences = ['这是一个例子句子1', '这是一个例子句子2'] # 将句子进行转换为向量 sentence_embeddings = model.encode(sentences, convert_to_tensor=True) # 打印转换后的句向量 for sentence, embedding in zip(sentences, sentence_embeddings): print("句子:", sentence) print("向量:", embedding) print("") ``` 上述代码首先加载了Sentence-BERT模型,其中选择了预训练的bert-base-nli-mean-tokens模型,也可以使用其他预训练模型。然后,定义了要转换为向量的句子列表。接下来,调用`model.encode()`方法,将句子列表作为参数传递进去,该方法会返回句子的嵌入向量。最后,通过迭代句子列表和嵌入向量列表,可以打印出每个句子及其对应的向量表示。 需要注意的是,转换后的向量是一个torch.Tensor对象,可以通过`embedding.tolist()`将其转换为列表形式。另外,如果想计算两个句子之间的相似度,可以使用`util.pytorch_cos_sim()`方法来计算余弦相似度。 ### 回答3: Sentence-BERTSBERT)是一种用于生成文本向量的预训练模型,它可以将句子转换为词向量表示。以下是一个使用Sentence-BERT转换向量的Python代码示例: 1. 安装必要的库: ```python !pip install -U sentence-transformers ``` 2. 导入必要的库: ```python from sentence_transformers import SentenceTransformer ``` 3. 加载预训练模型: ```python model = SentenceTransformer('paraphrase-MiniLM-L6-v2') ``` 这里我们加载了SBERT的一个预训练模型,例如:'paraphrase-MiniLM-L6-v2'。你也可以根据需要选择其他预训练模型。 4. 转换句子为向量: ```python sentence = '这是一个例子句子。' sentence_embedding = model.encode([sentence]) ``` 我们将待转换句子作为列表传递给模型的encode()方法,该方法将返回一个包含句子向量的列表。在这个例子中,我们只有一个句子,因此输出将是一个长度为1的列表。 5. 打印转换结果: ```python print('句子向量的维度:', len(sentence_embedding[0]), '维') print('句子向量:', sentence_embedding[0]) ``` 这里我们打印了输出向量的维度和向量本身。 通过以上代码,我们可以获得原始句子的向量表示。你还可以使用这些向量进行句子相似性计算、聚类、检索等自然语言处理任务。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值