PEFT documentation

Tamamen Parçalı Veri Paralelliği

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

and get access to the augmented documentation experience

to get started

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.

Creating Accelerate's config to use FSDP

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: false

Baş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 False

LoRA'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:

GPU memory usage for the training run

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: false

Baş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

  1. PEFT ve FSDP kullanırken birleştirme (merging) şu anda desteklenmemektedir ve hata oluşturacaktır.
  2. modules_to_save yapılandırma parametresinin geçirilmesi şu anda test edilmemiştir.
  3. CPU Offloading kullanılırken GPU bellek tasarrufu şu anda test edilmemiştir.
  4. FSDP+QLoRA kullanıldığında, paged_adamw_8bit şu anda bir kontrol noktası (checkpoint) kaydedilirken hata vermektedir.
  5. 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.
  6. FSDP2 ile set_adapter() ve set_requires_grad(), requires_grad değişikliklerinin parçalara ayrılmış parametrelere ulaşabilmesi için PeftModel içindeki FSDP2 modüllerini, PeftModel dahil 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ştirmenin requires_grad değ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=False kullanıldığında veya kök modül için varsayılan None durumunda, sonraki forward işlemi yeniden all-gather yapar. PeftModel’i saran FSDP2 modülleri yeniden parçalanmaz; bu yöntemleri çağırmadan önce bunlarda reshard() ç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.
Update on GitHub