AGI 之 【Hugging Face】 的【文本摘要】的 [评估PEGASUS ] / [ 微调PEGASUS ] / [生成对话摘要] 的简单整理

news2024/11/13 9:33:14

AGI 之 【Hugging Face】 的【文本摘要】的 [评估PEGASUS ] / [ 微调PEGASUS ] / [生成对话摘要]  的简单整理

目录

AGI 之 【Hugging Face】 的【文本摘要】的 [评估PEGASUS ] / [ 微调PEGASUS ] / [生成对话摘要]  的简单整理

一、简单介绍

二、文本摘要

三、在CNN/DailyMail数据集上评估PEGASUS

四、训练摘要模型

1、评估PEGASUS在SAMSum上的性能

2、微调PEGASUS

3、生成对话摘要


一、简单介绍

AGI,即通用人工智能(Artificial General Intelligence),是一种具备人类智能水平的人工智能系统。它不仅能够执行特定的任务,而且能够理解、学习和应用知识于广泛的问题解决中,具有较高的自主性和适应性。AGI的能力包括但不限于自我学习、自我改进、自我调整,并能在没有人为干预的情况下解决各种复杂问题。

  • AGI能做的事情非常广泛:

    跨领域任务执行:AGI能够处理多领域的任务,不受限于特定应用场景。
    自主学习与适应:AGI能够从经验中学习,并适应新环境和新情境。
    创造性思考:AGI能够进行创新思维,提出新的解决方案。
    社会交互:AGI能够与人类进行复杂的社会交互,理解情感和社会信号。

  • 关于AGI的未来发展前景,它被认为是人工智能研究的最终目标之一,具有巨大的变革潜力:

    技术创新:随着机器学习、神经网络等技术的进步,AGI的实现可能会越来越接近。
    跨学科整合:实现AGI需要整合计算机科学、神经科学、心理学等多个学科的知识。
    伦理和社会考量:AGI的发展需要考虑隐私、安全和就业等伦理和社会问题。
    增强学习和自适应能力:未来的AGI系统可能利用先进的算法,从环境中学习并优化行为。
    多模态交互:AGI将具备多种感知和交互方式,与人类和其他系统交互。

Hugging Face作为当前全球最受欢迎的开源机器学习社区和平台之一,在AGI时代扮演着重要角色。它提供了丰富的预训练模型和数据集资源,推动了机器学习领域的发展。Hugging Face的特点在于易用性和开放性,通过其Transformers库,为用户提供了方便的模型处理文本的方式。随着AI技术的发展,Hugging Face社区将继续发挥重要作用,推动AI技术的发展和应用,尤其是在多模态AI技术发展方面,Hugging Face社区将扩展其模型和数据集的多样性,包括图像、音频和视频等多模态数据。

  • 在AGI时代,Hugging Face可能会通过以下方式发挥作用:

        模型共享:作为模型共享的平台,Hugging Face将继续促进先进的AGI模型的共享和协作。
        开源生态:Hugging Face的开源生态将有助于加速AGI技术的发展和创新。
        工具和服务:提供丰富的工具和服务,支持开发者和研究者在AGI领域的研究和应用。
        伦理和社会责任:Hugging Face注重AI伦理,将推动负责任的AGI模型开发和应用,确保技术进步同时符合伦理标准。

AGI作为未来人工智能的高级形态,具有广泛的应用前景,而Hugging Face作为开源社区,将在推动AGI的发展和应用中扮演关键角色。

(注意:以下代码运行,可能需要科学上网)

二、文本摘要

你可能曾经需要总结一份文件,包括研究文章、财务收益报告、一系列电子邮件。如果你仔细思考,这需要一系列的能力,包括理解长篇内容、推理内容、然后产生一段流畅的、包括原始文档主要主题的文本。此外,准确地总结新闻文章与总结法律合同非常不同,因此需要复杂的领域泛化能力。出于这些原因,总结文本(专业术语为文本摘要)对于神经语言模型,包括Transformer模型来说是一项困难的任务。尽管面临这些挑战,文本摘要因为能够显著加速领域专家的工作流程,企业可以通过文本摘要压缩内部知识、总结合同、自动生成社交媒体发布内容等。因此文本摘要NLP任务很有价值。

为了帮助你理解相关的挑战,本节将探讨如何利用Transformer预训练模型来进行文本摘要。摘要是一种经典的序列到序列(seq2seq)任务,需要输入文本和目标文本。

文本摘要是一种自然语言处理任务,其目标是从一个长文本中提取出简洁、重要的信息,生成一个简短的版本。文本摘要可以分为两种主要类型:抽取式摘要和生成式摘要。

  • 抽取式摘要

抽取式摘要通过选择原始文本中的重要句子或段落,直接提取这些内容作为摘要。这种方法不改变原始文本中的词语和句子结构。

实现原理:

  1.     特征提取:首先,需要提取文本的各种特征,例如词频、句子位置、关键词、命名实体等。
  2.     重要性评分:基于提取的特征,计算每个句子的得分,以确定其重要性。
  3.     句子选择:根据重要性得分,选择最重要的句子来构建摘要。

难点:

  1.     重要性衡量:如何准确衡量句子的相对重要性。
  2.     冗余消除:避免选择内容重复的句子。

实现方式:

  1.     基于规则的方法:使用预定义的规则和统计方法来选择句子。
  2.     机器学习方法:使用有监督的学习算法,根据训练数据学习如何选择重要句子。
  • 生成式摘要

生成式摘要通过理解原始文本并生成新的句子来概括其内容。这种方法可以创建更为自然和连贯的摘要,但也更加复杂。

实现原理:

  1.     编码器-解码器架构:使用序列到序列(Seq2Seq)模型,其中编码器将输入文本编码成上下文向量,解码器根据上下文向量生成摘要。
  2.     注意力机制:在解码过程中,模型可以关注输入文本的不同部分,从而生成更相关的内容。
  3.     预训练模型:使用预训练的语言模型(如BERT、GPT等)来提高生成摘要的质量。

难点:

  1.     内容连贯性:生成的摘要需要保持逻辑连贯,避免内容断裂。
  2.     信息完整性:确保生成的摘要包含原始文本中的关键信息。
  3.     模型复杂度:生成式摘要模型通常比抽取式摘要模型更复杂,需要更多的计算资源和训练数据。

实现方式:

  1.     经典的 Seq2Seq 模型:如基于 LSTM 的编码器-解码器模型。
  2.     预训练的 Transformer 模型:如 BERTSUM、T5、BART 等。
  • Hugging Face 中的文本摘要

Hugging Face 提供了多种预训练模型和工具,可以方便地实现文本摘要任务。以下是一些常用的文本摘要模型和使用方法:

  1.  使用预训练模型进行摘要

以下是使用 Hugging Face 提供的 BART 模型进行文本摘要的示例代码:

from transformers import BartForConditionalGeneration, BartTokenizer
 
# 加载预训练的BART模型和对应的tokenizer
model_name = "facebook/bart-large-cnn"
model = BartForConditionalGeneration.from_pretrained(model_name)
tokenizer = BartTokenizer.from_pretrained(model_name)
 
# 输入文本
input_text = """Your text to summarize goes here."""
 
# 对输入文本进行tokenize,并添加必要的模型输入
inputs = tokenizer([input_text], max_length=1024, return_tensors='pt')
 
# 使用模型生成摘要
summary_ids = model.generate(inputs['input_ids'], num_beams=4, max_length=150, early_stopping=True)
 
# 将生成的token序列转换回文本
summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True)
 
print(summary)
  1. 支持的摘要模型

Hugging Face 提供了多种用于文本摘要的预训练模型,包括但不限于:

  1.     BART (facebook/bart-large-cnn)
  2.     T5 (t5-small, t5-base, t5-large, t5-3b, t5-11b)
  3.     PEGASUS (google/pegasus-xsum, google/pegasus-cnn_dailymail)
  •     训练自己的摘要模型

如果需要更好地适应特定领域的文本摘要任务,可以使用自己的数据集对预训练模型进行微调。以下是一个简单的微调示例:

from transformers import Trainer, TrainingArguments, BartForConditionalGeneration, BartTokenizer
from datasets import load_dataset
 
# 加载数据集
dataset = load_dataset("cnn_dailymail", "3.0.0")
 
# 加载预训练的BART模型和tokenizer
model_name = "facebook/bart-large-cnn"
model = BartForConditionalGeneration.from_pretrained(model_name)
tokenizer = BartTokenizer.from_pretrained(model_name)
 
# 数据预处理
def preprocess_function(examples):
    inputs = [doc for doc in examples['article']]
    model_inputs = tokenizer(inputs, max_length=1024, truncation=True)
    # 设定摘要作为目标
    with tokenizer.as_target_tokenizer():
        labels = tokenizer(examples['highlights'], max_length=150, truncation=True)
    model_inputs['labels'] = labels['input_ids']
    return model_inputs
 
tokenized_dataset = dataset.map(preprocess_function, batched=True)
 
# 定义训练参数
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=4,
    per_device_eval_batch_size=4,
    num_train_epochs=3,
    weight_decay=0.01,
)
 
# 使用Trainer进行训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["validation"],
)
 
trainer.train()

文本摘要是一个复杂且具有挑战性的自然语言处理任务。通过使用 Hugging Face 提供的预训练模型和工具,可以大大简化文本摘要的实现过程。用户可以根据具体需求选择合适的模型,进行微调,以获得最佳的摘要效果。

在本节中,我们将建立自己的编码器-解码器模型,将多人对话压缩成简明的摘要。但在此之前,我们先来看看摘要领域中一个经典数据集:CNN/DailyMail语料库。

三、在CNN/DailyMailPEGASUS

现在充分评估模型的条件都齐全了:我们拥有CNN/DailyMail测试集数据集、评估用的ROUGE指标,以及一个摘要模型。

# 导入所需的库
import matplotlib.pyplot as plt  # 导入 matplotlib.pyplot,用于绘制图形
import pandas as pd  # 导入 pandas,用于数据处理
from datasets import load_dataset, load_metric  # 从 datasets 库中导入 load_dataset 和 load_metric 函数
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer  # 从 transformers 库中导入 AutoModelForSeq2SeqLM 和 AutoTokenizer

# 加载 CNN/DailyMail 数据集,版本为 3.0.0
dataset = load_dataset("cnn_dailymail", "3.0.0")

# 加载 ROUGE 评价指标,用于计算文本摘要的质量
rouge_metric = load_metric("rouge", cache_dir=None)

# 定义要计算的 ROUGE 分数的名称列表
rouge_names = ["rouge1", "rouge2", "rougeL", "rougeLsum"]

我们只需要把这些部分组合起来。首先,我们评估三句话基准模型的性能:

# 定义一个函数,用于评估基线模型生成的摘要
def evaluate_summaries_baseline(dataset, metric, column_text="article", column_summary="highlights"):
    # 使用 three_sentence_summary 函数对数据集中的每篇文章生成摘要
    summaries = [three_sentence_summary(text) for text in dataset[column_text]]
    
    # 将生成的摘要和参考摘要添加到评价指标中
    metric.add_batch(predictions=summaries, references=dataset[column_summary])
    
    # 计算评价指标的分数
    score = metric.compute()
    
    # 返回评价指标的分数
    return score

然后我们把该函数应用于数据的一个子集。由于CNN/DailyMail数据集的测试部分包含大约10 000个样本,生成所有这些文章的摘要需要很多时间。回顾第5章,每个生成的词元都需要通过模型进行前向传递。为每个样本生成100个词元将需要100万次前向传递,如果我们使用束搜索,则此数字还需要乘以束的数量。为了让计算更快一些,我们将对测试集进行子采样,最终使用1000个样本进行评估。这样我们使用单个GPU上不到一小时就能完成PEGASUS模型的评估,而且得到稳定的分数估计:

# 从测试集中随机抽取1000条样本,用于评估
test_sampled = dataset["test"].shuffle(seed=42).select(range(1000))

# 使用基线模型生成摘要并评估其质量
score = evaluate_summaries_baseline(test_sampled, rouge_metric)

# 将评价指标的分数存储在字典中
rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)

# 将评价指标的分数转换为DataFrame格式,并转置以便显示
pd.DataFrame.from_dict(rouge_dict, orient="index", columns=["baseline"]).T

运行结果:

 rouge1rouge2rougeLrougeLsum
baseline0.389280.1712960.2450610.354239

分数大多数比上一个示例差,但仍然比GPT-2实现的分数要好!现在我们依样画葫芦来评估PEGASUS模型:

# 导入 tqdm 模块,用于显示进度条
from tqdm import tqdm
# 导入 torch 模块,用于使用 GPU 或 CPU 进行计算
import torch

# 设置设备为 GPU(如果可用)或 CPU
device = "cuda" if torch.cuda.is_available() else "cpu"

def chunks(list_of_elements, batch_size):
    """将 list_of_elements 按 batch_size 切分成多个小块"""
    for i in range(0, len(list_of_elements), batch_size):
        yield list_of_elements[i : i + batch_size]

def evaluate_summaries_pegasus(dataset, metric, model, tokenizer, 
                               batch_size=16, device=device, 
                               column_text="article", 
                               column_summary="highlights"):
    """评估使用 Pegasus 模型生成的摘要"""
    
    # 将文章和摘要分别按 batch_size 切分成多个小块
    article_batches = list(chunks(dataset[column_text], batch_size))
    target_batches = list(chunks(dataset[column_summary], batch_size))

    # 使用 tqdm 显示进度条,遍历每个文章批次和相应的摘要批次
    for article_batch, target_batch in tqdm(
        zip(article_batches, target_batches), total=len(article_batches)):
        
        # 对文章批次进行标记,将其转换为模型输入的张量
        inputs = tokenizer(article_batch, max_length=1024, truncation=True, 
                           padding="max_length", return_tensors="pt")
        
        # 使用 Pegasus 模型生成摘要
        summaries = model.generate(input_ids=inputs["input_ids"].to(device),
                                   attention_mask=inputs["attention_mask"].to(device), 
                                   length_penalty=0.8, num_beams=8, max_length=128)
        
        # 解码生成的摘要,将其从张量转换为字符串
        decoded_summaries = [tokenizer.decode(s, skip_special_tokens=True, 
                                              clean_up_tokenization_spaces=True) 
                             for s in summaries]
        decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
        
        # 将生成的摘要和目标摘要添加到评价指标中
        metric.add_batch(predictions=decoded_summaries, references=target_batch)
        
    # 计算评价指标分数
    score = metric.compute()
    return score

我们来详细解释一下这段评估代码。首先,我们将数据集分成较小的批量,以便可以同时处理。然后对于每个批量,我们对输入文章进行词元化,然后将它们提供给generate()函数,使用束搜索生成摘要。我们使用论文中的相同生成参数。惩罚参数新的长度确保模型不会生成过长的序列。最后,我们解码生成文本,替换<n>词元,并将解码的文本与参考文本一起添加到度量中。最后,我们计算并返回ROUGE分数。现在,我们再次使用用于seq2seq生成任务的AutoModelForSeq2SeqLM类来加载模型,并对其进行评估:

# 从 transformers 库中导入用于序列到序列任务的模型和标记器
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer

# 设置模型检查点名称,使用 Google 的 PEGASUS 模型,预训练于 CNN/DailyMail 数据集
model_ckpt = "google/pegasus-cnn_dailymail"

# 从预训练的模型检查点中加载标记器和模型,并将模型移动到指定的设备(CPU 或 GPU)
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)

# 使用评估函数 evaluate_summaries_pegasus 评估 PEGASUS 模型生成的摘要
# 输入参数包括测试数据、ROUGE 评价指标、模型、标记器和批处理大小
score = evaluate_summaries_pegasus(test_sampled, rouge_metric, 
                                   model, tokenizer, batch_size=8)

# 从评估结果中提取 ROUGE 分数,将其转换为字典格式,其中键为 ROUGE 指标名称,值为 F-measure 分数
rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)

# 将 ROUGE 分数字典转换为 pandas 数据框,并以 "pegasus" 作为索引
pd.DataFrame(rouge_dict, index=["pegasus"])

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto

,使用例子参考的运行结果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.434380.2108830.3071950.373231

这些数字非常接近论文中的结果。这里需要注意的是,损失和每个词元的准确率在某种程度上与ROUGE分数解耦。损失与解码策略无关,而ROUGE分数则强耦合。

由于ROUGE和BLEU比人工评估的损失或准确率更好,因此在构建文本生成模型时应重点关注它们,并仔细探索和选择解码策略。然而,这些指标远非完美,因此应始终考虑人工评估。

现在我们已经有了评估函数,可以训练我们自己的摘要模型了。

四、

至此,我们已经仔细研究了文本摘要和评估的许多细节,现在我们使用这些知识来训练一个自定义的文本摘要模型!对于我们这个自定义应用,我们将使用三星开发的SAMSum数据集(https://oreil.ly/n1ggq),该数据集包含了一系列对话以及简短的摘要。这些对话可以代表客户与客服中心之间的互动,并以此生成准确的摘要以帮助改善客户服务,并检测客户请求中的常见模式。我们先加载数据集并查看一个样本:

# 从 datasets 库中导入用于加载数据集的函数
from datasets import load_dataset

# 加载 SamSum 数据集,该数据集包含对话和相应的摘要
dataset_samsum = load_dataset("samsum",trust_remote_code=True)

# 获取数据集的每个划分(训练集、验证集、测试集)的长度,并存储在列表 split_lengths 中
split_lengths = [len(dataset_samsum[split]) for split in dataset_samsum]

# 打印每个数据集划分的长度
print(f"Split lengths: {split_lengths}")

# 打印训练集中列的名称(特征)
print(f"Features: {dataset_samsum['train'].column_names}")

# 打印测试集中第一个对话样本
print("\nDialogue:")
print(dataset_samsum["test"][0]["dialogue"])

# 打印测试集中第一个对话样本的摘要
print("\nSummary:")
print(dataset_samsum["test"][0]["summary"])

(注意:可能需要安装 py7zr,pip install py7zr)

运行结果:

Split lengths: [14732, 819, 818]
Features: ['id', 'dialogue', 'summary']

Dialogue:
Hannah: Hey, do you have Betty's number?
Amanda: Lemme check
Hannah: <file_gif>
Amanda: Sorry, can't find it.
Amanda: Ask Larry
Amanda: He called her last time we were at the park together
Hannah: I don't know him well
Hannah: <file_gif>
Amanda: Don't be shy, he's very nice
Hannah: If you say so..
Hannah: I'd rather you texted him
Amanda: Just text him 🙂
Hannah: Urgh.. Alright
Hannah: Bye
Amanda: Bye bye

Summary:
Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry.

对话看起来就像你通过短信或WhatsApp聊天一样,包括了表情符号和为GIF准备的占位符。dialogue字段包含了完整的文本,而summary字段则是对话的摘要。在CNN/DailyMail数据集上进行微调的模型能够处理这个数据集吗?我们来看看!

1、评PEGASUSSAMSum

首先,我们将使用PEGASUS运行相同的摘要生成流程,以查看输出结果。我们可以重用CNN/DailyMail摘要生成的代码:

# 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])

# 打印生成的摘要标题
print("Summary:")

# 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
# 这行代码会输出生成的摘要,其中 ". " 替换为 ".\n" 使其更易读
print(pipe_out[0]["summary_text"].replace(" .", ".\n"))

运行结果:

Summary:
Hannah asks Amanda for Betty's number. Amanda can't find it. Hannah asks Larry. Amanda asks Larry to text him. Hannah says she'll text him back. Hannah calls it a day and says she's going to go home. Hannah: "Bye bye"

我们可以看到,该模型主要尝试通过提取对话中的关键句子来进行摘要。这在CNN/DailyMail数据集上可能效果相对较好,但是在SAMSum中,摘要更加抽象,效果不一定好。我们可以通过在测试集上运行完整的ROUGE评估来确认这一点:

# 使用评估函数 evaluate_summaries_pegasus 对 SamSum 数据集的测试集进行摘要生成评估
# 传入的参数包括数据集、评价指标、模型、tokenizer、文本列名、摘要列名和批量大小
score = evaluate_summaries_pegasus(dataset_samsum["test"], rouge_metric, model,
                                   tokenizer, column_text="dialogue",
                                   column_summary="summary", batch_size=8)

# 创建一个字典 rouge_dict,用于存储 ROUGE 评分的中值 F-measure 值
rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)

# 将 ROUGE 评分字典转换为 Pandas 数据框,并以 "pegasus" 为索引
pd.DataFrame(rouge_dict, index=["pegasus"])

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto

,使用例子参考的运行结果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.296170.0878030.2296040.229514

虽然结果并不太好,但这并不出乎意料,因为远离了CNN/DailyMail数据分布。尽管如此,在训练之前设置评估流程有两个优点:我们可以直接使用度量指标来度量训练的成功,而且我们有一个很好的基准。在我们的数据集上对模型进行微调应该会立即改善ROUGE度量指标,如果没有改善,那么我们就知道我们的训练循环出了问题。

2、微PEGASUS

在我们对数据进行训练之前,我们快速查看输入和输出的长度分布:

# 编码训练集中的对话文本和摘要,并计算其长度
d_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["dialogue"]]
s_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["summary"]]

# 创建一个包含两个子图的图形对象
fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), sharey=True)

# 绘制对话文本的长度分布直方图
axes[0].hist(d_len, bins=20, color="C0", edgecolor="C0")
axes[0].set_title("Dialogue Token Length")
axes[0].set_xlabel("Length")
axes[0].set_ylabel("Count")

# 绘制摘要的长度分布直方图
axes[1].hist(s_len, bins=20, color="C0", edgecolor="C0")
axes[1].set_title("Summary Token Length")
axes[1].set_xlabel("Length")

# 调整子图布局,使其更加紧凑
plt.tight_layout()

# 显示绘制的图形
plt.show()

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto

,使用例子参考的运行结果如下)

我们可以看到,大多数对话比CNN/DailyMail的文章要短得多,每个对话有大约100~200个词元。同样地,摘要也要短得多,大约有20~40个词元(与推文的平均长度相同)。

我们先记住这些结果,后面会用到。首先,我们需要对数据集进行词元化。我们将对话和摘要的最大长度分别设置为1024和128:

def convert_examples_to_features(example_batch):
    """
    将示例批处理转换为模型输入特征。
    
    Args:
    - example_batch (dict): 包含对话和摘要的示例批处理字典。
    
    Returns:
    - dict: 包含转换后特征的字典,包括输入编码和目标编码。
    """
    # 对对话文本进行编码处理,生成输入编码
    input_encodings = tokenizer(example_batch["dialogue"], max_length=1024,
                                truncation=True)
    
    # 使用目标编码器处理摘要文本,生成目标编码
    with tokenizer.as_target_tokenizer():
        target_encodings = tokenizer(example_batch["summary"], max_length=128,
                                     truncation=True)
    
    # 返回包含输入编码、目标标签和注意力掩码的字典
    return {
        "input_ids": input_encodings["input_ids"],
        "attention_mask": input_encodings["attention_mask"],
        "labels": target_encodings["input_ids"]
    }

# 使用 map 方法将 SamSum 数据集转换为 PyTorch 格式
dataset_samsum_pt = dataset_samsum.map(convert_examples_to_features, 
                                       batched=True)

# 设置数据集格式为 Torch 张量类型,并指定列名
columns = ["input_ids", "labels", "attention_mask"]
dataset_samsum_pt.set_format(type="torch", columns=columns)

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)

在词元化步骤中有一个新事物:tokenizer.as_target_tokenizer()上下文。某些模型需要在解码器输入中使用特殊词元,因此将编码器和解码器输入的词元化步骤分开非常重要。在with语句中(称为上下文管理器),词元分析器知道它正在为解码器进行词元化处理。

现在,我们需要创建数据整理器。在大多数情况下,我们可以使用默认的整理器,它收集批量中的所有张量并将它们简单地堆叠起来。对于摘要任务,我们不仅需要堆叠输入,还需要在解码器侧准备目标。PEGASUS是一种编码器-解码器Transformer,因此具有经典的seq2seq架构。在seq2seq设置中,一种常见的方法是在解码器中应用teacher forcing。使用此策略时,解码器接收输入词元(与仅包含解码器的模型相同,如GPT-2),这些词元由标注向右移动一个位置,除此之外还有编码器输出。因此,在预测下一个词元时,解码器将获得向右移动一个位置的真实值作为输入,如下表所示:

# 示例文本序列和标签生成过程
text = ['PAD', 'Transformers', 'are', 'awesome', 'for', 'text', 'summarization']

# 初始化存储每步结果的列表
rows = []

# 循环生成每步的数据行
for i in range(len(text)-1):
    rows.append({
        'step': i+1,                       # 步骤号,从1开始
        'decoder_input': text[:i+1],       # 解码器输入序列,从文本开始到当前位置
        'label': text[i+1]                 # 标签,当前位置的下一个词
    })

# 创建数据帧,并以步骤号作为索引
pd.DataFrame(rows).set_index('step')

运行结果:

stepdecoder_inputlabel
1[PAD]Transformers
2[PAD, Transformers]are
3[PAD, Transformers, are]awesome
4[PAD, Transformers, are, awesome]for
5[PAD, Transformers, are, awesome, for]text
6[PAD, Transformers, are, awesome, for, text]summarization

我们将它向右移动一个位置,这样解码器只会看到前一个正确的标注,而不是当前或未来的标注。仅进行移位就足够了,因为解码器有一个掩码自注意力机制,它会掩码当前和未来的所有输入。

因此,在准备批量时,我们通过将标注向右移动一个位置来设置解码器的输入。之后,我们通过将标注中的填充词元设置为-100来确保忽略损失函数中的填充词元。实际上,我们不必手动执行这些步骤,因为DataCollatorForSeq2Seq会帮我们完成所有这些步骤:

# 导入 Seq2Seq 数据集整理器模块
from transformers import DataCollatorForSeq2Seq

# 创建 Seq2Seq 数据集整理器实例
seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)

然后,和往常一样,我们为训练设置了一个TrainingArguments:

# 导入训练参数和训练器模块
from transformers import TrainingArguments, Trainer

# 定义训练参数
training_args = TrainingArguments(
    output_dir='pegasus-samsum',            # 模型输出目录
    num_train_epochs=1,                     # 训练的轮数
    warmup_steps=500,                       # 学习率预热步数
    per_device_train_batch_size=1,          # 每个设备的训练批次大小
    per_device_eval_batch_size=1,           # 每个设备的评估批次大小
    weight_decay=0.01,                      # 权重衰减率
    logging_steps=10,                       # 训练日志记录步数
    push_to_hub=True,                       # 是否推送到模型中心
    evaluation_strategy='steps',            # 评估策略
    eval_steps=500,                         # 评估步数间隔
    save_steps=1e6,                         # 模型保存步数间隔
    gradient_accumulation_steps=16          # 梯度累积步数
)

与以往设置不同的是,这次有了一个新的参数gradient_accumulation_steps。由于模型非常大,因此我们不得不将批量大小设置为1。然而,批量大小太小会影响收敛。为了解决这个问题,我们可以使用一种称为梯度累积的巧妙技巧。顾名思义,我们不是一次性计算整个批量的梯度,而是分批计算并聚合梯度。当我们聚合足够的梯度时,我们运行优化步骤。这比一次性完成自然会慢一些,但它可以节省我们大量的GPU内存。

现在,我们登录到Hugging Face,这样我们就可以在训练后将模型推送到Hub上:

from huggingface_hub import notebook_login

notebook_login()

运行结果:

现在我们已经拥有初始化训练器所需的一切,包括模型、词元分析器、训练参数、数据整理器,以及训练和评估数据集:

from transformers import TrainingArguments, Trainer

# 创建一个 Trainer 实例用于训练序列到序列模型。
trainer = Trainer(
    model=model,  # 要训练的序列到序列模型
    args=training_args,  # 定义的训练参数
    tokenizer=tokenizer,  # 用于预处理输入数据的分词器
    data_collator=seq2seq_data_collator,  # 用于批处理数据的数据整理器
    train_dataset=dataset_samsum_pt["train"],  # 训练数据集
    eval_dataset=dataset_samsum_pt["validation"]  # 评估数据集
)

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)

我们已经准备好进行训练了。训练完成后,我们可以直接在测试集上运行评估函数,以查看模型的表现如何:

from transformers import TrainingArguments, Trainer

# 开始训练模型
trainer.train()

# 使用评估函数评估 Pegasus 模型的摘要质量
score = evaluate_summaries_pegasus(
    dataset_samsum["test"], rouge_metric, trainer.model, tokenizer,
    batch_size=2, column_text="dialogue", column_summary="summary")

# 提取 ROUGE 指标结果
rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)

# 创建 DataFrame 显示 ROUGE 指标
pd.DataFrame(rouge_dict, index=[f"pegasus"])

运行结果:

(这里暂时报错:

TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto

,使用例子参考的运行结果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.427610.2005710.3406480.340738

我们可以看到,ROUGE分数比没有进行微调的模型有了显著的提高,因此尽管之前的模型也是用于摘要生成训练的,但它并没有很好地适应新的领域。我们把我们的模型推送到Hub上吧:

# 将训练完成的模型推送到 Hub 上
trainer.push_to_hub("Training complete!")

接下来我们将使用这个模型为我们生成一些摘要。

你也可以将生成的结果作为训练循环的一部分进行评估:使用名为Seq2SeqTrainingArguments的TrainingArguments扩展,并指定predict_with_generate=True。将其传给名为Seq2SeqTrainer的专用Trainer,该Trainer使用generate()函数而不是模型的前向传递来创建用于评估的预测。你动手试一试吧!

3、生成

从损失和ROUGE分数来看,该模型似乎比仅在CNN/DailyMail上训练的原始模型表现出显著的改进。从测试集中的一个样本生成的摘要如下所示:

import transformers

# 设置transformers的日志级别为错误,以减少输出日志
transformers.logging.set_verbosity_error()

# 定义生成摘要时的参数
gen_kwargs = {"length_penalty": 0.8, "num_beams": 8, "max_length": 128}

# 从测试集中选择一个示例
sample_text = dataset_samsum["test"][0]["dialogue"]
reference = dataset_samsum["test"][0]["summary"]

# 使用预训练的pegasus-samsum模型创建摘要管道
pipe = pipeline("summarization", model="transformersbook/pegasus-samsum")

# 输出对话和参考摘要
print("Dialogue:")
print(sample_text)
print("\nReference Summary:")
print(reference)

# 使用模型生成摘要并输出
print("\nModel Summary:")
print(pipe(sample_text, **gen_kwargs)[0]["summary_text"])

运行结果:

Dialogue:
Hannah: Hey, do you have Betty's number?
Amanda: Lemme check
Hannah: <file_gif>
Amanda: Sorry, can't find it.
Amanda: Ask Larry
Amanda: He called her last time we were at the park together
Hannah: I don't know him well
Hannah: <file_gif>
Amanda: Don't be shy, he's very nice
Hannah: If you say so..
Hannah: I'd rather you texted him
Amanda: Just text him 🙂
Hannah: Urgh.. Alright
Hannah: Bye
Amanda: Bye bye

Reference Summary:
Hannah needs Betty's number but Amanda doesn't have it. She needs to contact
Larry.

Model Summary:
Amanda can't find Betty's number. Larry called Betty last time they were at the
park together. Hannah wants Amanda to text Larry instead of calling Betty.

这与参考摘要十分相似。看起来模型已经学会了将对话综合成摘要而不仅仅是提取段落。现在进行最终测试:模型在自定义输入上的表现如何?

# 自定义对话示例
custom_dialogue = """\
Thom: Hi guys, have you heard of transformers?
Lewis: Yes, I used them recently!
Leandro: Indeed, there is a great library by Hugging Face.
Thom: I know, I helped build it ;)
Lewis: Cool, maybe we should write a book about it. What do you think?
Leandro: Great idea, how hard can it be?!
Thom: I am in!
Lewis: Awesome, let's do it together!
"""

# 使用预训练的pegasus-samsum模型生成摘要,并输出摘要结果
print(pipe(custom_dialogue, **gen_kwargs)[0]["summary_text"])

运行结果:

Thom and Lewis wanted to write a book about transformers. They came up with the idea with the help of Hugging Face's Leandro. The book will be called "Transformers: The Power of Transformers" and will be published in 2015. The project is currently in the planning stages.

生成的自定义对话摘要很有意义。它很好地总结了讨论中所有人都想一起写书的内容,而不仅仅是提取单个句子。例如,它将第3行和第4行合成为一个逻辑组合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1919375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【接口设计】如何设计统一 RESTful 风格的数据接口

如何设计统一 RESTful 风格的数据接口 1.版本控制1.1 通过 URL1.2 通过自定义请求头1.3 通过 Accept 标头 2.过滤信息3.确定 HTTP 的方法4.确定 HTTP 的返回状态5.定义统一返回的格式 近年来&#xff0c;随着移动互联网的发展&#xff0c;各种类型的客户端层出不穷。如果不统一…

347. 前 K 个高频元素(中等)

347. 前 K 个高频元素 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转&#xff1a;347. 前 K 个高频元素 2.详细题解 寻找出现频率前 k k k高的元素&#xff0c;因此需要先统计各个元素出现的次数&#xff0c;该步骤时间复杂度为 O ( n ) O(n) O(n)…

javaweb中的请求与响应--基于postman工具的应用(附带postman的详细安装步骤)

一、前言 后端的第一天感觉难度就上来了&#xff0c;可能是基础太过薄弱了吧。目前看视频已经有点跟不上了&#xff0c;果然15天想要拿下还是太勉强了点。30天还差不多。不知道读者们有没有好好的去学这方面的知识&#xff0c;没有什么是学不会的&#xff0c;关键是坚持。 Po…

【C语言】C语言-学生籍贯信息记录系统(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

C#Winform窗体中嵌入exe文件

1&#xff0c;效果以嵌入Modbus Slave为例&#xff1a; 2&#xff0c;代码&#xff1a; public partial class Form1 : Form{//设置嵌入exe的常量private const int nIndex -16;private const int dwNewLong 0x10000000;Process m_AppProcess;public Form1(){InitializeCompo…

了解AsyncRotationController

概述 基于android 15.0, 以从强制横屏App上滑退回桌面流程来分析 frameworks/base/services/core/java/com/android/server/wm/AsyncRotationController.javaAsyncRotationController 是一种控制器&#xff0c;用于处理设备显示屏旋转时非活动窗口的异步更新。这种控制器通过…

【记录】CSS|Tailwind 的主题定义的颜色的使用方法(--color啥的)

文章目录 【记录】CSS&#xff5c;Tailwind 的主题定义的颜色的使用方法&#xff08;--color 啥的&#xff09;省流版GPT 详细解释版Tailwind CSS 配置文件示例使用自定义颜色定义 CSS 变量总结 附赠个 Tips 【记录】CSS&#xff5c;Tailwind 的主题定义的颜色的使用方法&#…

【Python】已解决:ModuleNotFoundError: No module named ‘sklearn.cross_validation

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 &#xff08;机器学习分割数据问题&#xff09;解决“ModuleNotFoundError: No module named ‘sklearn.cross_validation’” 一、问题背景 在机器学习的实践中&#xff0c;数据分割是…

聚鼎装饰画:现在做装饰画能不能相信

在艺术的殿堂中&#xff0c;装饰画以其多变的风格和独特的魅力占据了一席之地。它们或清新淡雅&#xff0c;或浓烈奔放&#xff0c;总能为现代家居带来一丝生气与美感。然而&#xff0c;在这美丽的背后&#xff0c;却隐藏着一个令人困惑的问题&#xff1a;现在做装饰画&#xf…

[EasilyOpenJCL] 使用 Java 调用显卡 计算 和Java调用 CPU 进行计算 的基准测试!

设备环境介绍 easily-openJCL 是一个轻量级的 Java 语言下的 GPU 显卡 计算库&#xff0c;它提供了一套简单易用的 API&#xff0c;让用户能够轻松实现 GPU 计算操作。 通过 Java 调用 GPU 计算的一个库&#xff0c;使用非常简单的API就可以轻松应付 Java 数据类型在 GPU 中的…

程序使用多进程,打包.exe后,程序陷入死循环

最近写了一个深度学习程序&#xff0c;用cxfreezee打包exe后&#xff0c;在本地运行突然出现死循环&#xff0c;明明在pycharm运行一切正常。 排查了问题&#xff0c;怀疑是多进程的原因&#xff0c;解决办法&#xff1a; 在你的主程序前添加一行代码&#xff1a; if __name_…

Typescript 模块小知识-global scope

问题表现 在编写ts代码的时候遇到一个问题, 表现为, 如果在某个ts工程中, 如果多个文件里面没有任何导出export或者是export default, 那么这些文件如果有const或者是let定义相同的声明都会报错如下 无法重新声明块范围变量 a/a.ts 和 index.ts 和 index2.ts 都没有进行expor…

C++系列-Vector(一)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Vector的介绍及使用 Vector的介绍 当vector构建的参数类型为char类型时&#xff0c;它是和string是极其类似的&#xff0c;但是二者之间也有不同&#xff0c;比如&#xff0c…

人工智能时代,零基础学IT,我首推Python作为你编程入门语言!

人工智能时代为什么将 Python 称为第一语言&#xff1f; 因为python适应了人工智能时代&#xff1a; 人工智能时代对于代码的简便性有很大要求&#xff0c;像传统的C/CPP/Java学习较为复杂&#xff0c;学习路线长&#xff0c;对于很多零基础的人入门困难。python的兼容性&…

24下软考高级-系统架构设计师100条知识点速记!

11月系统架构设计师现在准备真的太早了吗&#xff1f; 不不不~对于0基础和打工人&#xff0c;留给我们备考的时间其实已经不多了&#xff01; 想开始不晓得从哪里开始&#xff1f;这里给大家整理了24下系统架构设计师知识点100条&#xff0c;符合最新版教材和考试大纲&#x…

Python实现动态迷宫生成:自动生成迷宫的动画

文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame定义迷宫生成类主循环 完整代码 引言 迷宫生成算法在游戏开发和图形学中有着广泛的应用。它不仅可以用于创建迷宫游戏&#xff0c;还可以用于生成有趣的图案。在这篇博客中&#xff0c;我们将使用Python…

目前哪些充电宝是最强?曝光几款好用的充电宝排行榜

充电宝在我们的日常生活中能为我们带来无与伦比的便捷与体验。然而&#xff0c;当充电宝市场品牌和型号众多&#xff0c;功能丰富多样&#xff0c;口碑最佳的充电宝究竟有哪些&#xff1f;怎样才能挑选到口碑上佳、契合个人需求的充电宝&#xff0c;这已然成为消费者面临的难题…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【HMAC(C/C++)】

HMAC(C/C) HMAC是密钥相关的哈希运算消息认证码&#xff08;Hash-based Message Authentication Code&#xff09;&#xff0c;是一种基于Hash函数和密钥进行消息认证的方法。 在CMake脚本中链接相关动态库 target_link_libraries(entry PUBLIC libhuks_ndk.z.so)开发步骤 生…

基于Python/MATLAB长时间序列遥感数据处理及在全球变化、植被物候提取、植被变绿与生态系统固碳分析、生物量估算与趋势分析应用

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…

大模型【Qwen2-7B本地部署(WEB版)】(windows)

大模型系列文章目录 Qwen2-7B本地部署&#xff08;WEB版&#xff09; 前言 大模型是截止2024年上半年最强的AI&#xff0c;Qwen2是刚出来的号称国内最强开源大模型。这是大模型系列的第一篇文章&#xff0c;旨在快速部署看看最近出来的大模型效果怎么样&#xff0c;效果ok的话…