我们的日常活动都依赖于 LLM,但量化“LLM的效率如何”却是一个巨大的挑战。BLEU、ROUGE 和 METEOR 等传统指标往往无法理解文本的真正含义。它们过于热衷于匹配相似的词语,而不是理解其背后的概念。BERTScore 则通过应用 BERT 嵌入来评估文本质量,从而更好地理解意义和上下文,从而扭转了这一局面。
无论您是在训练聊天机器人、翻译还是做摘要,BERTScore 都能让您更轻松地评估您的模型。它能捕捉到两个句子虽然用词不同但却表达了相同意思的情况,而这正是旧指标完全忽略的地方。当我们深入探讨 BERTScore 如何运作时,您将了解到这种出色的评估方法如何将计算机测量和人类直觉结合在一起,并彻底改变我们测试和完善当今复杂语言模型的方式。
什么是BERTScore?
BERTScore 是一种用于文本生成的神经评估指标,它使用来自 BERT 等预训练语言模型的上下文嵌入来计算候选文本和参考文本之间的相似性分数。与传统的基于 n-gram 的度量方法不同,BERTScore 即使在使用不同词语的情况下也能识别语义等同性,因此非常适用于评估存在多种有效输出的语言任务。
BERTScore 由 Zhang 等人提出,并在他们 2019 年的论文《BERTScore:Evaluating Text Generation with BERT》一文中提出,由于该分数与一系列文本生成任务中的人类评估结果高度相关,因此在 NLP 界迅速获得认可。
BERTScore架构
BERTScore 的架构优雅简洁但功能强大,由三个主要部分组成:
- 嵌入生成:使用预先训练的上下文嵌入模型(通常为 BERT)嵌入参考文本和候选文本中的每个标记。
- 标记匹配:该算法计算参考文本和候选文本中所有标记之间的成对余弦相似度,创建相似度矩阵。
- 分数汇总:将这些相似度得分汇总为精确度、召回率和 F1 指标,以表示候选文本与参考文献的匹配程度。
BERTScore 的妙处在于它利用了预先训练好的模型对上下文的理解,而不需要对评估任务进行额外的训练。
如何使用BERTScore?
BERTScore 可以使用多个参数进行定制,以满足特定的评估需求:
参数 | 描述 | 默认 |
model_type | 要使用的预训练模型(如 “bert-base-uncased ”模型) | ‘roberta-large’ |
num_layers | 使用哪一层的嵌入 | 17 (for roberta-large) |
idf | 是否使用 IDF 对标记重要性进行加权 | False |
rescale_with_baseline | 是否根据基线重新缩放分数 | False |
baseline_path | 基线分数的路径 | None |
lang | 比较文本的语言 | ‘en’ |
use_fast_tokenizer | 是否使用 HuggingFace 的快速标记化器 | False |
通过这些参数,研究人员可以针对不同的语言、领域和评估要求对 BERTScore 进行微调。
BERTScore如何工作?
BERTScore 通过使用上下文嵌入的标记级匹配过程来评估生成文本和参考文本之间的相似性。以下是其工作原理的逐步分解:
Source: BERTScore
- 标记化:候选文本(生成文本)和参考文本均使用与所使用的预训练模型(如 BERT、RoBERTa)相对应的标记化器进行标记化。
- 上下文嵌入(Contextual Embedding):然后使用预先训练好的上下文模型嵌入每个标记。重要的是,这些嵌入模型捕捉的是单词在上下文中的含义,而不是静态的单词表征。例如,“bank”一词在“river bank”和“financial bank”中会有不同的嵌入。
- 余弦相似度计算:对于候选文本中的每个标记,BERTScore 会计算其与参考文本中每个标记的余弦相似度,从而创建一个相似度矩阵。
- 贪婪匹配:
- 为了精确:将每个候选标记与最相似的参考标记进行匹配
- 对于召回率:每个参考标记与最相似的候选标记匹配
- 重要性加权(可选):可通过反文档频率(IDF)对标记进行加权,以强调内容词而不是功能词。
- 得分汇总:
- 精确度按每个候选标记的最大相似性得分的平均值计算
- 召回率计算为每个参考标记的最大相似性得分的平均值
- F1使用调和平均数公式综合计算精确度和召回率
- 分数归一化(可选): 原始分数可根据基线分数重新标定,使其更易于解释。
这种方法使 BERTScore 即使在使用不同单词表达相同意思时也能捕捉到语义等同性,从而使其在评估现代文本生成系统时比词性匹配指标更稳健。
用Python实现
让我们逐步实现 BERTScore,以了解它在实践中是如何工作的。
1. 设置和安装
首先,安装必要的软件包:
# Install the bert-score package pip install bert-score
2. 基本实现
下面介绍如何计算候选文本和参考文本之间的 BERTScore:
import bert_score # Define reference and candidate texts references = ["The cat sat on the mat.", "The feline rested on the floor covering."] candidates = ["A cat was sitting on a mat.", "The cat was on the mat."] # Calculate BERTScore P, R, F1 = bert_score.score( candidates, references, lang="en", model_type="roberta-large", num_layers=17, verbose=True ) # Print results for i, (p, r, f) in enumerate(zip(P, R, F1)): print(f"Example {i+1}:") print(f" Precision: {p.item():.4f}") print(f" Recall: {r.item():.4f}") print(f" F1: {f.item():.4f}") print()
输出:
这说明了 BERTScore 是如何捕捉语义相似性的,即使使用了不同的措辞。
BERT嵌入和余弦相似性
BERTScore 的核心在于如何利用上下文嵌入和余弦相似性。让我们来分析一下这个过程:
1. 生成上下文嵌入:考虑到这一区别,BERTScore 是传统的基于 n-gram 的测量方法的真正替代品,因为它是基于上下文嵌入生成的。与静态词嵌入(如 Word2Vec 或 GloVe)不同,上下文嵌入是为语义相似性评估而精细调整的,因为它们考虑到了周围上下文在赋予词语意义时的重要性。
import torch from transformers import AutoTokenizer, AutoModel def get_bert_embeddings(texts, model_name="bert-base-uncased"): # Load tokenizer and model tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModel.from_pretrained(model_name) # Move model to GPU if available device = "cuda" if torch.cuda.is_available() else "cpu" model.to(device) # Process texts in batch encoded_input = tokenizer(texts, padding=True, truncation=True, return_tensors="pt") encoded_input = {k: v.to(device) for k, v in encoded_input.items()} # Get model output with torch.no_grad(): outputs = model(**encoded_input) # Use embeddings from the last layer embeddings = outputs.last_hidden_state # Remove padding tokens attention_mask = encoded_input['attention_mask'] embeddings = [emb[mask.bool()] for emb, mask in zip(embeddings, attention_mask)] return embeddings # Example usage texts = ["The cat sat on the mat.", "A cat was sitting on a mat."] embeddings = get_bert_embeddings(texts) print(f"Number of texts: {len(embeddings)}") print(f"Shape of first text embeddings: {embeddings[0].shape}")
输出:
2. 计算余弦相似度:BERTScore 使用余弦相似度来计算标记之间的语义相似度,余弦相似度是一种度量两个向量在嵌入空间中对齐程度的指标,无论其大小如何。
现在,让我们来实现标记之间的余弦相似性计算:
def token_cosine_similarity(embeddings1, embeddings2): # Normalize embeddings for cosine similarity embeddings1_norm = embeddings1 / embeddings1.norm(dim=1, keepdim=True) embeddings2_norm = embeddings2 / embeddings2.norm(dim=1, keepdim=True) similarity_matrix = torch.matmul(embeddings1_norm, embeddings2_norm.transpose(0, 1)) return similarity_matrix # Example usage with our previously generated embeddings sim_matrix = token_cosine_similarity(embeddings[0], embeddings[1]) print(f"Shape of similarity matrix: {sim_matrix.shape}") print("Similarity matrix (token-to-token):") print(sim_matrix)
输出:
BERTScore:精确度、召回率和F1
让我们从头开始实现 BERTScore 的核心计算,以了解其背后的数学原理:
数学公式
BERTScore 计算三个指标:
1. 精确度(Precision):候选文本中有多少词组与参考文献中的词组相匹配?
2. 召回率(Recall):候选文本覆盖了参考文本中多少标记?
3. F1:精确度和召回率的调和平均值
其中
- x 和 y 分别为候选文本和参考文本
- xi 和 yj 是标记嵌入。
实施情况
def calculate_bertscore(candidate_embeddings, reference_embeddings): # Compute similarity matrix sim_matrix = token_cosine_similarity(candidate_embeddings, reference_embeddings) # Compute precision (max similarity for each candidate token) precision = sim_matrix.max(dim=1)[0].mean().item() # Compute recall (max similarity for each reference token) recall = sim_matrix.max(dim=0)[0].mean().item() # Compute F1 f1 = 2 * precision * recall / (precision + recall) if precision + recall > 0 else 0 return precision, recall, f1 # Example cand_emb = embeddings[0] # "The cat sat on the mat." ref_emb = embeddings[1] # "A cat was sitting on a mat." precision, recall, f1 = calculate_bertscore(cand_emb, ref_emb) print(f"Custom BERTScore calculation:") print(f" Precision: {precision:.4f}") print(f" Recall: {recall:.4f}") print(f" F1: {f1:.4f}")
输出:
该实现演示了 BERTScore 背后的核心算法。实际库包括额外的优化、IDF 加权选项和基线重缩。
优势和局限
优势 | 局限 |
捕捉词汇重叠之外的语义相似性 | 计算密集度高于 n-gram 指标 |
更好地与人类判断相关联 | 性能取决于基础嵌入的质量 |
在不同的任务和领域都能很好地发挥作用 | 可能无法捕捉结构或逻辑一致性 |
无需专门为评估进行培训 | 可能对 BERT 层和模型的选择敏感 |
自然处理同义词和意译 | 可解释性不如显式匹配度量 |
语言无关(使用适当的模型) | 需要 GPU 才能高效处理大型数据集 |
可定制不同的嵌入模型 | 不是为评估事实正确性而设计 |
有效处理多个有效引用 | 可能难以处理极具创造性或不寻常的文本 |
实际应用
BERTScore 已在众多 NLP 任务中得到广泛应用:
- 机器翻译:BERTScore 可帮助评估翻译,其重点在于保留意义而非准确措辞,鉴于翻译一个句子的有效方法多种多样,这一点尤为重要。
- 总结:在评估摘要时,BERTScore 可以识别不同的措辞是否捕捉到了相同的关键信息,这使得它在评估摘要质量方面比 ROUGE 更加灵活。
- 对话系统:对于对话式人工智能,BERTScore 可以通过测量与参考回复的语义相似度来评估回复的适当性,即使措辞差别很大。
- 文本简化:BERTScore 可以评估简化后的文本在使用不同词汇的同时是否保持了原意,而词汇重叠度量通常在这项任务中无法达到这一要求。
- 内容创建:在评估人工智能生成的创意内容时,BERTScore 可以衡量生成的内容在不要求完全匹配的情况下对预期主题或信息的捕捉程度。
与其他指标的比较
BERTScore 与其他流行的评估指标相比如何?
指标 | 基数 | 优势 | 劣势 | 人类相关性 |
BLEU | N-gram 精确度 | 快速、可解释 | 表层、位置不敏感 | 中等 |
ROUGE | N-gram 召回率 | 利于总结 | 忽略语义等同性 | 中等 |
METEOR | 增强词汇匹配 | 处理同义词 | 仍以词法为主 | 中等偏高 |
BERTScore | 上下文嵌入 | 语义理解 | 计算密集 | 高 |
BLEURT | 学习度量(微调) | 针对具体任务 | 需要训练 | 非常高 |
LLM-as-Judge | 直接 LLM 评估 | 全面 | 黑盒、昂贵 | 非常高 |
BERTScore 在复杂性和实用性之间取得了平衡,无需进行特定任务培训即可捕捉语义相似性。
小结
通过利用上下文嵌入的语义理解能力,BERTScore 代表了文本生成技术的一大进步。BERTScore 能够捕捉表面词性匹配之外的意义,因此对于评估现代语言模型非常有价值,因为在现代语言模型中,人们既期待也希望输出结果具有创造性和差异性。
虽然没有任何一个指标可以完美地评估文本质量,但必须指出的是,BERTScore 提供了一个可靠的框架,它不仅与不同任务中的人类评估相一致,而且还能提供一致的结果。此外,当与传统指标和人工分析相结合时,它最终能让人们更深入地了解语言生成能力。
随着语言模型的不断发展,像 BERTScore 这样的工具对于确定模型的优缺点以及提高自然语言生成系统的整体质量来说是必不可少的。
评论留言