PEFT documentation
DeepSpeed
DeepSpeed
DeepSpeed adalah pustaka yang dirancang untuk kecepatan dan skala dalam pelatihan terdistribusi model besar dengan miliaran parameter. Inti dari pustaka ini adalah Zero Redundancy Optimizer (ZeRO) yang memecah (sharding) status optimizer (ZeRO-1), gradien (ZeRO-2), dan parameter (ZeRO-3) di antara proses paralel data. Hal ini secara drastis mengurangi penggunaan memori, memungkinkan Anda untuk menskalakan pelatihan hingga model dengan miliaran parameter. Untuk membuka efisiensi memori yang bahkan lebih besar, ZeRO-Offload mengurangi komputasi dan memori GPU dengan memanfaatkan sumber daya CPU selama optimasi.
Kedua fitur ini didukung di π€ Accelerate, dan Anda dapat menggunakannya dengan π€ PEFT.
Kompatibilitas dengan kuantisasi bitsandbytes + LoRA
Berikut adalah tabel yang merangkum kompatibilitas antara LoRA dari PEFT, pustaka bitsandbytes dan tahap DeepSpeed Zero terkait fine-tuning. DeepSpeed Zero-1 dan 2 tidak akan berdampak pada inferensi karena tahap 1 memecah (shard) status optimizer dan tahap 2 memecah status optimizer serta gradien:
| Tahap DeepSpeed | Apakah kompatibel? |
|---|---|
| Zero-1 | π’ |
| Zero-2 | π’ |
| Zero-3 | π’ |
Untuk DeepSpeed Stage 3 + QLoRA, silakan merujuk ke bagian Gunakan PEFT QLoRA dan DeepSpeed dengan ZeRO3 untuk finetuning model besar di beberapa GPU di bawah.
Untuk mengonfirmasi observasi ini, kami menjalankan skrip contoh resmi SFT (Supervised Fine-tuning) dari library Reinforcement Learning (TRL) Transformers menggunakan QLoRA + PEFT dan konfigurasi accelerate yang tersedia di sini. Kami menjalankan eksperimen ini pada 2x GPU NVIDIA T4.
Gunakan PEFT dan DeepSpeed dengan ZeRO3 untuk finetuning model besar di beberapa perangkat dan beberapa node
Bagian panduan ini akan membantu Anda mempelajari cara menggunakan skrip pelatihan DeepSpeed kami untuk melakukan SFT. Anda akan mengonfigurasi skrip tersebut untuk melakukan SFT (supervised fine-tuning) pada model Llama-70B dengan LoRA dan ZeRO-3 di 8xH100 80GB GPU pada satu mesin. Anda dapat mengonfigurasinya untuk diskalakan ke beberapa mesin dengan mengubah konfigurasi accelerate.
Konfigurasi
Mulai dengan menjalankan perintah berikut untuk membuat file konfigurasi DeepSpeed dengan π€ Accelerate. Flag --config_file memungkinkan Anda menyimpan file konfigurasi ke lokasi tertentu, jika tidak, file tersebut disimpan sebagai file default_config.yaml di cache π€ Accelerate.
File konfigurasi digunakan untuk mengatur opsi default saat Anda menjalankan skrip pelatihan.
accelerate config --config_file deepspeed_config.yaml
Anda akan diminta beberapa pertanyaan tentang konfigurasi Anda, dan mengatur argumen berikut. Dalam contoh ini, Anda akan menggunakan ZeRO-3, jadi pastikan Anda memilih opsi tersebut.
`zero_stage`: [0] Disabled, [1] optimizer state partitioning, [2] optimizer+gradient state partitioning and [3] optimizer+gradient+parameter partitioning
`gradient_accumulation_steps`: Number of training steps to accumulate gradients before averaging and applying them. Pass the same value as you would pass via cmd argument else you will encounter mismatch error.
`gradient_clipping`: Enable gradient clipping with value. Don't set this as you will be passing it via cmd arguments.
`offload_optimizer_device`: [none] Disable optimizer offloading, [cpu] offload optimizer to CPU, [nvme] offload optimizer to NVMe SSD. Only applicable with ZeRO >= Stage-2. Set this as `none` as don't want to enable offloading.
`offload_param_device`: [none] Disable parameter offloading, [cpu] offload parameters to CPU, [nvme] offload parameters to NVMe SSD. Only applicable with ZeRO Stage-3. Set this as `none` as don't want to enable offloading.
`zero3_init_flag`: Decides whether to enable `deepspeed.zero.Init` for constructing massive models. Only applicable with ZeRO Stage-3. Set this to `True`.
`zero3_save_16bit_model`: Decides whether to save 16-bit model weights when using ZeRO Stage-3. Set this to `True`.
`mixed_precision`: `no` for FP32 training, `fp16` for FP16 mixed-precision training and `bf16` for BF16 mixed-precision training. Set this to `True`.Setelah ini selesai, config yang sesuai seharusnya terlihat seperti di bawah ini dan dapat Anda temukan di folder config pada deepspeed_config.yaml:
compute_environment: LOCAL_MACHINE
debug: false
deepspeed_config:
deepspeed_multinode_launcher: standard
gradient_accumulation_steps: 4
offload_optimizer_device: none
offload_param_device: none
zero3_init_flag: true
zero3_save_16bit_model: true
zero_stage: 3
distributed_type: DEEPSPEED
downcast_bf16: 'no'
machine_rank: 0
main_training_function: main
mixed_precision: bf16
num_machines: 1
num_processes: 8
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: falsePerintah peluncuran
Perintah peluncuran tersedia di run_peft_deepspeed.sh dan juga ditampilkan di bawah ini:
accelerate launch --config_file "configs/deepspeed_config.yaml" train.py \
--seed 100 \
--model_name_or_path "meta-llama/Llama-2-70b-hf" \
--dataset_name "smangrul/ultrachat-10k-chatml" \
--chat_template_format "chatml" \
--add_special_tokens False \
--append_concat_token False \
--splits "train,test" \
--max_seq_len 2048 \
--num_train_epochs 1 \
--logging_steps 5 \
--log_level "info" \
--logging_strategy "steps" \
--eval_strategy "epoch" \
--save_strategy "epoch" \
--push_to_hub \
--hub_private_repo True \
--hub_strategy "every_save" \
--bf16 True \
--packing True \
--learning_rate 1e-4 \
--lr_scheduler_type "cosine" \
--weight_decay 1e-4 \
--warmup_steps 0 \
--max_grad_norm 1.0 \
--output_dir "llama-sft-lora-deepspeed" \
--per_device_train_batch_size 8 \
--per_device_eval_batch_size 8 \
--gradient_accumulation_steps 4 \
--gradient_checkpointing True \
--use_reentrant False \
--dataset_text_field "content" \
--use_flash_attn True \
--use_peft_lora True \
--lora_r 8 \
--lora_alpha 16 \
--lora_dropout 0.1 \
--lora_target_modules "all-linear" \
--use_4bit_quantization FalsePerhatikan bahwa kami menggunakan LoRA dengan rank=8, alpha=16 dan menargetkan semua lapisan linear. Kami meneruskan file konfigurasi deepspeed dan melakukan finetuning model Llama 70B pada subset dataset ultrachat.
Bagian-bagian penting
Mari kita selami skripnya sedikit lebih dalam agar Anda dapat melihat apa yang terjadi dan memahami cara kerjanya.
Hal pertama yang perlu diketahui adalah bahwa skrip ini menggunakan DeepSpeed untuk pelatihan terdistribusi karena konfigurasi DeepSpeed telah diberikan. Kelas SFTTrainer menangani seluruh proses pembuatan model PEFT menggunakan konfigurasi peft yang diberikan. Setelah itu, ketika Anda memanggil trainer.train(), SFTTrainer secara internal menggunakan π€ Accelerate untuk menyiapkan model, optimizer, dan trainer menggunakan konfigurasi DeepSpeed untuk membuat mesin DeepSpeed yang kemudian dilatih. Cuplikan kode utamanya ada di bawah ini:
# trainer
trainer = SFTTrainer(
model=model,
processing_class=tokenizer,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
peft_config=peft_config,
)
trainer.accelerator.print(f"{trainer.model}")
# train
checkpoint = None
if training_args.resume_from_checkpoint is not None:
checkpoint = training_args.resume_from_checkpoint
trainer.train(resume_from_checkpoint=checkpoint)
# saving final model
trainer.save_model()Penggunaan memori
Pada contoh di atas, memori yang dikonsumsi per GPU adalah 64 GB (80%) seperti yang terlihat pada tangkapan layar di bawah ini:

Sumber daya lainnya
Anda juga dapat merujuk pada artikel blog Falcon 180B Finetuning using π€ PEFT and DeepSpeed tentang cara melakukan finetuning model Falcon 180B pada 16 GPU A100 di 2 mesin.
Gunakan PEFT QLoRA dan DeepSpeed dengan ZeRO3 untuk finetuning model besar di beberapa GPU
Pada bagian ini, kita akan melihat cara menggunakan QLoRA dan DeepSpeed Stage-3 untuk finetuning model llama 70B pada 2X40GB GPU.
Untuk itu, kita pertama-tama membutuhkan bitsandbytes>=0.43.3, accelerate>=1.0.1, transformers>4.44.2, trl>0.11.4 dan peft>0.13.0. Kita perlu mengatur zero3_init_flag menjadi true saat menggunakan konfigurasi Accelerate. Berikut adalah konfigurasi yang dapat ditemukan di deepspeed_config_z3_qlora.yaml:
compute_environment: LOCAL_MACHINE
debug: false
deepspeed_config:
deepspeed_multinode_launcher: standard
offload_optimizer_device: none
offload_param_device: none
zero3_init_flag: true
zero3_save_16bit_model: true
zero_stage: 3
distributed_type: DEEPSPEED
downcast_bf16: 'no'
machine_rank: 0
main_training_function: main
mixed_precision: bf16
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: falsePerintah peluncuran diberikan di bawah ini yang tersedia di run_peft_qlora_deepspeed_stage3.sh:
accelerate launch --config_file "configs/deepspeed_config_z3_qlora.yaml" train.py \
--seed 100 \
--model_name_or_path "meta-llama/Llama-2-70b-hf" \
--dataset_name "smangrul/ultrachat-10k-chatml" \
--chat_template_format "chatml" \
--add_special_tokens False \
--append_concat_token False \
--splits "train,test" \
--max_seq_len 2048 \
--num_train_epochs 1 \
--logging_steps 5 \
--log_level "info" \
--logging_strategy "steps" \
--eval_strategy "epoch" \
--save_strategy "epoch" \
--push_to_hub \
--hub_private_repo True \
--hub_strategy "every_save" \
--bf16 True \
--packing True \
--learning_rate 1e-4 \
--lr_scheduler_type "cosine" \
--weight_decay 1e-4 \
--warmup_steps 0 \
--max_grad_norm 1.0 \
--output_dir "llama-sft-qlora-dsz3" \
--per_device_train_batch_size 2 \
--per_device_eval_batch_size 2 \
--gradient_accumulation_steps 2 \
--gradient_checkpointing True \
--use_reentrant True \
--dataset_text_field "content" \
--use_flash_attn True \
--use_peft_lora True \
--lora_r 8 \
--lora_alpha 16 \
--lora_dropout 0.1 \
--lora_target_modules "all-linear" \
--use_4bit_quantization True \
--use_nested_quant True \
--bnb_4bit_compute_dtype "bfloat16" \
--bnb_4bit_quant_storage_dtype "bfloat16"Perhatikan argumen baru yang diteruskan bnb_4bit_quant_storage_dtype yang menyatakan tipe data untuk pengemasan parameter 4-bit. Sebagai contoh, ketika diset ke bfloat16, 32/4 = 8 parameter 4-bit dikemas bersama setelah kuantisasi.
Dari segi kode pelatihan, perubahan kode yang penting adalah:
...
bnb_config = BitsAndBytesConfig(
load_in_4bit=args.use_4bit_quantization,
bnb_4bit_quant_type=args.bnb_4bit_quant_type,
bnb_4bit_compute_dtype=compute_dtype,
bnb_4bit_use_double_quant=args.use_nested_quant,
+ bnb_4bit_quant_storage=quant_storage_dtype,
)
...
model = AutoModelForCausalLM.from_pretrained(
args.model_name_or_path,
quantization_config=bnb_config,
trust_remote_code=True,
attn_implementation="flash_attention_2" if args.use_flash_attn else "eager",
+ dtype=quant_storage_dtype or torch.float32,
)Perhatikan bahwa dtype untuk AutoModelForCausalLM sama dengan tipe data bnb_4bit_quant_storage. Selesai. Hal lainnya ditangani oleh Trainer dan TRL.
Penggunaan memori
Pada contoh di atas, memori yang dikonsumsi per GPU adalah 36,6 GB. Oleh karena itu, yang sebelumnya membutuhkan 8X80GB GPU dengan DeepSpeed Stage 3+LoRA dan beberapa GPU 80GB dengan DDP+QLoRA, kini hanya memerlukan 2X40GB GPU. Hal ini membuat finetuning model besar menjadi lebih mudah diakses.
Gunakan PEFT dan DeepSpeed dengan ZeRO3 dan CPU Offloading untuk finetuning model besar pada satu GPU
Bagian panduan ini akan membantu Anda mempelajari cara menggunakan skrip pelatihan DeepSpeed kami. Anda akan mengonfigurasi skrip untuk melatih model besar untuk generasi kondisional dengan ZeRO-3 dan CPU Offload.
π‘ Untuk membantu Anda memulai, lihat skrip pelatihan contoh kami untuk causal language modeling dan conditional generation. Anda dapat menyesuaikan skrip ini untuk aplikasi Anda sendiri atau bahkan menggunakannya langsung jika tugas Anda mirip dengan yang ada di skrip.
Konfigurasi
Mulai dengan menjalankan perintah berikut untuk membuat file konfigurasi DeepSpeed dengan π€ Accelerate. Flag --config_file memungkinkan Anda menyimpan file konfigurasi ke lokasi tertentu, jika tidak, file tersebut disimpan sebagai file default_config.yaml di cache π€ Accelerate.
File konfigurasi digunakan untuk mengatur opsi default saat Anda menjalankan skrip pelatihan.
accelerate config --config_file ds_zero3_cpu.yaml
Anda akan diminta beberapa pertanyaan tentang konfigurasi Anda, dan mengatur argumen berikut. Dalam contoh ini, Anda akan menggunakan ZeRO-3 bersama dengan CPU-Offload, jadi pastikan Anda memilih opsi tersebut.
`zero_stage`: [0] Disabled, [1] optimizer state partitioning, [2] optimizer+gradient state partitioning and [3] optimizer+gradient+parameter partitioning
`gradient_accumulation_steps`: Number of training steps to accumulate gradients before averaging and applying them.
`gradient_clipping`: Enable gradient clipping with value.
`offload_optimizer_device`: [none] Disable optimizer offloading, [cpu] offload optimizer to CPU, [nvme] offload optimizer to NVMe SSD. Only applicable with ZeRO >= Stage-2.
`offload_param_device`: [none] Disable parameter offloading, [cpu] offload parameters to CPU, [nvme] offload parameters to NVMe SSD. Only applicable with ZeRO Stage-3.
`zero3_init_flag`: Decides whether to enable `deepspeed.zero.Init` for constructing massive models. Only applicable with ZeRO Stage-3.
`zero3_save_16bit_model`: Decides whether to save 16-bit model weights when using ZeRO Stage-3.
`mixed_precision`: `no` for FP32 training, `fp16` for FP16 mixed-precision training and `bf16` for BF16 mixed-precision training. Contoh file konfigurasi mungkin terlihat seperti berikut. Hal terpenting yang perlu diperhatikan adalah bahwa zero_stage diatur ke 3, dan offload_optimizer_device serta offload_param_device diatur ke cpu.
compute_environment: LOCAL_MACHINE
deepspeed_config:
gradient_accumulation_steps: 1
gradient_clipping: 1.0
offload_optimizer_device: cpu
offload_param_device: cpu
zero3_init_flag: true
zero3_save_16bit_model: true
zero_stage: 3
distributed_type: DEEPSPEED
downcast_bf16: 'no'
dynamo_backend: 'NO'
fsdp_config: {}
machine_rank: 0
main_training_function: main
megatron_lm_config: {}
mixed_precision: 'no'
num_machines: 1
num_processes: 1
rdzv_backend: static
same_network: true
use_cpu: falseBagian-bagian penting
Mari kita selami skripnya sedikit lebih dalam agar Anda dapat melihat apa yang terjadi dan memahami cara kerjanya.
Di dalam fungsi main, skrip membuat kelas Accelerator untuk menginisialisasi semua persyaratan yang diperlukan untuk pelatihan terdistribusi.
π‘ Silakan ubah model dan dataset di dalam fungsi
main. Jika format dataset Anda berbeda dari yang ada di skrip, Anda mungkin juga perlu menulis fungsi pra-pemrosesan Anda sendiri.
Skrip ini juga membuat konfigurasi untuk metode π€ PEFT yang Anda gunakan, yaitu LoRA dalam hal ini. LoraConfig menentukan jenis tugas dan parameter penting seperti dimensi matriks ber-rank rendah, faktor penskalaan matriks, dan probabilitas dropout dari lapisan LoRA. Jika Anda ingin menggunakan metode π€ PEFT yang berbeda, pastikan Anda mengganti LoraConfig dengan class yang sesuai.
def main():
+ accelerator = Accelerator()
model_name_or_path = "facebook/bart-large"
dataset_name = "twitter_complaints"
+ peft_config = LoraConfig(
task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1
)Sepanjang skrip, Anda akan melihat fungsi main_process_first dan wait_for_everyone yang membantu mengontrol dan menyinkronkan kapan proses dieksekusi.
Fungsi get_peft_model() menerima model dasar dan peft_config yang Anda siapkan sebelumnya untuk membuat PeftModel:
model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
+ model = get_peft_model(model, peft_config)Lewatkan semua objek pelatihan yang relevan ke prepare dari π€ Accelerate untuk memastikan semuanya siap untuk pelatihan:
model, train_dataloader, eval_dataloader, test_dataloader, optimizer, lr_scheduler = accelerator.prepare(
model, train_dataloader, eval_dataloader, test_dataloader, optimizer, lr_scheduler
)Bagian kode berikutnya memeriksa apakah plugin DeepSpeed digunakan dalam Accelerator, dan jika plugin tersebut ada, maka kami memeriksa apakah kami menggunakan ZeRO-3. Flag kondisional ini digunakan saat memanggil fungsi generate selama inferensi untuk menyinkronkan GPU ketika parameter model di-shard:
is_ds_zero_3 = False
if getattr(accelerator.state, "deepspeed_plugin", None):
is_ds_zero_3 = accelerator.state.deepspeed_plugin.zero_stage == 3Di dalam loop pelatihan, loss.backward() yang biasa digunakan diganti dengan backward dari π€ Accelerate yang menggunakan metode backward() yang benar berdasarkan konfigurasi Anda:
for epoch in range(num_epochs):
with TorchTracemalloc() as tracemalloc:
model.train()
total_loss = 0
for step, batch in enumerate(tqdm(train_dataloader)):
outputs = model(**batch)
loss = outputs.loss
total_loss += loss.detach().float()
+ accelerator.backward(loss)
optimizer.step()
lr_scheduler.step()
optimizer.zero_grad()Itu saja! Sisa dari skrip menangani loop pelatihan, evaluasi, dan bahkan mendorongnya ke Hub untuk Anda.
Latih
Jalankan perintah berikut untuk meluncurkan skrip pelatihan. Sebelumnya, Anda menyimpan file konfigurasi ke ds_zero3_cpu.yaml, jadi Anda perlu meneruskan path ke launcher dengan argumen --config_file seperti ini:
accelerate launch --config_file ds_zero3_cpu.yaml examples/conditional_generation/peft_lora_seq2seq_accelerate_ds_zero3_offload.py
Anda akan melihat beberapa log output yang melacak penggunaan memori selama pelatihan, dan setelah selesai, skrip mengembalikan akurasi dan membandingkan prediksi dengan label:
GPU Memory before entering the train : 1916
GPU Memory consumed at the end of the train (end-begin): 66
GPU Peak Memory consumed during the train (max-begin): 7488
GPU Total Peak Memory consumed during the train (max): 9404
CPU Memory before entering the train : 19411
CPU Memory consumed at the end of the train (end-begin): 0
CPU Peak Memory consumed during the train (max-begin): 0
CPU Total Peak Memory consumed during the train (max): 19411
epoch=4: train_ppl=tensor(1.0705, device='cuda:0') train_epoch_loss=tensor(0.0681, device='cuda:0')
100%|ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 7/7 [00:27<00:00, 3.92s/it]
GPU Memory before entering the eval : 1982
GPU Memory consumed at the end of the eval (end-begin): -66
GPU Peak Memory consumed during the eval (max-begin): 672
GPU Total Peak Memory consumed during the eval (max): 2654
CPU Memory before entering the eval : 19411
CPU Memory consumed at the end of the eval (end-begin): 0
CPU Peak Memory consumed during the eval (max-begin): 0
CPU Total Peak Memory consumed during the eval (max): 19411
accuracy=100.0
eval_preds[:10]=['no complaint', 'no complaint', 'complaint', 'complaint', 'no complaint', 'no complaint', 'no complaint', 'complaint', 'complaint', 'no complaint']
dataset['train'][label_column][:10]=['no complaint', 'no complaint', 'complaint', 'complaint', 'no complaint', 'no complaint', 'no complaint', 'complaint', 'complaint', 'no complaint']Catatan
- Merging saat menggunakan PEFT dan DeepSpeed saat ini tidak didukung dan akan memicu error.
- Saat menggunakan CPU offloading, keuntungan utama dari penggunaan PEFT untuk mengecilkan state optimizer dan gradien menjadi sebesar bobot adapter akan terealisasi pada RAM CPU, dan tidak akan ada penghematan terkait memori GPU.
- DeepSpeed Stage 3 dan qlora yang digunakan dengan CPU offloading menyebabkan penggunaan memori GPU yang lebih tinggi dibandingkan saat CPU offloading dinonaktifkan.
Update on GitHubπ‘ Ketika Anda memiliki kode yang memerlukan penggabungan (dan pemisahan) bobot, coba kumpulkan parameter secara manual dengan DeepSpeed Zero-3 terlebih dahulu:
import deepspeed is_ds_zero_3 = ... # check if Zero-3 with deepspeed.zero.GatheredParameters(list(model.parameters()), enabled= is_ds_zero_3): model.merge_adapter() # do whatever is needed, then unmerge in the same context if unmerging is required ... model.unmerge_adapter()