2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Table des matières
3. Évaluez PEGASUS sur l'ensemble de données CNN/DailyMail
4. Modèle de synthèse de formation
1. Évaluer les performances de PEGASUS sur SAMSum
3. Générer un résumé de la conversation
AGI, ou Artificial General Intelligence, est un système d’intelligence artificielle doté de niveaux d’intelligence humaine. Il peut non seulement effectuer des tâches spécifiques, mais également comprendre, apprendre et appliquer des connaissances pour résoudre un large éventail de problèmes, avec une grande autonomie et adaptabilité. Les capacités d'AGI incluent, sans s'y limiter, l'auto-apprentissage, l'auto-amélioration, l'auto-ajustement et la capacité de résoudre divers problèmes complexes sans intervention humaine.
- Ce que AGI peut faire est très vaste :
Exécution de tâches inter-domaines : AGI peut gérer des tâches dans plusieurs domaines et ne se limite pas à des scénarios d'application spécifiques.
Apprentissage autonome et adaptation : AGI peut apprendre de l’expérience et s’adapter à de nouveaux environnements et situations.
Pensée créative : AGI est capable de penser de manière innovante et de proposer de nouvelles solutions.
Interaction sociale : AGI est capable d'interactions sociales complexes avec les humains et comprend les signaux émotionnels et sociaux.
- Concernant les perspectives de développement futur de l’AGI, elle est considérée comme l’un des objectifs ultimes de la recherche sur l’intelligence artificielle et présente un énorme potentiel de changement :
Innovation technologique : avec l'avancement des technologies telles que l'apprentissage automatique et les réseaux de neurones, la réalisation de l'AGI pourrait se rapprocher.
Intégration interdisciplinaire : la mise en œuvre de l'AGI nécessite l'intégration des connaissances de plusieurs disciplines telles que l'informatique, les neurosciences et la psychologie.
Considérations éthiques et sociales : le développement de l'AGI nécessite la prise en compte de questions éthiques et sociales telles que la vie privée, la sécurité et l'emploi.
Capacités d’apprentissage et d’adaptation améliorées : les futurs systèmes AGI pourraient utiliser des algorithmes avancés pour apprendre de l’environnement et optimiser le comportement.
Interaction multimodale : AGI disposera de plusieurs méthodes de perception et d'interaction pour interagir avec les humains et d'autres systèmes.
En tant que l'une des communautés et plateformes d'apprentissage automatique open source les plus populaires au monde, Hugging Face joue un rôle important à l'ère de l'AGI. Il fournit de riches ressources de modèles et d'ensembles de données pré-entraînés, favorisant le développement du domaine de l'apprentissage automatique. Hugging Face se caractérise par sa facilité d'utilisation et son ouverture. Grâce à sa bibliothèque Transformers, il offre aux utilisateurs un moyen pratique pour les modèles de traiter le texte. Avec le développement de la technologie de l'IA, la communauté Hugging Face continuera à jouer un rôle important dans la promotion du développement et de l'application de la technologie de l'IA, en particulier dans le développement de la technologie d'IA multimodale. La communauté Hugging Face élargira la diversité de ses modèles. et des ensembles de données, y compris des données multimodales telles que des images, de l'audio et de la vidéo.
- À l’ère de l’AGI, Hugging Face pourrait entrer en jeu des manières suivantes :
Partage de modèles : en tant que plateforme de partage de modèles, Hugging Face continuera à promouvoir le partage et la collaboration de modèles AGI avancés.
Écosystème open source : L’écosystème open source de Hugging Face contribuera à accélérer le développement et l’innovation de la technologie AGI.
Outils et services : Fournir une multitude d'outils et de services pour soutenir les développeurs et les chercheurs dans leurs recherches et applications dans le domaine de l'AGI.
Éthique et responsabilité sociale : Hugging Face se concentre sur l'éthique de l'IA et favorisera le développement et l'application de modèles AGI responsables pour garantir le progrès technologique tout en respectant les normes éthiques.
L'AGI, en tant que forme avancée d'intelligence artificielle du futur, a de larges perspectives d'application, et Hugging Face, en tant que communauté open source, jouera un rôle clé dans la promotion du développement et de l'application de l'AGI.
(Remarque : le code suivant peut nécessiter un accès scientifique à Internet pour s'exécuter)
Vous avez peut-être dû résumer un document, notamment un article de recherche, un rapport sur les résultats financiers ou une série de courriels. Si vous y réfléchissez, cela nécessite une gamme de capacités, notamment comprendre un contenu long, raisonner sur le contenu, puis produire un texte fluide qui englobe les thèmes principaux du document original. De plus, résumer avec précision un article d’actualité est très différent du résumé d’un contrat juridique et nécessite donc des capacités complexes de généralisation de domaine. Pour ces raisons, résumer un texte (le terme technique est résumé de texte) est une tâche difficile pour les modèles de langage neuronal, y compris les modèles Transformer. Malgré ces défis, le résumé de texte peut accélérer considérablement le flux de travail des experts du domaine. Les entreprises peuvent utiliser le résumé de texte pour condenser les connaissances internes, résumer les contrats, générer automatiquement du contenu de publication sur les réseaux sociaux, etc. Par conséquent, la tâche PNL de synthèse de texte est précieuse.
Pour vous aider à comprendre les défis, cette section explique comment exploiter les modèles pré-entraînés de Transformer pour la synthèse de texte. La synthèse est une tâche classique de séquence à séquence (seq2seq) qui nécessite la saisie d'un texte et d'un texte cible.
Le résumé de texte est une tâche de traitement du langage naturel dont le but est d'extraire des informations concises et importantes d'un texte long et de générer une version courte. Le résumé de texte peut être divisé en deux types principaux : le résumé extractif et le résumé génératif.
- Résumé extractif
Le résumé extractif sélectionne les phrases ou paragraphes importants du texte original et extrait directement ces contenus sous forme de résumés. Cette méthode ne modifie pas les mots et la structure des phrases dans le texte original.
Principe de mise en œuvre :
- Extraction de fonctionnalités : tout d'abord, diverses caractéristiques du texte doivent être extraites, telles que la fréquence des mots, la position de la phrase, les mots-clés, les entités nommées, etc.
- Score d'importance : sur la base des caractéristiques extraites, un score est calculé pour chaque phrase afin de déterminer son importance.
- Sélection de phrases : sur la base du score d'importance, les phrases les plus importantes sont sélectionnées pour construire le résumé.
difficulté:
- Mesure de l'importance : Comment mesurer avec précision l'importance relative des phrases.
- Élimination des redondances : évitez de sélectionner des phrases dont le contenu est répété.
Méthode pour réaliser :
- Approche basée sur des règles : utilise des règles prédéfinies et des méthodes statistiques pour sélectionner des phrases.
- Méthode d'apprentissage automatique : utilisez des algorithmes d'apprentissage supervisé pour apprendre à sélectionner des phrases importantes en fonction des données d'entraînement.
- Résumé génératif
Le résumé génératif fonctionne en comprenant le texte original et en générant de nouvelles phrases pour résumer son contenu. Cette approche crée un résumé plus naturel et cohérent, mais est également plus complexe.
Principe de mise en œuvre :
- Architecture encodeur-décodeur : utilise un modèle séquence à séquence (Seq2Seq), dans lequel l'encodeur encode le texte d'entrée dans des vecteurs de contexte et le décodeur génère des résumés basés sur les vecteurs de contexte.
- Mécanisme d'attention : pendant le processus de décodage, le modèle peut se concentrer sur différentes parties du texte saisi pour générer un contenu plus pertinent.
- Modèle pré-entraîné : utilisez des modèles de langage pré-entraînés (tels que BERT, GPT, etc.) pour améliorer la qualité des résumés générés.
difficulté:
- Cohérence du contenu : le résumé généré doit maintenir une cohérence logique et éviter les ruptures de contenu.
- Intégrité des informations : garantit que le résumé généré contient des informations clés du texte original.
- Complexité du modèle : les modèles de synthèse génératifs sont généralement plus complexes que les modèles de synthèse extractifs et nécessitent plus de ressources informatiques et de données de formation.
Méthode pour réaliser :
- Modèle Seq2Seq classique : tel que le modèle codeur-décodeur basé sur LSTM.
- Modèles de transformateurs pré-entraînés : tels que BERTSUM, T5, BART, etc.
- Résumé du texte dans Hugging Face
Hugging Face fournit une variété de modèles et d'outils pré-entraînés pour mettre en œuvre facilement des tâches de résumé de texte. Voici quelques modèles de résumé de texte couramment utilisés et comment les utiliser :
- Récapitulatif à l'aide de modèles pré-entraînés
Voici un exemple de code pour le résumé de texte à l'aide du modèle BART fourni par Hugging Face :
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)
- Modèles de résumé pris en charge
Hugging Face propose une variété de modèles pré-entraînés pour la synthèse de texte, notamment, mais sans s'y limiter :
- BART (facebook/bart-large-cnn)
- T5 (t5-petit, t5-base, t5-grand, t5-3b, t5-11b)
- PÉGASE (google/pegasus-xsum, google/pegasus-cnn_dailymail)
- Entraînez votre propre modèle de synthèse
Si vous avez besoin de mieux vous adapter aux tâches de résumé de texte spécifiques à un domaine, vous pouvez affiner le modèle pré-entraîné à l'aide de votre propre ensemble de données. Voici un exemple simple de réglage fin :
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()Le résumé de texte est une tâche de traitement du langage naturel complexe et difficile. En utilisant les modèles et outils pré-entraînés fournis par Hugging Face, le processus de mise en œuvre du résumé de texte peut être considérablement simplifié. Les utilisateurs peuvent sélectionner le modèle approprié en fonction de besoins spécifiques et l'affiner pour obtenir le meilleur effet récapitulatif.
Dans cette section, nous allons construire notre propre modèle d'encodeur-décodeur pour compresser les conversations à plusieurs personnes en résumés concis. Mais avant cela, intéressons-nous à un ensemble de données classique dans le domaine du résumé : le corpus CNN/DailyMail.
Les conditions sont désormais réunies pour évaluer pleinement le modèle : nous disposons de l'ensemble de données de test CNN/DailyMail, de la métrique ROUGE pour l'évaluation et d'un modèle récapitulatif.
- # 导入所需的库
- 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"]
Il nous suffit de rassembler les pièces. Tout d’abord, nous évaluons les performances du modèle de référence en trois phrases :
- # 定义一个函数,用于评估基线模型生成的摘要
- 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
Nous appliquons ensuite la fonction à un sous-ensemble de données. Étant donné que la partie test de l’ensemble de données CNN/DailyMail contient environ 10 000 échantillons, générer des résumés de tous ces articles prend beaucoup de temps. Rappelez-vous du chapitre 5 que chaque jeton généré doit être transmis à travers le modèle. Générer 100 jetons par échantillon nécessiterait 1 million de passes avant, et si nous utilisions la recherche de faisceaux, ce nombre devrait également être multiplié par le nombre de faisceaux. Pour accélérer le calcul, nous sous-échantillonnerons l'ensemble de test et utiliserons finalement 1 000 échantillons pour l'évaluation. De cette manière, nous pouvons compléter l'évaluation du modèle PEGASUS en moins d'une heure sur un seul GPU et obtenir des estimations de score stables :
- # 从测试集中随机抽取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
résultat de l'opération :
rouge1 | rouge2 | rougeL | rougeLsum | |
ligne de base | 0.38928 | 0.171296 | 0.245061 | 0.354239 |
Les scores sont pour la plupart moins bons que l’exemple précédent, mais toujours meilleurs que ceux obtenus par GPT-2 ! Nous suivons maintenant le même schéma pour évaluer le modèle 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
Expliquons ce code d'évaluation en détail. Tout d’abord, nous divisons l’ensemble de données en lots plus petits afin qu’ils puissent être traités simultanément. Ensuite, pour chaque lot, nous tokenisons les articles d'entrée et les transmettons à la fonction generate() pour générer des résumés à l'aide de la recherche par faisceau. Nous utilisons les mêmes paramètres de génération que dans l'article. La nouvelle longueur du paramètre de pénalité garantit que le modèle ne génère pas de séquences trop longues.Enfin, nous décodons le texte résultant en remplaçant<n> jetons et ajoutez le texte décodé à la métrique avec le texte de référence. Enfin, nous calculons et renvoyons le score ROUGE. Nous utilisons maintenant à nouveau la classe AutoModelForSeq2SeqLM pour la tâche de génération seq2seq afin de charger le modèle et de l'évaluer :
- # 从 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"])
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, les résultats d'exécution pour référence à l'aide d'exemples sont les suivants)
rouge1 | rouge2 | rougeL | rougeLsum | |
Pégase | 0.43438 | 0.210883 | 0.307195 | 0.373231 |
Ces chiffres sont très proches des résultats de l’article. La chose importante à noter ici est que la perte et la précision de chaque jeton sont quelque peu découplées du score ROUGE. La perte est indépendante de la stratégie de décodage, alors que le score ROUGE est fortement couplé.
Étant donné que ROUGE et BLEU obtiennent une meilleure perte ou précision que l'évaluation humaine, vous devez vous concentrer sur eux lors de la construction de modèles de génération de texte et explorer et sélectionner soigneusement les stratégies de décodage. Cependant, ces mesures sont loin d’être parfaites, c’est pourquoi une évaluation humaine doit toujours être prise en compte.
Maintenant que nous disposons de la fonction d'évaluation, nous pouvons former notre propre modèle de synthèse.
À ce stade, nous avons parcouru de nombreux détails de résumé et d'évaluation de texte, nous utilisons maintenant ces connaissances pour former un modèle de résumé de texte personnalisé ! Pour notre application personnalisée, nous utiliserons l'ensemble de données SAMSum développé par Samsung (httpm://ouletjel.let/n1ggq ), cet ensemble de données contient une série de conversations et de courts résumés. Ces conversations peuvent représenter les interactions entre les clients et les centres d'appels, générant des résumés précis pour aider à améliorer le service client et à détecter les modèles courants dans les demandes des clients. Chargeons d'abord l'ensemble de données et visualisons un exemple :
- # 从 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"])
(Remarque : vous devrez peut-être installer py7zr, pip install py7zr)
résultat de l'opération :
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.
Les conversations ressemblent à celles que vous discuteriez via un message texte ou WhatsApp, y compris des émojis et des espaces réservés pour les GIF. Le champ de dialogue contient le texte complet, tandis que le champ de résumé est un résumé du dialogue. Un modèle affiné sur l'ensemble de données CNN/DailyMail peut-il gérer cet ensemble de données ? Nous allons jeter un coup d'oeil!
Tout d’abord, nous exécuterons le même processus de génération de résumé en utilisant PEGASUS pour voir le résultat. Nous pouvons réutiliser le code généré par le résumé CNN/DailyMail :
- # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
- pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
-
- # 打印生成的摘要标题
- print("Summary:")
-
- # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
- # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
- print(pipe_out[0]["summary_text"].replace(" .", ".n"))
résultat de l'opération :
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"
On voit que le modèle tente principalement de résumer en extrayant des phrases clés de la conversation. Cela peut fonctionner relativement bien sur l'ensemble de données CNN/DailyMail, mais dans SAMSum, le résumé est plus abstrait et l'effet peut ne pas être bon. Nous pouvons le confirmer en exécutant l’évaluation complète de ROUGE sur l’ensemble de test :
- # 使用评估函数 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"])
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, les résultats d'exécution pour référence à l'aide d'exemples sont les suivants)
rouge1 | rouge2 | rougeL | rougeLsum | |
Pégase | 0.29617 | 0.087803 | 0.229604 | 0.229514 |
Bien que les résultats ne soient pas excellents, ils ne sont pas inattendus car ils sont très éloignés de la distribution des données de CNN/DailyMail. Néanmoins, mettre en place le processus d’évaluation avant la formation présente deux avantages : nous pouvons utiliser directement des métriques pour mesurer le succès de la formation, et nous disposons d’une bonne base de référence. Affiner le modèle sur notre ensemble de données devrait immédiatement améliorer la métrique ROUGE, s'il n'y a pas d'amélioration, nous savons qu'il y a quelque chose qui ne va pas avec notre boucle de formation.
Avant de nous entraîner sur les données, nous examinons rapidement les distributions de longueur d'entrée et de sortie :
- # 编码训练集中的对话文本和摘要,并计算其长度
- 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()
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, les résultats d'exécution pour référence à l'aide d'exemples sont les suivants)
Nous pouvons constater que la plupart des conversations sont beaucoup plus courtes que les articles de CNN/DailyMail, avec environ 100 à 200 tokens chacune. De même, les résumés sont beaucoup plus courts, environ 20 à 40 tokens (la même longueur que le tweet moyen).
Rappelons d'abord ces résultats, nous les utiliserons plus tard. Tout d’abord, nous devons tokeniser l’ensemble de données. Nous fixons la durée maximale du dialogue et du résumé à 1024 et 128 respectivement :
- 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)
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Il y a une nouveauté dans l'étape de tokenisation : le contexte tokenizer.as_target_tokenizer(). Certains modèles nécessitent des jetons spéciaux dans l'entrée du décodeur, il est donc important de séparer les étapes de tokenisation pour les entrées du codeur et du décodeur. Dans une instruction with (appelée gestionnaire de contexte), le tokeniseur sait qu'il effectue une tokenisation pour le décodeur.
Maintenant, nous devons créer l'organisateur de données. Dans la plupart des cas, nous pouvons utiliser l'assembleur par défaut, qui collecte tous les tenseurs dans un lot et les empile simplement. Pour la tâche de récapitulation, nous devons non seulement empiler les entrées, mais également préparer les cibles côté décodeur. PEGASUS est un Transformateur codeur-décodeur et possède donc une architecture seq2seq classique. Dans un environnement seq2seq, une approche courante consiste à appliquer le forçage d'enseignant dans le décodeur. Lors de l'utilisation de cette stratégie, le décodeur reçoit des jetons d'entrée (identiques à un modèle de décodeur uniquement tel que GPT-2), qui sont décalés d'une position vers la droite par l'annotation, en plus de la sortie de l'encodeur. Par conséquent, lors de la prédiction du prochain jeton, le décodeur obtiendra en entrée la vraie valeur décalée d'une position vers la droite, comme indiqué dans le tableau suivant :
- # 示例文本序列和标签生成过程
- 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')
résultat de l'opération :
étape | décodeur_entrée | étiquette |
1 | [TAMPON] | Transformateurs |
2 | [PAD, Transformateurs] | sont |
3 | [PAD, Transformers, sont] | génial |
4 | [PAD, Transformers, sont, géniaux] | pour |
5 | [PAD, Transformers, sont, géniaux, pour] | texte |
6 | [PAD, Les Transformers, sont, géniaux, pour, le, texte] | récapitulation |
Nous le déplaçons d'une position vers la droite afin que le décodeur ne voie que l'annotation correcte précédente, pas les annotations actuelles ou futures. Un simple décalage suffit car le décodeur dispose d'un mécanisme d'auto-attention masqué qui masque toutes les entrées actuelles et futures.
Par conséquent, lors de la préparation du lot, nous définissons l'entrée du décodeur en déplaçant l'annotation d'une position vers la droite. Ensuite, nous nous assurons que les jetons de remplissage dans la fonction de perte sont ignorés en les définissant à -100 dans l'annotation. En fait, nous n'avons pas besoin d'effectuer ces étapes manuellement car DataCollatorForSeq2Seq fait tout pour nous :
- # 导入 Seq2Seq 数据集整理器模块
- from transformers import DataCollatorForSeq2Seq
-
- # 创建 Seq2Seq 数据集整理器实例
- seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
Ensuite, comme d'habitude, nous mettons en place un TrainingArguments pour la formation :
- # 导入训练参数和训练器模块
- 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 # 梯度累积步数
- )
La différence avec les paramètres précédents est que cette fois il y a un nouveau paramètre gradient_accumulation_steps. Le modèle étant très grand, nous devons définir la taille du lot sur 1. Cependant, des tailles de lots trop petites peuvent affecter la convergence. Pour résoudre ce problème, nous pouvons utiliser une astuce astucieuse appelée accumulation de gradient. Comme son nom l'indique, au lieu de calculer les dégradés pour l'ensemble du lot en une seule fois, nous calculons et regroupons les dégradés par lots. Lorsque nous avons agrégé suffisamment de dégradés, nous effectuons une étape d'optimisation. C'est naturellement plus lent que de tout faire en une seule fois, mais cela nous permet d'économiser beaucoup de mémoire GPU.
Maintenant, nous nous connectons à Hugging Face afin de pouvoir pousser le modèle vers le Hub après la formation :
- from huggingface_hub import notebook_login
-
- notebook_login()
résultat de l'opération :
Nous avons désormais tout ce dont nous avons besoin pour initialiser le formateur, y compris le modèle, le tokenizer, les paramètres de formation, les organisateurs de données et les ensembles de données de formation et d'évaluation :
- 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"] # 评估数据集
- )
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Nous sommes prêts à nous entraîner. Une fois la formation terminée, nous pouvons exécuter la fonction d'évaluation directement sur l'ensemble de test pour voir comment le modèle a fonctionné :
- 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"])
résultat de l'opération :
(Une erreur temporaire est signalée ici :
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, les résultats d'exécution pour référence à l'aide d'exemples sont les suivants)
rouge1 | rouge2 | rougeL | rougeLsum | |
Pégase | 0.42761 | 0.200571 | 0.340648 | 0.340738 |
Nous pouvons voir que le score ROUGE est significativement amélioré par rapport au modèle sans ajustement fin, donc bien que le modèle précédent ait également été entraîné pour la génération de résumés, il ne s'est pas bien adapté au nouveau domaine. Poussons notre modèle vers Hub :
- # 将训练完成的模型推送到 Hub 上
- trainer.push_to_hub("Training complete!")
Nous utiliserons ensuite ce modèle pour générer des résumés pour nous.
Vous pouvez également évaluer les résultats générés dans le cadre d'une boucle d'entraînement : utilisez l'extension TrainingArguments appelée Seq2SeqTrainingArguments et spécifiez prédict_with_generate=True. Transmettez-le à un formateur dédié appelé Seq2SeqTrainer, qui utilise la fonction generate() au lieu d'une transmission directe du modèle pour créer des prédictions à évaluer. Essaie!
En regardant la perte et les scores ROUGE, le modèle semble montrer une amélioration significative par rapport au modèle original formé uniquement sur CNN/DailyMail. Un résumé généré à partir d'un échantillon de l'ensemble de test ressemble à ceci :
- 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"])
résultat de l'opération :
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.
Ceci est très similaire à un résumé de référence. Il semble que le modèle ait appris à synthétiser les conversations en résumés au lieu de simplement en extraire des passages. Passons maintenant au test final : comment le modèle fonctionne-t-il sur les entrées personnalisées ?
- # 自定义对话示例
- 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"])
résultat de l'opération :
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.
Le résumé de conversation personnalisé généré est logique. Il résume bien ce sur quoi tous les participants à la discussion voulaient écrire un livre ensemble, plutôt que de simplement extraire une seule phrase. Par exemple, il combine les lignes 3 et 4 en une seule combinaison logique.