PEFT documentation
Tamamen Parçalı Veri Paralelliği
Tamamen Parçalı Veri Paralelliği
Fully sharded data parallel (FSDP), 1T parametreye kadar büyük ön eğitilmiş modellerin dağıtık eğitimi için geliştirilmiştir. FSDP, model parametrelerini, gradyanları ve optimizör durumlarını veri paralel süreçler arasında dilimleyerek (sharding) bunu başarır ve dilimlenmiş model parametrelerini bir CPU'ya aktarabilir (offload). FSDP'nin sağladığı bellek verimliliği, eğitimi daha büyük batch veya model boyutlarına ölçeklendirmenizi sağlar.
Her iki özellik de 🤗 Accelerate tarafından desteklenmektedir ve 🤗 PEFT ile birlikte kullanabilirsiniz.
PEFT ve FSDP kullanın
Bu kılavuz bölümü, SFT (denetimli ince ayar) işlemi için eğitim betiğimizi nasıl kullanacağınızı öğrenmenize yardımcı olacaktır. Betiği, tek bir makinede 8xH100 80GB GPU'larda Llama-70B modelini LoRA ve FSDP ile SFT yapmak üzere yapılandıracaksınız. accelerate yapılandırmasını değiştirerek birden fazla makineye ölçeklendirmek üzere yapılandırabilirsiniz.
Yapılandırma
🤗 Accelerate ile FSDP yapılandırma dosyası oluşturmak için aşağıdaki komutu çalıştırarak başlayın. --config_file bayrağı, yapılandırma dosyasını belirli bir konuma kaydetmenizi sağlar; aksi takdirde dosya, 🤗 Accelerate önbelleğinde default_config.yaml adıyla kaydedilir.
Yapılandırma dosyası, eğitim betiğini başlattığınızda varsayılan seçenekleri ayarlamak için kullanılır.
accelerate config --config_file fsdp_config.yaml
Kurulumunuzla ilgili birkaç soru sorulacak ve aşağıdaki argümanları yapılandıracaksınız. Bu örnekte, aşağıdaki görüntüde gösterildiği gibi anketi yanıtlayacaksınız.

Bu işlem tamamlandıktan sonra, ilgili yapılandırma aşağıdaki gibi görünmeli ve fsdp_config.yaml dosyası config klasöründe bulunabilir:
compute_environment: LOCAL_MACHINE
debug: false
distributed_type: FSDP
downcast_bf16: 'no'
fsdp_config:
fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
fsdp_backward_prefetch: BACKWARD_PRE
fsdp_cpu_ram_efficient_loading: true
fsdp_forward_prefetch: false
fsdp_offload_params: false
fsdp_sharding_strategy: FULL_SHARD
fsdp_state_dict_type: SHARDED_STATE_DICT
fsdp_sync_module_states: true
fsdp_use_orig_params: false
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: falseBaşlatma komutu
Başlatma komutu run_peft_fsdp.sh adresinde mevcuttur ve aşağıda da gösterilmektedir:
accelerate launch --config_file "configs/fsdp_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-fsdp" \
--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 FalseLoRA'nın rank=8, alpha=16 parametreleriyle ve tüm lineer katmanları hedef alacak şekilde kullanıldığını fark edin. FSDP yapılandırma dosyasını geçiriyor ve 70B Llama modelini ultrachat veri setinin bir alt kümesi üzerinde ince ayarlıyoruz.
Önemli kısımlar
Betik biraz daha derinlemesine inceleyelim, böylece neler olduğunu görebilir ve nasıl çalıştığını anlayabilirsiniz.
Bilmeniz gereken ilk şey, FSDP yapılandırmasının iletildiği için script'in dağıtık eğitimde FSDP kullandığıdır. SFTTrainer sınıfı, iletilen peft yapılandırmasını kullanarak PEFT modelini oluşturma işinin tamamını üstlenir. Ardından trainer.train() çağrıldığında, Trainer, FSDP yapılandırmasını kullanarak model, optimizer ve trainer'ı hazırlamak için içsel olarak 🤗 Accelerate'ı kullanır; bu sayede oluşturulan FSDP sarmalı model eğitilir. Ana kod parçası aşağıdadır:
# 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}")
if model_args.use_peft_lora:
# handle PEFT+FSDP case
trainer.model.print_healthcheck()
if getattr(trainer.accelerator.state, "fsdp_plugin", None):
from peft.utils.other import fsdp_auto_wrap_policy
fsdp_plugin = trainer.accelerator.state.fsdp_plugin
fsdp_plugin.auto_wrap_policy = fsdp_auto_wrap_policy(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
if trainer.is_fsdp_enabled:
trainer.accelerator.state.fsdp_plugin.set_state_dict_type("FULL_STATE_DICT")
trainer.save_model()Burada, FSDP'yi PEFT ile kullanırken şu anda dikkat edilmesi gereken ana nokta, GPU bellek tasarrufunu gerçekleştirmek için use_orig_params'in False olması gerektiğidir. use_orig_params=False nedeniyle, FSDP için otomatik sarma politikası, eğitilebilir ve eğitilemez parametrelerin ayrı ayrı sarılacak şekilde değiştirilmelidir. Bu, aşağıdaki kod parçasında PEFT'den fsdp_auto_wrap_policy yardımcı işlevini kullanarak yapılır:
if getattr(trainer.accelerator.state, "fsdp_plugin", None):
from peft.utils.other import fsdp_auto_wrap_policy
fsdp_plugin = trainer.accelerator.state.fsdp_plugin
fsdp_plugin.auto_wrap_policy = fsdp_auto_wrap_policy(trainer.model)Bellek kullanımı
Yukarıdaki örnekte, aşağıdaki ekran görüntüsünde de görüldüğü üzere GPU başına tüketilen bellek 72-80 GB (%90-98) civarındadır. Son kısımdaki hafif GPU bellek artışı, modelin çıkarım sırasında from_pretrained yöntemiyle normal şekilde yüklenebilecek adaptör ağırlıklarına sahip olması için SHARDED_STATE_DICT yerine FULL_STATE_DICT state dict türü kullanılarak kaydedilmesi sırasında gerçekleşir:

Büyük modelleri birden fazla GPU üzerinde ince ayarlamak için PEFT QLoRA ve FSDP kullanın
Bu bölümde, 70B llama modelini 2X24GB GPU'larda ince ayar yapmak için QLoRA ve FSDP'nin nasıl kullanılacağına bakacağız. Answer.AI, bitsandbytes ve Hugging Face 🤗 ile iş birliği içinde, FSDP+QLoRA kullanımını mümkün kılan kodu açık kaynak olarak yayımlamış ve tüm süreci içgörülü blog yazılarında You can now train a 70b language model at home açıkladı. Bu özellik artık Hugging Face ekosistemine entegre edildi.
Bunun için öncelikle bitsandbytes>=0.43.3, accelerate>=1.0.1, transformers>4.44.2, trl>0.11.4 ve peft>0.13.0 gereklidir. Accelerate yapılandırması kullanıldığında fsdp_cpu_ram_efficient_loading=true, fsdp_use_orig_params=false ve fsdp_offload_params=true (cpu offloading) değerlerini ayarlamamız gerekir. accelerate launcher kullanılmadığında, alternatif olarak export FSDP_CPU_RAM_EFFICIENT_LOADING=true ortam değişkenini ayarlayabilirsiniz. Burada accelerate config kullanacağız ve fsdp_config_qlora.yaml adresinde bulunabilen yapılandırma aşağıdaki gibidir:
compute_environment: LOCAL_MACHINE
debug: false
distributed_type: FSDP
downcast_bf16: 'no'
fsdp_config:
fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
fsdp_backward_prefetch: BACKWARD_PRE
fsdp_cpu_ram_efficient_loading: true
fsdp_forward_prefetch: false
fsdp_offload_params: true
fsdp_sharding_strategy: FULL_SHARD
fsdp_state_dict_type: SHARDED_STATE_DICT
fsdp_sync_module_states: true
fsdp_use_orig_params: false
machine_rank: 0
main_training_function: main
mixed_precision: 'no'
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: falseBaşlatma komutu, run_peft_qlora_fsdp.sh adresinde bulunan aşağıdaki gibidir:
accelerate launch --config_file "configs/fsdp_config_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-fsdp" \
--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"Geçirilen yeni argümanı, 4 bit parametrelerin paketlenmesi için veri türünü belirten bnb_4bit_quant_storage_dtype argümanını fark edin. Örneğin, bfloat16 olarak ayarlandığında, 16/4 = 4 adet 4 bit parametre, kuantizasyon sonrası birlikte paketlenir. bfloat16 ile karma hassasiyetli eğitim kullanıldığında, bnb_4bit_quant_storage_dtype saf bfloat16 ince ayarı için bfloat16 veya otomatik karma hassasiyet için (bu daha fazla GPU belleği tüketir) float32 olabilir. float16 ile karma hassasiyetli eğitim kullanıldığında, bnb_4bit_quant_storage_dtype kararlı otomatik karma hassasiyetli eğitim için float32 olarak ayarlanmalıdır.
Eğitim kodu açısından önemli kod değişiklikleri şunlardır:
...
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,
)AutoModelForCausalLM için dtype'nin, bnb_4bit_quant_storage veri tipiyle aynı olduğunu fark edin. Bu kadar. Geri kalan her şey Trainer ve TRL tarafından ele alınır.
Bellek kullanımı
Yukarıdaki örnekte, GPU başına tüketilen bellek 19.6 GB iken CPU RAM kullanımı yaklaşık 107 GB'dir. CPU offloading devre dışı bırakıldığında, GPU bellek kullanımı 35.6 GB/ GPU olur. Dolayısıyla, tam finetuning için 16X80GB GPU, FSDP+LoRA ile 8X80GB GPU ve DDP+QLoRA ile birkaç 80GB GPU gerektiren işlem, artık 2X24GB GPU ile yapılabilir. Bu, büyük modellerin finetuning'ini daha erişilebilir hale getirir.
Daha fazla kaynak
FSDP ve PEFT kullanarak ince ayar yapma konusunda llama-recipes deposuna ve Getting started with Llama kılavuzuna da başvurabilirsiniz.
Dikkat Edilmesi Gerekenler
- PEFT ve FSDP kullanırken birleştirme (merging) şu anda desteklenmemektedir ve hata oluşturacaktır.
modules_to_saveyapılandırma parametresinin geçirilmesi şu anda test edilmemiştir.- CPU Offloading kullanılırken GPU bellek tasarrufu şu anda test edilmemiştir.
- FSDP+QLoRA kullanıldığında,
paged_adamw_8bitşu anda bir kontrol noktası (checkpoint) kaydedilirken hata vermektedir. - FSDP ile DoRA eğitimi çalışmalıdır (LoRA'ya kıyasla daha düşük hızda). bitsandbytes ile birleştirildiğinde (QDoRA), 4-bit kuantizasyon da çalışmalıdır, ancak 8-bit kuantizasyonun bilinen sorunları vardır ve önerilmez.
- FSDP2 ile
set_adapter()veset_requires_grad(),requires_graddeğişikliklerinin parçalara ayrılmış parametrelere ulaşabilmesi için PeftModel içindeki FSDP2 modüllerini,PeftModeldahil olmak üzere yeniden parçalar (reshard).disable_adapter()içinden çıkış, yalnızca FSDP2’nin içinde kayıtlı parametre nesnelerini değiştirmesi (parçalara ayrılmış parametrelerde olduğu gibi bir forward’ın yaptığı gibi) veya yeniden etkinleştirmeninrequires_graddeğerini girişteki durumundan değiştirmesi durumunda bunu yapar. Birleştirilmiş (merged) bir adaptör katmanının parametrelerini parçalara ayıran FSDP2 modülleri yeniden parçalanmaz; bu nedenle bu yöntemleri çağırmadan önce birleştirmeyi geri alın (unmerge).reshard_after_forward=Falsekullanıldığında veya kök modül için varsayılanNonedurumunda, sonraki forward işlemi yeniden all-gather yapar.PeftModel’i saran FSDP2 modülleri yeniden parçalanmaz; bu yöntemleri çağırmadan önce bunlardareshard()çağrın. Bu çağrılar temel ağırlıkların parçalara ayrılmış halde kalmasına neden olabileceğinden, hemen ardından birleştirme işlemi doğru çalışmaz (bkz. 1). Prompt öğrenme yöntemleri ve adaption prompt henüz kapsam dışıdır.