Compartilhamento de tecnologia

Arranjo simples de [Avaliar PEGASUS] / [Ajustar PEGASUS] / [Gerar resumo da conversa] de [Resumo do texto] de [Hugging Face] do AGI

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Arranjo simples de [Avaliar PEGASUS] / [Ajustar PEGASUS] / [Gerar resumo da conversa] de [Resumo do texto] de [Hugging Face] do AGI

Índice

Arranjo simples de [Avaliar PEGASUS] / [Ajustar PEGASUS] / [Gerar resumo da conversa] de [Resumo do texto] de [Hugging Face] do AGI

1. Breve introdução

2. Resumo do texto

3. Avalie o PEGASUS no conjunto de dados CNN/DailyMail

4. Modelo de resumo de treinamento

1. Avalie o desempenho do PEGASUS no SAMSum

2. Ajuste o PEGASUS

3. Gere um resumo da conversa


1. Breve introdução

AGI, ou Artificial General Intelligence, é um sistema de inteligência artificial com níveis de inteligência humana. Pode não apenas realizar tarefas específicas, mas também compreender, aprender e aplicar conhecimentos para resolver uma ampla gama de problemas, com elevada autonomia e adaptabilidade. As capacidades da AGI incluem, mas não estão limitadas a, autoaprendizagem, autoaperfeiçoamento, autoajuste e a capacidade de resolver vários problemas complexos sem intervenção humana.

  • O que a AGI pode fazer é muito amplo:

Execução de tarefas entre domínios: o AGI pode lidar com tarefas em vários domínios e não está limitado a cenários de aplicativos específicos.
Aprendizagem e adaptação autônoma: AGI pode aprender com a experiência e se adaptar a novos ambientes e situações.
Pensamento criativo: AGI é capaz de pensar de forma inovadora e apresentar novas soluções.
Interação social: AGI é capaz de interações sociais complexas com humanos e compreende sinais emocionais e sociais.

  • No que diz respeito às perspectivas futuras de desenvolvimento da AGI, esta é considerada um dos objectivos finais da investigação em inteligência artificial e tem um enorme potencial de mudança:

Inovação tecnológica: Com o avanço de tecnologias como aprendizado de máquina e redes neurais, a realização da AGI pode estar cada vez mais próxima.
Integração interdisciplinar: A implementação da AGI requer a integração de conhecimentos de múltiplas disciplinas, como ciência da computação, neurociência e psicologia.
Considerações éticas e sociais: O desenvolvimento da AGI requer a consideração de questões éticas e sociais, como privacidade, segurança e emprego.
Aprendizagem aprimorada e capacidades adaptativas: Os futuros sistemas AGI poderão usar algoritmos avançados para aprender com o ambiente e otimizar o comportamento.
Interação multimodal: AGI terá múltiplos métodos de percepção e interação para interagir com humanos e outros sistemas.

Como uma das comunidades e plataformas de aprendizado de máquina de código aberto mais populares do mundo, o Hugging Face desempenha um papel importante na era AGI. Fornece recursos ricos de modelos e conjuntos de dados pré-treinados, promovendo o desenvolvimento do campo de aprendizado de máquina. Hugging Face é caracterizado pela facilidade de uso e abertura. Por meio de sua biblioteca Transformers, ele fornece aos usuários uma maneira conveniente de os modelos processarem texto. Com o desenvolvimento da tecnologia de IA, a comunidade Hugging Face continuará a desempenhar um papel importante na promoção do desenvolvimento e aplicação da tecnologia de IA, especialmente no desenvolvimento de tecnologia de IA multimodal. A comunidade Hugging Face expandirá a diversidade de seus modelos. e conjuntos de dados, incluindo dados multimodais, como imagens, áudio e vídeo.

  • Na era da AGI, Hugging Face pode entrar em ação das seguintes maneiras:

Compartilhamento de modelos: Como plataforma de compartilhamento de modelos, Hugging Face continuará a promover o compartilhamento e a colaboração de modelos AGI avançados.
Ecossistema de código aberto: O ecossistema de código aberto da Hugging Face ajudará a acelerar o desenvolvimento e a inovação da tecnologia AGI.
Ferramentas e serviços: Fornece uma variedade de ferramentas e serviços para apoiar desenvolvedores e pesquisadores em suas pesquisas e aplicações na área de AGI.
Ética e responsabilidade social: Hugging Face concentra-se na ética da IA ​​e promoverá o desenvolvimento e aplicação de modelos AGI responsáveis ​​para garantir o progresso tecnológico, ao mesmo tempo que cumpre os padrões éticos.

AGI, como uma forma avançada de inteligência artificial no futuro, tem amplas perspectivas de aplicação, e Hugging Face, como uma comunidade de código aberto, desempenhará um papel fundamental na promoção do desenvolvimento e aplicação da AGI.

(Observação: o código a seguir pode exigir acesso científico à Internet para ser executado)

2. Resumo do texto

Talvez você tenha que resumir um documento, incluindo um artigo de pesquisa, um relatório de ganhos financeiros ou uma série de e-mails. Se você pensar bem, isso requer uma série de habilidades, incluindo a compreensão de conteúdo extenso, raciocinar sobre ele e, em seguida, produzir um texto fluente que englobe os temas principais do documento original. Além disso, resumir com precisão um artigo de notícias é muito diferente de resumir um contrato legal e, portanto, requer capacidades complexas de generalização de domínio. Por estas razões, resumir texto (o termo técnico é resumo de texto) é uma tarefa difícil para modelos de linguagem neural, incluindo modelos Transformer. Apesar desses desafios, a sumarização de texto pode acelerar significativamente o fluxo de trabalho dos especialistas do domínio. As empresas podem usar a sumarização de texto para condensar o conhecimento interno, resumir contratos, gerar automaticamente conteúdo de publicação em mídias sociais, etc. Portanto, a tarefa de PNL de resumo de texto é valiosa.

Para ajudá-lo a compreender os desafios, esta seção explora como aproveitar modelos pré-treinados do Transformer para resumo de texto. A sumarização é uma tarefa clássica de sequência a sequência (seq2seq) que requer texto de entrada e texto de destino.

A sumarização de texto é uma tarefa de processamento de linguagem natural cujo objetivo é extrair informações concisas e importantes de um texto longo e gerar uma versão curta. A sumarização de texto pode ser dividida em dois tipos principais: sumarização extrativa e sumarização generativa.

  • Resumo extrativo

A sumarização extrativa seleciona frases ou parágrafos importantes do texto original e extrai diretamente esses conteúdos como resumos. Este método não altera as palavras e a estrutura das frases no texto original.

Princípio de implementação:

  1. Extração de características: Primeiro, várias características do texto precisam ser extraídas, como frequência das palavras, posição da frase, palavras-chave, entidades nomeadas, etc.
  2. Pontuação de importância: Com base nas características extraídas, uma pontuação é calculada para cada frase para determinar sua importância.
  3. Seleção de frases: Com base na pontuação de importância, as frases mais importantes são selecionadas para construir o resumo.

dificuldade:

  1. Medição de importância: como medir com precisão a importância relativa das sentenças.
  2. Eliminação de Redundância: Evite selecionar frases com conteúdo repetido.

Método para realizar:

  1. Abordagem baseada em regras: usa regras predefinidas e métodos estatísticos para selecionar sentenças.
  2. Método de aprendizado de máquina: use algoritmos de aprendizado supervisionado para aprender como selecionar frases importantes com base em dados de treinamento.
  • Resumo generativo

A sumarização generativa funciona através da compreensão do texto original e da geração de novas frases para resumir seu conteúdo. Esta abordagem cria um resumo mais natural e coerente, mas também é mais complexo.

Princípio de implementação:

  1. Arquitetura codificador-decodificador: usa um modelo sequência a sequência (Seq2Seq), onde o codificador codifica o texto de entrada em vetores de contexto e o decodificador gera resumos com base nos vetores de contexto.
  2. Mecanismo de atenção: Durante o processo de decodificação, o modelo pode focar em diferentes partes do texto de entrada para gerar conteúdo mais relevante.
  3. Modelo pré-treinado: Use modelos de linguagem pré-treinados (como BERT, GPT, etc.) para melhorar a qualidade dos resumos gerados.

dificuldade:

  1. Coerência de conteúdo: O resumo gerado precisa manter a coerência lógica e evitar quebras de conteúdo.
  2. Integridade das informações: Garante que o resumo gerado contenha informações importantes do texto original.
  3. Complexidade do modelo: Os modelos de resumo generativos são geralmente mais complexos do que os modelos de resumo extrativos e requerem mais recursos computacionais e dados de treinamento.

Método para realizar:

  1. Modelo Seq2Seq clássico: como o modelo codificador-decodificador baseado em LSTM.
  2. Modelos de transformadores pré-treinados: como BERTSUM, T5, BART, etc.
  • Resumo de texto em Hugging Face

Hugging Face oferece uma variedade de modelos e ferramentas pré-treinados para implementar facilmente tarefas de resumo de texto. A seguir estão alguns modelos de resumo de texto comumente usados ​​e como usá-los:

  1. Resumo usando modelos pré-treinados

A seguir está um exemplo de código para resumo de texto usando o modelo BART fornecido por Hugging Face:

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

Hugging Face oferece uma variedade de modelos pré-treinados para resumo de texto, incluindo, mas não se limitando a:

  1. BART (facebook/bart-large-cnn)
  2. T5 (t5-pequeno, t5-base, t5-grande, t5-3b, t5-11b)
  3. PEGASUS (google/pegasus-xsum, google/pegasus-cnn_dailymail)
  • Treine seu próprio modelo de resumo

Se precisar se adaptar melhor às tarefas de resumo de texto específicas do domínio, você poderá ajustar o modelo pré-treinado usando seu próprio conjunto de dados. Aqui está um exemplo simples de ajuste fino:

  1. from transformers import Trainer, TrainingArguments, BartForConditionalGeneration, BartTokenizer
  2. from datasets import load_dataset
  3. # 加载数据集
  4. dataset = load_dataset("cnn_dailymail", "3.0.0")
  5. # 加载预训练的BART模型和tokenizer
  6. model_name = "facebook/bart-large-cnn"
  7. model = BartForConditionalGeneration.from_pretrained(model_name)
  8. tokenizer = BartTokenizer.from_pretrained(model_name)
  9. # 数据预处理
  10. def preprocess_function(examples):
  11. inputs = [doc for doc in examples['article']]
  12. model_inputs = tokenizer(inputs, max_length=1024, truncation=True)
  13. # 设定摘要作为目标
  14. with tokenizer.as_target_tokenizer():
  15. labels = tokenizer(examples['highlights'], max_length=150, truncation=True)
  16. model_inputs['labels'] = labels['input_ids']
  17. return model_inputs
  18. tokenized_dataset = dataset.map(preprocess_function, batched=True)
  19. # 定义训练参数
  20. training_args = TrainingArguments(
  21. output_dir="./results",
  22. evaluation_strategy="epoch",
  23. learning_rate=2e-5,
  24. per_device_train_batch_size=4,
  25. per_device_eval_batch_size=4,
  26. num_train_epochs=3,
  27. weight_decay=0.01,
  28. )
  29. # 使用Trainer进行训练
  30. trainer = Trainer(
  31. model=model,
  32. args=training_args,
  33. train_dataset=tokenized_dataset["train"],
  34. eval_dataset=tokenized_dataset["validation"],
  35. )
  36. trainer.train()

O resumo de texto é uma tarefa complexa e desafiadora de processamento de linguagem natural. Ao usar os modelos e ferramentas pré-treinados fornecidos pelo Hugging Face, o processo de implementação de resumo de texto pode ser bastante simplificado. Os usuários podem selecionar o modelo apropriado de acordo com necessidades específicas e ajustá-lo para obter o melhor efeito de resumo.

Nesta seção, construiremos nosso próprio modelo codificador-decodificador para compactar conversas entre várias pessoas em resumos concisos. Mas antes disso, vamos dar uma olhada em um conjunto de dados clássico no campo do resumo: corpus CNN/DailyMail.

três,em CNãoãoNãoão/EaeueueMaeueunúmerode acordo comdefinirsuperiorComenteestimativaPEGASvocêS

Agora temos tudo o que precisamos para avaliar completamente o modelo: temos o conjunto de dados do conjunto de testes CNN/DailyMail, a métrica ROUGE para avaliação e um modelo resumido.

  1. # 导入所需的库
  2. import matplotlib.pyplot as plt # 导入 matplotlib.pyplot,用于绘制图形
  3. import pandas as pd # 导入 pandas,用于数据处理
  4. from datasets import load_dataset, load_metric # 从 datasets 库中导入 load_dataset 和 load_metric 函数
  5. from transformers import AutoModelForSeq2SeqLM, AutoTokenizer # 从 transformers 库中导入 AutoModelForSeq2SeqLM 和 AutoTokenizer
  6. # 加载 CNN/DailyMail 数据集,版本为 3.0.0
  7. dataset = load_dataset("cnn_dailymail", "3.0.0")
  8. # 加载 ROUGE 评价指标,用于计算文本摘要的质量
  9. rouge_metric = load_metric("rouge", cache_dir=None)
  10. # 定义要计算的 ROUGE 分数的名称列表
  11. rouge_names = ["rouge1", "rouge2", "rougeL", "rougeLsum"]

Só precisamos juntar as peças. Primeiro, avaliamos o desempenho do modelo de benchmark de três frases:

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

Em seguida, aplicamos a função a um subconjunto de dados. Como a parte de teste do conjunto de dados CNN/DailyMail contém aproximadamente 10.000 amostras, gerar resumos de todos esses artigos leva muito tempo. Lembre-se do Capítulo 5 que cada token gerado precisa ser transmitido através do modelo. A geração de 100 tokens por amostra exigiria 1 milhão de passes para frente e, se estivéssemos usando a pesquisa de feixe, esse número também precisaria ser multiplicado pelo número de feixes. Para tornar o cálculo mais rápido, subamostraremos o conjunto de teste e, por fim, usaremos 1.000 amostras para avaliação. Desta forma, podemos concluir a avaliação do modelo PEGASUS em menos de uma hora em uma única GPU e obter estimativas de pontuação estáveis:

  1. # 从测试集中随机抽取1000条样本,用于评估
  2. test_sampled = dataset["test"].shuffle(seed=42).select(range(1000))
  3. # 使用基线模型生成摘要并评估其质量
  4. score = evaluate_summaries_baseline(test_sampled, rouge_metric)
  5. # 将评价指标的分数存储在字典中
  6. rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
  7. # 将评价指标的分数转换为DataFrame格式,并转置以便显示
  8. pd.DataFrame.from_dict(rouge_dict, orient="index", columns=["baseline"]).T

resultado da operação:

 vermelho1vermelho2vermelhoLvermelhoLsum
linha de base0.389280.1712960.2450610.354239

As pontuações são em sua maioria piores que as do exemplo anterior, mas ainda melhores que as alcançadas pelo GPT-2! Agora seguimos o mesmo padrão para avaliar o modelo PEGASUS:

  1. # 导入 tqdm 模块,用于显示进度条
  2. from tqdm import tqdm
  3. # 导入 torch 模块,用于使用 GPU 或 CPU 进行计算
  4. import torch
  5. # 设置设备为 GPU(如果可用)或 CPU
  6. device = "cuda" if torch.cuda.is_available() else "cpu"
  7. def chunks(list_of_elements, batch_size):
  8. """将 list_of_elements 按 batch_size 切分成多个小块"""
  9. for i in range(0, len(list_of_elements), batch_size):
  10. yield list_of_elements[i : i + batch_size]
  11. def evaluate_summaries_pegasus(dataset, metric, model, tokenizer,
  12. batch_size=16, device=device,
  13. column_text="article",
  14. column_summary="highlights"):
  15. """评估使用 Pegasus 模型生成的摘要"""
  16. # 将文章和摘要分别按 batch_size 切分成多个小块
  17. article_batches = list(chunks(dataset[column_text], batch_size))
  18. target_batches = list(chunks(dataset[column_summary], batch_size))
  19. # 使用 tqdm 显示进度条,遍历每个文章批次和相应的摘要批次
  20. for article_batch, target_batch in tqdm(
  21. zip(article_batches, target_batches), total=len(article_batches)):
  22. # 对文章批次进行标记,将其转换为模型输入的张量
  23. inputs = tokenizer(article_batch, max_length=1024, truncation=True,
  24. padding="max_length", return_tensors="pt")
  25. # 使用 Pegasus 模型生成摘要
  26. summaries = model.generate(input_ids=inputs["input_ids"].to(device),
  27. attention_mask=inputs["attention_mask"].to(device),
  28. length_penalty=0.8, num_beams=8, max_length=128)
  29. # 解码生成的摘要,将其从张量转换为字符串
  30. decoded_summaries = [tokenizer.decode(s, skip_special_tokens=True,
  31. clean_up_tokenization_spaces=True)
  32. for s in summaries]
  33. decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
  34. # 将生成的摘要和目标摘要添加到评价指标中
  35. metric.add_batch(predictions=decoded_summaries, references=target_batch)
  36. # 计算评价指标分数
  37. score = metric.compute()
  38. return score

Vamos explicar esse código de avaliação em detalhes. Primeiro, dividimos o conjunto de dados em lotes menores para que possam ser processados ​​simultaneamente. Então, para cada lote, tokenizamos os artigos de entrada e os alimentamos na função generate() para gerar resumos usando a pesquisa de feixe. Usamos os mesmos parâmetros de geração do artigo. O novo comprimento do parâmetro de penalidade garante que o modelo não gere sequências muito longas.Por fim, decodificamos o texto gerado, substituindo<n> tokens e adicione o texto decodificado à métrica junto com o texto de referência. Por fim, calculamos e retornamos a pontuação ROUGE. Agora usamos novamente a classe AutoModelForSeq2SeqLM para a tarefa de geração seq2seq para carregar o modelo e avaliá-lo:

  1. # 从 transformers 库中导入用于序列到序列任务的模型和标记器
  2. from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
  3. # 设置模型检查点名称,使用 Google 的 PEGASUS 模型,预训练于 CNN/DailyMail 数据集
  4. model_ckpt = "google/pegasus-cnn_dailymail"
  5. # 从预训练的模型检查点中加载标记器和模型,并将模型移动到指定的设备(CPU 或 GPU)
  6. tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
  7. model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)
  8. # 使用评估函数 evaluate_summaries_pegasus 评估 PEGASUS 模型生成的摘要
  9. # 输入参数包括测试数据、ROUGE 评价指标、模型、标记器和批处理大小
  10. score = evaluate_summaries_pegasus(test_sampled, rouge_metric,
  11. model, tokenizer, batch_size=8)
  12. # 从评估结果中提取 ROUGE 分数,将其转换为字典格式,其中键为 ROUGE 指标名称,值为 F-measure 分数
  13. rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
  14. # 将 ROUGE 分数字典转换为 pandas 数据框,并以 "pegasus" 作为索引
  15. pd.DataFrame(rouge_dict, index=["pegasus"])

resultado da operação:

(O erro temporário é relatado aqui:

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

, os resultados em execução para referência usando exemplos são os seguintes)

 vermelho1vermelho2vermelhoLvermelhoLsum
pégaso0.434380.2108830.3071950.373231

Esses números estão muito próximos dos resultados do artigo. O importante a notar aqui é que a perda e a precisão de cada token estão um tanto dissociadas da pontuação ROUGE. A perda é independente da estratégia de decodificação, enquanto a pontuação ROUGE está fortemente acoplada.

Como ROUGE e BLEU alcançam melhor perda ou precisão do que a avaliação humana, você deve se concentrar neles ao construir modelos de geração de texto e explorar e selecionar cuidadosamente estratégias de decodificação. No entanto, estas métricas estão longe de ser perfeitas, pelo que a avaliação humana deve ser sempre considerada.

Agora que temos a função de avaliação, podemos treinar nosso próprio modelo de resumo.

Quatro,treinamentopráticaescolhaquerermofotipo

Neste ponto, já passamos por muitos detalhes de resumo e avaliação de texto, agora usamos esse conhecimento para treinar um modelo personalizado de resumo de texto! Para nosso aplicativo personalizado, usaremos o conjunto de dados SAMSum desenvolvido pela Samsung (oparaparape://oreeueu.eue/não1ggq ), este conjunto de dados contém uma série de conversas e breves resumos. Essas conversas podem representar interações entre clientes e call centers, gerando resumos precisos para ajudar a melhorar o atendimento ao cliente e detectar padrões comuns nas solicitações dos clientes. Vamos primeiro carregar o conjunto de dados e ver uma amostra:

  1. # 从 datasets 库中导入用于加载数据集的函数
  2. from datasets import load_dataset
  3. # 加载 SamSum 数据集,该数据集包含对话和相应的摘要
  4. dataset_samsum = load_dataset("samsum",trust_remote_code=True)
  5. # 获取数据集的每个划分(训练集、验证集、测试集)的长度,并存储在列表 split_lengths 中
  6. split_lengths = [len(dataset_samsum[split]) for split in dataset_samsum]
  7. # 打印每个数据集划分的长度
  8. print(f"Split lengths: {split_lengths}")
  9. # 打印训练集中列的名称(特征)
  10. print(f"Features: {dataset_samsum['train'].column_names}")
  11. # 打印测试集中第一个对话样本
  12. print("nDialogue:")
  13. print(dataset_samsum["test"][0]["dialogue"])
  14. # 打印测试集中第一个对话样本的摘要
  15. print("nSummary:")
  16. print(dataset_samsum["test"][0]["summary"])

(Nota: pode ser necessário instalar o py7zr, pip install py7zr)

resultado da operação:

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.

As conversas se parecem com as de um bate-papo por mensagem de texto ou WhatsApp, incluindo emojis e espaços reservados para GIFs. O campo de diálogo contém o texto completo, enquanto o campo de resumo é um resumo do diálogo. Um modelo ajustado no conjunto de dados CNN/DailyMail pode lidar com esse conjunto de dados? Vamos dar uma olhada!

1 comentárioestimativaPEGASvocêSexistirSAMSvocêeusuperiordesexocapaz

Primeiro, executaremos o mesmo processo de geração de resumo usando PEGASUS para ver o resultado. Podemos reutilizar o código gerado pelo resumo do CNN/DailyMail:

  1. # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
  2. pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
  3. # 打印生成的摘要标题
  4. print("Summary:")
  5. # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
  6. # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
  7. print(pipe_out[0]["summary_text"].replace(" .", ".n"))

resultado da operação:

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"

Podemos ver que o modelo tenta principalmente resumir extraindo frases-chave da conversa. Isso pode funcionar relativamente bem no conjunto de dados CNN/DailyMail, mas no SAMSum, o resumo é mais abstrato e o efeito não é necessariamente bom. Podemos confirmar isso executando a avaliação ROUGE completa no conjunto de testes:

  1. # 使用评估函数 evaluate_summaries_pegasus 对 SamSum 数据集的测试集进行摘要生成评估
  2. # 传入的参数包括数据集、评价指标、模型、tokenizer、文本列名、摘要列名和批量大小
  3. score = evaluate_summaries_pegasus(dataset_samsum["test"], rouge_metric, model,
  4. tokenizer, column_text="dialogue",
  5. column_summary="summary", batch_size=8)
  6. # 创建一个字典 rouge_dict,用于存储 ROUGE 评分的中值 F-measure 值
  7. rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
  8. # 将 ROUGE 评分字典转换为 Pandas 数据框,并以 "pegasus" 为索引
  9. pd.DataFrame(rouge_dict, index=["pegasus"])

resultado da operação:

(O erro temporário é relatado aqui:

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

, os resultados em execução para referência usando exemplos são os seguintes)

 vermelho1vermelho2vermelhoLvermelhoLsum
pégaso0.296170.0878030.2296040.229514

Embora os resultados não sejam bons, não é inesperado, pois está longe da distribuição de dados da CNN/DailyMail. No entanto, estabelecer o processo de avaliação antes da formação tem duas vantagens: podemos utilizar métricas diretamente para medir o sucesso da formação e temos uma boa base. O ajuste fino do modelo em nosso conjunto de dados deve melhorar imediatamente a métrica ROUGE. Se não houver melhoria, saberemos que há algo errado com nosso ciclo de treinamento.

2. MicroafinaçãoPEGASvocêS

Antes de treinarmos os dados, damos uma olhada rápida nas distribuições de comprimento de entrada e saída:

  1. # 编码训练集中的对话文本和摘要,并计算其长度
  2. d_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["dialogue"]]
  3. s_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["summary"]]
  4. # 创建一个包含两个子图的图形对象
  5. fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), sharey=True)
  6. # 绘制对话文本的长度分布直方图
  7. axes[0].hist(d_len, bins=20, color="C0", edgecolor="C0")
  8. axes[0].set_title("Dialogue Token Length")
  9. axes[0].set_xlabel("Length")
  10. axes[0].set_ylabel("Count")
  11. # 绘制摘要的长度分布直方图
  12. axes[1].hist(s_len, bins=20, color="C0", edgecolor="C0")
  13. axes[1].set_title("Summary Token Length")
  14. axes[1].set_xlabel("Length")
  15. # 调整子图布局,使其更加紧凑
  16. plt.tight_layout()
  17. # 显示绘制的图形
  18. plt.show()

resultado da operação:

(O erro temporário é relatado aqui:

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

, os resultados em execução para referência usando exemplos são os seguintes)

Podemos ver que a maioria das conversas são muito mais curtas do que os artigos da CNN/DailyMail, com cerca de 100 a 200 tokens cada. Da mesma forma, os resumos são muito mais curtos, cerca de 20 a 40 tokens (o mesmo comprimento de um tweet médio).

Vamos lembrar esses resultados primeiro, vamos usá-los mais tarde. Primeiro, precisamos tokenizar o conjunto de dados. Definimos a duração máxima do diálogo e do resumo em 1024 e 128, respectivamente:

  1. def convert_examples_to_features(example_batch):
  2. """
  3. 将示例批处理转换为模型输入特征。
  4. Args:
  5. - example_batch (dict): 包含对话和摘要的示例批处理字典。
  6. Returns:
  7. - dict: 包含转换后特征的字典,包括输入编码和目标编码。
  8. """
  9. # 对对话文本进行编码处理,生成输入编码
  10. input_encodings = tokenizer(example_batch["dialogue"], max_length=1024,
  11. truncation=True)
  12. # 使用目标编码器处理摘要文本,生成目标编码
  13. with tokenizer.as_target_tokenizer():
  14. target_encodings = tokenizer(example_batch["summary"], max_length=128,
  15. truncation=True)
  16. # 返回包含输入编码、目标标签和注意力掩码的字典
  17. return {
  18. "input_ids": input_encodings["input_ids"],
  19. "attention_mask": input_encodings["attention_mask"],
  20. "labels": target_encodings["input_ids"]
  21. }
  22. # 使用 map 方法将 SamSum 数据集转换为 PyTorch 格式
  23. dataset_samsum_pt = dataset_samsum.map(convert_examples_to_features,
  24. batched=True)
  25. # 设置数据集格式为 Torch 张量类型,并指定列名
  26. columns = ["input_ids", "labels", "attention_mask"]
  27. dataset_samsum_pt.set_format(type="torch", columns=columns)

resultado da operação:

(O erro temporário é relatado aqui:

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

Há uma novidade na etapa de tokenização: o contexto tokenizer.as_target_tokenizer(). Alguns modelos requerem tokens especiais na entrada do decodificador, por isso é importante separar as etapas de tokenização para as entradas do codificador e do decodificador. Dentro de uma instrução with (chamada de gerenciador de contexto), o tokenizer sabe que está tokenizando para o decodificador.

Agora precisamos criar o organizador de dados. Na maioria dos casos podemos usar o agrupamento padrão, que coleta todos os tensores em um lote e simplesmente os empilha. Para a tarefa de resumo, não precisamos apenas empilhar as entradas, mas também preparar os alvos no lado do decodificador. PEGASUS é um transformador codificador-decodificador e, portanto, possui uma arquitetura seq2seq clássica. Em uma configuração seq2seq, uma abordagem comum é aplicar forçamento do professor no decodificador. Ao usar esta estratégia, o decodificador recebe tokens de entrada (iguais a um modelo somente decodificador como o GPT-2), que são deslocados uma posição para a direita pela anotação, além da saída do codificador. Portanto, ao prever o próximo token, o decodificador obterá como entrada o valor verdadeiro deslocado uma posição para a direita, conforme mostrado na tabela a seguir:

  1. # 示例文本序列和标签生成过程
  2. text = ['PAD', 'Transformers', 'are', 'awesome', 'for', 'text', 'summarization']
  3. # 初始化存储每步结果的列表
  4. rows = []
  5. # 循环生成每步的数据行
  6. for i in range(len(text)-1):
  7. rows.append({
  8. 'step': i+1, # 步骤号,从1开始
  9. 'decoder_input': text[:i+1], # 解码器输入序列,从文本开始到当前位置
  10. 'label': text[i+1] # 标签,当前位置的下一个词
  11. })
  12. # 创建数据帧,并以步骤号作为索引
  13. pd.DataFrame(rows).set_index('step')

resultado da operação:

etapaentrada_decodificadorrótulo
1[ALMOFADA]Transformadores
2[PAD, Transformadores]são
3[PAD, Transformers, são]incrível
4[PAD, Transformers, são, incríveis]para
5[PAD, Transformers, são, incríveis, para]texto
6[PAD, Transformers, são, incríveis, para, texto]resumo

Nós o movemos uma posição para a direita para que o decodificador veja apenas a anotação correta anterior, e não as anotações atuais ou futuras. Apenas mudar é suficiente porque o decodificador possui um mecanismo de autoatenção mascarado que mascara todas as entradas atuais e futuras.

Portanto, ao preparar o lote, definimos a entrada para o decodificador movendo a anotação uma posição para a direita. Posteriormente, garantimos que os tokens de preenchimento na função de perda sejam ignorados, definindo-os como -100 na anotação. Na verdade, não precisamos executar essas etapas manualmente porque DataCollatorForSeq2Seq faz tudo para nós:

  1. # 导入 Seq2Seq 数据集整理器模块
  2. from transformers import DataCollatorForSeq2Seq
  3. # 创建 Seq2Seq 数据集整理器实例
  4. seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)

Então, como de costume, configuramos um TrainingArguments para treinamento:

  1. # 导入训练参数和训练器模块
  2. from transformers import TrainingArguments, Trainer
  3. # 定义训练参数
  4. training_args = TrainingArguments(
  5. output_dir='pegasus-samsum', # 模型输出目录
  6. num_train_epochs=1, # 训练的轮数
  7. warmup_steps=500, # 学习率预热步数
  8. per_device_train_batch_size=1, # 每个设备的训练批次大小
  9. per_device_eval_batch_size=1, # 每个设备的评估批次大小
  10. weight_decay=0.01, # 权重衰减率
  11. logging_steps=10, # 训练日志记录步数
  12. push_to_hub=True, # 是否推送到模型中心
  13. evaluation_strategy='steps', # 评估策略
  14. eval_steps=500, # 评估步数间隔
  15. save_steps=1e6, # 模型保存步数间隔
  16. gradient_accumulation_steps=16 # 梯度累积步数
  17. )

A diferença das configurações anteriores é que desta vez há um novo parâmetro gradiente_accumulation_steps. Como o modelo é muito grande, temos que definir o tamanho do lote como 1. No entanto, tamanhos de lote muito pequenos podem afetar a convergência. Para resolver esse problema, podemos usar um truque inteligente chamado acumulação de gradiente. Como o nome sugere, em vez de calcular os gradientes de todo o lote de uma vez, calculamos e agregamos os gradientes em lotes. Quando agregamos gradientes suficientes, executamos uma etapa de otimização. Isso é naturalmente mais lento do que fazer tudo de uma vez, mas nos economiza muita memória da GPU.

Agora, fazemos login no Hugging Face para que possamos enviar o modelo para o Hub após o treinamento:

  1. from huggingface_hub import notebook_login
  2. notebook_login()

resultado da operação:

Agora temos tudo o que precisamos para inicializar o treinador, incluindo o modelo, o tokenizer, os parâmetros de treinamento, os organizadores de dados e os conjuntos de dados de treinamento e avaliação:

  1. from transformers import TrainingArguments, Trainer
  2. # 创建一个 Trainer 实例用于训练序列到序列模型。
  3. trainer = Trainer(
  4. model=model, # 要训练的序列到序列模型
  5. args=training_args, # 定义的训练参数
  6. tokenizer=tokenizer, # 用于预处理输入数据的分词器
  7. data_collator=seq2seq_data_collator, # 用于批处理数据的数据整理器
  8. train_dataset=dataset_samsum_pt["train"], # 训练数据集
  9. eval_dataset=dataset_samsum_pt["validation"] # 评估数据集
  10. )

resultado da operação:

(O erro temporário é relatado aqui:

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

Estamos prontos para treinar. Assim que o treinamento for concluído, podemos executar a função de avaliação diretamente no conjunto de teste para ver o desempenho do modelo:

  1. from transformers import TrainingArguments, Trainer
  2. # 开始训练模型
  3. trainer.train()
  4. # 使用评估函数评估 Pegasus 模型的摘要质量
  5. score = evaluate_summaries_pegasus(
  6. dataset_samsum["test"], rouge_metric, trainer.model, tokenizer,
  7. batch_size=2, column_text="dialogue", column_summary="summary")
  8. # 提取 ROUGE 指标结果
  9. rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
  10. # 创建 DataFrame 显示 ROUGE 指标
  11. pd.DataFrame(rouge_dict, index=[f"pegasus"])

resultado da operação:

(O erro temporário é relatado aqui:

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

, os resultados em execução para referência usando exemplos são os seguintes)

 vermelho1vermelho2vermelhoLvermelhoLsum
pégaso0.427610.2005710.3406480.340738

Podemos ver que a pontuação ROUGE melhorou significativamente em relação ao modelo sem ajuste fino, portanto, embora o modelo anterior também tenha sido treinado para geração de resumos, ele não se adaptou bem ao novo domínio. Vamos enviar nosso modelo para o Hub:

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

A seguir usaremos este modelo para gerar alguns resumos para nós.

Você também pode avaliar os resultados gerados como parte de um loop de treinamento: use a extensão TrainingArguments chamada Seq2SeqTrainingArguments e especifique predict_with_generate=True. Passe isso para um instrutor dedicado chamado Seq2SeqTrainer, que usa a função generate() em vez de uma passagem direta do modelo para criar previsões para avaliação. De uma chance!

3. Gerarcertofalarescolhaquerer

Olhando para as pontuações de perda e ROUGE, o modelo parece mostrar uma melhoria significativa em relação ao modelo original treinado apenas na CNN/DailyMail. Um resumo gerado a partir de uma amostra no conjunto de teste é semelhante a este:

  1. import transformers
  2. # 设置transformers的日志级别为错误,以减少输出日志
  3. transformers.logging.set_verbosity_error()
  4. # 定义生成摘要时的参数
  5. gen_kwargs = {"length_penalty": 0.8, "num_beams": 8, "max_length": 128}
  6. # 从测试集中选择一个示例
  7. sample_text = dataset_samsum["test"][0]["dialogue"]
  8. reference = dataset_samsum["test"][0]["summary"]
  9. # 使用预训练的pegasus-samsum模型创建摘要管道
  10. pipe = pipeline("summarization", model="transformersbook/pegasus-samsum")
  11. # 输出对话和参考摘要
  12. print("Dialogue:")
  13. print(sample_text)
  14. print("nReference Summary:")
  15. print(reference)
  16. # 使用模型生成摘要并输出
  17. print("nModel Summary:")
  18. print(pipe(sample_text, **gen_kwargs)[0]["summary_text"])

resultado da operação:

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.

Isso é muito semelhante a um resumo de referência. Parece que o modelo aprendeu a sintetizar conversas em resumos, em vez de apenas extrair trechos. Agora, para o teste final: qual é o desempenho do modelo em entradas personalizadas?

  1. # 自定义对话示例
  2. custom_dialogue = """
  3. Thom: Hi guys, have you heard of transformers?
  4. Lewis: Yes, I used them recently!
  5. Leandro: Indeed, there is a great library by Hugging Face.
  6. Thom: I know, I helped build it ;)
  7. Lewis: Cool, maybe we should write a book about it. What do you think?
  8. Leandro: Great idea, how hard can it be?!
  9. Thom: I am in!
  10. Lewis: Awesome, let's do it together!
  11. """
  12. # 使用预训练的pegasus-samsum模型生成摘要,并输出摘要结果
  13. print(pipe(custom_dialogue, **gen_kwargs)[0]["summary_text"])

resultado da operação:

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.

O resumo da conversa personalizado gerado faz sentido. Ele faz um bom trabalho ao resumir o que todos na discussão queriam escrever em um livro juntos, em vez de apenas extrair uma única frase. Por exemplo, combina as linhas 3 e 4 em uma combinação lógica.