私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
目次
AGIの「抱き顔」の「テキスト要約」の「ペガサス評価」/「ペガサス微調整」/「会話要約生成」を簡易アレンジ
3. CNN/DailyMail データセットで PEGASUS を評価する
1. SAMSum での PEGASUS のパフォーマンスを評価する
AGI (Artificial General Intelligence) は、人間の知能レベルの人工知能システムです。特定のタスクを実行するだけでなく、高い自律性と適応性により、幅広い問題を解決するための知識を理解し、学習し、適用することができます。 AGI の機能には、自己学習、自己改善、自己調整、および人間の介入なしにさまざまな複雑な問題を解決する能力が含まれますが、これらに限定されません。
- AGI でできることは非常に多岐にわたります。
クロスドメイン タスクの実行: AGI は複数のドメインでタスクを処理でき、特定のアプリケーション シナリオに限定されません。
自律的な学習と適応: AGI は経験から学習し、新しい環境や状況に適応できます。
創造的思考: AGI は革新的に思考し、新しいソリューションを考え出すことができます。
社会的相互作用: AGI は人間との複雑な社会的相互作用が可能であり、感情的および社会的信号を理解します。
- AGI の将来の開発の見通しに関しては、それは人工知能研究の最終目標の 1 つと考えられており、大きな変化の可能性を秘めています。
技術革新:機械学習やニューラルネットワークなどの技術の進歩により、AGIの実現が近づく可能性があります。
学際的な統合: AGI を実装するには、コンピューター サイエンス、神経科学、心理学などの複数の分野の知識を統合する必要があります。
倫理的および社会的配慮: AGI の開発には、プライバシー、セキュリティ、雇用などの倫理的および社会的問題を考慮する必要があります。
学習機能と適応機能の強化: 将来の AGI システムは、高度なアルゴリズムを使用して環境から学習し、動作を最適化する可能性があります。
マルチモーダル インタラクション: AGI には、人間や他のシステムと対話するための複数の認識およびインタラクション方法があります。
Hugging Face は、世界で最も人気のあるオープンソース機械学習コミュニティおよびプラットフォームの 1 つとして、AGI 時代に重要な役割を果たしています。事前トレーニングされたモデルとデータセットの豊富なリソースを提供し、機械学習分野の発展を促進します。 Hugging Face は、使いやすさとオープンさが特徴で、Transformers ライブラリを通じて、モデルがテキストを処理する便利な方法をユーザーに提供します。 AI テクノロジーの発展に伴い、Hugging Face コミュニティは、AI テクノロジーの開発と応用、特にマルチモーダル AI テクノロジーの開発を促進する上で重要な役割を果たし続けるでしょう。Hugging Face コミュニティはモデルの多様性を拡大します。画像、音声、ビデオなどのマルチモーダル データを含むデータ セット。
- AGI の時代では、Hugging Face は次のような形で活用される可能性があります。
モデル共有: モデル共有プラットフォームとして、Hugging Face は高度な AGI モデルの共有とコラボレーションを促進し続けます。
オープンソース エコシステム: Hugging Face のオープンソース エコシステムは、AGI テクノロジーの開発と革新を加速するのに役立ちます。
ツールとサービス: AGI 分野での研究とアプリケーションにおける開発者と研究者をサポートする豊富なツールとサービスを提供します。
倫理と社会的責任: Hugging Face は AI 倫理に焦点を当てており、倫理基準を遵守しながら技術の進歩を確実にするために、責任ある AGI モデルの開発と適用を促進します。
AGI は将来の人工知能の高度な形式として幅広い応用の可能性を秘めており、オープンソース コミュニティとして Hugging Face は AGI の開発と応用を促進する上で重要な役割を果たすことになります。
(注: 次のコードを実行するには科学インターネット アクセスが必要な場合があります)
研究論文、財務報告書、一連の電子メールなどの文書を要約する必要があったかもしれません。考えてみると、これには、長文の内容を理解し、内容を推論し、元の文書の主要なテーマを含む流暢な文章を作成するなど、さまざまな能力が必要です。さらに、ニュース記事を正確に要約することは、法的契約を要約することとは大きく異なるため、複雑な領域の一般化機能が必要です。これらの理由により、Transformer モデルを含むニューラル言語モデルにとって、テキストの要約 (専門用語ではテキスト要約) は困難な作業です。これらの課題にもかかわらず、テキスト要約により、ドメイン専門家のワークフローが大幅に高速化され、企業はテキスト要約を使用して社内知識を凝縮したり、契約を要約したり、ソーシャルメディア公開コンテンツを自動生成したりすることができます。したがって、テキスト要約 NLP タスクは価値があります。
課題を理解するために、このセクションでは、テキストの要約に Transformer の事前トレーニング済みモデルを活用する方法を説明します。要約は、入力テキストとターゲット テキストを必要とする古典的なシーケンス間 (seq2seq) タスクです。
テキストの要約は自然言語処理タスクであり、その目的は長いテキストから簡潔で重要な情報を抽出し、短いバージョンを生成することです。テキストの要約は、抽出的要約と生成的要約の 2 つの主なタイプに分類できます。
- 抜粋要約
抽出要約では、原文から重要な文や段落を選択し、その内容を直接要約として抽出します。この方法では、元のテキストの単語や文の構造は変わりません。
実装原則:
- 特徴抽出: まず、単語の頻度、文の位置、キーワード、固有表現など、テキストのさまざまな特徴を抽出する必要があります。
- 重要度スコアリング: 抽出された特徴に基づいて、各文のスコアが計算され、その重要性が判断されます。
- 文の選択: 重要度スコアに基づいて、要約を作成するために最も重要な文が選択されます。
困難:
- 重要度の測定: 文章の相対的な重要性を正確に測定する方法。
- 冗長性の除去: 内容が重複する文を選択しないようにします。
実現方法:
- ルールベースのアプローチ: 事前定義されたルールと統計的手法を使用して文を選択します。
- 機械学習方法: 教師あり学習アルゴリズムを使用して、トレーニング データに基づいて重要な文を選択する方法を学習します。
- 生成的要約
生成的要約は、元のテキストを理解し、その内容を要約する新しい文を生成することによって機能します。このアプローチでは、より自然で一貫した要約が作成されますが、より複雑になります。
実装原則:
- エンコーダ/デコーダ アーキテクチャ: シーケンスツーシーケンス (Seq2Seq) モデルを使用します。エンコーダは入力テキストをコンテキスト ベクトルにエンコードし、デコーダはコンテキスト ベクトルに基づいて要約を生成します。
- アテンション メカニズム: デコード プロセス中に、モデルは入力テキストのさまざまな部分に焦点を当てて、より関連性の高いコンテンツを生成できます。
- 事前トレーニングされたモデル: 事前トレーニングされた言語モデル (BERT、GPT など) を使用して、生成される概要の品質を向上させます。
困難:
- コンテンツの一貫性: 生成された概要は、論理的な一貫性を維持し、コンテンツの中断を避ける必要があります。
- 情報の整合性: 生成された概要に元のテキストからの重要な情報が含まれていることを確認します。
- モデルの複雑さ: 生成要約モデルは一般に、抽出要約モデルよりも複雑で、より多くのコンピューティング リソースとトレーニング データを必要とします。
実現方法:
- クラシック Seq2Seq モデル: LSTM に基づくエンコーダー/デコーダー モデルなど。
- 事前トレーニング済みの Transformer モデル: BERTSUM、T5、BART など。
- ハグフェイスでのテキスト要約
Hugging Face は、テキスト要約タスクを簡単に実装するためのさまざまな事前トレーニング済みモデルとツールを提供します。以下に、一般的に使用されるテキスト要約モデルとその使用方法を示します。
- 事前学習済みモデルを使用した要約
以下は、Hugging Face が提供する BART モデルを使用したテキスト要約のサンプル コードです。
from transformers import BartForConditionalGeneration, BartTokenizer # 加载预训练的BART模型和对应的tokenizer model_name = "facebook/bart-large-cnn" model = BartForConditionalGeneration.from_pretrained(model_name) tokenizer = BartTokenizer.from_pretrained(model_name) # 输入文本 input_text = """Your text to summarize goes here.""" # 对输入文本进行tokenize,并添加必要的模型输入 inputs = tokenizer([input_text], max_length=1024, return_tensors='pt') # 使用模型生成摘要 summary_ids = model.generate(inputs['input_ids'], num_beams=4, max_length=150, early_stopping=True) # 将生成的token序列转换回文本 summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True) print(summary)
- サポートされている要約モデル
Hugging Face は、テキスト要約用のさまざまな事前トレーニング済みモデルを提供します。これには以下が含まれますが、これらに限定されません。
- BART (facebook/bart-large-cnn)
- T5 (t5-small、t5-base、t5-large、t5-3b、t5-11b)
- ペガサス (google/pegasus-xsum、google/pegasus-cnn_dailymail)
- 独自の要約モデルをトレーニングする
ドメイン固有のテキスト要約タスクにさらに適応する必要がある場合は、独自のデータセットを使用して事前トレーニングされたモデルを微調整できます。簡単な微調整の例を次に示します。
from transformers import Trainer, TrainingArguments, BartForConditionalGeneration, BartTokenizer from datasets import load_dataset # 加载数据集 dataset = load_dataset("cnn_dailymail", "3.0.0") # 加载预训练的BART模型和tokenizer model_name = "facebook/bart-large-cnn" model = BartForConditionalGeneration.from_pretrained(model_name) tokenizer = BartTokenizer.from_pretrained(model_name) # 数据预处理 def preprocess_function(examples): inputs = [doc for doc in examples['article']] model_inputs = tokenizer(inputs, max_length=1024, truncation=True) # 设定摘要作为目标 with tokenizer.as_target_tokenizer(): labels = tokenizer(examples['highlights'], max_length=150, truncation=True) model_inputs['labels'] = labels['input_ids'] return model_inputs tokenized_dataset = dataset.map(preprocess_function, batched=True) # 定义训练参数 training_args = TrainingArguments( output_dir="./results", evaluation_strategy="epoch", learning_rate=2e-5, per_device_train_batch_size=4, per_device_eval_batch_size=4, num_train_epochs=3, weight_decay=0.01, ) # 使用Trainer进行训练 trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset["train"], eval_dataset=tokenized_dataset["validation"], ) trainer.train()テキストの要約は、複雑で困難な自然言語処理タスクです。 Hugging Face が提供する事前トレーニング済みモデルとツールを使用することで、テキスト要約の実装プロセスを大幅に簡素化できます。ユーザーは、特定のニーズに応じて適切なモデルを選択し、最適な要約効果を得るために微調整することができます。
このセクションでは、複数人の会話を簡潔な要約に圧縮するための独自のエンコーダー/デコーダー モデルを構築します。その前に、要約分野の古典的なデータセットである CNN/DailyMail コーパスを見てみましょう。
これで、モデルを完全に評価するために必要なものがすべて揃いました。CNN/DailyMail テスト セット データセット、評価用の ROUGE メトリクス、および概要モデルができました。
- # 导入所需的库
- import matplotlib.pyplot as plt # 导入 matplotlib.pyplot,用于绘制图形
- import pandas as pd # 导入 pandas,用于数据处理
- from datasets import load_dataset, load_metric # 从 datasets 库中导入 load_dataset 和 load_metric 函数
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer # 从 transformers 库中导入 AutoModelForSeq2SeqLM 和 AutoTokenizer
-
- # 加载 CNN/DailyMail 数据集,版本为 3.0.0
- dataset = load_dataset("cnn_dailymail", "3.0.0")
-
- # 加载 ROUGE 评价指标,用于计算文本摘要的质量
- rouge_metric = load_metric("rouge", cache_dir=None)
-
- # 定义要计算的 ROUGE 分数的名称列表
- rouge_names = ["rouge1", "rouge2", "rougeL", "rougeLsum"]
あとはピースを組み立てるだけです。まず、3 文のベンチマーク モデルのパフォーマンスを評価します。
- # 定义一个函数,用于评估基线模型生成的摘要
- def evaluate_summaries_baseline(dataset, metric, column_text="article", column_summary="highlights"):
- # 使用 three_sentence_summary 函数对数据集中的每篇文章生成摘要
- summaries = [three_sentence_summary(text) for text in dataset[column_text]]
-
- # 将生成的摘要和参考摘要添加到评价指标中
- metric.add_batch(predictions=summaries, references=dataset[column_summary])
-
- # 计算评价指标的分数
- score = metric.compute()
-
- # 返回评价指标的分数
- return score
次に、その関数をデータのサブセットに適用します。 CNN/DailyMail データセットのテスト部分には約 10,000 のサンプルが含まれているため、これらすべての記事の概要を生成するには時間がかかります。第 5 章で、生成された各トークンをモデルに順方向に渡す必要があることを思い出してください。サンプルごとに 100 個のトークンを生成するには、100 万回の順方向パスが必要になります。また、ビーム検索を使用している場合は、この数値にビームの数を掛ける必要もあります。計算を高速化するために、テスト セットをサブサンプリングし、最終的に 1000 個のサンプルを評価に使用します。このようにして、単一 GPU で 1 時間未満で PEGASUS モデルの評価を完了し、安定したスコア推定値を取得できます。
- # 从测试集中随机抽取1000条样本,用于评估
- test_sampled = dataset["test"].shuffle(seed=42).select(range(1000))
-
- # 使用基线模型生成摘要并评估其质量
- score = evaluate_summaries_baseline(test_sampled, rouge_metric)
-
- # 将评价指标的分数存储在字典中
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将评价指标的分数转换为DataFrame格式,并转置以便显示
- pd.DataFrame.from_dict(rouge_dict, orient="index", columns=["baseline"]).T
操作結果:
ルージュ1 | ルージュ2 | ルージュL | ルージュルサム | |
ベースライン | 0.38928 | 0.171296 | 0.245061 | 0.354239 |
スコアは前の例よりもほとんど悪くなりますが、それでも GPT-2 で達成されたスコアよりは優れています。次に、同じパターンに従って PEGASUS モデルを評価します。
- # 导入 tqdm 模块,用于显示进度条
- from tqdm import tqdm
- # 导入 torch 模块,用于使用 GPU 或 CPU 进行计算
- import torch
-
- # 设置设备为 GPU(如果可用)或 CPU
- device = "cuda" if torch.cuda.is_available() else "cpu"
-
- def chunks(list_of_elements, batch_size):
- """将 list_of_elements 按 batch_size 切分成多个小块"""
- for i in range(0, len(list_of_elements), batch_size):
- yield list_of_elements[i : i + batch_size]
-
- def evaluate_summaries_pegasus(dataset, metric, model, tokenizer,
- batch_size=16, device=device,
- column_text="article",
- column_summary="highlights"):
- """评估使用 Pegasus 模型生成的摘要"""
-
- # 将文章和摘要分别按 batch_size 切分成多个小块
- article_batches = list(chunks(dataset[column_text], batch_size))
- target_batches = list(chunks(dataset[column_summary], batch_size))
-
- # 使用 tqdm 显示进度条,遍历每个文章批次和相应的摘要批次
- for article_batch, target_batch in tqdm(
- zip(article_batches, target_batches), total=len(article_batches)):
-
- # 对文章批次进行标记,将其转换为模型输入的张量
- inputs = tokenizer(article_batch, max_length=1024, truncation=True,
- padding="max_length", return_tensors="pt")
-
- # 使用 Pegasus 模型生成摘要
- summaries = model.generate(input_ids=inputs["input_ids"].to(device),
- attention_mask=inputs["attention_mask"].to(device),
- length_penalty=0.8, num_beams=8, max_length=128)
-
- # 解码生成的摘要,将其从张量转换为字符串
- decoded_summaries = [tokenizer.decode(s, skip_special_tokens=True,
- clean_up_tokenization_spaces=True)
- for s in summaries]
- decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
-
- # 将生成的摘要和目标摘要添加到评价指标中
- metric.add_batch(predictions=decoded_summaries, references=target_batch)
-
- # 计算评价指标分数
- score = metric.compute()
- return score
この評価コードについて詳しく説明していきます。まず、データセットを小さなバッチに分割して、同時に処理できるようにします。次に、バッチごとに入力記事をトークン化し、generate() 関数にフィードして、ビーム検索を使用して要約を生成します。論文と同じ生成パラメータを使用します。ペナルティ パラメーターの新しい長さにより、モデルが長すぎるシーケンスを生成しないことが保証されます。最後に、生成されたテキストをデコードし、置き換えます。<n>トークンを取得し、デコードされたテキストを参照テキストとともにメトリックに追加します。最後に、ROUGE スコアを計算して返します。ここで、再度 seq2seq 生成タスクに AutoModelForSeq2SeqLM クラスを使用して、モデルをロードして評価します。
- # 从 transformers 库中导入用于序列到序列任务的模型和标记器
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
-
- # 设置模型检查点名称,使用 Google 的 PEGASUS 模型,预训练于 CNN/DailyMail 数据集
- model_ckpt = "google/pegasus-cnn_dailymail"
-
- # 从预训练的模型检查点中加载标记器和模型,并将模型移动到指定的设备(CPU 或 GPU)
- tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
- model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)
-
- # 使用评估函数 evaluate_summaries_pegasus 评估 PEGASUS 模型生成的摘要
- # 输入参数包括测试数据、ROUGE 评价指标、模型、标记器和批处理大小
- score = evaluate_summaries_pegasus(test_sampled, rouge_metric,
- model, tokenizer, batch_size=8)
-
- # 从评估结果中提取 ROUGE 分数,将其转换为字典格式,其中键为 ROUGE 指标名称,值为 F-measure 分数
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将 ROUGE 分数字典转换为 pandas 数据框,并以 "pegasus" 作为索引
- pd.DataFrame(rouge_dict, index=["pegasus"])
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
、例を使用した参考の実行結果は次のとおりです)
ルージュ1 | ルージュ2 | ルージュL | ルージュルサム | |
ペガサス | 0.43438 | 0.210883 | 0.307195 | 0.373231 |
これらの数値は論文の結果に非常に近いです。ここで注意すべき重要な点は、各トークンの損失と精度が ROUGE スコアからある程度切り離されていることです。損失はデコード戦略とは独立していますが、ROUGE スコアは強く関連しています。
ROUGE と BLEU は人間の評価よりも優れた損失または精度を達成するため、テキスト生成モデルを構築する際にはこれらに焦点を当て、デコード戦略を慎重に検討して選択する必要があります。ただし、これらの指標は完璧には程遠いため、人間による評価を常に考慮する必要があります。
評価関数が完成したので、独自の要約モデルをトレーニングできます。
この時点で、テキストの要約と評価について多くの詳細を確認しました。今度は、この知識を使用してカスタムのテキスト要約モデルをトレーニングします。カスタム アプリケーションには、Samsung が開発した SAMSum データセットを使用します (https://ore私l.lええ/ん1ググq )、このデータセットには一連の会話と短い要約が含まれています。これらの会話は顧客とコールセンターの間のやりとりを表し、顧客サービスを向上させ、顧客の要求に共通するパターンを検出するのに役立つ正確な要約を生成します。まずデータセットをロードしてサンプルを表示しましょう。
- # 从 datasets 库中导入用于加载数据集的函数
- from datasets import load_dataset
-
- # 加载 SamSum 数据集,该数据集包含对话和相应的摘要
- dataset_samsum = load_dataset("samsum",trust_remote_code=True)
-
- # 获取数据集的每个划分(训练集、验证集、测试集)的长度,并存储在列表 split_lengths 中
- split_lengths = [len(dataset_samsum[split]) for split in dataset_samsum]
-
- # 打印每个数据集划分的长度
- print(f"Split lengths: {split_lengths}")
-
- # 打印训练集中列的名称(特征)
- print(f"Features: {dataset_samsum['train'].column_names}")
-
- # 打印测试集中第一个对话样本
- print("nDialogue:")
- print(dataset_samsum["test"][0]["dialogue"])
-
- # 打印测试集中第一个对话样本的摘要
- print("nSummary:")
- print(dataset_samsum["test"][0]["summary"])
(注: py7zr、pip install py7zr のインストールが必要な場合があります)
操作結果:
Split lengths: [14732, 819, 818] Features: ['id', 'dialogue', 'summary'] Dialogue: Hannah: Hey, do you have Betty's number? Amanda: Lemme check Hannah: <file_gif> Amanda: Sorry, can't find it. Amanda: Ask Larry Amanda: He called her last time we were at the park together Hannah: I don't know him well Hannah: <file_gif> Amanda: Don't be shy, he's very nice Hannah: If you say so.. Hannah: I'd rather you texted him Amanda: Just text him 🙂 Hannah: Urgh.. Alright Hannah: Bye Amanda: Bye bye Summary: Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry.
会話は、絵文字や GIF のプレースホルダーを含め、テキスト メッセージや WhatsApp 経由でチャットするのと同じように見えます。 ダイアログ フィールドには完全なテキストが含まれ、概要フィールドにはダイアログの概要が表示されます。 CNN/DailyMail データセットで微調整されたモデルは、このデータセットを処理できますか?見てみましょう!
まず、PEGASUS を使用して同じ概要生成プロセスを実行し、出力を確認します。 CNN/DailyMail の概要によって生成されたコードを再利用できます。
- # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
- pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
-
- # 打印生成的摘要标题
- print("Summary:")
-
- # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
- # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
- print(pipe_out[0]["summary_text"].replace(" .", ".n"))
操作結果:
Summary: Hannah asks Amanda for Betty's number. Amanda can't find it. Hannah asks Larry. Amanda asks Larry to text him. Hannah says she'll text him back. Hannah calls it a day and says she's going to go home. Hannah: "Bye bye"
このモデルは主に会話の中の重要な文を抽出して要約しようとしていることがわかります。これは CNN/DailyMail データ セットでは比較的うまく機能する可能性がありますが、SAMSum では要約がより抽象的であり、効果は必ずしも良好ではありません。これは、テスト セットで完全な ROUGE 評価を実行することで確認できます。
- # 使用评估函数 evaluate_summaries_pegasus 对 SamSum 数据集的测试集进行摘要生成评估
- # 传入的参数包括数据集、评价指标、模型、tokenizer、文本列名、摘要列名和批量大小
- score = evaluate_summaries_pegasus(dataset_samsum["test"], rouge_metric, model,
- tokenizer, column_text="dialogue",
- column_summary="summary", batch_size=8)
-
- # 创建一个字典 rouge_dict,用于存储 ROUGE 评分的中值 F-measure 值
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将 ROUGE 评分字典转换为 Pandas 数据框,并以 "pegasus" 为索引
- pd.DataFrame(rouge_dict, index=["pegasus"])
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
、例を使用した参考の実行結果は次のとおりです)
ルージュ1 | ルージュ2 | ルージュL | ルージュルサム | |
ペガサス | 0.29617 | 0.087803 | 0.229604 | 0.229514 |
結果はあまり良くありませんが、CNN/DailyMail のデータ分布からは遠く離れているため、予想外の結果ではありません。それにもかかわらず、トレーニング前に評価プロセスを設定することには 2 つの利点があります。1 つはメトリクスを直接使用してトレーニングの成功を測定できること、もう 1 つは適切なベースラインが得られることです。データセットのモデルを微調整すると、ROUGE メトリクスがすぐに改善されるはずです。改善が見られない場合は、トレーニング ループに問題があることがわかります。
データでトレーニングする前に、入力と出力の長さの分布を簡単に見てみましょう。
- # 编码训练集中的对话文本和摘要,并计算其长度
- d_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["dialogue"]]
- s_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["summary"]]
-
- # 创建一个包含两个子图的图形对象
- fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), sharey=True)
-
- # 绘制对话文本的长度分布直方图
- axes[0].hist(d_len, bins=20, color="C0", edgecolor="C0")
- axes[0].set_title("Dialogue Token Length")
- axes[0].set_xlabel("Length")
- axes[0].set_ylabel("Count")
-
- # 绘制摘要的长度分布直方图
- axes[1].hist(s_len, bins=20, color="C0", edgecolor="C0")
- axes[1].set_title("Summary Token Length")
- axes[1].set_xlabel("Length")
-
- # 调整子图布局,使其更加紧凑
- plt.tight_layout()
-
- # 显示绘制的图形
- plt.show()
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
、例を使用した参考の実行結果は次のとおりです)
ほとんどの会話は CNN/DailyMail の記事よりもはるかに短く、それぞれのトークンが約 100 ~ 200 であることがわかります。同様に、概要ははるかに短く、約 20 ~ 40 トークン (平均的なツイートと同じ長さ) です。
後で使用するので、最初にこれらの結果を覚えておきましょう。まず、データセットをトークン化する必要があります。ダイアログと要約の最大長をそれぞれ 1024 と 128 に設定します。
- def convert_examples_to_features(example_batch):
- """
- 将示例批处理转换为模型输入特征。
-
- Args:
- - example_batch (dict): 包含对话和摘要的示例批处理字典。
-
- Returns:
- - dict: 包含转换后特征的字典,包括输入编码和目标编码。
- """
- # 对对话文本进行编码处理,生成输入编码
- input_encodings = tokenizer(example_batch["dialogue"], max_length=1024,
- truncation=True)
-
- # 使用目标编码器处理摘要文本,生成目标编码
- with tokenizer.as_target_tokenizer():
- target_encodings = tokenizer(example_batch["summary"], max_length=128,
- truncation=True)
-
- # 返回包含输入编码、目标标签和注意力掩码的字典
- return {
- "input_ids": input_encodings["input_ids"],
- "attention_mask": input_encodings["attention_mask"],
- "labels": target_encodings["input_ids"]
- }
-
- # 使用 map 方法将 SamSum 数据集转换为 PyTorch 格式
- dataset_samsum_pt = dataset_samsum.map(convert_examples_to_features,
- batched=True)
-
- # 设置数据集格式为 Torch 张量类型,并指定列名
- columns = ["input_ids", "labels", "attention_mask"]
- dataset_samsum_pt.set_format(type="torch", columns=columns)
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
トークン化ステップには、tokenizer.as_target_tokenizer() コンテキストという新しいものがあります。一部のモデルではデコーダー入力に特別なトークンが必要なため、エンコーダー入力とデコーダー入力のトークン化ステップを分離することが重要です。 with ステートメント (コンテキスト マネージャーと呼ばれる) 内では、トークナイザーはデコーダー用にトークン化していることを認識します。
次に、データ オーガナイザーを作成する必要があります。ほとんどの場合、デフォルトのコレーターを使用できます。これは、すべてのテンソルをバッチで収集し、単純にスタックします。要約タスクでは、入力をスタックするだけでなく、デコーダ側でターゲットを準備する必要もあります。 PEGASUS はエンコーダ/デコーダ トランスフォーマであるため、古典的な seq2seq アーキテクチャを備えています。 seq2seq 設定では、デコーダで教師強制を適用するのが一般的なアプローチです。この戦略を使用すると、デコーダーはエンコーダーの出力に加えて、アノテーションによって右に 1 位置シフトされた入力トークン (GPT-2 などのデコーダー専用モデルと同じ) を受け取ります。したがって、次のトークンを予測するとき、デコーダーは、次の表に示すように、1 つ右にシフトされた真の値を入力として取得します。
- # 示例文本序列和标签生成过程
- 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')
操作結果:
ステップ | デコーダー入力 | ラベル |
1 | [パッド] | トランスフォーマー |
2 | [PAD、トランスフォーマー] | は |
3 | [PAD、トランスフォーマーは] | 素晴らしい |
4 | [PAD、トランスフォーマーは、すごい] | のために |
5 | [PAD、トランスフォーマーは、素晴らしいです、] | 文章 |
6 | [PAD、トランスフォーマーは、テキストとしては素晴らしい] | 要約 |
これを 1 つ右に移動して、デコーダが現在または将来の注釈ではなく、以前の正しい注釈のみを参照できるようにします。デコーダには、現在および将来のすべての入力をマスクするマスクされたセルフアテンション メカニズムがあるため、シフトするだけで十分です。
したがって、バッチを準備するときに、注釈を 1 つ右の位置に移動してデコーダーへの入力を設定します。その後、アノテーションで損失関数のフィラー トークンを -100 に設定することで、それらのトークンが無視されるようにします。実際には、DataCollatorForSeq2Seq がすべてを自動的に実行してくれるため、これらの手順を手動で実行する必要はありません。
- # 导入 Seq2Seq 数据集整理器模块
- from transformers import DataCollatorForSeq2Seq
-
- # 创建 Seq2Seq 数据集整理器实例
- seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
次に、いつものように、トレーニング用の TrainingArguments を設定します。
- # 导入训练参数和训练器模块
- from transformers import TrainingArguments, Trainer
-
- # 定义训练参数
- training_args = TrainingArguments(
- output_dir='pegasus-samsum', # 模型输出目录
- num_train_epochs=1, # 训练的轮数
- warmup_steps=500, # 学习率预热步数
- per_device_train_batch_size=1, # 每个设备的训练批次大小
- per_device_eval_batch_size=1, # 每个设备的评估批次大小
- weight_decay=0.01, # 权重衰减率
- logging_steps=10, # 训练日志记录步数
- push_to_hub=True, # 是否推送到模型中心
- evaluation_strategy='steps', # 评估策略
- eval_steps=500, # 评估步数间隔
- save_steps=1e6, # 模型保存步数间隔
- gradient_accumulation_steps=16 # 梯度累积步数
- )
以前の設定との違いは、今回は新しいパラメーター gradient_accumulation_steps があることです。モデルが非常に大きいため、バッチ サイズを 1 に設定する必要があります。ただし、バッチ サイズが小さすぎると収束に影響を与える可能性があります。この問題を解決するには、勾配累積と呼ばれる賢いトリックを使用できます。名前が示すように、バッチ全体の勾配を一度に計算するのではなく、バッチで勾配を計算して集計します。十分な勾配を集計したら、最適化ステップを実行します。これは当然、すべてを一度に実行するよりも遅くなりますが、GPU メモリを大幅に節約できます。
ここで、トレーニング後にモデルをハブにプッシュできるように、Hugging Face にログインします。
- from huggingface_hub import notebook_login
-
- notebook_login()
操作結果:
これで、モデル、トークナイザー、トレーニング パラメーター、データ オーガナイザー、トレーニングおよび評価データセットなど、トレーナーを初期化するために必要なものがすべて揃いました。
- from transformers import TrainingArguments, Trainer
-
- # 创建一个 Trainer 实例用于训练序列到序列模型。
- trainer = Trainer(
- model=model, # 要训练的序列到序列模型
- args=training_args, # 定义的训练参数
- tokenizer=tokenizer, # 用于预处理输入数据的分词器
- data_collator=seq2seq_data_collator, # 用于批处理数据的数据整理器
- train_dataset=dataset_samsum_pt["train"], # 训练数据集
- eval_dataset=dataset_samsum_pt["validation"] # 评估数据集
- )
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
トレーニングの準備はできています。トレーニングが完了したら、テスト セットに対して評価関数を直接実行して、モデルがどのように実行されたかを確認できます。
- from transformers import TrainingArguments, Trainer
-
- # 开始训练模型
- trainer.train()
-
- # 使用评估函数评估 Pegasus 模型的摘要质量
- score = evaluate_summaries_pegasus(
- dataset_samsum["test"], rouge_metric, trainer.model, tokenizer,
- batch_size=2, column_text="dialogue", column_summary="summary")
-
- # 提取 ROUGE 指标结果
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 创建 DataFrame 显示 ROUGE 指标
- pd.DataFrame(rouge_dict, index=[f"pegasus"])
操作結果:
(一時的なエラーがここで報告されます:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
、例を使用した参考の実行結果は次のとおりです)
ルージュ1 | ルージュ2 | ルージュL | ルージュルサム | |
ペガサス | 0.42761 | 0.200571 | 0.340648 | 0.340738 |
ROUGE スコアは微調整なしのモデルに比べて大幅に改善されていることがわかります。そのため、以前のモデルも概要生成用にトレーニングされましたが、新しいドメインにうまく適応できませんでした。モデルをハブにプッシュしましょう。
- # 将训练完成的模型推送到 Hub 上
- trainer.push_to_hub("Training complete!")
次に、このモデルを使用していくつかの概要を生成します。
生成された結果をトレーニング ループの一部として評価することもできます。Seq2SeqTrainingArguments という TrainingArguments 拡張機能を使用し、predict_with_generate=True を指定します。これを Seq2SeqTrainer という専用のトレーナーに渡します。このトレーナーは、モデルのフォワード パスの代わりにgenerate() 関数を使用して、評価用の予測を作成します。試してみる!
損失と ROUGE スコアを見ると、このモデルは CNN/DailyMail のみでトレーニングされた元のモデルと比較して大幅な改善を示しているようです。テスト セット内の 1 つのサンプルから生成された概要は次のようになります。
- import transformers
-
- # 设置transformers的日志级别为错误,以减少输出日志
- transformers.logging.set_verbosity_error()
-
- # 定义生成摘要时的参数
- gen_kwargs = {"length_penalty": 0.8, "num_beams": 8, "max_length": 128}
-
- # 从测试集中选择一个示例
- sample_text = dataset_samsum["test"][0]["dialogue"]
- reference = dataset_samsum["test"][0]["summary"]
-
- # 使用预训练的pegasus-samsum模型创建摘要管道
- pipe = pipeline("summarization", model="transformersbook/pegasus-samsum")
-
- # 输出对话和参考摘要
- print("Dialogue:")
- print(sample_text)
- print("nReference Summary:")
- print(reference)
-
- # 使用模型生成摘要并输出
- print("nModel Summary:")
- print(pipe(sample_text, **gen_kwargs)[0]["summary_text"])
操作結果:
Dialogue: Hannah: Hey, do you have Betty's number? Amanda: Lemme check Hannah: <file_gif> Amanda: Sorry, can't find it. Amanda: Ask Larry Amanda: He called her last time we were at the park together Hannah: I don't know him well Hannah: <file_gif> Amanda: Don't be shy, he's very nice Hannah: If you say so.. Hannah: I'd rather you texted him Amanda: Just text him 🙂 Hannah: Urgh.. Alright Hannah: Bye Amanda: Bye bye Reference Summary: Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry. Model Summary: Amanda can't find Betty's number. Larry called Betty last time they were at the park together. Hannah wants Amanda to text Larry instead of calling Betty.
これは参考資料の概要とよく似ています。このモデルは、単に文章を抽出するのではなく、会話を要約に合成することを学習したようです。次は最後のテストです。モデルはカスタム入力に対してどのように動作しますか?
- # 自定义对话示例
- custom_dialogue = """
- Thom: Hi guys, have you heard of transformers?
- Lewis: Yes, I used them recently!
- Leandro: Indeed, there is a great library by Hugging Face.
- Thom: I know, I helped build it ;)
- Lewis: Cool, maybe we should write a book about it. What do you think?
- Leandro: Great idea, how hard can it be?!
- Thom: I am in!
- Lewis: Awesome, let's do it together!
- """
-
- # 使用预训练的pegasus-samsum模型生成摘要,并输出摘要结果
- print(pipe(custom_dialogue, **gen_kwargs)[0]["summary_text"])
操作結果:
Thom and Lewis wanted to write a book about transformers. They came up with the idea with the help of Hugging Face's Leandro. The book will be called "Transformers: The Power of Transformers" and will be published in 2015. The project is currently in the planning stages.
生成されたカスタム会話の概要は理にかなっています。単に 1 つの文を抽出するのではなく、ディスカッションの参加者全員が一緒に本を書きたかった内容をうまく要約しています。たとえば、行 3 と行 4 を 1 つの論理的な組み合わせに結合します。