LLM 課程文件

監督式微調

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Ask a Question Open In Colab

監督式微調

監督式微調(SFT)主要用於使預訓練語言模型能夠遵循指令、進行對話以及使用特定的輸出格式。儘管預訓練模型具有令人印象深刻的通用能力,但 SFT 有助於將它們轉換為類似助手的模型,以便更好地理解和響應使用者提示。這通常透過對人類編寫的對話和指令資料集進行訓練來完成。

本頁提供了使用 SFTTrainer 微調 deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B 模型的逐步指南。透過遵循這些步驟,您可以使模型更有效地執行特定任務。

何時使用 SFT

在深入實施之前,瞭解何時將 SFT 作為專案選擇是重要的。第一步,您應該考慮使用現有指令微調模型和精心設計的提示是否足以滿足您的用例。SFT 涉及大量的計算資源和工程工作,因此只有當現有模型的提示不足時才應考慮使用。

僅在以下情況下考慮 SFT: - 您需要超出提示所能達到的額外效能 - 您有一個特定的用例,其中使用大型通用模型的成本高於微調小型模型的成本 - 您需要現有模型難以處理的特定輸出格式或領域特定知識

如果您確定 SFT 是必要的,則是否繼續取決於兩個主要因素

模板控制

SFT 允許精確控制模型的輸出結構。這在您需要模型執行以下操作時特別有價值

  1. 生成特定聊天模板格式的響應
  2. 遵循嚴格的輸出模式
  3. 在響應中保持一致的樣式

領域適應

在專業領域中,SFT 透過以下方式幫助模型與領域特定要求保持一致:

  1. 教授領域術語和概念
  2. 強制執行專業標準
  3. 適當處理技術查詢
  4. 遵循行業特定指南
在開始 SFT 之前,評估您的用例是否需要:- 精確的輸出格式 - 領域特定知識 - 一致的響應模式 - 遵守特定指南

此評估將有助於確定 SFT 是否是滿足您需求的正確方法。

資料集準備

監督式微調過程需要一個具有輸入-輸出對的特定任務資料集。每對應該包含

  1. 一個輸入提示
  2. 預期的模型響應
  3. 任何額外的上下文或元資料

訓練資料的質量對於成功的微調至關重要。讓我們看看如何準備和驗證資料集

訓練配置

微調的成功在很大程度上取決於選擇正確的訓練引數。讓我們探討每個重要引數以及如何有效地配置它們

SFTTrainer 配置需要考慮幾個控制訓練過程的引數。讓我們探討每個引數及其目的

  1. 訓練時長引數:

    • num_train_epochs:控制總訓練時長
    • max_steps: epoch 的替代,設定最大訓練步數
    • 更多 epoch 允許更好的學習,但有過度擬合的風險
  2. 批處理大小引數:

    • per_device_train_batch_size:決定記憶體使用和訓練穩定性
    • gradient_accumulation_steps:允許更大的有效批處理大小
    • 更大的批處理提供更穩定的梯度,但需要更多記憶體
  3. 學習率引數:

    • learning_rate:控制權重更新的大小
    • warmup_ratio:用於學習率預熱的訓練部分
    • 過高會導致不穩定,過低會導致學習緩慢
  4. 監控引數:

    • logging_steps:指標日誌記錄的頻率
    • eval_steps:在驗證資料上評估的頻率
    • save_steps:模型檢查點儲存的頻率
從保守值開始,並根據監控進行調整:- 從 1-3 個 epoch 開始 - 最初使用較小的批處理大小 - 密切監控驗證指標 - 如果訓練不穩定,調整學習率

TRL 實施

現在我們瞭解了關鍵元件,讓我們使用適當的驗證和監控來實施訓練。我們將使用 Transformers 強化學習 (TRL) 庫中的 SFTTrainer 類,該類建立在 transformers 庫之上。這是一個使用 TRL 庫的完整示例

from datasets import load_dataset
from trl import SFTConfig, SFTTrainer
import torch

# Set device
device = "cuda" if torch.cuda.is_available() else "cpu"

# Load dataset
dataset = load_dataset("HuggingFaceTB/smoltalk", "all")

# Configure model and tokenizer
model_name = "HuggingFaceTB/SmolLM2-135M"
model = AutoModelForCausalLM.from_pretrained(pretrained_model_name_or_path=model_name).to(
    device
)
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model_name)
# Setup chat template
model, tokenizer = setup_chat_format(model=model, tokenizer=tokenizer)

# Configure trainer
training_args = SFTConfig(
    output_dir="./sft_output",
    max_steps=1000,
    per_device_train_batch_size=4,
    learning_rate=5e-5,
    logging_steps=10,
    save_steps=100,
    eval_strategy="steps",
    eval_steps=50,
)

# Initialize trainer
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    processing_class=tokenizer,
)

# Start training
trainer.train()
當使用包含“messages”欄位的資料集(如上例)時,SFTTrainer 會自動應用模型的聊天模板,該模板從 hub 中檢索。這意味著您不需要任何額外的配置來處理聊天式對話——訓練器將根據模型預期的模板格式格式化訊息。

打包資料集

SFTTrainer 支援示例打包以最佳化訓練效率。此功能允許多個短示例打包到相同的輸入序列中,從而在訓練期間最大限度地利用 GPU。要啟用打包,只需在 SFTConfig 建構函式中將 packing 設定為 True。當使用 max_steps 打包資料集時,請注意您可能會根據打包配置訓練比預期更多的 epoch。您可以使用格式化函式自定義示例組合方式——這在使用具有多個欄位(如問答對)的資料集時特別有用。對於評估資料集,您可以透過在 SFTConfig 中將 eval_packing 設定為 False 來停用打包。以下是自定義打包配置的基本示例

# Configure packing
training_args = SFTConfig(packing=True)

trainer = SFTTrainer(model=model, train_dataset=dataset, args=training_args)

trainer.train()

當打包具有多個欄位的資料集時,您可以定義一個自定義格式化函式,將這些欄位組合成單個輸入序列。此函式應接受一個示例列表,並返回一個包含打包輸入序列的字典。以下是一個自定義格式化函式的示例

def formatting_func(example):
    text = f"### Question: {example['question']}\n ### Answer: {example['answer']}"
    return text


training_args = SFTConfig(packing=True)
trainer = SFTTrainer(
    "facebook/opt-350m",
    train_dataset=dataset,
    args=training_args,
    formatting_func=formatting_func,
)

監控訓練進度

有效的監控對於成功的微調至關重要。讓我們探討在訓練期間需要注意什麼

理解損失模式

訓練損失通常遵循三個不同的階段

  1. 初始急劇下降:快速適應新的資料分佈
  2. 逐漸穩定:隨著模型微調,學習率減慢
  3. 收斂:損失值穩定,表明訓練完成
SFTTrainer Training

要監控的指標

有效的監控包括跟蹤定量指標和評估定性指標。可用指標包括

  • 訓練損失
  • 驗證損失
  • 學習率進展
  • 梯度範數
在訓練期間注意這些警告訊號:1. 驗證損失增加而訓練損失減少(過擬合)2. 損失值沒有顯著改善(欠擬合)3. 損失值極低(可能記憶)4. 輸出格式不一致(模板學習問題)

收斂之路

隨著訓練的進行,損失曲線應逐漸穩定。健康訓練的關鍵指標是訓練損失和驗證損失之間存在很小的差距,這表明模型正在學習可泛化的模式,而不是記憶特定示例。絕對損失值將根據您的任務和資料集而有所不同。

監控訓練進度

上圖顯示了典型的訓練程序。請注意,訓練損失和驗證損失最初都急劇下降,然後逐漸趨於平穩。這種模式表明模型正在有效地學習,同時保持泛化能力。

需要注意的警告訊號

損失曲線中的幾種模式可以指示潛在問題。下面我們說明常見的警告訊號和我們可以考慮的解決方案。

SFTTrainer Training

如果驗證損失的下降速度明顯慢於訓練損失,則您的模型可能對訓練資料過度擬合。考慮

  • 減少訓練步驟
  • 增加資料集大小
  • 驗證資料集質量和多樣性
SFTTrainer Training

如果損失沒有顯著改善,模型可能

  • 學習速度過慢(嘗試提高學習率)
  • 難以完成任務(檢查資料質量和任務複雜性)
  • 達到架構限制(考慮不同的模型)
SFTTrainer Training

極低的損失值可能表明記憶而非學習。如果出現以下情況,這尤其令人擔憂

  • 模型在新穎的、類似的示例上表現不佳
  • 輸出缺乏多樣性
  • 響應與訓練示例過於相似
在訓練期間同時監控損失值和模型的實際輸出。有時損失看起來不錯,但模型卻產生了不必要的行為。對模型響應進行定期定性評估有助於發現僅靠指標可能遺漏的問題。

我們應該注意到,我們在此概述的損失值解釋主要針對最常見的情況,事實上,損失值可能會根據模型、資料集、訓練引數等表現出各種行為。如果您有興趣深入瞭解所概述的模式,您應該檢視 Fast AI 團隊的這篇部落格文章。

SFT 後的評估

11.4 節中,我們將學習如何使用基準資料集評估模型。目前,我們將重點關注模型的定性評估。

完成 SFT 後,考慮以下後續操作

  1. 在保留的測試資料上徹底評估模型
  2. 驗證各種輸入下的模板遵循情況
  3. 測試領域特定知識的保留
  4. 監控實際效能指標
記錄您的訓練過程,包括:- 資料集特徵 - 訓練引數 - 效能指標 - 已知限制。此文件對於未來的模型迭代將非常有價值。

測驗

1. SFT 中控制訓練時長的引數是什麼?

2. 損失曲線中的哪種模式表明可能出現過擬合?

3. gradient_accumulation_steps 的作用是什麼?

4. SFT 訓練期間應監控什麼?

5. 訓練期間健康的收斂表明什麼?

💐 幹得好!

您已經學會了如何使用 SFT 微調模型!要繼續學習,請

  1. 嘗試使用不同的引數執行 Notebook
  2. 嘗試使用其他資料集
  3. 為課程材料改進做出貢獻

其他資源

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.