NLP Course documentation

使用 Trainer API 微調模型

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

使用 Trainer API 微調模型

Ask a Question Open In Colab Open In Studio Lab

🤗 Transformers提供了一個 Trainer 類來幫助您在自己的數據集上微調任何預訓練模型。完成上一節中的所有數據預處理工作後,您只需要執行幾個步驟來創建 Trainer .最難的部分可能是為 Trainer.train()配置運行環境,因為它在 CPU 上運行速度會非常慢。如果您沒有設置 GPU,您可以訪問免費的 GPU 或 TPUGoogle Colab.

下面的示例假設您已經執行了上一節中的示例。下面這段代碼,概括了您需要提前運行的代碼:

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)

Training

在我們定義我們的 Trainer 之前首先要定義一個 TrainingArguments 類,它將包含 Trainer用於訓練和評估的所有超參數。您唯一必須提供的參數是保存訓練模型的目錄,以及訓練過程中的檢查點。對於其餘的參數,您可以保留默認值,這對於基本微調應該非常有效。

from transformers import TrainingArguments

training_args = TrainingArguments("test-trainer")

💡 如果您想在訓練期間自動將模型上傳到 Hub,請將push_to_hub=True添加到TrainingArguments之中. 我們將在第四章中詳細介紹這部分。

第二步是定義我們的模型。正如在[之前的章節](/2_Using Transformers/Introduction)一樣,我們將使用 AutoModelForSequenceClassification 類,它有兩個參數:

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

你會注意到,和第二章不一樣的是,在實例化此預訓練模型後會收到警告。這是因為 BERT 沒有在句子對分類方面進行過預訓練,所以預訓練模型的頭部已經被丟棄,而是添加了一個適合句子序列分類的新頭部。警告表明一些權重沒有使用(對應於丟棄的預訓練頭的那些),而其他一些權重被隨機初始化(新頭的那些)。最後鼓勵您訓練模型,這正是我們現在要做的。

一旦我們有了我們的模型,我們就可以定義一個 Trainer 通過將之前構造的所有對象傳遞給它——我們的modeltraining_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 節中向您展示這部分處理仍然很重要!

為了讓預訓練模型在在我們的數據集上微調,我們只需要調用Trainertrain() 方法 :

trainer.train()

這將開始微調(在GPU上應該需要幾分鐘),並每500步報告一次訓練損失。但是,它不會告訴您模型的性能如何(或質量如何)。這是因為:

  1. 我們沒有通過將evaluation_strategy設置為“steps”(在每次更新參數的時候評估)或“epoch”(在每個epoch結束時評估)來告訴Trainer在訓練期間進行評估。
  2. 我們沒有為Trainer提供一個compute_metrics()函數來直接計算模型的好壞(否則評估將只輸出loss,這不是一個非常直觀的數字)。

評估

讓我們看看如何構建一個有用的 compute_metrics() 函數並在我們下次訓練時使用它。該函數必須採用 EvalPrediction 對象(帶有 predictionslabel_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 字段將只包含傳遞的數據集的loss,以及一些運行時間(預測所需的總時間和平均時間)。如果我們定義了自己的 compute_metrics() 函數並將其傳遞給 Trainer ,該字段還將包含compute_metrics()的結果。

predict() 方法是具有三個字段的命名元組: predictions , label_ids , 和 metrics .這 metrics 字段將只包含傳遞的數據集的loss,以及一些運行時間(預測所需的總時間和平均時間)。如果我們定義了自己的 compute_metrics() 函數並將其傳遞給 Trainer ,該字段還將包含compute_metrics() 的結果。如你看到的, predictions 是一個形狀為 408 x 2 的二維數組(408 是我們使用的數據集中元素的數量)。這些是我們傳遞給predict()的數據集的每個元素的結果(logits)(正如你在之前的章節看到的情況)。要將我們的預測的可以與真正的標籤進行比較,我們需要在第二個軸上取最大值的索引:

import numpy as np

preds = np.argmax(predictions.predictions, axis=-1)

現在建立我們的 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)

為了查看模型在每個訓練週期結束的好壞,下面是我們如何使用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()

這一次,它將在訓練loss之外,還會輸出每個 epoch 結束時的驗證loss和指標。同樣,由於模型的隨機頭部初始化,您達到的準確率/F1 分數可能與我們發現的略有不同,但它應該在同一範圍內。

Trainer 將在多個 GPU 或 TPU 上開箱即用,並提供許多選項,例如混合精度訓練(在訓練的參數中使用 fp16 = True )。我們將在第 10 章討論它支持的所有內容。

使用Trainer API微調的介紹到此結束。對最常見的 NLP 任務執行此操作的示例將在第 7 章中給出,但現在讓我們看看如何在純 PyTorch 中執行相同的操作。

✏️ 試試看! 使用您在第 2 節中進行的數據處理,在 GLUE SST-2 數據集上微調模型。