AGI 之 【Hugging Face】 的【文本摘要】的 [評估PEGASUS ] / [ 微調PEGASUS ] / [生成對話摘要] 的簡單整理

AGI 之 【Hugging Face】 的【文本摘要】的 [評估PEGASUS ] / [ 微調PEGASUS ] / [生成對話摘要]? 的簡單整理

目錄

AGI 之 【Hugging Face】 的【文本摘要】的 [評估PEGASUS ] / [ 微調PEGASUS ] / [生成對話摘要]? 的簡單整理

一、簡單介紹

二、文本摘要

三、在CNN/DailyMail數據集上評估PEGASUS

四、訓練摘要模型

1、評估PEGASUS在SAMSum上的性能

2、微調PEGASUS

3、生成對話摘要


一、簡單介紹

AGI,即通用人工智能(Artificial General Intelligence),是一種具備人類智能水平的人工智能系統。它不僅能夠執行特定的任務,而且能夠理解、學習和應用知識于廣泛的問題解決中,具有較高的自主性和適應性。AGI的能力包括但不限于自我學習、自我改進、自我調整,并能在沒有人為干預的情況下解決各種復雜問題。

  • AGI能做的事情非常廣泛:

??? 跨領域任務執行:AGI能夠處理多領域的任務,不受限于特定應用場景。
??? 自主學習與適應:AGI能夠從經驗中學習,并適應新環境和新情境。
??? 創造性思考:AGI能夠進行創新思維,提出新的解決方案。
??? 社會交互:AGI能夠與人類進行復雜的社會交互,理解情感和社會信號。

  • 關于AGI的未來發展前景,它被認為是人工智能研究的最終目標之一,具有巨大的變革潛力:

??? 技術創新:隨著機器學習、神經網絡等技術的進步,AGI的實現可能會越來越接近。
??? 跨學科整合:實現AGI需要整合計算機科學、神經科學、心理學等多個學科的知識。
??? 倫理和社會考量:AGI的發展需要考慮隱私、安全和就業等倫理和社會問題。
??? 增強學習和自適應能力:未來的AGI系統可能利用先進的算法,從環境中學習并優化行為。
??? 多模態交互:AGI將具備多種感知和交互方式,與人類和其他系統交互。

Hugging Face作為當前全球最受歡迎的開源機器學習社區和平臺之一,在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)任務,需要輸入文本和目標文本。

文本摘要是一種自然語言處理任務,其目標是從一個長文本中提取出簡潔、重要的信息,生成一個簡短的版本。文本摘要可以分為兩種主要類型:抽取式摘要和生成式摘要。

  • 抽取式摘要

抽取式摘要通過選擇原始文本中的重要句子或段落,直接提取這些內容作為摘要。這種方法不改變原始文本中的詞語和句子結構。

實現原理:

  1. ??? 特征提取:首先,需要提取文本的各種特征,例如詞頻、句子位置、關鍵詞、命名實體等。
  2. ??? 重要性評分:基于提取的特征,計算每個句子的得分,以確定其重要性。
  3. ??? 句子選擇:根據重要性得分,選擇最重要的句子來構建摘要。

難點:

  1. ??? 重要性衡量:如何準確衡量句子的相對重要性。
  2. ??? 冗余消除:避免選擇內容重復的句子。

實現方式:

  1. ??? 基于規則的方法:使用預定義的規則和統計方法來選擇句子。
  2. ??? 機器學習方法:使用有監督的學習算法,根據訓練數據學習如何選擇重要句子。
  • 生成式摘要

生成式摘要通過理解原始文本并生成新的句子來概括其內容。這種方法可以創建更為自然和連貫的摘要,但也更加復雜。

實現原理:

  1. ??? 編碼器-解碼器架構:使用序列到序列(Seq2Seq)模型,其中編碼器將輸入文本編碼成上下文向量,解碼器根據上下文向量生成摘要。
  2. ??? 注意力機制:在解碼過程中,模型可以關注輸入文本的不同部分,從而生成更相關的內容。
  3. ??? 預訓練模型:使用預訓練的語言模型(如BERT、GPT等)來提高生成摘要的質量。

難點:

  1. ??? 內容連貫性:生成的摘要需要保持邏輯連貫,避免內容斷裂。
  2. ??? 信息完整性:確保生成的摘要包含原始文本中的關鍵信息。
  3. ??? 模型復雜度:生成式摘要模型通常比抽取式摘要模型更復雜,需要更多的計算資源和訓練數據。

實現方式:

  1. ??? 經典的 Seq2Seq 模型:如基于 LSTM 的編碼器-解碼器模型。
  2. ??? 預訓練的 Transformer 模型:如 BERTSUM、T5、BART 等。
  • Hugging Face 中的文本摘要

Hugging Face 提供了多種預訓練模型和工具,可以方便地實現文本摘要任務。以下是一些常用的文本摘要模型和使用方法:

  1. ?使用預訓練模型進行摘要

以下是使用 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)
  1. 支持的摘要模型

Hugging Face 提供了多種用于文本摘要的預訓練模型,包括但不限于:

  1. ??? BART (facebook/bart-large-cnn)
  2. ??? T5 (t5-small, t5-base, t5-large, t5-3b, t5-11b)
  3. ??? PEGASUS (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_inputstokenized_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/DailyMailPEGASUS

現在充分評估模型的條件都齊全了:我們擁有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"]

我們只需要把這些部分組合起來。首先,我們評估三句話基準模型的性能:

# 定義一個函數,用于評估基線模型生成的摘要
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上不到一小時就能完成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

運行結果:

 rouge1rouge2rougeLrougeLsum
baseline0.389280.1712960.2450610.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

,使用例子參考的運行結果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.434380.2108830.3071950.373231

這些數字非常接近論文中的結果。這里需要注意的是,損失和每個詞元的準確率在某種程度上與ROUGE分數解耦。損失與解碼策略無關,而ROUGE分數則強耦合。

由于ROUGE和BLEU比人工評估的損失或準確率更好,因此在構建文本生成模型時應重點關注它們,并仔細探索和選擇解碼策略。然而,這些指標遠非完美,因此應始終考慮人工評估。

現在我們已經有了評估函數,可以訓練我們自己的摘要模型了。

四、

至此,我們已經仔細研究了文本摘要和評估的許多細節,現在我們使用這些知識來訓練一個自定義的文本摘要模型!對于我們這個自定義應用,我們將使用三星開發的SAMSum數據集(https://oreil.ly/n1ggq),該數據集包含了一系列對話以及簡短的摘要。這些對話可以代表客戶與客服中心之間的互動,并以此生成準確的摘要以幫助改善客戶服務,并檢測客戶請求中的常見模式。我們先加載數據集并查看一個樣本:

# 從 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 byeSummary:
Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry.

對話看起來就像你通過短信或WhatsApp聊天一樣,包括了表情符號和為GIF準備的占位符。dialogue字段包含了完整的文本,而summary字段則是對話的摘要。在CNN/DailyMail數據集上進行微調的模型能夠處理這個數據集嗎?我們來看看!

1、評PEGASUSSAMSum

首先,我們將使用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

,使用例子參考的運行結果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.296170.0878030.2296040.229514

雖然結果并不太好,但這并不出乎意料,因為遠離了CNN/DailyMail數據分布。盡管如此,在訓練之前設置評估流程有兩個優點:我們可以直接使用度量指標來度量訓練的成功,而且我們有一個很好的基準。在我們的數據集上對模型進行微調應該會立即改善ROUGE度量指標,如果沒有改善,那么我們就知道我們的訓練循環出了問題。

2、微調PEGASUS

在我們對數據進行訓練之前,我們快速查看輸入和輸出的長度分布:

# 編碼訓練集中的對話文本和摘要,并計算其長度
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是一種編碼器-解碼器Transformer,因此具有經典的seq2seq架構。在seq2seq設置中,一種常見的方法是在解碼器中應用teacher?forcing。使用此策略時,解碼器接收輸入詞元(與僅包含解碼器的模型相同,如GPT-2),這些詞元由標注向右移動一個位置,除此之外還有編碼器輸出。因此,在預測下一個詞元時,解碼器將獲得向右移動一個位置的真實值作為輸入,如下表所示:

# 示例文本序列和標簽生成過程
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')

運行結果:

stepdecoder_inputlabel
1[PAD]Transformers
2[PAD, Transformers]are
3[PAD, Transformers, are]awesome
4[PAD, Transformers, are, awesome]for
5[PAD, Transformers, are, awesome, for]text
6[PAD, Transformers, are, awesome, for, text]summarization

我們將它向右移動一個位置,這樣解碼器只會看到前一個正確的標注,而不是當前或未來的標注。僅進行移位就足夠了,因為解碼器有一個掩碼自注意力機制,它會掩碼當前和未來的所有輸入。

因此,在準備批量時,我們通過將標注向右移動一個位置來設置解碼器的輸入。之后,我們通過將標注中的填充詞元設置為-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,這樣我們就可以在訓練后將模型推送到Hub上:

from huggingface_hub import notebook_loginnotebook_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

,使用例子參考的運行結果如下)

 rouge1rouge2rougeLrougeLsum
pegasus0.427610.2005710.3406480.340738

我們可以看到,ROUGE分數比沒有進行微調的模型有了顯著的提高,因此盡管之前的模型也是用于摘要生成訓練的,但它并沒有很好地適應新的領域。我們把我們的模型推送到Hub上吧:

# 將訓練完成的模型推送到 Hub 上
trainer.push_to_hub("Training complete!")

接下來我們將使用這個模型為我們生成一些摘要。

你也可以將生成的結果作為訓練循環的一部分進行評估:使用名為Seq2SeqTrainingArguments的TrainingArguments擴展,并指定predict_with_generate=True。將其傳給名為Seq2SeqTrainer的專用Trainer,該Trainer使用generate()函數而不是模型的前向傳遞來創建用于評估的預測。你動手試一試吧!

3、生成

從損失和ROUGE分數來看,該模型似乎比僅在CNN/DailyMail上訓練的原始模型表現出顯著的改進。從測試集中的一個樣本生成的摘要如下所示:

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 byeReference 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.

生成的自定義對話摘要很有意義。它很好地總結了討論中所有人都想一起寫書的內容,而不僅僅是提取單個句子。例如,它將第3行和第4行合成為一個邏輯組合。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45100.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

秋招突擊——7/9——MySQL索引的使用

文章目錄 引言正文B站網課索引基礎創建索引如何在一個表中查看索引為字符串建立索引全文索引復合索引復合索引中的排序問題索引失效的情況使用索引進行排序覆蓋索引維護索引 數據庫基礎——文檔資料學習整理創建索引刪除索引創建唯一索引索引提示復合索引聚集索引索引基數字符串…

C#基于任務的異步模式(TAP)

1、C#異步模式分類 基于任務的異步模式&#xff08;TAP&#xff09; 基于事件的異步模式&#xff08;EAP&#xff09;和異步編程模型模式&#xff08;APM&#xff09; 2、基于任務的異步模式&#xff08;TAP&#xff09; 基于任務的異步模式&#xff08;TAP&#xff09;用單個方…

從零手寫實現 nginx-28-error pages 指令

前言 大家好&#xff0c;我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的&#xff0c;可以參考我的另一個項目&#xff1a; 手寫從零實現簡易版 tomcat minicat 手寫 nginx 系列 …

夾子音轉換器matlab

操作過程點擊此處觀看 上段時間補習了一下傅里葉變化的知識&#xff0c;突發奇想可以根據此做一款聲音轉換器&#xff0c;使用工科神器Matlab進行完成&#xff0c;并且開發了可操作界面如下圖所示&#xff1a; 功能實現與描述 軟件中可以實現聲音的錄制、回放、文件的保存與…

【C++】動態內存分配(關于構造與析構函數的調用)動態數組類 動態創建多維數組 知識點+代碼學習記錄

一.動態內存分配相關知識點 1.堆和棧內存&#xff1a; 堆內存&#xff1a;動態分配的內存位于堆中&#xff0c;它不受作用域限制&#xff0c;由程序員控制其生命周期。 棧內存&#xff1a;局部變量和函數參數等自動分配的內存位于棧中&#xff0c;由編譯器自動管理。 2.new…

性能測試(2)

jmeter參數化 loadrunner Jmeter IP欺騙&#xff0c;也稱為IP欺詐&#xff0c;是指通過偽裝、篡改IP地址的方式&#xff0c;進行網絡攻擊或欺騙行為。這種行為可能會導致網絡安全問題&#xff0c;包括身份盜竊、數據泄露、DDoS攻擊等。為了保護自己的網絡安全&#xff0c;用戶…

MySQL-表的約束

文章目錄 一、空屬性二、默認值三、zerofill四、列描述五、主鍵刪除主鍵追加主鍵復合主鍵根據主鍵快速索引 六、自增長last_insert_id() 七、唯一鍵八、外鍵class表&#xff08;主表&#xff09;student表&#xff08;從表&#xff09; 一、空屬性 之前我們將表的機構&#xff…

單例模式java

并發的有序性會導致返回空指針 class A{private static volatil A a;private A(){}public A getInstance(){if(anull){synchronized(A.class){if(anull)anew A();}}return a; }anew A();這條語句&#xff0c;他需要&#xff1a;開辟空間&#xff0c;初始化空間&#xff0c;指針…

python熱門面試題三

面試題1&#xff1a;Python中的列表推導式是什么&#xff1f;請給出一個例子。 回答&#xff1a; 列表推導式&#xff08;List Comprehension&#xff09;是Python中一種非常強大且簡潔的構建列表的工具。它允許你通過一個表達式來創建一個新的列表&#xff0c;這個表達式定義…

無顯卡也可以玩大模型-MiniGPT-4篇

MiniGPT-4學習 1.Colab上部署MiniGPT-42.論文摘要3.模型架構4.模型訓練5.總結 1.Colab上部署MiniGPT-4 代碼&#xff1a; https://github.com/Czi24/Awesome-MLLM-LLM-Colab/blob/master/MLLM/MiniGPT-4-colab/MiniGPT-4.md 2.論文摘要 最近的 GPT-4 展示了非凡的多模式能力&…

【設計模式之美】【建造型】工廠模式:通過面向接口編程思路,串起業務流程

文章目錄 一. 簡單工廠&#xff08;Simple Factory&#xff09;第一種簡單工廠&#xff1a;面向接口編程與工廠類&#xff1a;劃分功能職責第二種&#xff1a;單例簡單工廠&#xff1a;節省內存和對象創建的時間 二. 工廠方法&#xff08;Factory Method&#xff09;&#xff1…

文心一言:如何備考軟考架構師

提問&#xff1a;軟考高級:架構師指導&#xff0c;有哪些考點、重點考點有哪些&#xff1f;需要如何備考&#xff1f;案例分析題如何做&#xff1f;論文如何寫&#xff1f; 文心一言回答1700字如下&#xff1a; 針對軟考高級架構師的考試&#xff0c;以下是對考點、重點考點、備…

DiffusionModel-Transformer知識回顧

論文鏈接&#xff1a; Attention Is All You Need CNN vs RNN vs Transformer CNN&#xff08;卷積神經網絡&#xff09; 特點&#xff1a; 局部連接&#xff1a;每個卷積神經元只與輸入數據的局部區域連接&#xff0c;這有助于捕捉局部特征。權重共享&#xff1a;卷積核的權重…

Android筆記:Constructor (xxx) has been changed after generation.

遇到此報錯時&#xff0c;onstructor (xxx) has been changed after generation.是因為修改了實體類字段后什么都不修改的話就會報這個錯 這條信息是關于代碼生成和代碼變更的警告。當你使用某些工具&#xff08;如注解處理器、代碼生成庫等&#xff09;來自動生成代碼時&…

運行在Linux上的程序越來越慢的排查思路

1、通過free -h 排查內存使用情況&#xff0c;是否內存滿了 2、通過df -h 排查磁盤的使用情況&#xff0c;磁盤是否沒有空間了 3、檢查系統資源配置情況&#xff0c;比如使用ulimit -a檢查當前會話的資源限制&#xff0c;如最大文件數、打開文件描述符數等&#xff0c;看是否…

清華計算幾何-ConvexHull(凸包)-求極點InTriangle/ToLeft Test

ConvexHull(凸包) 凸包是什么 凸包是計算幾何一個非常基礎核心的概念。我理解的凸包就是給定一個點集合, 最外圍的點的包圍體就是凸包。如下所示: 極點(ExtremityPoint) 給定的點集合中, 如果一個點存在一條直線, 讓其他所有點都在于該直線的同一側, 則該點為極點。 非極點 …

如何理解electron 的預加載腳本

在 Electron 應用中,預加載腳本(Preload Script)是一個非常重要的概念,它允許你在渲染進程(web 頁面)和主進程之間創建一個安全的橋梁。預加載腳本運行在 Node.js 環境中,但位于渲染進程的一個單獨的上下文中,這意味著它可以訪問 Node.js 的 API,但無法直接訪問 DOM。…

JavaScript進階(7) ----構造函數和原型對象

目錄 構造函數 prototype 定義&#xff1a; 使用場景&#xff1a; constructor 使用場景&#xff1a; 原型proto 原型鏈 定義 特點 instanceof 運算符 原型繼承的基本概念 在JavaScript中&#xff0c;構造函數和原型是面向對象編程的核心概念&#xff0c;它們共同構…

海康工業相機驅動

1.新建基于對話框的MFC程序&#xff0c;界面布局如下 2.修改控件ID&#xff0c;為控件綁定變量 3.創建全局變量&#xff0c;構造函數中初始化變量&#xff0c;初始化對話框界面&#xff0c;補齊各控件按鈕響應函數 全文程序如下&#xff1a; // MFC_GrabimageDlg.h : 頭文件 /…

【動態規劃Ⅰ】斐波那契、爬樓梯、楊輝三角

動態規劃—斐波那契系列 什么是動態規劃斐波那契數組相關題目509. 斐波那契數 Easy1137. 第 N 個泰波那契數 Easy 楊輝三角118. 楊輝三角 Easy 爬樓梯相關題目70. 爬樓梯 Easy746. 使用最小花費爬樓梯 Easy 什么是動態規劃 動態規劃是一種通過將原問題分解為相對簡單的子問題來…