当前位置: 首页 > news >正文

Transformer实战(22)——使用FLAIR进行语义相似性评估

Transformer实战(22)——使用FLAIR进行语义相似性评估

    • 0. 前言
    • 1. 使用 FLAIR 进行语义相似性评估
    • 2. 平均池化词嵌入
    • 3. 基于循环神经网络的文档嵌入
    • 4. 基于 Transformer 的 BERT 嵌入
    • 4. Sentence-BERT 嵌入
    • 系列链接

0. 前言

在自然语言处理中,句子表示的质量直接影响下游任务(如语义检索、文本聚类)的效果。在本节中,我们将通过 FLAIR 库对句子表示模型进行定性评估,该库极大地简化了获取文档嵌入的过程,系统评估四种主流句子嵌入方法——平均池化、循环神经网络编码、BERT 嵌入及 SBERT 嵌入,揭示其语义区分能力。

1. 使用 FLAIR 进行语义相似性评估

在开始之前,使用 pip 安装所需库:

$ pip install flair

为了进行定性评估,我们定义了一组相似的句子对和一组不相似的句子对(每组五对)。我们期望嵌入模型能够对相似句子对给出较高的分数,对不相似句子对给出较低的分数。这些句子对是从语义文本相似性 (Semantic Textual Similarity, STS) 基准数据集中提取的。对于相似的句子对,两个句子是完全等价的,且意义相同。

(1)STS 数据集中随机选取相似度分数约为 5 的句子对:

import pandas as pd
similar=[("A black dog walking beside a pool.","A black dog is walking along the side of a pool."),
("A blonde woman looks for medical supplies for work in a suitcase.	"," The blond woman is searching for medical supplies in a suitcase."),
("A doubly decker red bus driving down the road.","A red double decker bus driving down a street."),
("There is a black dog jumping into a swimming pool.","A black dog is leaping into a swimming pool."),
("The man used a sword to slice a plastic bottle.	","A man sliced a plastic bottle with a sword.")]
pd.DataFrame(similar, columns=["sen1", "sen2"])

输出结果如下:

输出结果

(1) 定义相似度分数约为 0 的不相似句子对,同样取自STS基准数据集:

import pandas as pd
dissimilar= [("A little girl and boy are reading books. ", "An older child is playing with a doll while gazing out the window."),
("Two horses standing in a field with trees in the background.", "A black and white bird on a body of water with grass in the background."),
("Two people are walking by the ocean." , "Two men in fleeces and hats looking at the camera."),
("A cat is pouncing on a trampoline.","A man is slicing a tomato."),
("A woman is riding on a horse.","A man is turning over tables in anger.")]
pd.DataFrame(dissimilar, columns=["sen1", "sen2"])

输出结果如下:

输出结果

(3) 定义 sim() 函数来评估嵌入模型,sim() 函数计算两个句子之间的余弦相似度:

import torch, numpy as np
def sim(s1,s2):# cosine similarity function outputs in the range 0-1s1=s1.embedding.unsqueeze(0)s2=s2.embedding.unsqueeze(0)sim=torch.cosine_similarity(s1,s2).item() return np.round(sim,2)

(4) 该节中使用的文档嵌入模型均为预训练模型。我们将把文档嵌入模型对象和句子对列表(相似或不相似)传递给 evaluate() 函数, evaluate() 函数会对句子嵌入进行编码,计算每对句子的相似度分数,并返回所有句子对的平均分数:

def evaluate(embeddings, myPairList):# it evaluates embeddings for a given list of sentence pairscores=[]for s1, s2 in myPairList:s1,s2=Sentence(s1), Sentence(s2)embeddings.embed(s1)embeddings.embed(s2)score=sim(s1,s2)scores.append(score)return scores, np.round(np.mean(scores),2)

接下来,评估句子嵌入模型的时候,首先从平均池化方法开始。

2. 平均池化词嵌入

平均池化词嵌入(也称文档池化)对句子中的所有词应用均值池化操作,即将所有词嵌入的平均值作为句子嵌入。

(1) 接下来,实例化基于 GloVe 向量的文档池化嵌入。需要注意的是,虽然我们这里仅使用 GloVe 向量,但 FLAIR API 允许使用多种词嵌入:

from flair.data import Sentence
from flair.embeddings import WordEmbeddings, DocumentPoolEmbeddings
glove_embedding = WordEmbeddings('glove')
glove_pool_embeddings = DocumentPoolEmbeddings([glove_embedding])

(2) 在相似句子对上评估 GloVe 池化模型:

evaluate(glove_pool_embeddings, similar)
# ([0.97, 0.99, 0.97, 0.99, 0.98], 0.98)

可以看到,结果符合预期。但模型对不相似的句子对也给出了很高的分数,平均得分为 0.94,我们期望的分数应低于 0.4,得到这种情况的原因将在后续学习中解释:

evaluate(glove_pool_embeddings, dissimilar)
# ([0.94, 0.97, 0.94, 0.92, 0.93], 0.94)

接下来,在相同问题上评估循环神经网络 (Recurrent Neural Network, RNN) 嵌入。

3. 基于循环神经网络的文档嵌入

(1) 基于 GloVe 嵌入实例化一个门控循环单元 (Gated Recurrent Unit, GRU) 模型,其中 DocumentRNNEmbeddings 的默认模型是 GRU

from flair.embeddings import WordEmbeddings, DocumentRNNEmbeddings
gru_embeddings = DocumentRNNEmbeddings([glove_embedding])

(2) 执行评估方法:

evaluate(gru_embeddings, similar)
# ([0.99, 1.0, 0.97, 1.0, 0.9], 0.97)
evaluate(gru_embeddings, dissimilar)
# ([0.93, 1.0, 0.91, 0.88, 0.89], 0.92)

同样,不相似句子对得到了很高的分数,这并不是我们期望的句子嵌入表现。

4. 基于 Transformer 的 BERT 嵌入

(1) 实例化一个 bert-base-uncased 模型,并对最后一层进行池化:

from flair.embeddings import TransformerDocumentEmbeddings
from flair.data import Sentence
bert_embeddings = TransformerDocumentEmbeddings('bert-base-uncased')

(2) 执行评估:

evaluate(bert_embeddings, similar)
# ([0.85, 0.9, 0.96, 0.91, 0.89], 0.9)
evaluate(bert_embeddings, dissimilar)
# ([0.93, 0.94, 0.86, 0.93, 0.92], 0.92)

可以看到,不相似句子对的得分甚至高于相似句子对的得分。

4. Sentence-BERT 嵌入

接下来,使用 Sentence-BERT (SBERT) 来区分相似句子对和不相似句子对。

(1) 首先,我们需要确保已经安装了 sentence-transformers 库:

$ pip install sentence-transformers

(2) SBERT 提供了多种预训练模型。我们选择 bert-base-nli-mean-tokens 模型进行评估:

from flair.data import Sentence
from flair.embeddings import SentenceTransformerDocumentEmbeddings
# init embedding
sbert_embeddings = SentenceTransformerDocumentEmbeddings('bert-base-nli-mean-tokens')

(3) 评估模型:

evaluate(sbert_embeddings, similar)
# ([0.98, 0.95, 0.96, 0.99, 0.98], 0.97)
evaluate(sbert_embeddings, dissimilar)
# ([0.48, 0.41, 0.19, -0.05, 0.0], 0.21)

可以看到,SBERT 模型能够得到更好的结果。该模型对不相似句子对给出了较低的相似度分数,这符合我们的预期。

(4) 接下来,我们进行一个更复杂的测试,将相互矛盾的句子传递给模型:

tricky_pairs=[("An elephant is bigger than a lion","A lion is bigger than an elephant") ,("the cat sat on the mat","the mat sat on the cat")]
evaluate(glove_pool_embeddings, tricky_pairs)
# ([1.0, 1.0], 1.0)
evaluate(gru_embeddings, tricky_pairs)
# ([0.85, 0.75], 0.8)
evaluate(bert_embeddings, tricky_pairs)
# ([1.0, 0.98], 0.99)
evaluate(sbert_embeddings, tricky_pairs)
# ([0.93, 0.97], 0.95)

可以看到,得分非常高,因为句子相似度模型的工作原理类似于主题检测,衡量的是内容相似性。观察这些句子,虽然它们相互矛盾,但共享相同的内容。因此,模型产生了较高的相似度分数。由于 GloVe 嵌入方法对词汇进行平均池化,而不考虑单词顺序,因此它将两句话视为同义句。而 GRU 模型由于关注词序,因此生成的分数较低。即使是 SBERT 模型也未能产生有效的分数,这是由于 SBERT 模型中使用了基于内容相似性的监督方法。

(5) 要正确检测句子对的语义,包含三种类别——即中立 (Neutral)、矛盾 (Contradiction) 和蕴含 (Entailment),可以使用在 MultiNLI (Multi-Genre Natural Language Inference) 上微调的模型。使用 XLM-RoBERTa 模型,并在 XNLI (Cross-lingual Natural Language Inference) 数据集上微调,使用相同的句子对:

from transformers import AutoModelForSequenceClassification, AutoTokenizer
nli_model = AutoModelForSequenceClassification.from_pretrained('joeddav/xlm-roberta-large-xnli')
tokenizer = AutoTokenizer.from_pretrained('joeddav/xlm-roberta-large-xnli')
import numpy as np
for permise, hypothesis in tricky_pairs:x = tokenizer.encode(permise,hypothesis,return_tensors='pt',truncation=True)logits = nli_model(x)[0]print(f"Permise: {permise}")print(f"Hypothesis: {hypothesis}")print("Top Class:")print(nli_model.config.id2label[np.argmax(logits[0].detach().numpy())])print("Full softmax scores:")for i in range(3):print(nli_model.config.id2label[i],logits.softmax(dim=1)[0][i].detach().numpy())print("="*20)

可以看到,模型输出了每个句子对的正确标签:

输出结果

模型对于第一个示例表现成功,但对于第二个示例结果并不明确。

系列链接

Transformer实战(1)——词嵌入技术详解
Transformer实战(2)——循环神经网络详解
Transformer实战(3)——从词袋模型到Transformer:NLP技术演进
Transformer实战(4)——从零开始构建Transformer
Transformer实战(5)——Hugging Face环境配置与应用详解
Transformer实战(6)——Transformer模型性能评估
Transformer实战(7)——datasets库核心功能解析
Transformer实战(8)——BERT模型详解与实现
Transformer实战(9)——Transformer分词算法详解
Transformer实战(10)——生成式语言模型 (Generative Language Model, GLM)
Transformer实战(11)——从零开始构建GPT模型
Transformer实战(12)——基于Transformer的文本到文本模型
Transformer实战(13)——从零开始训练GPT-2语言模型
Transformer实战(14)——微调Transformer语言模型用于文本分类
Transformer实战(15)——使用PyTorch微调Transformer语言模型
Transformer实战(16)——微调Transformer语言模型用于多类别文本分类
Transformer实战(17)——微调Transformer语言模型进行多标签文本分类
Transformer实战(18)——微调Transformer语言模型进行回归分析
Transformer实战(19)——微调Transformer语言模型进行词元分类
Transformer实战(20)——微调Transformer语言模型进行问答任务
Transformer实战(21)——文本表示(Text Representation)

http://www.dtcms.com/a/478087.html

相关文章:

  • Kubernetes:初始化集群(导入Rancher2)
  • 通用:JVM垃圾回收机制
  • Shell脚本技巧:去除文件中字符串两端空白
  • python内置模块-re模块介绍使用
  • JavaWeb后端实战(事务文件上传[本地上传与阿里云OSS上传])
  • USB通讯学习
  • 成都哪里可以做网站涿州网站建设天峰
  • 最新MPAS跨尺度、可变分辨率模式实践技术应用及典型案例分析
  • DSP EDMA3使用
  • 做网站在哪里租服务器家用电脑做网站服务器
  • 第四篇《通信的“世界语“:为什么网络需要HTTP、FTP、DNS等协议?》
  • Helm 与 Ansible 深度对比解析文档
  • 网站域名使用费多少集客crm
  • 阜新市建设小学网站wordpress php 5.2.17
  • 2025年--Lc182--sql(排序和分组)--Java版
  • 生产环境下,前端项目为什么要部署
  • 免费图片素材网站推荐怎样建立一个免费的网站
  • [论文阅读] AI | PynguinML——破解ML库自动化测试难题,覆盖率最高提升63.9%
  • 【HarmonyOS AI赋能】AI字幕AICaption详解
  • 极海APM32F107V6 + 合宙Air780E
  • 做欧洲电商看哪个网站网站建设开发案例教程视频教程
  • C++11(可变参数模板、新的类功能和STL中的一些变化)
  • 医疗运营管理系统编程可靠性、安全性与动态性融合路径
  • 昂瑞微——以创新驱动未来,用芯连接世界
  • 网站承建商有哪些济南seo外贸网站建设
  • Flink1.20 CEP【水位线异常原因深度分析】
  • 30个酷炫HTML+CSS特效源码
  • vtkGaussianBlurPass代码解析
  • 网站制作过程合理的步骤是福州网站推广优化
  • 牛客算法基础noob71 学生综合评估系统