2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Inhaltsverzeichnis
3. Bewerten Sie PEGASUS anhand des CNN/DailyMail-Datensatzes
4. Trainingszusammenfassungsmodell
1. Bewerten Sie die Leistung von PEGASUS auf SAMSum
3. Erstellen Sie eine Gesprächszusammenfassung
AGI, oder Artificial General Intelligence, ist ein künstliches Intelligenzsystem mit menschlichem Intelligenzniveau. Es kann nicht nur bestimmte Aufgaben ausführen, sondern auch Wissen verstehen, lernen und anwenden, um ein breites Spektrum von Problemen zu lösen, und das mit hoher Autonomie und Anpassungsfähigkeit. Zu den Fähigkeiten von AGI gehören unter anderem Selbstlernen, Selbstverbesserung, Selbstanpassung und die Fähigkeit, verschiedene komplexe Probleme ohne menschliches Eingreifen zu lösen.
- Was AGI leisten kann, ist sehr umfassend:
Domänenübergreifende Aufgabenausführung: AGI kann Aufgaben in mehreren Domänen verarbeiten und ist nicht auf bestimmte Anwendungsszenarien beschränkt.
Autonomes Lernen und Anpassung: AGI kann aus Erfahrungen lernen und sich an neue Umgebungen und Situationen anpassen.
Kreatives Denken: AGI ist in der Lage, innovativ zu denken und neue Lösungen zu finden.
Soziale Interaktion: AGI ist zu komplexen sozialen Interaktionen mit Menschen fähig und versteht emotionale und soziale Signale.
- Was die zukünftigen Entwicklungsaussichten von AGI betrifft, gilt es als eines der ultimativen Ziele der Forschung im Bereich der künstlichen Intelligenz und birgt großes Potenzial für Veränderungen:
Technologische Innovation: Mit der Weiterentwicklung von Technologien wie maschinellem Lernen und neuronalen Netzen rückt die Verwirklichung von AGI möglicherweise näher.
Interdisziplinäre Integration: Die Implementierung von AGI erfordert die Integration von Wissen aus mehreren Disziplinen wie Informatik, Neurowissenschaften und Psychologie.
Ethische und soziale Überlegungen: Die Entwicklung von AGI erfordert die Berücksichtigung ethischer und sozialer Fragen wie Privatsphäre, Sicherheit und Beschäftigung.
Verbesserte Lern- und Anpassungsfähigkeiten: Zukünftige AGI-Systeme können fortschrittliche Algorithmen verwenden, um von der Umgebung zu lernen und das Verhalten zu optimieren.
Multimodale Interaktion: AGI wird über mehrere Wahrnehmungs- und Interaktionsmethoden verfügen, um mit Menschen und anderen Systemen zu interagieren.
Als eine der beliebtesten Open-Source-Communitys und Plattformen für maschinelles Lernen weltweit spielt Hugging Face eine wichtige Rolle in der AGI-Ära. Es bietet umfangreiche Ressourcen an vorab trainierten Modellen und Datensätzen und fördert so die Entwicklung des Bereichs maschinelles Lernen. Hugging Face zeichnet sich durch Benutzerfreundlichkeit und Offenheit aus. Durch seine Transformers-Bibliothek bietet es Benutzern eine bequeme Möglichkeit für Modelle, Text zu verarbeiten. Mit der Entwicklung der KI-Technologie wird die Hugging Face-Community weiterhin eine wichtige Rolle bei der Förderung der Entwicklung und Anwendung der KI-Technologie spielen, insbesondere bei der Entwicklung der multimodalen KI-Technologie wird die Hugging Face-Community die Vielfalt ihrer Modelle erweitern und Datensätze, einschließlich multimodaler Daten wie Bilder, Audio und Video.
- Im Zeitalter von AGI könnte Hugging Face auf folgende Weise ins Spiel kommen:
Model-Sharing: Als Model-Sharing-Plattform wird Hugging Face weiterhin den Austausch und die Zusammenarbeit fortschrittlicher AGI-Modelle fördern.
Open-Source-Ökosystem: Das Open-Source-Ökosystem von Hugging Face wird dazu beitragen, die Entwicklung und Innovation der AGI-Technologie zu beschleunigen.
Tools und Dienste: Bereitstellung einer Fülle von Tools und Diensten zur Unterstützung von Entwicklern und Forschern bei ihrer Forschung und Anwendung im AGI-Bereich.
Ethik und soziale Verantwortung: Hugging Face konzentriert sich auf KI-Ethik und wird die Entwicklung und Anwendung verantwortungsvoller AGI-Modelle fördern, um den technologischen Fortschritt bei gleichzeitiger Einhaltung ethischer Standards sicherzustellen.
AGI hat als fortschrittliche Form der künstlichen Intelligenz in der Zukunft breite Anwendungsaussichten, und Hugging Face wird als Open-Source-Community eine Schlüsselrolle bei der Förderung der Entwicklung und Anwendung von AGI spielen.
(Hinweis: Für die Ausführung des folgenden Codes ist möglicherweise ein wissenschaftlicher Internetzugang erforderlich.)
Möglicherweise mussten Sie ein Dokument zusammenfassen, einschließlich eines Forschungsartikels, eines Finanzberichts oder einer Reihe von E-Mails. Wenn Sie darüber nachdenken, erfordert dies eine Reihe von Fähigkeiten, darunter das Verstehen langer Inhalte, das Nachdenken über den Inhalt und das anschließende Verfassen eines flüssigen Textes, der die Hauptthemen des Originaldokuments umfasst. Darüber hinaus unterscheidet sich die genaue Zusammenfassung eines Nachrichtenartikels stark von der Zusammenfassung eines Rechtsvertrags und erfordert daher komplexe Funktionen zur Domänenverallgemeinerung. Aus diesen Gründen ist das Zusammenfassen von Text (der Fachbegriff lautet Textzusammenfassung) eine schwierige Aufgabe für neuronale Sprachmodelle, einschließlich Transformer-Modellen. Trotz dieser Herausforderungen kann die Textzusammenfassung den Arbeitsablauf von Fachexperten erheblich beschleunigen. Unternehmen können die Textzusammenfassung nutzen, um internes Wissen zu verdichten, Verträge zusammenzufassen, automatisch Inhalte für die Veröffentlichung in sozialen Medien zu generieren usw. Daher ist die NLP-Aufgabe zur Textzusammenfassung wertvoll.
Um Ihnen das Verständnis der Herausforderungen zu erleichtern, wird in diesem Abschnitt erläutert, wie Sie vorab trainierte Transformer-Modelle für die Textzusammenfassung nutzen können. Die Zusammenfassung ist eine klassische Sequenz-zu-Sequenz-Aufgabe (seq2seq), die Eingabetext und Zieltext erfordert.
Die Textzusammenfassung ist eine Aufgabe zur Verarbeitung natürlicher Sprache, deren Ziel darin besteht, prägnante und wichtige Informationen aus einem langen Text zu extrahieren und eine kurze Version zu erstellen. Die Textzusammenfassung kann in zwei Haupttypen unterteilt werden: extraktive Zusammenfassung und generative Zusammenfassung.
- Extraktive Zusammenfassung
Die extraktive Zusammenfassung wählt wichtige Sätze oder Absätze im Originaltext aus und extrahiert diese Inhalte direkt als Zusammenfassungen. Durch diese Methode werden die Wörter und die Satzstruktur im Originaltext nicht verändert.
Umsetzungsprinzip:
- Merkmalsextraktion: Zunächst müssen verschiedene Merkmale des Textes extrahiert werden, wie z. B. Worthäufigkeit, Satzposition, Schlüsselwörter, benannte Entitäten usw.
- Wichtigkeitsbewertung: Basierend auf den extrahierten Merkmalen wird für jeden Satz eine Bewertung berechnet, um seine Wichtigkeit zu bestimmen.
- Satzauswahl: Basierend auf der Wichtigkeitsbewertung werden die wichtigsten Sätze ausgewählt, um die Zusammenfassung zu erstellen.
Schwierigkeit:
- Wichtigkeitsmessung: So messen Sie die relative Wichtigkeit von Sätzen genau.
- Eliminierung von Redundanz: Vermeiden Sie die Auswahl von Sätzen mit wiederholtem Inhalt.
Methode zur Realisierung:
- Regelbasierter Ansatz: Verwendet vordefinierte Regeln und statistische Methoden zur Auswahl von Sätzen.
- Methode des maschinellen Lernens: Verwenden Sie überwachte Lernalgorithmen, um zu lernen, wie Sie wichtige Sätze basierend auf Trainingsdaten auswählen.
- Generative Zusammenfassung
Bei der generativen Zusammenfassung wird der Originaltext verstanden und neue Sätze generiert, um seinen Inhalt zusammenzufassen. Dieser Ansatz führt zu einer natürlicheren und kohärenteren Zusammenfassung, ist aber auch komplexer.
Umsetzungsprinzip:
- Encoder-Decoder-Architektur: Verwendet ein Sequenz-zu-Sequenz-Modell (Seq2Seq), bei dem der Encoder Eingabetext in Kontextvektoren codiert und der Decoder Zusammenfassungen basierend auf den Kontextvektoren generiert.
- Aufmerksamkeitsmechanismus: Während des Dekodierungsprozesses kann sich das Modell auf verschiedene Teile des Eingabetextes konzentrieren, um relevantere Inhalte zu generieren.
- Vorab trainiertes Modell: Verwenden Sie vorab trainierte Sprachmodelle (wie BERT, GPT usw.), um die Qualität der generierten Zusammenfassungen zu verbessern.
Schwierigkeit:
- Inhaltliche Kohärenz: Die generierte Zusammenfassung muss die logische Kohärenz wahren und Inhaltsunterbrechungen vermeiden.
- Informationsintegrität: Stellt sicher, dass die generierte Zusammenfassung wichtige Informationen aus dem Originaltext enthält.
- Modellkomplexität: Generative Zusammenfassungsmodelle sind im Allgemeinen komplexer als extraktive Zusammenfassungsmodelle und erfordern mehr Rechenressourcen und Trainingsdaten.
Methode zur Realisierung:
- Klassisches Seq2Seq-Modell: etwa das auf LSTM basierende Encoder-Decoder-Modell.
- Vorab trainierte Transformer-Modelle: wie BERTSUM, T5, BART usw.
- Textzusammenfassung in Hugging Face
Hugging Face bietet eine Vielzahl vorgefertigter Modelle und Tools zur einfachen Implementierung von Textzusammenfassungsaufgaben. Im Folgenden finden Sie einige häufig verwendete Textzusammenfassungsmodelle und deren Verwendung:
- Zusammenfassung mithilfe vorab trainierter Modelle
Im Folgenden finden Sie einen Beispielcode für die Textzusammenfassung mithilfe des von Hugging Face bereitgestellten BART-Modells:
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)
- Unterstützte Zusammenfassungsmodelle
Hugging Face bietet eine Vielzahl vortrainierter Modelle für die Textzusammenfassung, darunter unter anderem:
- BART (Facebook/Bart-Large-CNN)
- T5 (t5-klein, t5-Basis, t5-groß, t5-3b, t5-11b)
- PEGASUS (google/pegasus-xsum, google/pegasus-cnn_dailymail)
- Trainieren Sie Ihr eigenes Zusammenfassungsmodell
Wenn Sie sich besser an domänenspezifische Textzusammenfassungsaufgaben anpassen müssen, können Sie das vorab trainierte Modell mithilfe Ihres eigenen Datensatzes verfeinern. Hier ist ein einfaches Beispiel für die Feinabstimmung:
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()Die Textzusammenfassung ist eine komplexe und herausfordernde Aufgabe zur Verarbeitung natürlicher Sprache. Durch die Verwendung der von Hugging Face bereitgestellten vorab trainierten Modelle und Tools kann der Implementierungsprozess der Textzusammenfassung erheblich vereinfacht werden. Benutzer können das geeignete Modell entsprechend ihren spezifischen Anforderungen auswählen und es verfeinern, um den besten Zusammenfassungseffekt zu erzielen.
In diesem Abschnitt erstellen wir unser eigenes Encoder-Decoder-Modell, um Gespräche mit mehreren Personen in prägnante Zusammenfassungen zu komprimieren. Aber werfen wir vorher noch einen Blick auf einen klassischen Datensatz im Bereich Zusammenfassung: CNN/DailyMail-Korpus.
Jetzt sind die Bedingungen für die vollständige Bewertung des Modells erfüllt: Wir haben den CNN/DailyMail-Testsatzdatensatz, die ROUGE-Metrik zur Bewertung und ein zusammenfassendes Modell.
- # 导入所需的库
- 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"]
Wir müssen nur die Teile zusammenfügen. Zunächst bewerten wir die Leistung des Drei-Satz-Benchmark-Modells:
- # 定义一个函数,用于评估基线模型生成的摘要
- 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
Anschließend wenden wir die Funktion auf eine Teilmenge der Daten an. Da der Testteil des CNN/DailyMail-Datensatzes etwa 10.000 Beispiele enthält, nimmt die Erstellung von Zusammenfassungen all dieser Artikel viel Zeit in Anspruch. Erinnern Sie sich an Kapitel 5, dass jedes generierte Token vorwärts durch das Modell weitergeleitet werden muss. Die Generierung von 100 Token pro Probe würde 1 Million Vorwärtsdurchgänge erfordern, und wenn wir die Strahlsuche verwenden würden, müsste diese Zahl auch mit der Anzahl der Strahlen multipliziert werden. Um die Berechnung zu beschleunigen, werden wir den Testsatz einer Unterabtastung unterziehen und letztendlich 1000 Proben zur Auswertung verwenden. Auf diese Weise können wir die Evaluierung des PEGASUS-Modells in weniger als einer Stunde auf einer einzelnen GPU abschließen und stabile Score-Schätzungen erhalten:
- # 从测试集中随机抽取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
Operationsergebnis:
rouge1 | rouge2 | Abonnieren | Abonnieren | |
Basislinie | 0.38928 | 0.171296 | 0.245061 | 0.354239 |
Die Ergebnisse sind größtenteils schlechter als im vorherigen Beispiel, aber immer noch besser als die von GPT-2! Nun folgen wir dem gleichen Muster, um das PEGASUS-Modell zu bewerten:
- # 导入 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
Lassen Sie uns diesen Bewertungscode im Detail erklären. Zunächst teilen wir den Datensatz in kleinere Stapel auf, damit diese gleichzeitig verarbeitet werden können. Dann tokenisieren wir für jeden Stapel die Eingabeartikel und geben sie an die Funktion „generate()“ weiter, um mithilfe der Strahlsuche Zusammenfassungen zu generieren. Wir verwenden die gleichen Generierungsparameter wie in der Arbeit. Durch die neue Länge des Penalty-Parameters wird sichergestellt, dass das Modell keine zu langen Sequenzen generiert.Schließlich dekodieren wir den resultierenden Text und ersetzen ihn<n> Tokens und fügen Sie den dekodierten Text zusammen mit dem Referenztext zur Metrik hinzu. Schließlich berechnen wir den ROUGE-Score und geben ihn zurück. Jetzt verwenden wir erneut die Klasse AutoModelForSeq2SeqLM für die seq2seq-Generierungsaufgabe, um das Modell zu laden und auszuwerten:
- # 从 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"])
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, die laufenden Ergebnisse als Referenz unter Verwendung von Beispielen sind wie folgt)
rouge1 | rouge2 | Abonnieren | Abonnieren | |
Pegasus | 0.43438 | 0.210883 | 0.307195 | 0.373231 |
Diese Zahlen kommen den Ergebnissen in der Arbeit sehr nahe. Hierbei ist zu beachten, dass der Verlust und die Genauigkeit jedes Tokens etwas vom ROUGE-Score entkoppelt sind. Der Verlust ist unabhängig von der Dekodierungsstrategie, während der ROUGE-Score stark gekoppelt ist.
Da ROUGE und BLEU einen besseren Verlust oder eine bessere Genauigkeit erzielen als die menschliche Auswertung, sollten Sie sich beim Erstellen von Textgenerierungsmodellen auf sie konzentrieren und Dekodierungsstrategien sorgfältig untersuchen und auswählen. Allerdings sind diese Kennzahlen alles andere als perfekt, daher sollte immer eine menschliche Bewertung berücksichtigt werden.
Da wir nun über die Bewertungsfunktion verfügen, können wir unser eigenes Zusammenfassungsmodell trainieren.
Zu diesem Zeitpunkt haben wir viele Details der Textzusammenfassung und -bewertung durchgearbeitet. Jetzt nutzen wir dieses Wissen, um ein benutzerdefiniertes Textzusammenfassungsmodell zu trainieren! Für unsere benutzerdefinierte Anwendung verwenden wir den von Samsung entwickelten SAMSum-Datensatz (HTTPS://ÖRtichchchm.mj/N1GGQ ) enthält dieser Datensatz eine Reihe von Gesprächen und kurzen Zusammenfassungen. Diese Gespräche können Interaktionen zwischen Kunden und Callcentern darstellen und genaue Zusammenfassungen generieren, um den Kundenservice zu verbessern und gemeinsame Muster in Kundenanfragen zu erkennen. Laden wir zunächst den Datensatz und sehen uns ein Beispiel an:
- # 从 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"])
(Hinweis: Möglicherweise müssen Sie py7zr installieren, pip install py7zr)
Operationsergebnis:
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.
Gespräche sehen genauso aus, als würden Sie per SMS oder WhatsApp chatten, einschließlich Emojis und Platzhaltern für GIFs. Das Dialogfeld enthält den vollständigen Text, während das Zusammenfassungsfeld eine Zusammenfassung des Dialogs ist. Kann ein auf den CNN/DailyMail-Datensatz abgestimmtes Modell diesen Datensatz verarbeiten? Lass uns einen Blick darauf werfen!
Zuerst führen wir denselben Zusammenfassungsgenerierungsprozess mit PEGASUS aus, um die Ausgabe anzuzeigen. Wir können den durch die CNN/DailyMail-Zusammenfassung generierten Code wiederverwenden:
- # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
- pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
-
- # 打印生成的摘要标题
- print("Summary:")
-
- # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
- # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
- print(pipe_out[0]["summary_text"].replace(" .", ".n"))
Operationsergebnis:
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"
Wir können sehen, dass das Modell hauptsächlich versucht, zusammenzufassen, indem es Schlüsselsätze aus der Konversation extrahiert. Dies funktioniert möglicherweise relativ gut im CNN/DailyMail-Datensatz, aber in SAMSum ist die Zusammenfassung abstrakter und der Effekt ist möglicherweise nicht gut. Wir können dies bestätigen, indem wir die vollständige ROUGE-Bewertung für den Testsatz ausführen:
- # 使用评估函数 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"])
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, die laufenden Ergebnisse als Referenz unter Verwendung von Beispielen sind wie folgt)
rouge1 | rouge2 | Abonnieren | Abonnieren | |
Pegasus | 0.29617 | 0.087803 | 0.229604 | 0.229514 |
Obwohl die Ergebnisse nicht großartig sind, ist dies nicht unerwartet, da sie weit von der CNN/DailyMail-Datenverteilung entfernt sind. Dennoch hat die Einrichtung des Bewertungsprozesses vor dem Training zwei Vorteile: Wir können den Erfolg des Trainings direkt anhand von Metriken messen und haben eine gute Ausgangslage. Die Feinabstimmung des Modells an unserem Datensatz sollte die ROUGE-Metrik sofort verbessern. Wenn es keine Verbesserung gibt, wissen wir, dass mit unserer Trainingsschleife etwas nicht stimmt.
Bevor wir die Daten trainieren, werfen wir einen kurzen Blick auf die Eingabe- und Ausgabelängenverteilungen:
- # 编码训练集中的对话文本和摘要,并计算其长度
- 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()
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, die laufenden Ergebnisse als Referenz unter Verwendung von Beispielen sind wie folgt)
Wir können sehen, dass die meisten Konversationen mit jeweils etwa 100 bis 200 Token viel kürzer sind als CNN/DailyMail-Artikel. Ebenso sind Zusammenfassungen viel kürzer, etwa 20 bis 40 Token (die gleiche Länge wie ein durchschnittlicher Tweet).
Merken wir uns zunächst diese Ergebnisse, wir werden sie später verwenden. Zuerst müssen wir den Datensatz tokenisieren. Wir legen die maximale Länge des Dialogs und der Zusammenfassung auf 1024 bzw. 128 fest:
- 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)
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Im Tokenisierungsschritt gibt es etwas Neues: den tokenizer.as_target_tokenizer()-Kontext. Einige Modelle erfordern spezielle Token im Decoder-Eingang, daher ist es wichtig, die Tokenisierungsschritte für die Encoder- und Decoder-Eingänge zu trennen. Innerhalb einer with-Anweisung (Kontextmanager genannt) weiß der Tokenizer, dass er für den Decoder tokenisiert.
Jetzt müssen wir den Datenorganisator erstellen. In den meisten Fällen können wir den Standard-Collator verwenden, der alle Tensoren in einem Stapel sammelt und sie einfach stapelt. Für die Zusammenfassungsaufgabe müssen wir nicht nur die Eingaben stapeln, sondern auch die Ziele auf der Decoderseite vorbereiten. PEGASUS ist ein Encoder-Decoder-Transformer und verfügt daher über eine klassische seq2seq-Architektur. In einer seq2seq-Einstellung besteht ein gängiger Ansatz darin, Teacher-Forcing im Decoder anzuwenden. Bei Verwendung dieser Strategie empfängt der Decoder zusätzlich zur Encoder-Ausgabe Eingabe-Tokens (wie bei einem Nur-Decoder-Modell wie GPT-2), die durch die Annotation um eine Position nach rechts verschoben werden. Daher erhält der Decoder bei der Vorhersage des nächsten Tokens als Eingabe den wahren Wert, der um eine Position nach rechts verschoben ist, wie in der folgenden Tabelle gezeigt:
- # 示例文本序列和标签生成过程
- 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')
Operationsergebnis:
Schritt | Decoder-Eingabe | Etikett |
1 | [UNTERLAGE] | Transformer |
2 | [PAD, Transformers] | Sind |
3 | [PAD, Transformers, sind] | Eindrucksvoll |
4 | [PAD, Transformers, sind, großartig] | für |
5 | [PAD, Transformers, sind, großartig, für] | Text |
6 | [PAD, Transformers, sind, genial, für, Text] | Zusammenfassung |
Wir verschieben es um eine Position nach rechts, sodass der Decoder nur die vorherige korrekte Anmerkung sieht, nicht jedoch aktuelle oder zukünftige Anmerkungen. Nur das Verschieben reicht aus, da der Decoder über einen maskierten Selbstaufmerksamkeitsmechanismus verfügt, der alle aktuellen und zukünftigen Eingaben maskiert.
Daher legen wir bei der Stapelvorbereitung die Eingabe für den Decoder fest, indem wir die Anmerkung um eine Position nach rechts verschieben. Anschließend stellen wir sicher, dass Fülltokens in der Verlustfunktion ignoriert werden, indem wir sie in der Annotation auf -100 setzen. Tatsächlich müssen wir diese Schritte nicht manuell ausführen, da DataCollatorForSeq2Seq alles für uns erledigt:
- # 导入 Seq2Seq 数据集整理器模块
- from transformers import DataCollatorForSeq2Seq
-
- # 创建 Seq2Seq 数据集整理器实例
- seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
Dann richten wir wie üblich ein TrainingArguments für das Training ein:
- # 导入训练参数和训练器模块
- 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 # 梯度累积步数
- )
Der Unterschied zu den vorherigen Einstellungen besteht darin, dass es diesmal einen neuen Parameter „gradient_accumulation_steps“ gibt. Da das Modell sehr groß ist, müssen wir die Batchgröße auf 1 setzen. Allerdings können zu kleine Batchgrößen die Konvergenz beeinträchtigen. Um dieses Problem zu lösen, können wir einen cleveren Trick namens Gradientenakkumulation anwenden. Wie der Name schon sagt, berechnen wir die Farbverläufe nicht für den gesamten Stapel auf einmal, sondern berechnen und aggregieren sie in Stapeln. Wenn wir genügend Farbverläufe aggregiert haben, führen wir einen Optimierungsschritt durch. Das ist natürlich langsamer, als alles auf einmal zu erledigen, aber es spart uns viel GPU-Speicher.
Jetzt melden wir uns bei Hugging Face an, damit wir das Modell nach dem Training an den Hub schieben können:
- from huggingface_hub import notebook_login
-
- notebook_login()
Operationsergebnis:
Jetzt haben wir alles, was wir zum Initialisieren des Trainers benötigen, einschließlich Modell, Tokenizer, Trainingsparameter, Datenorganisatoren sowie Trainings- und Bewertungsdatensätze:
- 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"] # 评估数据集
- )
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Wir sind bereit zu trainieren. Sobald das Training abgeschlossen ist, können wir die Bewertungsfunktion direkt auf dem Testsatz ausführen, um zu sehen, wie das Modell funktioniert:
- 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"])
Operationsergebnis:
(Vorübergehender Fehler wird hier gemeldet:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, die laufenden Ergebnisse als Referenz unter Verwendung von Beispielen sind wie folgt)
rouge1 | rouge2 | Abonnieren | Abonnieren | |
Pegasus | 0.42761 | 0.200571 | 0.340648 | 0.340738 |
Wir können sehen, dass der ROUGE-Score im Vergleich zum Modell ohne Feinabstimmung erheblich verbessert wurde. Obwohl das vorherige Modell also auch für die Zusammenfassungsgenerierung trainiert wurde, passte es sich nicht gut an die neue Domäne an. Lassen Sie uns unser Modell auf Hub übertragen:
- # 将训练完成的模型推送到 Hub 上
- trainer.push_to_hub("Training complete!")
Als nächstes werden wir dieses Modell verwenden, um einige Zusammenfassungen für uns zu erstellen.
Sie können die generierten Ergebnisse auch als Teil einer Trainingsschleife auswerten: Verwenden Sie die TrainingArguments-Erweiterung namens Seq2SeqTrainingArguments und geben Sie Predict_with_generate=True an. Übergeben Sie dies an einen dedizierten Trainer namens Seq2SeqTrainer, der die Funktion „generate()“ anstelle eines Vorwärtsdurchlaufs des Modells verwendet, um Vorhersagen für die Auswertung zu erstellen. Versuche es!
Betrachtet man die Verlust- und ROUGE-Scores, scheint das Modell eine deutliche Verbesserung gegenüber dem Originalmodell zu zeigen, das nur auf CNN/DailyMail trainiert wurde. Eine aus einer Probe im Testsatz generierte Zusammenfassung sieht folgendermaßen aus:
- 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"])
Operationsergebnis:
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.
Dies ist einer Referenzzusammenfassung sehr ähnlich. Es sieht so aus, als hätte das Modell gelernt, Gespräche zu Zusammenfassungen zusammenzufassen, anstatt nur Passagen zu extrahieren. Nun zum letzten Test: Wie verhält sich das Modell bei benutzerdefinierten Eingaben?
- # 自定义对话示例
- 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"])
Operationsergebnis:
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.
Die generierte benutzerdefinierte Konversationszusammenfassung ist sinnvoll. Es gelingt gut, das zusammenzufassen, worüber alle in der Diskussion gemeinsam ein Buch schreiben wollten, anstatt nur einen einzigen Satz herauszuarbeiten. Beispielsweise werden die Zeilen 3 und 4 zu einer logischen Kombination zusammengefasst.