Transformers documentation

Tinh chỉnh hiệu quả tham số

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Tinh chỉnh hiệu quả tham số

Phương pháp tinh chỉnh hiệu quả tham số (PEFT) chỉ tinh chỉnh một số lượng nhỏ các tham số mô hình bổ sung (adapter) trên nền một mô hình đã được huấn luyện trước. Vì chỉ các tham số adapter được cập nhật, bộ tối ưu hóa theo dõi ít gradient và trạng thái hơn nhiều, giúp giảm đáng kể lượng bộ nhớ sử dụng. Các adapter có kích thước nhẹ, khiến chúng thuận tiện để chia sẻ, lưu trữ và nạp.

Transformers tích hợp trực tiếp với thư viện PEFT thông qua PeftAdapterMixin, được thêm vào tất cả các lớp PreTrainedModel. Bạn có thể tải, thêm, huấn luyện, chuyển đổi và xóa các adapter mà không cần bọc mô hình của mình trong một PeftModel riêng biệt. Tất cả các phương pháp PEFT không dựa trên prompt đều được hỗ trợ (LoRA, IA3, AdaLoRA). Các phương pháp dựa trên prompt như prompt tuning và prefix tuning yêu cầu sử dụng trực tiếp PEFT library.

Cài đặt PEFT để bắt đầu. Tích hợp này yêu cầu peft >= 0.20.0.

pip install -U peft

Thêm một adapter

Tạo một cấu hình PEFT, chẳng hạn như LoraConfig, và gắn nó vào một mô hình bằng add_adapter().

from peft import LoraConfig, TaskType
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("google/gemma-2-2b")

lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    inference_mode=False,
    r=8,
    lora_alpha=32,
    lora_dropout=0.1,
)

model.add_adapter(lora_config, adapter_name="my_adapter")

Tinh chỉnh hoàn toàn các lớp cụ thể

Để huấn luyện các module bổ sung cùng với một adapter (ví dụ: đầu mô hình ngôn ngữ), hãy chỉ định chúng trong modules_to_save. modules_to_save chỉ định các lớp được tinh chỉnh hoàn toàn cùng với adapter, do đó tất cả tham số của chúng đều được cập nhật. Điều này hữu ích khi một số lớp cần được cập nhật, ví dụ như đầu mô hình ngôn ngữ (lm_head), khi điều chỉnh một LM nhân quả cho phân loại chuỗi.

lora_config = LoraConfig(
    modules_to_save=["lm_head"],
    ...
)
model.add_adapter(lora_config)

Chọn các lớp cần thích ứng

Đối với các kiến trúc phổ biến (Llama, Gemma, Qwen, v.v.), PEFT có các mục tiêu mặc định được định nghĩa sẵn (như q_proj và v_proj), vì vậy bạn không cần chỉ định target_modules. Nếu bạn muốn nhắm đến các lớp khác, hoặc mô hình không có các mục tiêu được định nghĩa sẵn, hãy truyền target_modules một cách tường minh dưới dạng danh sách tên module hoặc một mẫu regex.

lora_config = LoraConfig(
    target_modules=["q_proj", "k_proj"],
    ...
)
model.add_adapter(lora_config)

Huấn luyện

Truyền model có gắn adapter vào Trainer và gọi train(). Trainer chỉ cập nhật các tham số của adapter (những tham số có requires_grad=True) vì model cơ sở đã được đóng băng.

from transformers import Trainer, TrainingArguments

training_args = TrainingArguments(
    output_dir="./output",
    num_train_epochs=3,
    per_device_train_batch_size=4,
)

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

trainer.train()

Trong quá trình huấn luyện, các checkpoint của Trainer chỉ chứa trọng số adapter (adapter_model.safetensors) và cấu hình (adapter_config.json), giúp giữ cho các checkpoint có kích thước nhỏ. Mô hình cơ sở không được bao gồm.

Sau khi huấn luyện, hãy lưu adapter cuối cùng bằng save_pretrained().

model.save_pretrained("./my_adapter")

Tiếp tục từ một checkpoint

Trainer tự động phát hiện các checkpoint của adapter khi tiếp tục huấn luyện. Trainer quét thư mục checkpoint để tìm các thư mục con chứa trọng số adapter và nạp lại từng adapter với trạng thái có thể huấn luyện chính xác.

trainer.train(resume_from_checkpoint="./output/checkpoint-1000")

Huấn luyện phân tán

PEFT adapters hoạt động với huấn luyện phân tán ngay từ đầu.

Đối với ZeRO-3, Trainer truyền exclude_frozen_parameters=True khi lưu checkpoint với một mô hình PEFT. Các trọng số của mô hình cơ sở bị đóng băng sẽ được bỏ qua. Chỉ các tham số adapter có thể huấn luyện được lưu, giúp giảm kích thước checkpoint và thời gian lưu.

Đối với FSDP, Trainer cập nhật chính sách tự động bọc (auto-wrap) của FSDP để xử lý đúng các lớp LoRA. Đối với QLoRA (mô hình cơ sở lượng tử hóa + LoRA), Trainer cũng điều chỉnh chính thức độ chính xác hỗn hợp (mixed precision) để khớp với kiểu dữ liệu lưu trữ của lượng tử hóa.

Bạn có thể nạp các adapter PEFT lên một mô hình cơ sở song song tensor và để PEFT xử lý việc chia nhỏ trọng số adapter. Việc nạp adapter yêu cầu peft >= 0.21.1. Xem Song song tensor để biết về huấn luyện với TP.

Tải một adapter

Để tải một adapter, kho Hub hoặc thư mục cục bộ phải chứa tệp adapter_config.json và trọng số của adapter.

from_pretrained
load_adapter

from_pretrained() tự động phát hiện các adapter. Khi tìm thấy adapter_config.json, nó đọc trường base_model_name_or_path để tải đúng base model, sau đó tải adapter lên trên.

from transformers import AutoModelForCausalLM

# Automatically loads the base model and attaches the adapter
model = AutoModelForCausalLM.from_pretrained("klcsp/gemma7b-lora-alpaca-11-v1")

Đối với các mô hình lớn, hãy tải phiên bản lượng tử hóa ở độ chính xác 8-bit hoặc 4-bit bằng bitsandbytes để tiết kiệm bộ nhớ. Thêm device_map="auto" để phân phối mô hình trên các phần cứng khả dụng.

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

model = AutoModelForCausalLM.from_pretrained(
    "klcsp/gemma7b-lora-alpaca-11-v1",
    quantization_config=BitsAndBytesConfig(load_in_8bit=True),
    device_map="auto",
)

Quản lý nhiều bộ thích ứng

Một mô hình có thể chứa nhiều adapter cùng lúc. Thêm các adapter với tên duy nhất và chuyển đổi giữa chúng khi cần.

from peft import LoraConfig

model.add_adapter(LoraConfig(r=8, lora_alpha=32), adapter_name="adapter_1")
model.add_adapter(LoraConfig(r=16, lora_alpha=64), adapter_name="adapter_2")

Sử dụng set_adapter() để kích hoạt một adapter cụ thể. Các adapter khác sẽ bị vô hiệu hóa nhưng vẫn được giữ trong bộ nhớ.

model.set_adapter("adapter_2")

enable_adapters() kích hoạt tất cả các adapter đã gắn, và disable_adapters() vô hiệu hóa tất cả chúng.

# Disable all adapters for base model inference
model.disable_adapters()

# Re-enable all adapters
model.enable_adapters()

Sử dụng active_adapters() để xem các adapter nào đang hoạt động.

model.active_adapters()
# ["adapter_1"]

Xóa các adapter không còn cần thiết bằng delete_adapter() để giải phóng bộ nhớ.

model.delete_adapter("adapter_1")

Đổi adapter

Việc nạp một adapter mới mỗi khi phục vụ một yêu cầu sẽ cấp phát bộ nhớ mới. Nếu mô hình được biên dịch bằng torch.compile, mỗi adapter mới sẽ kích hoạt việc biên dịch lại. Hotswapping thay thế trọng số adapter tại chỗ, tránh được cả hai vấn đề trên. Chỉ hỗ trợ các adapter LoRA.

Truyền hotswap=True khi tải một adapter LoRA để thay thế trọng số của nó vào một slot adapter hiện có. Đặt adapter_name thành tên của adapter cần thay thế ("default" là tên adapter mặc định).

model = AutoModel.from_pretrained(...)
# Load the first adapter normally
model.load_adapter(adapter_path_1)
# Generate outputs with adapter 1
...
# Hotswap the second adapter in-place
model.load_adapter(adapter_path_2, hotswap=True, adapter_name="default")
# Generate outputs with adapter 2

torch.compile

Đối với các mô hình đã biên dịch, hãy gọi enable_peft_hotswap() trước khi nạp adapter đầu tiên và trước khi biên dịch.

model = AutoModel.from_pretrained(...)
max_rank = ...  # highest rank among all LoRAs you'll load
model.enable_peft_hotswap(target_rank=max_rank)
model.load_adapter(adapter_path_1, adapter_name="default")
model = torch.compile(model, ...)
output_1 = model(...)

# Hotswap without recompilation
model.load_adapter(adapter_path_2, adapter_name="default")
output_2 = model(...)

Tham số target_rank đặt bậc tối đa trong số tất cả các bộ thích ứng LoRA mà bạn sẽ nạp. Nếu bạn có các bộ thích ứng với bậc 8 và bậc 16, hãy truyền target_rank=16. Giá trị mặc định là 128.

Sau khi gọi enable_peft_hotswap, tất cả các lần gọi load_adapter tiếp theo sẽ hotswap theo mặc định. Truyền hotswap=False một cách rõ ràng để tắt hotswapping.

Việc biên dịch lại vẫn có thể xảy ra nếu adapter được thay thế nóng nhắm đến nhiều lớp hơn so với adapter ban đầu. Hãy tải adapter nhắm đến nhiều lớp nhất trước tiên để tránh việc biên dịch lại.

Bọc mã của bạn trong with torch._dynamo.config.patch(error_on_recompile=True) để phát hiện việc biên dịch lại không mong muốn. Nếu bạn phát hiện việc biên dịch lại dù đã làm theo các bước ở trên, hãy mở một issue với PEFT kèm theo một ví dụ tái hiện được.

Các bước tiếp theo

  • Tài liệu PEFT bao phủ toàn bộ các phương pháp và tùy chọn của PEFT.
  • Tài liệu tham chiếu về việc thay đổi nóng của PEFT nêu chi tiết các hạn chế và các trường hợp ngoại lệ.
  • Một bài đăng trên blog đo lường hiệu năng xem torch.compile với hotswapping cải thiện thời gian chạy như thế nào.
Update on GitHub