PEFT documentation
LoRA dönüşümü
LoRA dönüşümü
LoRA olmayan PEFT modellerini LoRA modellerine dönüştürmeye izin veren işlevler.
Açıklama
PEFT, onlarca farklı parametre verimli ince ayar tekniğini destekler. Şu ana kadar en popüler olanı tartışmasız LoRA'dır. Bu durum, LoRA'yı destekleyen birçok başka paketin de var olduğu anlamına gelir. Örneğin, Diffusers, difüzyon modellerinin yeteneklerini değiştirmek için LoRA adaptörlerinin yüklenmesine olanak tanır. vLLM, LoRA adaptörleriyle modellerin sunulmasına (serving) izin verir. Bu iyi bir durum olmakla birlikte ne yazık ki LoRA dışındaki diğer PEFT yöntemleri nadiren desteklenmektedir. Dolayısıyla, belirli kullanım senaryonuz için başka bir PEFT yöntemi daha iyi çalışsa bile, aşağı akış (downstream) paketlerinin destek sunmaması nedeniyle bu yöntemi kullanmanız engellenebilir.
Burada olası bir çözüm sunuyoruz. PEFT, bir PEFT adaptörünü LoRA adaptörüne dönüştürmeye olanak tanıyan save_as_lora() ve convert_to_lora() olmak üzere iki işlev sunar. Şu an için tüm PEFT yöntemleri bunu desteklememektedir, ancak destekleyen bir yöntem kullanıyorsanız, sizin için en iyi çalışan PEFT yöntemiyle başlayıp ardından onu bir LoRA adaptörüymüş gibi kullanabilirsiniz.
Örnek
Dönüştürülen adaptör için LoRA rütbesi, rank argümanına 0'dan büyük bir int geçirerek sabit bir rütbe olarak ayarlanabilir veya rank argümanına 0 ile 1 arasında bir float geçirerek her katmana uyan dinamik bir rütbe olarak ayarlanabilir. Dinamik rütbe, daha verimli olabilir (daha az parametreyle aynı performans).
Sabit LoRA rütbesi
save_as_lora() kullanımı oldukça basittir:
from peft import get_peft_model, save_as_lora
# first load and train your non-LoRA PEFT model as normal
base_model = ...
non_lora_config = ...
model = get_peft_model(base_model, non_lora_config)
# check that this PEFT method can indeed be converted to LoRA
assert model.supports_lora_conversion()
... # train the model
# the rank of the LoRA adapter that you want to convert to
target_rank = 64
# save as a LoRA checkpoint
save_as_lora(output_path, model, rank=target_rank)Bu işlem, herhangi bir LoRA adaptörü gibi yükleyebileceğiniz veya Diffusers veya vLLM gibi aşağı akış paketlerinde kullanabileceğiniz bir LoRA kontrol noktasını output_path konumunda oluşturur.
convert_to_lora() fonksiyonu, dönüştürülen LoRA adaptörünü kaydetmek yerine dönüştürülmüş ağırlıkları hemen kullanmak istediğinizde, örneğin değerlendirmeler yapmak için, faydalıdır:
from peft import convert_to_lora, get_peft_model, set_peft_model_state_dict
base_model = ...
non_lora_config = ...
model = get_peft_model(base_model, non_lora_config)
... # train the model
# get the lora config and state dict of the converted lora model
lora_config, lora_state_dict = convert_to_lora(model, rank=target_rank)
# reload the base model, or use model.unload()
base_model = ...
# apply the lora config to the base model
lora_model = get_peft_model(base_model, lora_config)
# load the LoRA weights onto the base model
set_peft_model_state_dict(lora_model, state_dict)Dinamik LoRA rütbesi
Yukarıdaki örneklerde, dönüşüm için sabit bir LoRA rütbesi kullandık. Ancak, bazı katmanların doğru bir şekilde dönüştürülmesi için yüksek bir rütbeye ihtiyaç duymadığı, diğer katmanların ise daha yüksek bir rütbe gerektirdiği düşünülebilir. Bunu karşılamak için PEFT, rank argümanı olarak 0 ile 1 arasında bir ondalık sayı geçme seçeneği sunar. Diyelim ki rank=0.5 geçtiniz. Bu, her katman için LoRA adaptörünün rütbesinin, orijinal adaptörün ağırlıklara getirdiği varyansın %50'sini açıklayacak şekilde seçildiği anlamına gelir. Daha teknik bir ifadeyle, perdenin arkasında adaptörün ağırlık katkısına bir Singular Value Decomposition uyguluyor ve normalize edildiğinde geçirilen değere eşitlenen en üst tekil değerleri alıyoruz.
# set a dynamic rank by passing a float
threshold = 0.7
# save as a LoRA checkpoint
save_as_lora(output_path, model, rank=threshold)
# get the lora config and state dict directly:
lora_config, lora_state_dict = convert_to_lora(model, rank=threshold)
# inspect the different ranks per layer:
print(lora_config.rank_pattern)Farklı katmanların katkısının büyük ölçüde değiştiği durumlarda bu tür dinamik LoRA rütbesi kullanmak faydalı olabilir. Dezavantajı, bazı katmanların çok yüksek bir LoRA rütbesine sahip olması gerekebilecek ve bunun bellek sıçramalarına yol açabilmesidir. Lütfen kullanım senaryonuz için en iyi sonucu veren ayarı test edin.
Modelin derlenmesi
Büyük modeller için dönüştürme işlemi biraz zaman alabilir; örneğin her PEFT modülü bir SVD hesaplama işleminden geçmelidir. compile_kwargs parametresini save_as_lora() veya convert_to_lora() fonksiyonlarına ileterek, dönüştürme fonksiyonuna torch.compile uygulayabilir ve süreci potansiyel olarak hızlandırabilirsiniz. compile_kwargs, torch.compile fonksiyonuna iletilen anahtar kelime argümanlarından oluşan bir sözlüktür (boş sözlük de çalışır). Aşağıda bir örnek bulunmaktadır:
compile_kwargs = {"dynamic": True, "mode": "max-autotune-no-cudagraphs", "fullgraph": True}
save_as_lora(output_path, model, rank=rank, compile_kwargs=compile_kwargs)LoRA'dan LoRA'ya dönüştürme
Bir LoRA adaptörünü başka bir LoRA adaptörüne dönüştürmek de mümkündür. Bunu neden yapmak istersiniz? Bunun bir nedeni vardır: LoRA adaptörünün rütbesini (rank) azaltmak istiyorsanız. Eğitimden sonra LoRA adaptörünü küçültmek istiyorsanız, save_as_lora() veya convert_to_lora() fonksiyonlarını kullanın ve daha küçük bir rütbe değeri iletin. Bu işlem, daha küçük bir bellek ve depolama alanı gerektiren yeni bir LoRA adaptörü oluşturur.
Metrikler
LoRA olmayandan LoRA'ya dönüştürme
Elbette, bir PEFT adaptörünü başka bir adaptöre dönüştürmek kayıplı bir süreçtir. Yeni adaptör, büyük olasılıkla başlangıçtaki adaptör kadar iyi performans göstermeyecektir. Bu nedenle, dönüştürülen LoRA adaptörünü değerlendirmeniz şiddetle tavsiye edilir. Bu sayede, dönüştürülen adaptörün kullanım senaryonuz için yeterince iyi performans gösterdiğinden emin olabilirsiniz. Genel kural, LoRA adaptörünün rütbesi ne kadar yüksekse, başlangıçtaki adaptörünüzü o kadar iyi yakınsayacağı yönündedir. Bu, benzer bir performans elde etmek için dönüştürülen LoRA adaptörünün orijinal adaptöre kıyasla daha fazla parametreye ihtiyaç duyabileceği anlamına gelir.
Örnek olarak, PEFT MetaMathQA benchmark üzerinde türetilen bazı sayılar aşağıdadır. Bunun için, meta-llama/Llama-3.2-3B modeli MetaMathQA üzerinde ince ayar yapmak üzere LoHa adaptörü kullanılmış ve GSM8K üzerinde değerlendirilmiştir. Başlangıçtaki LoKr adaptörünün rütbesi 32 idi; bu, 18.350.080 eğitilebilir parametreye ve %41,85 test doğruluğuna yol açmıştır. Değerlendirme 12,25 GB bellek gerektirmiştir. Kontrol noktası, rank için farklı değerlerle LoRA'ya dönüştürülmüştür. Elde edilen sonuç şudur:
| rank | eğitilebilir parametreler | test doğruluğu (%) | doğruluk değişimi | ayrılan bellek (maks., GB) | bellek artışı |
|---|---|---|---|---|---|
| 8 | 2293760 | 37.60 | -4.25 | 12.41 | 0.16 |
| 16 | 4587520 | 38.89 | -2.96 | 12.15 | -0.10 |
| 32 | 9175040 | 40.11 | -1.74 | 12.41 | 0.16 |
| 64 | 18350080 | 39.20 | -2.65 | 12.18 | -0.07 |
| 0.4 | 2428928 | 37.60 | -4.25 | 12.41 | 0.16 |
| 0.5 | 4761600 | 40.18 | -1.67 | 12.41 | 0.16 |
| 0.6 | 8857600 | 39.42 | -2.43 | 12.41 | 0.16 |
| 0.7 | 16230400 | 39.04 | -2.81 | 12.15 | -0.10 |
Gördüğünüz gibi, rank yeterince yüksekse, orijinal LoHa adaptörüne yakın bir test doğruluğuna ulaşabiliriz. Doğru rankı seçmek, model performansı ile model verimliliği arasında bir denge gerektirir. Bu deneyi yeniden oluşturmak için https://github.com/huggingface/peft/tree/main/scripts/evaluate-lora-conversion.py adresindeki betiği izleyin.
Eğitilebilir parametre sayısının bellek kullanımına birebir karşılık gelmediğine dikkat edin. Aynı eğitimlenebilir parametre sayısına sahip olsalar bile, bazı PEFT yöntemleri daha fazla, bazıları daha az bellek gerektirir. Bu nedenle, dönüştürme sonrasında LoRA adaptörü orijinalinden daha fazla parametreye sahip olsa bile, sunum sırasında hâlâ daha bellek verimli olabilir.
LoRA'dan LoRA'ya dönüştürme
Yukarıdaki deneyde olduğu gibi, LoRA'dan LoRA'ya dönüştürmeyi (yani LoRA sıkıştırmasını) da değerlendirebiliriz. Burada, RS-LoRA ile yukarıdakiyle aynı kurulumda eğitilen, 64 rütbeli bir LoRA adaptörüyle başlıyoruz. Başlangıç adaptörünün 18.350.080 eğitilebilir parametresi, %52,92 test doğruluğu vardır ve değerlendirme için 12,58 GB bellek gerektirir. Aşağıdaki tablo, bu adaptörün daha küçük rütbeli LoRA adaptörlerine dönüştürülmesinin sonuçlarını göstermektedir:
| rank | eğitilebilir parametreler | test doğruluğu (%) | doğruluk değişimi | ayrılan bellek (maks., GB) | bellek artışı |
|---|---|---|---|---|---|
| 8 | 2293760 | 43.37 | -9.55 | 12.38 | -0.20 |
| 16 | 4587520 | 48.90 | -4.02 | 12.38 | -0.20 |
| 32 | 9175040 | 51.48 | -1.44 | 12.49 | -0.09 |
| 48 | 13762560 | 52.01 | -0.91 | 12.38 | -0.20 |
| 0.5 | 2150400 | 44.12 | -8.80 | 12.37 | -0.21 |
| 0.6 | 3082240 | 47.54 | -5.38 | 12.37 | -0.21 |
| 0.7 | 4448256 | 50.49 | -2.43 | 12.37 | -0.21 |
| 0.8 | 6510592 | 50.11 | -2.81 | 12.37 | -0.21 |
| 0.9 | 10022912 | 51.55 | -1.37 | 12.38 | -0.20 |
| 0.95 | 12976128 | 52.62 | -0.30 | 12.39 | -0.19 |
Örneğin 0.95 rütbesi için, parametre sayısını %30 azaltırken doğruluk farkını yalnızca 0.3 yüzde puanına kadar daraltabiliriz. Ayrıca, bu sıkıştırılmış LoRA'ların, doğrudan daha düşük rütbede eğitilmelerinden daha iyi olabileceğini de not edelim — örneğin 32 rütbesi için doğrudan eğitim %48.22 test doğruluğu verirken, 64 rütbesinden dönüşüm %51.48 vermektedir.
Dikkat Edilmesi Gerekenler
LoRA dönüşümünün bazı kısıtlamaları vardır. Yukarıda belirtildiği gibi, performans düşüşü beklenir ve dönüştürülen LoRA, orijinal adaptöre kıyasla büyük olasılıkla daha az parametre verimli olacaktır. Ayrıca, LoRA dönüşümünün şu kısıtlamaları vardır:
- Şu anda yalnızca doğrusal katmanlara uygulanan adaptörler dönüştürülebilir.
- Tüm PEFT yöntemleri şu anda LoRA dönüşümünü desteklememektedir.
LoRA dönüşümünü genişletmeye yönelik yoğun bir talep varsa, lütfen bir GitHub tartışması oluşturarak bize bildirin; daha fazla katman türü ve PEFT yöntemiyle çalışmasını sağlayacağız.
API
LoRA olmayan bir modeli LoRA modeline dönüştürün, LoraConfig ve state_dict değerlerini döndürün
peft.convert_to_lora
< source >( model: Modulerank: floatadapter_name: str = 'default'progressbar: bool = Falsecompile_kwargs = None )
Parametreler
- model — Dönüştürülecek model. Dönüşümü destekleyen PEFT katmanlarına sahip bir model olmalıdır.
- rank (
intveyafloat) — Döndürülen LoRA adaptörü için istenen rank. Daha yüksek bir rank, orijinal adaptörü daha doğru bir şekilde yansıtan bir LoRA adaptörü sonucunu verir. Ancak bu, daha fazla bellek, hesaplama ve disk alanı gerektirir. Bu nedenle, kullanım senaryonuz için en iyi dengeyi temsil eden bir değer seçin ve nihai adaptörü doğrulayın. Bir float değeri geçirilirse, bu, açıklanan varyans / enerji eşiği olarak yorumlanır: toplam karelenmiş tekil değerlerin en az o oranını temsil eden en küçük k tekil değerini seçeriz. Bu, birkaç tekil değerin bu katmanın adaptasyonunu yakalayabilmesi durumunda, fiilen daha düşük rankların atanmasıyla sonuçlanır. Daha düşük bir float değeri, rankın daha düşük olduğu anlamına gelir ve bunun tersi de geçerlidir. Dinamik rankların, katman başına çok eşitsiz ranklara yol açabileceğini ve bunun da bazı katmanların aktivasyonlar için orantısız derecede yüksek miktarda bellek gerektirebileceğini göz önünde bulundurun. Öngörülebilir bellek gereksinimi elde etmek için sabit bir (int) rank seçmek daha iyidir. - adapter_name (
str, isteğe bağlı) — Dönüştürülecek adaptörün adı. Bir seferde yalnızca tek bir adaptör dönüştürülebilir. Varsayılan değer"default"'tur. - progressbar (
bool) — dönüşümün ilerlemesini gösteren bir ilerleme çubuğu gösterilip gösterilmeyeceğini belirtir (büyük modeller için birkaç dakika sürebilir). - compile_kwargs (
dict, isteğe bağlı) — Verilirse, verilen kwargs'lartorch.compile'e aktarılacak şekilde, bireysel modülleri LoRA'ya dönüştürmek için fonksiyonu derler. Bu, büyük modellerde dönüşümü potansiyel olarak hızlandırabilir.
PEFT katmanlarına sahip bir LoRA olmayan modeli bir LoRA kontrol noktasına dönüştürün.
Bu, yalnızca eşdeğer bir dönüştürmeye izin veren bazı belirli PEFT yöntemleri için desteklenir. Temelde bu, temel ağırlığı bir delta ağırlığı ile güncelleyerek çalışan PEFT yöntemlerine indirgenir. Ayrıca, şu anda yalnızca doğrusal katmanlar desteklenmektedir.
LoRA adaptörü, başlangıç adaptörünü olabildiğince yakından taklit etmeye çalışacaktır. Rank ne kadar yüksekse, yaklaşım o kadar iyi olur. Yaklaşımın asla orijinal adaptörün tam performansına ulaşmayacağı ve LoRA adaptörünün parametre verimliliğinin orijinal adaptörden düşük olacağı (yani benzer bir performans için daha fazla parametre gerektireceği) beklenmektedir. Dönüşüm yine de birçok durumda faydalı olabilir:
- PEFT'de LoRA, karışık adaptör toplamları gibi çoğu diğer yöntemden daha fazla özelliği destekler. Bu nedenle dönüştürülen adaptör, bu özelliklerle birlikte kullanılabilir.
- Bazı downstream paketler LoRA adaptörlerini destekler ancak diğer PEFT yöntemlerini desteklemez, örneğin Diffusers. Dönüşüm, bu paketlerde LoRA olmayan bir adaptörün kullanılmasına olanak tanır.
LoRA ölçekleme faktörü zaten LoRA ağırlıklarına gömülü olduğundan, ölçekleme her zaman bir olacaktır (yani rank ve alpha aynı olacak şekilde seçilir).
Not: Bu fonksiyon (henüz) parçalı modelleri desteklemiyor.
Raises
TypeError:
Sağlanan modelde LoRA'ya dönüştürülebilecek katman yoksa TypeError yükseltilir.
ValueError:
Geçersiz bir rank seçildiyse (çok yüksek veya çok düşük).
LoRA olmayan bir modeli LoRA modeline dönüştürün, adaptör kontrol noktasını ve yapılandırmayı verilen yolda kaydedin
peft.save_as_lora
< source >( path: str | os.PathLikemodel: Modulerank: floatadapter_name: str = 'default'progressbar: bool = Falsecompile_kwargs = None )
Parametreler
- model — Dönüştürülecek model. Dönüşümü destekleyen PEFT katmanlarına sahip bir model olmalıdır.
- rank (
intveyafloat) — Döndürülen LoRA adaptörü için istenen rank. Daha yüksek bir rank, orijinal adaptörü daha doğru bir şekilde yansıtan bir LoRA adaptörü sonucunu verir. Ancak bu, daha fazla bellek, hesaplama ve disk alanı gerektirir. Bu nedenle, kullanım senaryonuz için en iyi dengeyi temsil eden bir değer seçin ve nihai adaptörü doğrulayın. Bir float değeri geçirilirse, bu, açıklanan varyans / enerji eşiği olarak yorumlanır: toplam karelenmiş tekil değerlerin en az o oranını temsil eden en küçük k tekil değerini seçeriz. Bu, birkaç tekil değerin bu katmanın adaptasyonunu yakalayabilmesi durumunda, fiilen daha düşük rankların atanmasıyla sonuçlanır. Daha düşük bir float değeri, rankın daha düşük olduğu anlamına gelir ve bunun tersi de geçerlidir. Dinamik rankların, katman başına çok eşitsiz ranklara yol açabileceğini ve bunun da bazı katmanların aktivasyonlar için orantısız derecede yüksek miktarda bellek gerektirebileceğini göz önünde bulundurun. Öngörülebilir bellek gereksinimi elde etmek için sabit bir (int) rank seçmek daha iyidir. - adapter_name (
str, isteğe bağlı) — Dönüştürülecek adaptörün adı. Bir seferde yalnızca tek bir adaptör dönüştürülebilir. Varsayılan değer"default"'tur. - progressbar (
bool) — dönüşümün ilerlemesini gösteren bir ilerleme çubuğu gösterilip gösterilmeyeceğini belirtir (büyük modeller için birkaç dakika sürebilir). - compile_kwargs (
dict, isteğe bağlı) — Verilirse, verilen kwargs'lartorch.compile'e aktarılacak şekilde, bireysel modülleri LoRA'ya dönüştürmek için fonksiyonu derler. Bu, büyük modellerde dönüşümü potansiyel olarak hızlandırabilir.
PEFT katmanlarına sahip bir LoRA olmayan modeli LoRA'ya dönüştürün, ardından checkpoint dosyasını ve PEFT yapılandırmasını kaydedin.
Bu, yalnızca eşdeğer bir dönüştürmeye izin veren bazı belirli PEFT yöntemleri için desteklenir. Temelde bu, temel ağırlığı bir delta ağırlığı ile güncelleyerek çalışan PEFT yöntemlerine indirgenir. Ayrıca, şu anda yalnızca doğrusal katmanlar desteklenmektedir.
LoRA adaptörü, başlangıç adaptörünü olabildiğince yakından taklit etmeye çalışacaktır. Rank ne kadar yüksekse, yaklaşım o kadar iyi olur. Yaklaşımın asla orijinal adaptörün tam performansına ulaşmayacağı ve LoRA adaptörünün parametre verimliliğinin orijinal adaptörden düşük olacağı (yani benzer bir performans için daha fazla parametre gerektireceği) beklenmektedir. Dönüşüm yine de birçok durumda faydalı olabilir:
- PEFT'de LoRA, karışık adaptör toplamları gibi çoğu diğer yöntemden daha fazla özelliği destekler. Bu nedenle dönüştürülen adaptör, bu özelliklerle birlikte kullanılabilir.
- Bazı downstream paketler LoRA adaptörlerini destekler ancak diğer PEFT yöntemlerini desteklemez, örneğin Diffusers. Dönüşüm, bu paketlerde LoRA olmayan bir adaptörün kullanılmasına olanak tanır.
LoRA ölçekleme faktörü zaten LoRA ağırlıklarına gömülü olduğundan, ölçekleme her zaman bir olacaktır (yani rank ve alpha aynı olacak şekilde seçilir).
Dönüştürülen LoRA ağırlığını şu şekilde yükleyebilirsiniz:
>>> lora_path = ...
>>> save_as_lora(lora_path, model, rank=...)
>>> base_model = AutoModel.from_pretrained(...)
>>> lora_model = PeftModel.from_pretrained(base_model, lora_path)Not: Bu fonksiyon (henüz) parçalı modelleri desteklemiyor.
Raises
TypeError:
Sağlanan modelde LoRA'ya dönüştürülebilecek katman yoksa TypeError yükseltilir.
ValueError:
Geçersiz bir rank seçildiyse (çok yüksek veya çok düşük).