PEFT documentation
Adaptation de rang faible décomposée par poids (DoRA)
Adaptation de rang faible décomposée par poids (DoRA)
Il s’agit d’une variante de LoRA et, par conséquent, tout ce qui est possible avec LoRA s’applique à cette méthode, sauf indication contraire sur cette page.
Cette technique décompose les mises à jour des poids en deux parties, l’amplitude et la direction. La direction est gérée par LoRA standard, tandis que l’amplitude est gérée par un paramètre apprenable distinct. Cela peut améliorer les performances de LoRA, en particulier à faible rang. Pour plus d’informations sur DoRA, voir https://huggingface.co/papers/2402.09353.
from peft import LoraConfig
config = LoraConfig(use_dora=True, ...)Si des parties du modèle ou de l’adaptateur DoRA sont déchargées sur le CPU, vous pouvez obtenir une accélération significative au prix d’un léger surcoût temporaire (éphémère) en VRAM en utilisant ephemeral_gpu_offload=True dans config.runtime_config.
from peft import LoraConfig, LoraRuntimeConfig
config = LoraConfig(use_dora=True, runtime_config=LoraRuntimeConfig(ephemeral_gpu_offload=True), ...)Un PeftModel avec un adaptateur DoRA peut également être chargé avec le drapeau ephemeral_gpu_offload=True en utilisant la méthode from_pretrained ainsi que la méthode load_adapter.
from peft import PeftModel
model = PeftModel.from_pretrained(base_model, peft_model_id, ephemeral_gpu_offload=True)Optimisation
DoRA est optimisé (calculs plus rapides et moins de mémoire) pour les modèles en mode d'évaluation, ou lorsque dropout est réglé sur 0. Nous réutilisons le résultat de base dans ces cas pour obtenir l'accélération.
L'exécution de dora finetuning avec CUDA_VISIBLE_DEVICES=0 ZE_AFFINITY_MASK=0 time python examples/dora_finetuning/dora_finetuning.py --quantize --lora_dropout 0 --batch_size 16 --eval_step 2 --use_dora sur une 4090, avec l'accumulation de gradients réglée sur 2 et le nombre maximal d'étapes sur 20, a donné les observations suivantes :
| Sans optimisation | Avec l’optimisation | |
|---|---|---|
| durée d'exécution de l'entraînement (sec) | 359.7298 | 279.2676 |
| échantillons d'entraînement par seconde | 1.779 | 2.292 |
| étapes d'entraînement par seconde | 0.056 | 0.072 |
De plus, il est possible d’augmenter encore les performances d’exécution de DoRA en utilisant le contexte auxiliaire DoraCaching. Cela nécessite que le modèle soit en mode eval :
from peft.helpers import DoraCaching
model.eval()
with DoraCaching():
output = model(inputs)Pour meta-llama/Llama-3.1-8B, le script de benchmark de mise en cache DoRA montre que, par rapport à LoRA :
- DoRA sans mise en cache nécessite 139 % de temps supplémentaire
- DoRA sans mise en cache nécessite 4 % de mémoire supplémentaire
- DoRA avec mise en cache nécessite 17 % de temps supplémentaire
- DoRA avec mise en cache nécessite 41 % de mémoire supplémentaire
Le cache peut donc accélérer considérablement l'inférence avec DoRA, mais il nécessite également beaucoup plus de mémoire. Idéalement, si le cas d'usage le permet, il est préférable de fusionner l'adaptateur DoRA afin d'éviter à la fois la surcharge mémoire et celle liée au temps d'exécution.
Limites
- DoRA ne prend en charge que les couches embedding, linear et Conv2d pour le moment.
- DoRA introduit un surcoût plus important que le LoRA pur, il est donc recommandé de fusionner les poids pour l'inférence, voir LoraModel.merge_and_unload().
- DoRA devrait fonctionner avec des poids quantifiés via bitsandbytes (« QDoRA »). Toutefois, des problèmes ont été signalés lors de l’utilisation de QDoRA avec DeepSpeed Zero2.