赞
踩
文本摘要(Text Summarization),作为自然语言处理(NLP)领域的一个分支,其核心目标是从长篇文档中提取关键信息,并生成简短的摘要,以提供对原始内容的高度概括。这一过程不仅有助于用户迅速把握信息的核心,而且对于有效组织和归纳大量的文本数据至关重要。
文本摘要的任务可以根据不同的输入和输出进行分类。首先,根据输入文档的数量,可以将摘要任务分为单文档摘要和多文档摘要。单文档摘要专注于处理单个文档,而多文档摘要则需要整合多个相关文档的信息。其次,根据输入和输出的语言,摘要任务可以分为单语言摘要、跨语言摘要和多语言摘要。在本课程中,我们将重点关注单文档单语言摘要,即处理单个文档并以同一种语言生成摘要。
在单文档单语言摘要中,系统需要理解文档的语义和结构,并从中提取最重要的信息,然后以简洁明了的方式呈现给用户。这个过程涉及对文本的理解、分析和重构,要求模型能够准确捕捉文档的主要观点,同时保持信息的完整性。
T5(Text-to-Text Transfer Transformer)是一种基于Transformer架构的文本到文本的预训练语言模型领域的通用模型,由Google Research开发。T5模型的主要特点是将文本生成任务视为一种文本到文本的转换,这使得它可以被广泛应用于多种文本生成任务,如文本摘要、机器翻译、问答系统、文本生成等。
T5模型通过预训练来学习文本的通用表示,这使得它在下游任务中能够快速适应并表现出色。预训练的过程包括在大规模文本数据上进行自监督学习,模型通过预测文本中的缺失部分来学习文本的表示。
T5模型的一个重要特点是它采用了统一的编码器-解码器架构,这意味着它可以在多种文本生成任务中使用相同的模型,只需调整模型的输入和输出即可。这种统一的架构使得T5模型在各种文本生成任务中表现出了强大的通用性和灵活性。
T5模型的另一个特点是它采用了简单的任务提示(Task Prompt)技术,通过在输入文本中添加一些简单的提示词,如“摘要:”、“翻译:”等,来指导模型生成相应的文本。这种方法可以有效地提高模型的生成质量,并且可以很容易地应用于不同的文本生成任务。
总的来说,T5模型是一种强大的文本到文本的预训练模型,它在多种文本生成任务中都表现出了出色的性能。随着研究的不断深入,T5模型有望在未来的文本生成任务中发挥更大的作用。
序列到序列(Seq2Seq)模型是一种用于处理序列数据的神经网络模型,它由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。这种模型通常用于机器翻译、语音识别、文本摘要等任务
评价指标包括Rouge,具体又分为Rouge-1、Rouge-2、Rouge-L,它们分别基于1-gram、2-gram、LCS。
ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一种用于自动评估文本摘要质量的指标,它主要关注召回率(Recall)和F1分数。ROUGE-1、ROUGE-2和ROUGE-L是ROUGE的不同变体,它们分别计算不同长度的匹配项。
以下是计算ROUGE-1、ROUGE-2和ROUGE-L的基本步骤:
假设我们有一个生成的摘要和一个参考摘要,我们想要计算ROUGE-1、ROUGE-2和ROUGE-L。
生成摘要:今天不错
参考摘要:今天天气不错
常见的数据集
我们使用的是lcsts摘要数据:
lcsts摘要数据是哈尔滨工业大学整理,基于新闻媒体在微博上发布的新闻摘要创建了该数据集,每篇短文约100个字符,每篇摘要约20个字符。
整理后数据信息如下:
总数量:2108915个样本;
摘要:平均字数 18,字数标准差 5,最大字数 30,最小数字 4;
正文:平均字数 104,字数标准差 10,最大字数 152,最小数字 69;
sum_datasets = load_dataset("hugcyp/LCSTS") sum_datasets DatasetDict({ train: Dataset({ features: ['summary', 'text'], num_rows: 2400591 }) validation: Dataset({ features: ['summary', 'text'], num_rows: 8685 }) test: Dataset({ features: ['summary', 'text'], num_rows: 725 }) })
数据集太大了,所以我们做一个简单的
sum_datasets = load_dataset("hugcyp/LCSTS",split="train[:10000]")
sum_datasets = sum_datasets.train_test_split(test_size=0.2)
sum_datasets
DatasetDict({
train: Dataset({
features: ['summary', 'text'],
num_rows: 8000
})
test: Dataset({
features: ['summary', 'text'],
num_rows: 2000
})
})
查看数据
sum_datasets["train"][0]
{'summary': '美国学生如何吐槽第一夫人的营养餐?',
'text': '在米歇尔强力推动下,美国国会通过了法案,要求学生午餐必须包括一份水果或蔬菜,并设定了卡路里的上限。从此美国学校饭堂出现了各种奇葩的“达标”午餐(如下图),譬如用番茄酱来代替水果,引发学生吐槽。'}
在hugging face中找一个T5Chinese的模型试一下
tokenizer = AutoTokenizer.from_pretrained("uer/t5-base-chinese-cluecorpussmall")
def process_func(exmaples):
contents = ["摘要生成: \n" + e for e in exmaples["text"]]
inputs = tokenizer(contents, max_length=384, truncation=True)
labels = tokenizer(text_target=exmaples["summary"], max_length=64, truncation=True)
inputs["labels"] = labels["input_ids"]
return inputs
这段代码是一个函数,名为process_func
,它的目的是处理输入的数据,以便用于训练一个序列到序列(Seq2Seq)模型。在这个函数中,它接受一个字典exmaples
作为输入,该字典包含原始文本"text"
和对应的摘要"summary"
。
函数的步骤如下:
exmaples["text"]
列表,为每个文本生成一个摘要生成提示。提示的格式为"摘要生成: \n"加上文本内容。tokenizer
对生成的内容列表进行分词。这里设置了max_length=384
和truncation=True
,这意味着分词器将尝试将每个内容分词后的序列长度限制在384个token以内,如果超过这个长度,则进行截断。tokenizer
对exmaples["summary"]
进行分词。这里同样设置了max_length=64
和truncation=True
,确保摘要分词后的序列长度不超过64个token。inputs
中。inputs
字典,这些数据可以被模型用于训练。总的来说,这个函数将原始文本和摘要转换为模型可以处理的整数序列格式,并为模型提供了输入和标签,以便于训练。
tokenized_ds = sum_datasets.map(process_func, batched=True)
tokenized_ds
DatasetDict({
train: Dataset({
features: ['summary', 'text', 'input_ids', 'token_type_ids', 'attention_mask', 'labels'],
num_rows: 8000
})
test: Dataset({
features: ['summary', 'text', 'input_ids', 'token_type_ids', 'attention_mask', 'labels'],
num_rows: 2000
})
})
print(tokenized_ds["train"][0])
{'summary': '新民评论:罚丁书苗25亿意义深远', 'text': '加大对行贿者的惩治力度,应当以人身处罚和财产处罚并重,让行贿者把非法获利“吐”出来,防止“一人坐牢,全家享福”的不正常现象。对丁书苗案的判决,能否在刑法修订、行贿成本有望提高的背景之下,成为一个具有典型意义的判例,令人期待。', 'input_ids': [101, 3036, 6206, 4495, 2768, 131, 1217, 1920, 2190, 6121, 6594, 5442, 4638, 2674, 3780, 1213, 2428, 8024, 2418, 2496, 809, 782, 6716, 1905, 5385, 1469, 6568, 772, 1905, 5385, 2400, 7028, 8024, 6375, 6121, 6594, 5442, 2828, 7478, 3791, 5815, 1164, 100, 1402, 100, 1139, 3341, 8024, 7344, 3632, 100, 671, 782, 1777, 4286, 8024, 1059, 2157, 775, 4886, 100, 4638, 679, 3633, 2382, 4385, 6496, 511, 2190, 672, 741, 5728, 3428, 4638, 1161, 1104, 8024, 5543, 1415, 1762, 1152, 3791, 934, 6370, 510, 6121, 6594, 2768, 3315, 3300, 3307, 2990, 7770, 4638, 5520, 3250, 722, 678, 8024, 2768, 711, 671, 702, 1072, 3300, 1073, 1798, 2692, 721, 4638, 1161, 891, 8024, 808, 782, 3309, 2521, 511, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'labels': [101, 3173, 3696, 6397, 6389, 8038, 5385, 672, 741, 5728, 8132, 783, 2692, 721, 3918, 6823, 102]}
model = AutoModelForSeq2SeqLM.from_pretrained("uer/t5-base-chinese-cluecorpussmall")
!pip install rouge_chinese import numpy as np from rouge_chinese import Rouge rouge = Rouge() def compute_metric(evalPred): predictions, labels = evalPred decode_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True) labels = np.where(labels != -100, labels, tokenizer.pad_token_id) decode_labels = tokenizer.batch_decode(labels, skip_special_tokens=True) decode_preds = [" ".join(p) for p in decode_preds] decode_labels = [" ".join(l) for l in decode_labels] scores = rouge.get_scores(decode_preds, decode_labels, avg=True) return { "rouge-1": scores["rouge-1"]["f"], "rouge-2": scores["rouge-2"]["f"], "rouge-l": scores["rouge-l"]["f"], }
这段代码的目的是计算ROUGE(Recall-Oriented Understudy for Gisting Evaluation)分数,这是一种用于评估文本摘要质量的指标。
函数的步骤如下:
numpy
和rouge_chinese
库。numpy
是一个用于科学计算的库,而rouge_chinese
是一个用于计算中文文本ROUGE分数的库。Rouge()
创建了一个Rouge
对象,这通常是一个计算ROUGE分数的函数或类。compute_metric
接受一个评估预测(evalPred
)作为输入。tokenizer
批量解码预测(predictions
)和标签(labels
)。skip_special_tokens=True
参数确保了在解码过程中特殊标记(如<sos>
和<eos>
)被忽略。-100
替换为分词器的pad_token_id
,以确保标签长度与预测长度一致。rouge.get_scores()
函数计算ROUGE-1、ROUGE-2和ROUGE-L的分数。avg=True
参数表示计算平均分数。args = Seq2SeqTrainingArguments(
output_dir="./summary",
per_device_train_batch_size=4,
per_device_eval_batch_size=8,
gradient_accumulation_steps=8,
logging_steps=8,
evaluation_strategy="steps",
eval_steps=200,
save_strategy="epoch",
metric_for_best_model="rouge-l",
predict_with_generate=True,
report_to=['tensorboard']
)
因为训练速度比较慢,我们根据step打印一次预测结果
trainer = Seq2SeqTrainer(
args=args,
model=model,
train_dataset=tokenized_ds["train"],
eval_dataset=tokenized_ds["test"],
compute_metrics=compute_metric,
tokenizer=tokenizer,
data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer)
)
trainer.train()
TrainOutput(global_step=750, training_loss=7.258201690673828, metrics={'train_runtime': 948.8402, 'train_samples_per_second': 25.294, 'train_steps_per_second': 0.79, 'total_flos': 3313311337635840.0, 'train_loss': 7.258201690673828, 'epoch': 3.0})
效果很差,虽然我们训练的次数比较少,但是这个效果还是不能接受的,原因很有可能是我们的模型选的有问题,我们重新选一个模型在测试一下
。
重新选择一个模型,选择搜索出来的第一个试一下
tokenizer = AutoTokenizer.from_pretrained("lemon234071/t5-base-Chinese")
model = AutoModelForSeq2SeqLM.from_pretrained("lemon234071/t5-base-Chinese")
trainer.train()
TrainOutput(global_step=750, training_loss=4.802234703063965, metrics={‘train_runtime’: 979.7099, ‘train_samples_per_second’: 24.497, ‘train_steps_per_second’: 0.766, ‘total_flos’: 2839954114953216.0, ‘train_loss’: 4.802234703063965, ‘epoch’: 3.0})
这个明显好了很多
from transformers import pipeline
pipe = pipeline("text2text-generation", model=model, tokenizer=tokenizer, device=0)
pipe("摘要生成:\n" + sum_datasets["test"][10]["text"], max_length=64, do_sample=True)
[{'generated_text': '<extra_id_0>海口首条水上巴士航线试运行'}]
sum_datasets["test"][10]["summary"]
'海口首条水上巴士将启航航线从万绿园至西秀海滩'
其实生成的效果不是很好,还需要多训练几轮,因为现在的loss还是比较大,而且Rouge-1才0.3
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。