本文介紹如何微調 T5 和 Llama-2 模型以進行摘要生成任務。首先使用 Hugging Face 的 datasets 函式庫載入 XSum 資料集,接著使用 transformers 函式庫中的 T5Tokenizer 對資料進行分詞和格式化,並使用 DataCollatorForSeq2Seq 進行資料整理。利用 Seq2SeqTrainer 簡化模型訓練流程,並使用 ROUGE 分數評估模型效能。最後,構建摘要生成管道,展示模型的摘要生成能力。更進一步,示範如何使用量化技術微調 Llama-2-7B-chat 模型,以減少記憶體佔用和提升訓練效率,包含提示格式化、Tokenizer 設定、模型載入和量化引數設定等步驟,提供完整程式碼和技術說明。
模型訓練準備
初始化模型
from transformers import AutoModelForSeq2SeqLM
model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint, device_map="auto")
內容解密:
- 使用
AutoModelForSeq2SeqLM從 Transformers 函式庫中載入預訓練的序列到序列模型。 device_map="auto"自動選擇適合的運算裝置(CPU 或 GPU)。
設定訓練引數
from transformers import Seq2SeqTrainingArguments
batch_size = 8
num_train_epochs = 8
logging_steps = len(tokenized_datasets["train"]) // batch_size
model_name = model_checkpoint.split("/")[-1]
args = Seq2SeqTrainingArguments(
output_dir=f"{model_name}-finetuned-xsum",
evaluation_strategy="epoch",
learning_rate=5.6e-5,
per_device_train_batch_size=batch_size,
per_device_eval_batch_size=batch_size,
weight_decay=0.01,
save_total_limit=3,
num_train_epochs=num_train_epochs,
predict_with_generate=True,
logging_steps=logging_steps,
)
內容解密:
- 設定訓練引數,包括批次大小、訓練輪數、學習率等。
evaluation_strategy="epoch"表示在每個訓練輪數結束後進行評估。
自定義評估指標計算函式
import numpy as np
def calculate_evaluation_metrics(prediction_data):
predicted, true_labels = prediction_data
translated_predictions = tokenizer.batch_decode(predicted, skip_special_tokens=True)
true_labels = np.where(true_labels != -100, true_labels, tokenizer.pad_token_id)
translated_labels = tokenizer.batch_decode(true_labels, skip_special_tokens=True)
formatted_predictions = ["\n".join(sent_tokenize(pred_text.strip())) for pred_text in translated_predictions]
formatted_labels = ["\n".join(sent_tokenize(label_text.strip())) for label_text in translated_labels]
rouge_results = rouge_score.compute(predictions=formatted_predictions, references=formatted_labels, use_stemmer=True)
scaled_results = {metric: score * 100 for metric, score in rouge_results.items()}
return {metric_key: round(score_value, 4) for metric_key, score_value in scaled_results.items()}
內容解密:
- 該函式用於計算模型的評估指標,主要涉及解碼預測結果和真實標籤,並計算 ROUGE 分數。
初始化資料整理器
from transformers import DataCollatorForSeq2Seq
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
內容解密:
DataCollatorForSeq2Seq負責動態填充輸入資料,以確保同一批次內的資料具有相同的長度。
資料預處理
tokenized_datasets = tokenized_datasets.remove_columns(xsum_dataset["train"].column_names)
內容解密:
- 清理 tokenized 資料集,移除不必要的欄位,以節省記憶體並簡化資料處理流程。
進階技術應用於大語言模型
微調T5模型進行摘要生成
在前面的章節中,我們已經瞭解瞭如何使用預訓練模型進行自然語言處理任務。現在,我們將探討如何微調T5模型以進行摘要生成。
首先,我們需要準備資料集。在這個例子中,我們使用了XSum資料集,這是一個用於訓練和評估摘要生成模型的標準資料集。
from datasets import load_dataset
xsum_dataset = load_dataset("xsum")
內容解密:
這段程式碼的作用是載入XSum資料集。load_dataset函式來自於Hugging Face的Datasets函式庫,它允許我們輕鬆地載入和處理各種自然語言處理資料集。
接下來,我們需要對資料進行預處理,包括分詞和格式化。
from transformers import T5Tokenizer
tokenizer = T5Tokenizer.from_pretrained("t5-small")
def preprocess_data(examples):
model_inputs = tokenizer(examples["document"], max_length=512, truncation=True)
with tokenizer.as_target_tokenizer():
labels = tokenizer(examples["summary"], max_length=128, truncation=True)
model_inputs["labels"] = labels["input_ids"]
return model_inputs
tokenized_datasets = xsum_dataset.map(preprocess_data, batched=True)
內容解密:
這段程式碼定義了一個預處理函式preprocess_data,它將原始文字資料轉換為模型可以接受的格式。tokenizer用於將文字分詞並轉換為輸入ID。max_length引數控制了輸入序列的最大長度,超出這個長度的序列將被截斷。labels代表了目標摘要,同樣被分詞和格式化。最後,預處理後的資料被儲存在tokenized_datasets中。
然後,我們需要定義一個資料整理器,用於將預處理後的資料整理成模型訓練所需的格式。
from transformers import DataCollatorForSeq2Seq
data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model="t5-small")
features = [tokenized_datasets["train"][i] for i in range(2)]
data_collator(features)
內容解密:
這段程式碼建立了一個DataCollatorForSeq2Seq例項,用於將預處理後的資料整理成模型訓練所需的格式。features變數包含了從訓練資料集中選取的一些樣本資料,data_collator將這些資料整理成批次。
接下來,我們初始化了一個Seq2SeqTrainer例項,用於進行模型的訓練。
from transformers import Seq2SeqTrainer
trainer = Seq2SeqTrainer(
model,
args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=calculate_evaluation_metrics,
)
內容解密:
這段程式碼設定了Seq2SeqTrainer,它是一個用於簡化模型訓練過程的工具。trainer被組態了模型、訓練引數、訓練和評估資料集、資料整理器、分詞器和評估指標計算函式。
最後,我們開始訓練模型。
trainer.train()
內容解密:
這行程式碼啟動了模型的訓練過程。train()方法會根據設定的引數和資料對模型進行訓練。
模型評估
在模型訓練完成後,我們需要對其進行評估,以瞭解其在未見資料上的表現。
trainer.evaluate()
內容解密:
這行程式碼對模型進行評估,使用的是驗證資料集。評估結果提供了模型的表現指標,例如ROUGE分數等。
初始化摘要生成管道
為了使用訓練好的模型進行摘要生成,我們需要初始化一個摘要生成管道。
from transformers import pipeline
model_id = "t5-small-finetuned-xsum/checkpoint-204000/"
summarizer = pipeline("summarization", model=model_id)
內容解密:
這段程式碼建立了一個摘要生成管道,使用的是微調後的T5模型。pipeline函式來自於Hugging Face的Transformers函式庫,它簡化了模型的佈署和使用。
測試摘要生成
最後,我們定義了一個函式,用於列印原始檔案和生成的摘要。
def print_summary(idx):
document = xsum_dataset["test"][idx]["document"]
summary = summarizer(xsum_dataset["test"][idx]["document"])[0]["summary_text"]
print(f"'>>> Document: {document}'")
print(f"\n'>>> Summary: {summary}'")
print_summary(100)
print_summary(0)
內容解密:
這段程式碼定義了一個函式print_summary,它接受一個索引,列印預出對應的檔案和生成的摘要。我們測試了兩個不同的索引,以展示模型的摘要生成能力。
使用解碼器模型進行抽象摘要生成
接下來,我們將探討如何使用解碼器模型(例如Llama-2-7B-chat)進行抽象摘要生成。同樣地,我們使用了XSum資料集來微調這個模型。
大語言模型的進階技術:Llama-2-chat-7B 微調實作
步驟 1:安裝函式庫與載入資料
本步驟與前一節相同,請參照之前的指示執行以下程式碼:
!pip install -U \
accelerate bitsandbytes datasets \
peft safetensors transformers trl
from datasets import load_dataset
# 載入訓練集中的前 1,000 筆資料
train_dataset = load_dataset("EdinburghNLP/xsum", split='train[:1000]')
train_dataset[0]
與前一節的不同之處在於,我們只使用了資料集的子集,即前 1,000 筆資料,以避免災難性遺忘(catastrophic forgetting),如第六章所述。
內容解密:
上述程式碼安裝了必要的函式庫,並載入了 EdinburghNLP/xsum 資料集的前 1,000 筆訓練資料。輸出的第一筆資料範例如下:
{'document': '...', 'summary': '...', 'id': '35232142'}
這裡的 document 是原始文字,summary 是對應的摘要。
步驟 2:資料前處理
我們將準備資料以微調 Llama-2-chat-7B 模型。首先,定義一個實用函式來格式化提示(prompt),指示大語言模型(LLM)進行摘要任務。
def prompt_formatter(sample):
return f"""<s>### 指示:
你是一個有幫助、尊重和誠實的助手。\
你的任務是摘要以下對話。\
你的答案應僅根據提供的對話。
### 對話:
{sample['document']}
### 摘要:
{sample['summary']} </s>"""
n = 0
print(prompt_formatter(train_dataset[n]))
內容解密:
prompt_formatter 函式接收一個 sample 引數,格式化一個提示字串,包含特殊標記和指示資訊,以便 LLM 能夠理解任務。該函式傳回一個格式化的字串,包含三個主要部分:
- 指示:提供明確的指示給 LLM,描述其任務和行為。
- 對話:包含需要被摘要的文字,即
sample['document']。 - 摘要:指定摘要的位置,使用
sample['summary']。
接下來,我們將設定資料集的 tokenizer:
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
內容解密:
首先,從預訓練模型 model_id 載入 tokenizer。然後,將 pad_token 設定為與 eos_token 相同,表示填充應該被視為句子結尾。最後,指定填充應該新增到序列的右側(結尾),以確保文字輸入的一致處理。
步驟 3:模型訓練
首先,使用量化技術設定預訓練模型 Llama-2-chat-7B 進行訓練:
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import prepare_model_for_kbit_training
# model_id = "meta-llama/Llama-2-7b-chat-hf"
model_id = "daryl149/llama-2-7b-chat-hf"
# 以 NF4 量化載入模型,啟用雙重量化,計算資料型別設為 bfloat16
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
內容解密:
上述程式碼載入了 Llama-2-chat-7B 模型,並使用 BitsAndBytesConfig 設定量化引數。量化技術能夠減少模型的記憶體佔用和計算需求,從而提高訓練效率。
此圖示呈現了模型的量化設定流程:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 微調T5與Llama2模型實作摘要生成
package "摘要生成微調" {
package "資料處理" {
component [XSum 資料集] as xsum
component [T5Tokenizer] as tokenizer
component [DataCollator] as collator
}
package "模型架構" {
component [T5 Seq2Seq] as t5
component [Llama-2-7B] as llama
component [量化技術] as quant
}
}
package "訓練與評估" {
component [Seq2SeqTrainer] as trainer
component [ROUGE 分數] as rouge
component [摘要管道] as pipeline
}
xsum --> tokenizer : 原始文本
tokenizer --> collator : Token IDs
collator --> t5 : 批次資料
collator --> llama : 批次資料
llama --> quant : 記憶體優化
t5 --> trainer : 訓練
trainer --> rouge : 效能評估
rouge --> pipeline : 摘要生成
note right of rouge
ROUGE 指標:
- 特徵選擇
- 特徵轉換
- 降維處理
end note
note right of eval
評估指標:
- 準確率/召回率
- F1 Score
- AUC-ROC
end note
@enduml圖表翻譯: 該圖表展示了使用量化技術訓練 Llama-2-chat-7B 模型的流程。首先載入模型,接著設定量化引數,然後啟用量化,最後開始訓練。
本章節介紹瞭如何使用量化技術微調 Llama-2-chat-7B 模型,包括資料準備、模型設定和訓練流程。透過這些步驟,可以有效地提高模型的效能和效率。