Accelerate documentation

DeepSpeed ile birden fazla model kullanma

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

and get access to the augmented documentation experience

to get started

DeepSpeed ile birden fazla model kullanma

Bu kılavuz, DeepSpeed kullanım kılavuzunu okuduğunuzu ve anladığınızı varsayar.

Accelerate ve DeepSpeed ile birden fazla model çalıştırmak şunlar için faydalıdır:

  • Bilgi damıtma
  • RLHF gibi eğitim sonrası teknikleri (daha fazla örnek için TRL kütüphanesine bakın)
  • Aynı anda birden fazla model eğitimi

Şu anda Accelerate, birden fazla model kullanmanıza yardımcı olmak için çok deneysel bir API içerir.

Bu eğitim, iki yaygın kullanım senaryosuna odaklanacaktır:

  1. Bilgi damıtma (knowledge distillation), daha küçük bir öğrenci modelinin, daha büyük ve daha iyi performans gösteren bir öğretmene benzemesi için eğitildiği bir tekniktir. Öğrenci modeli tek bir GPU'ya sığıyorsa, eğitim için ZeRO-2'yi ve öğretmenin çıkarım (inference) için parçalanması (sharding) için ZeRO-3'ü kullanabiliriz. Bu, her iki model için de ZeRO-3 kullanmaktan önemli ölçüde daha hızlıdır.
  2. Birden fazla ayrık modeli aynı anda eğitme.

Bilgi damıtma

Bilgi damıtma, birden fazla model kullanmanın ancak bunlardan yalnızca birinin eğitilmesinin iyi bir örneğidir.

Normalde, her iki model için tek bir utils.DeepSpeedPlugin kullanırdınız. Ancak bu durumda, iki ayrı yapılandırma bulunmaktadır. Accelerate, yalnızca dict içinde olduklarında, gerektiğinde doğru eklentiyi referans alıp etkinleştirebilmeniz için birden fazla eklenti oluşturmanıza ve kullanmanıza yalnızca ve ancak izin verir.

from accelerate.utils import DeepSpeedPlugin

zero2_plugin = DeepSpeedPlugin(hf_ds_config="zero2_config.json")
zero3_plugin = DeepSpeedPlugin(hf_ds_config="zero3_config.json")

deepspeed_plugins = {"student": zero2_plugin, "teacher": zero3_plugin}

zero2_config.json tam eğitim için yapılandırılmalıdır (kendi scheduler ve optimizer bileşenlerinizi kullanmıyorsanız bunları belirtin), zero3_config.json ise aşağıdaki örnekte gösterildiği gibi yalnızca çıkarım modeli için yapılandırılmalıdır.

{
    "bf16": {
        "enabled": "auto"
    },
    "zero_optimization": {
        "stage": 3,
        "overlap_comm": true,
        "reduce_bucket_size": "auto",
        "stage3_prefetch_bucket_size": "auto",
        "stage3_param_persistence_threshold": "auto",
        "stage3_max_live_parameters": "auto",
        "stage3_max_reuse_distance": "auto",
    },
    "train_micro_batch_size_per_gpu": 1
}

Aşağıda zero2_config.json yapılandırmasının bir örneği gösterilmektedir.

{
    "bf16": {
        "enabled": "auto"
    },
    "optimizer": {
        "type": "AdamW",
        "params": {
            "lr": "auto",
            "weight_decay": "auto",
            "torch_adam": true,
            "adam_w_mode": true
        }
    },
    "scheduler": {
        "type": "WarmupLR",
        "params": {
            "warmup_min_lr": "auto",
            "warmup_max_lr": "auto",
            "warmup_num_steps": "auto"
        }
    },
    "zero_optimization": {
        "stage": 2,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": true
        },
    },
    "gradient_accumulation_steps": 1,
    "gradient_clipping": "auto",
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
}

DeepSpeed, bu belirli model eğitilmiyor olsa bile, train_micro_batch_size_per_gpu belirtilmediyse bir hata oluşturur.

Buradan itibaren tek bir Accelerator oluşturun ve her iki yapılandırmayı da iletin.

from accelerate import Accelerator

accelerator = Accelerator(deepspeed_plugins=deepspeed_plugins)

Şimdi bunların nasıl kullanılacağını görelim.

Öğrenci modeli

Varsayılan olarak Accelerate, dict içindeki ilk öğeyi varsayılan veya etkin eklenti olarak ("student" eklentisi) ayarlar. Hangi eklentinin etkin olduğunu görmek için utils.deepspeed.get_active_deepspeed_plugin() işlevini kullanarak bunu doğrulayın.

active_plugin = get_active_deepspeed_plugin(accelerator.state)
assert active_plugin is deepspeed_plugins["student"]

AcceleratorState, etkin DeepSpeed eklentisini de state.deepspeed_plugin içinde saklar.

assert active_plugin is accelerator.deepspeed_plugin

student şu anda etkin eklenti olduğundan, model, optimizör ve zamanlayıcıyı hazırlayalım.

student_model, optimizer, scheduler = ...
student_model, optimizer, scheduler, train_dataloader = accelerator.prepare(student_model, optimizer, scheduler, train_dataloader)

Şimdi sıra öğretmen modelini ele almaya geldi.

Öğretmen modeli

Öncelikle, zero3_config.json yapılandırmasının kullanılacağını Accelerator içinde belirtmeniz gerekir.

accelerator.state.select_deepspeed_plugin("teacher")

Bu, "student" eklentisini devre dışı bırakır ve bunun yerine "teacher" eklentisini etkinleştirir. Transformers içindeki DeepSpeed durumlu yapılandırması güncellenir ve deepspeed.initialize() kullanıldığında hangi eklenti yapılandırmasının çağrılacağını değiştirir. Bu sayede Transformers'ın sağladığı otomatik deepspeed.zero.Init bağlam yöneticisi entegrasyonunu kullanabilirsiniz.

teacher_model = AutoModel.from_pretrained(...)
teacher_model = accelerator.prepare(teacher_model)

Aksi takdirde, modeli deepspeed.zero.Init ile manuel olarak başlatmanız gerekir.

with deepspeed.zero.Init(accelerator.deepspeed_plugin.config):
    model = MyModel(...)

Eğitim

Buradan itibaren, teacher_model üzerinde asla eğitim yapılmadığı sürece eğitim döngünüz istediğiniz gibi olabilir.

teacher_model.eval()
student_model.train()
for batch in train_dataloader:
    with torch.no_grad():
        output_teacher = teacher_model(**batch)
    output_student = student_model(**batch)
    # Combine the losses or modify it in some way
    loss = output_teacher.loss + output_student.loss
    accelerator.backward(loss)
    optimizer.step()
    scheduler.step()
    optimizer.zero_grad()

Birden fazla ayrık modeli eğitin

Birden fazla model eğitmek daha karmaşık bir senaryodur. Mevcut haliyle, eğitim sırasında her modelin diğerinden tamamen bağımsız olduğunu varsayıyoruz.

Bu senaryoda hâlâ iki utils.DeepSpeedPlugin oluşturulması gerekir. Ancak farklı zamanlarda farklı deepspeed motorlarının çağrılması nedeniyle ikinci bir Accelerator da gereklidir. Tek bir Accelerator aynı anda yalnızca bir örneği taşıyabilir.

Ancak state.AcceleratorState durumlu bir nesne olduğu için, mevcut utils.DeepSpeedPlugin örneklerinin farkındadır. Ek argümanlar olmadan ikinci bir Accelerator örneği oluşturmanız yeterlidir.

first_accelerator = Accelerator(deepspeed_plugins=deepspeed_plugins)
second_accelerator = Accelerator()

Belirli bir eklentiyi etkinleştirmek veya devre dışı bırakmak için first_accelerator.state.select_deepspeed_plugin() çağrısını yapabilir ve ardından prepare çağrısını yapabilirsiniz.

# can be `accelerator_0`, `accelerator_1`, or by calling `AcceleratorState().select_deepspeed_plugin(...)`
first_accelerator.state.select_deepspeed_plugin("first_model")
first_model = AutoModel.from_pretrained(...)
# For this example, `get_training_items` is a nonexistent function that gets the setup we need for training
first_optimizer, first_scheduler, train_dl, eval_dl = get_training_items(model1)
first_model, first_optimizer, first_scheduler, train_dl, eval_dl = accelerator.prepare(
    first_model, first_optimizer, first_scheduler, train_dl, eval_dl
)

second_accelerator.state.select_deepspeed_plugin("second_model")
second_model = AutoModel.from_pretrained(...)
# For this example, `get_training_items` is a nonexistent function that gets the setup we need for training
second_optimizer, second_scheduler, _, _ = get_training_items(model2)
second_model, second_optimizer, second_scheduler = accelerator.prepare(
    second_model, second_optimizer, second_scheduler
)

Ve şimdi eğitebilirsiniz:

for batch in dl:
    outputs1 = first_model(**batch)
    first_accelerator.backward(outputs1.loss)
    first_optimizer.step()
    first_scheduler.step()
    first_optimizer.zero_grad()
    
    outputs2 = model2(**batch)
    second_accelerator.backward(outputs2.loss)
    second_optimizer.step()
    second_scheduler.step()
    second_optimizer.zero_grad()

Kaynaklar

Daha fazla örnek için lütfen [Accelerate] içindeki ilgili testlere göz atın.

Update on GitHub