並獲得增強文件體驗
開始使用
使用Trainer API微調模型
🤗 Transformers 提供了一個 Trainer 類,可以幫助您在您的資料集上微調它提供的任何預訓練模型。完成上一節中的所有資料預處理工作後,您只需執行幾個步驟即可定義 Trainer。最困難的部分可能是準備執行 Trainer.train() 的環境,因為它在 CPU 上執行速度會非常慢。如果您沒有設定 GPU,則可以在 Google Colab 上訪問免費的 GPU 或 TPU。
下面的程式碼示例假設您已經執行了上一節中的示例。這是一個簡短的摘要,回顧您需要的內容
from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding
raw_datasets = load_dataset("glue", "mrpc")
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
def tokenize_function(example):
return tokenizer(example["sentence1"], example["sentence2"], truncation=True)
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)訓練
在定義 Trainer 之前,第一步是定義一個 TrainingArguments 類,其中將包含 Trainer 用於訓練和評估的所有超引數。您必須提供的唯一引數是訓練好的模型將儲存到的目錄,以及儲存過程中的檢查點。對於所有其他引數,您可以保留預設值,這對於基本微調應該可以很好地工作。
from transformers import TrainingArguments
training_args = TrainingArguments("test-trainer")💡 如果您希望在訓練期間自動將模型上傳到 Hub,請在 TrainingArguments 中傳遞 push_to_hub=True。我們將在 第 4 章 中瞭解更多關於此內容。
第二步是定義我們的模型。與 上一章 一樣,我們將使用 AutoModelForSequenceClassification 類,有兩個標籤。
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)您會注意到,與 第 2 章 不同,在例項化此預訓練模型後,您會收到一個警告。這是因為 BERT 沒有在對句子對進行分類上進行預訓練,因此預訓練模型的頭已被丟棄,並且已添加了一個適合序列分類的新頭。警告表明一些權重未被使用(對應於已丟棄的預訓練頭的權重),而另一些權重則被隨機初始化(新頭的權重)。最後,它鼓勵您訓練模型,這正是我們現在要做的。
擁有模型後,我們可以透過將所有構造好的物件傳遞給它來定義 Trainer——model、training_args、訓練和驗證資料集、我們的 data_collator 和我們的 tokenizer。
from transformers import Trainer
trainer = Trainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
data_collator=data_collator,
tokenizer=tokenizer,
)請注意,當您像這裡這樣傳遞 tokenizer 時,Trainer 使用的預設 data_collator 將是之前定義的 DataCollatorWithPadding,因此您可以在此呼叫中跳過 data_collator=data_collator 這行。在第 2 節中向您展示處理的這一部分仍然很重要!
要對我們的資料集微調模型,我們只需要呼叫 Trainer 的 train() 方法。
trainer.train()
這將開始微調(在 GPU 上應該需要幾分鐘)並在每 500 步報告訓練損失。但是,它不會告訴您模型的效能如何(或有多差)。這是因為
- 我們沒有告訴
Trainer在訓練期間進行評估,方法是將evaluation_strategy設定為"steps"(每eval_steps步評估一次)或"epoch"(在每個 epoch 結束時評估)。 - 我們沒有為
Trainer提供compute_metrics()函式來在上述評估期間計算指標(否則評估只會列印損失,這並不是一個非常直觀的數字)。
評估
讓我們看看如何構建一個有用的 compute_metrics() 函式並在下次訓練時使用它。該函式必須接收一個 EvalPrediction 物件(它是一個名為元組,具有 predictions 欄位和 label_ids 欄位),並將返回一個字典,將字串對映到浮點數(字串是返回的指標的名稱,浮點數是其值)。要從模型中獲取一些預測,我們可以使用 Trainer.predict() 命令。
predictions = trainer.predict(tokenized_datasets["validation"])
print(predictions.predictions.shape, predictions.label_ids.shape)(408, 2) (408,)predict() 方法的輸出是另一個名為元組,具有三個欄位:predictions、label_ids 和 metrics。metrics 欄位將只包含傳遞給資料集的損失,以及一些時間指標(預測花費的時間,總時間和平均時間)。一旦我們完成了 compute_metrics() 函式並將其傳遞給 Trainer,該欄位還將包含 compute_metrics() 返回的指標。
如您所見,predictions 是一個二維陣列,形狀為 408 x 2(408 是我們使用的資料集中元素的數量)。這些是我們傳遞給 predict() 的資料集每個元素的 logits(正如您在 上一章 中看到的,所有 Transformer 模型都返回 logits)。要將它們轉換為可以與我們的標籤進行比較的預測,我們需要獲取第二軸上具有最大值的索引。
import numpy as np
preds = np.argmax(predictions.predictions, axis=-1)現在我們可以將這些 preds 與標籤進行比較。要構建我們的 compute_metric() 函式,我們將依賴於 🤗 Evaluate 庫中的指標。我們可以像載入資料集一樣輕鬆地載入與 MRPC 資料集關聯的指標,這次使用 evaluate.load() 函式。返回的物件有一個 compute() 方法,我們可以用它來進行指標計算。
import evaluate
metric = evaluate.load("glue", "mrpc")
metric.compute(predictions=preds, references=predictions.label_ids){'accuracy': 0.8578431372549019, 'f1': 0.8996539792387542}您獲得的確切結果可能會有所不同,因為模型頭的隨機初始化可能會改變它達到的指標。在這裡,我們可以看到我們的模型在驗證集上的準確率為 85.78%,F1 分數為 89.97。這是用於評估 GLUE 基準測試中 MRPC 資料集結果的兩個指標。 BERT 論文 中的表格報告了基本模型的 F1 分數為 88.9。那是 uncased 模型,而我們目前正在使用 cased 模型,這解釋了更好的結果。
將所有內容整合在一起,我們得到了我們的 compute_metrics() 函式。
def compute_metrics(eval_preds):
metric = evaluate.load("glue", "mrpc")
logits, labels = eval_preds
predictions = np.argmax(logits, axis=-1)
return metric.compute(predictions=predictions, references=labels)為了看到它在每個 epoch 結束時報告指標的實際應用,以下是如何使用此 compute_metrics() 函式定義一個新的 Trainer
training_args = TrainingArguments("test-trainer", evaluation_strategy="epoch")
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
trainer = Trainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)請注意,我們建立了一個新的 TrainingArguments,其 evaluation_strategy 設定為 "epoch",並建立了一個新的模型——否則,我們將只是繼續訓練我們已經訓練過的模型。要啟動新的訓練執行,我們執行
trainer.train()
這次,除了訓練損失之外,它還會在每個 epoch 結束時報告驗證損失和指標。同樣,由於模型的隨機頭部初始化,您達到的準確率/F1 分數可能與我們發現的略有不同,但應該在同一個範圍內。
Trainer 將在多個 GPU 或 TPU 上開箱即用,並提供許多選項,例如混合精度訓練(在訓練引數中使用 fp16 = True)。我們將在第 10 章中介紹它支援的所有內容。
這結束了使用 Trainer API 進行微調的介紹。在第 7 章中將提供針對大多數常見 NLP 任務的示例,但現在讓我們看看如何在純 PyTorch 中執行相同的操作。
✏️ 動手試試! 使用你在第 2 節中完成的資料處理,在 GLUE SST-2 資料集上微調模型。