- LoRA (Low-Rank Adaptation), tüm LLM’yi yeniden eğitmeden yalnızca küçük düşük dereceli matrisleri güncelleyerek fine-tuning maliyetini azaltan bir tekniktir; bu Studio ise LoRA katmanını doğrudan uygulayıp nasıl çalıştığını doğrular
- Temel fikir, standart fine-tuning’deki ağırlık değişimini ΔW iki küçük matris
A ve B çarpımıyla yaklaşıklaştırmaktır; rank r küçüldükçe hem eğitilen parametreler hem de ifade kapasitesi azalır
- 5.000×10.000’lik bir ağırlık matrisi 50 milyon parametreye sahipken,
r=8 LoRA yalnızca 5.000×8 boyutlu B ile 8×10.000 boyutlu A ekleyerek 120 bin parametre kullanır; bu da 400 kat daha küçüktür
- DistilBERT tabanlı IMDb duygu sınıflandırmasında temel LoRA Test acc 89.44% elde ederek yalnızca son iki katmanın eğitildiği 86.22%’yi geçti, ancak tam fine-tuning’in 92.31% sonucunun altında kaldı
- Hiperparametre aramasından sonra LoRA, yaklaşık 500 bin eğitim parametresiyle Val acc 92.96% ve Test acc 92.39% elde ederek, 66.955.010 parametrenin eğitildiği tam fine-tuning’den az da olsa daha yüksek doğruluk verdi
LoRA’nın düşürdüğü fine-tuning maliyeti
- LoRA, Low-Rank Adaptation ifadesinin kısaltmasıdır ve LLM’leri daha verimli biçimde fine-tuning yapmak için kullanılan bir tekniktir
- Standart fine-tuning, derin öğrenme modelindeki tüm parametreleri ayarlarken LoRA yalnızca küçük bir düşük dereceli matris kümesini günceller
- Önceden eğitilmiş LLM’ler birçok görevde kullanılabilir, ancak belirli bir veri kümesine ya da göreve uyarlamak için fine-tuning faydalıdır
- Model büyüdükçe tüm katmanları güncelleyen yaklaşımın hesaplama maliyeti de ciddi biçimde artar
ΔW’yi küçük matris çarpımıyla yaklaşıklaştırma
- Standart fine-tuning’de ağırlık matrisi
W üzerindeki güncelleme ΔW olarak hesaplanır
- LoRA,
ΔW’yi iki küçük matris A ve B çarpımıyla yaklaşıklaştırır
- PCA veya SVD’ye aşinaysanız, bu yaklaşım
ΔW’nin A ve B ile ayrıştırılmasına benzer görülebilir
- Rank
r, LoRA’nın bir hiperparametresidir
- Daha küçük
r, eğitilen parametre sayısını azaltabilir, eğitimi hızlandırabilir ve hesaplama gereksinimini düşürebilir
- Aynı zamanda göreve özgü bilgiyi yakalayan düşük dereceli matrislerin kapasitesini de azaltır
- 5.000×10.000’lik ağırlık matrisi örneği:
- Standart güncelleme
ΔW: toplam 50 milyon parametre
r=8 LoRA: B 5.000×8, A 8×10.000
- Ek parametreler: 80.000 + 40.000 = 120.000
- Standart fine-tuning’e göre 400 kat daha küçüktür
- Pratikte performans ve maliyet dengesini bulmak için farklı
r değerlerini denemek gerekir
PyTorch ile LoRA katmanı uygulama
- Temel
LoRALayer, giriş boyutu, çıkış boyutu, rank ve ölçekleme katsayısı alpha alır
class LoRALayer(torch.nn.Module):
def __init__(self, in_dim, out_dim, rank, alpha):
super().__init__()
std_dev = 1 / torch.sqrt(torch.tensor(rank).float())
self.A = torch.nn.Parameter(torch.randn(in_dim, rank) * std_dev)
self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
self.alpha = alpha
def forward(self, x):
x = self.alpha * (x @ self.A @ self.B)
return x
in_dim, LoRA uygulanacak katmanın giriş boyutudur; out_dim ise çıkış boyutudur
rank, A ve B matrislerinin karmaşıklığını ve LoRA’nın eklediği parametre sayısını kontrol eder
alpha, LoRA’nın mevcut model ağırlıkları üzerinde oluşturduğu değişimin büyüklüğünü belirler
alpha yükseldikçe model davranışı daha güçlü biçimde ayarlanır
alpha düştükçe değişim daha ince olur
A, küçük rastgele değerlerle başlatılır ve standart sapma rank’in kareköküne göre belirlenir
- Bu tercih, başlangıçtaki
A değerlerinin fazla büyümemesini sağlar
B ise 0 ile başlatılır
- Eğitim başlamadan önce
B=0 olduğundan AB=0 olur
- Geri yayılım ile
A ve B güncellenene kadar LoRALayer, orijinal ağırlıkları etkilemez
Linear katmanını LinearWithLoRA ile değiştirme
- LoRA genellikle sinir ağlarındaki Linear/feed-forward katmanlara uygulanır
- Mevcut forward akışı iki Linear katmanı sırasıyla çağırıyorsa, LoRA uygulandıktan sonra her Linear çıktısına LoRA çıktısı eklenir
def forward(self, x):
x = self.linear_1(x) + self.lora_1(x)
x = F.relu(x)
x = self.linear_2(x) + self.lora_2(x)
return logits
- Mevcut bir PyTorch modelini değiştirirken, her
Linear katmanını LinearWithLoRA ile değiştirmek basit bir yöntemdir
class LinearWithLoRA(torch.nn.Module):
def __init__(self, linear, rank, alpha):
super().__init__()
self.linear = linear
self.lora = LoRALayer(
linear.in_features, linear.out_features, rank, alpha
)
def forward(self, x):
return self.linear(x) + self.lora(x)
LinearWithLoRA, hem orijinal Linear katmanını hem de yeni LoRALayer katmanını birlikte tutar
- Önceden eğitilmiş modeldeki
Linear katmanlarını LinearWithLoRA ile değiştirerek LoRA eklenmiş halde fine-tuning yapılabilir
DistilBERT ile IMDb sınıflandırma deneyi
- Uygulama örneği, üretken metin yerine doğruluk değerlendirmesi daha kolay olan metin sınıflandırmayı kullanır
- Model olarak Hugging Face transformers içindeki önceden eğitilmiş DistilBERT kullanılır
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2)
- Yalnızca yeni LoRA ağırlıklarını eğitmek için, modeldeki tüm parametrelerin
requires_grad değeri False yapılır
for param in model.parameters():
param.requires_grad = False
- DistilBERT’te 6 Transformer katmanı vardır ve her katmanın içinde Linear katmanlar bulunur
- attention içinde
q_lin, k_lin, v_lin, out_lin vardır
- FFN içinde
lin1, lin2 vardır
- çıktı tarafında
pre_classifier ve classifier olmak üzere iki Linear katman vardır
LoRA’yı seçmeli olarak uygulama ayarları
- Temel LoRA ayarı, yalnızca attention içindeki query ve value ağırlık matrislerine LoRA uygular
lora_r = 8
lora_alpha = 16
lora_dropout = 0.05
lora_query = True
lora_key = False
lora_value = True
lora_projection = False
lora_mlp = False
lora_head = False
- Döngü içinde DistilBERT’in her Transformer katmanında seçilen Linear katmanlar
LinearWithLoRA ile değiştirilir
lora_query=True ise q_lin değiştirilir
lora_key=True ise k_lin değiştirilir
lora_value=True ise v_lin değiştirilir
lora_projection=True ise out_lin değiştirilir
lora_mlp=True ise ffn.lin1 ve ffn.lin2 değiştirilir
lora_head=True ise pre_classifier ve classifier değiştirilir
- Değişiklikten sonra model çıktısında
q_lin ve v_lin gibi katmanların LinearWithLoRA olarak değiştiği görülebilir
Temel LoRA ile standart fine-tuning karşılaştırması
- Temel LoRA ayarıyla IMDb Movie Reviews sınıflandırmasını eğitme sonuçları:
- Train acc: 92.15%
- Val acc: 89.98%
- Test acc: 89.44%
- Yalnızca son iki çıktı katmanını fine-tuning yapmanın sonucu:
- Train acc: 86.68%
- Val acc: 87.26%
- Test acc: 86.22%
- Eğitim parametresi sayısı: 592.130
- Temel LoRA, yalnızca son iki katmanı eğiten yönteme göre daha yüksek Test acc verdi ve eğitim parametresi sayısı da 147.456 ile daha düşüktü
- Tüm katmanları geleneksel yöntemle fine-tuning yapmanın sonucu:
- Train acc: 96.41%
- Val acc: 92.80%
- Test acc: 92.31%
- Eğitim parametresi sayısı: 66.955.010
- Tam fine-tuning, temel LoRA’dan Test acc açısından yaklaşık %2 daha yüksek olsa da LoRA ayarına göre yaklaşık 450 kat daha fazla parametre günceller
LoRA hiperparametre araması
- LoRA performansı
lora_r, lora_alpha ve uygulandığı katman ayarlarına göre değişebilir
03_finetune-lora.py, hiperparametreleri komut satırı argümanları olarak alır
python 03_finetune-lora.py --lora_alpha 32 --lora_r 16
- Farklı LoRA uygulama hedefleri de birlikte etkinleştirilebilir
python 03_finetune-lora.py \
--lora_alpha 32 \
--lora_r 16 \
--lora_query True \
--lora_key True \
--lora_value True \
--lora_projection True \
--lora_mlp True \
--lora_head True
03_gridsearch.py, mevcut tüm GPU’larda şu grid’i çalıştırır
alpha_values = [1, 4, 8, 16, 32, 64]
rank_values = [1, 2, 4, 8, 16, 32]
lora_query = ["True"]
lora_key = ["False", "True"]
lora_value = ["True"]
lora_projection = ["False", "True"]
lora_mlp = ["False", "True"]
lora_head = ["False", "True"]
- Betik Visual Studio Code, komut satırı terminali veya Job olarak çalıştırılabilir; Job çalıştırması tamamlandığında otomatik kapanır
- Sonuçlar
results.txt içine kaydedilir
Grid aramasından çıkan en iyi ayar
results.txt temel alındığında en iyi hiperparametre yapılandırması şöyledir
lora_r: 8
lora_alpha: 1
lora_query: True
lora_key: False
lora_value: True
lora_projection: False
lora_mlp: True
lora_head: False
- Bu ayarın sonuçları:
- Val acc: 92.96%
- Test acc: 92.39%
- Bu LoRA ayarında yaklaşık 500k eğitim parametresi vardır; bu sayı tam fine-tuning’deki 66M parametreden çok daha düşüktür
- Doğruluk ise tam fine-tuning’in Val acc 92.80% ve Test acc 92.31% sonuçlarından az da olsa daha yüksektir
Çalışma ortamı ve ek kaynaklar
- Studio’nun üst kısmındaki Run düğmesine tıklayarak kodun da dahil olduğu ortamı klonlayabilirsiniz
- Studio klonlandıktan sonra ek kurulum, indirme veya yapılandırma adımı olmadan kod dosyaları çalıştırılabilir
- İlgili notebook ve betikler:
00_lora-layer.ipynb: LoRA katmanı uygulaması
01_finetune-last-layers.ipynb: Son katmanların fine-tuning’i
02_finetune-with-lora.ipynb: LoRA ile fine-tuning
03_finetune-lora.py: LoRA hiperparametre argümanlarıyla çalıştırma
03_gridsearch.py: LoRA hiperparametre grid araması
04_finetune-all-layers.ipynb: Tüm katmanların fine-tuning’i
- Ek kaynaklar:
1 yorum
Hacker News görüşleri
Teknik akış, Maxime Labonne’un LLMs 101 içeriğini takip ediyor: https://github.com/mlabonne/llm-course#4-supervised-fine-tun...
LoRA != LoRa olduğu için sürekli kafa karıştırıyor. Zaten var olan bir kısaltmanın yeniden kullanılmasından hoşlanmıyorum
Özellikle de HN ana sayfası gibi iki anlamın da doğal göründüğü yerlerde
Bilgisayar bilimi alanında “bu sayılar, yani hiperparametreler, sonucu tam olarak nasıl etkiliyor bilmiyoruz; o yüzden birkaç farklı değer deneyip en iyi çalışanı kullanalım” gibi şeyler söylenmesi bana hâlâ garip geliyor
Bazen optimum/doğru cevap yerine yerel maksimuma takılabilir ama yine de işe yarıyor. Kapalı form bir formülle çözemediğimiz için milyarlarca kez rastgele örnek alıp istediğimiz değeri buluyoruz; LLM’ler de aynıdır demiyorum ama bu tür yaklaşım oldukça sık kullanılıyor
Sektörde şimdiye kadarki şeylerin çoğu mühendislik ürünü olarak tasarlanmıştı; LLM’ler ise keşfedilmiş bir şeye daha yakın
İdeal olarak teorik bir temel gerekir ama bazen teori üretmek ya da doğrulamak için gerekli veriyi elde edebilmek adına rastgele arama yapmak gerekir
Olmamız gereken yerin birkaç yıl gerisindeyiz. 1990’larda oyun sektöründe çalışırken sinir ağlarının en iyi ihtimalle çıkmaz sokak, en kötü ihtimalle dolandırıcılık olduğu “genel kabul”dü. Birkaç otorite figürünün herkesi vazgeçirmesi yüzünden bu kadar zaman kaybetmiş olmamız gerçekten üzücü; bu kez bunun tekrar etmesine izin vermemeliyiz
İnce ayarın ne zaman yapılıp ne zaman RAG kullanılması gerektiği hâlâ net değil
Eskiden ince ayarın daha çok modelin davranışını değiştirmek için kullanıldığını düşünürdüm ama son zamanlarda bazı şirketlerin bilgi eklemek için de ince ayar kullandığı görülüyor. İnce ayarın başlıca kullanım alanının ne olduğunu merak ediyorum
Bence başlıca kullanım alanı hâlâ davranış değişikliği. Talimat ince ayarı, sınıflandırma için ince ayar vb. buna giriyor
Ağırlıklara bilgi eklemek en iyi ön eğitimle yapılır. Ya da üretim sırasında sorgulanacak harici bir veritabanı veya belge varsa, sorudaki gibi RAG kullanılabilir. Bu arada NeurIPS 2023 LLM Efficiency Challenge’da 24 saat içinde tek GPU ile “en iyi” LLM’i ince ayarlayan tüm kazananlar LoRA veya QLoRA (nicemlenmiş LoRA) kullandı
Ek veriler kısa ve öz değilse ya da bağlam gerektiriyorsa ince ayar, RAG’den daha iyidir
Bağlam fazla uzarsa veya odak bulanıklaşırsa prompt takibi zayıflayabilir ve RAG, modelin daha yüksek boyutlu token ilişkileri öğrenmesini sağlayamaz. Bu durumda gerekli şeyleri destek materyalinden şans eseri çekip getirmek gerekir; o zaman da pek gelişmiş bir arama motorundan daha iyi olmaz. Bu durum özellikle kamu kurumları veya büyük şirketlerin iç belgeleri gibi, herkese açık veri setlerinde iyi temsil edilmeyen kendine özgü ince lehçelere sahip uzmanlaşmış derlemler için sorun yaratır
Benim anladığım kadarıyla ince ayar alışılmadık derecede etkili [0]. Bağlam içi öğrenme ise temel modelin ne kadar güçlü olduğuna ve RAG’in nasıl kurulduğuna, yani sorgu işleme, embedding araması, sonuç sıralaması vb. şeylere büyük ölçüde bağlı [1]
Okuduğum makalelere göre ince ayar yeni alan bilgisi ekleyebilir veya belirli bilgileri güçlendirebilir; RAG ise yalnızca güçlendirmeyle sınırlı kalır. Yine de farklı ödünleşimlere sahip bu iki teknik bazen benzer düzeyde yetenek gösterebilir [2]
[0] Fast.ai: Can Models learn from one sample, https://www.fast.ai/posts/2023-09-04-learning-jumps/ / https://archive.is/eJMPR
[1] LlamaIndex: Advanced RAG, https://blog.llamaindex.ai/a-cheat-sheet-and-some-recipes-fo... / https://archive.is/qtBXX
[2] Microsoft: RAG vs Fine-tuning: Pipelines, Tradeoffs, and a Case Study, https://arxiv.org/html/2401.08406v2#S6 / https://archive.is/UQ8Sa#S6
Bunlar otoregresif modeller. Önceki bölümden sonrasında gelecek öğeleri tahmin etmeyi mümkün kılan yeni bir dizi türü varsa ve bu yöntem modelin daha önce gördüklerinden farklıysa, ince ayar mantıklı görünüyor
Belirli bir veri durumunda ne yapılacağına karar vermek için bu oldukça belirsiz bir ölçüt ama kabaca bir sezgisel kural olarak yeterli olabilir. Bilgi eklemenin buna girip girmediği ise deney yapılmadan belki de bir tercih meselesidir
Güzel bir yazı. Bu alanın insanı değilim ama özgün makaleyi okuduğumda LoRA’nın yalnızca son yoğun katmana uygulandığını, tüm katmanlara birbirinden bağımsız biçimde uygulanmadığını anlamıştım. Yanlış okumuş da olabilirim
Bağlantıdaki uygulamanın neden böyle olduğunu biraz araştırınca QLoRA’da bu yaklaşımın kullanıldığını ve ilginç etkileri var gibi göründüğünü fark ettim. QLoRA’nın bu tercihine dair bir not eklenirse iyi olabilir. Yine de bunun neden çalıştığını pek bilmiyorum; yeni başlayan biri açısından son katmana LoRA uygulamak mantıklı geliyor ama her doğrusal katmana tekrar tekrar uygulamanın dayanağı pek sezgisel gelmiyor. Bunun sezgisini açıklayabilir misiniz?
LoRA katmanlarıyla değiştirilen katman sayısı arttıkça optimizasyonun serbestlik derecesi de artar. Bazı ince ayar yöntemleri, girdinin “en yüksek seviyeli” temsillerini taşıdığı varsayıldığı için yalnızca son katmanın ince ayarlanmasını önerir. Başka yöntemler ise tüm katmanları ince ayarlar. Bu çoğunlukla veriye ve probleme bağlıdır ve LoRA da bu yaygın pratiği olduğu gibi yansıtır
Axolotl’un “sıfırdan” yaklaşımındansa konfigürasyondan başlayan yaklaşımını tercih ediyorum. Axolotl, Mistral ve Llama 2 ince ayarını destekliyor; örnek paketleme, FlashAttention, xFormers gibi güncel tekniklerin çoğunu da destekliyor
Ben LoRA’yı sıfırdan öğrenmektense ince ayar verisini toplama ve kürasyonuna odaklanarak veri merkezli ince ayar yapıyorum
https://github.com/Lightning-AI/lit-gpt
İsim vermek gerçekten zor. İlk başta bunun “long range” anlamındaki LoRa ya da IoT sensör iletişimi olan LoRaWAN ile ilgili olduğunu sanmıştım
İnce ayarda en çok hangi kütüphaneler kullanılıyor? “Sıfırdan” olmayan yaklaşımlar için soruyorum
Vay, ben de ilk başta doğal olarak bunun LoRa ile ilgili olduğunu sanmıştım
LoRA’nın performans maliyeti ne kadar?
Çıkarım sırasında ise iki seçenek vardır. İleri geçişte LoRA değerlerini dinamik olarak eklerseniz teorik olarak biraz daha yavaş olabilir; ancak müşteri başına küçük ağırlık kümelerini ayrı tutmak istiyorsanız bu bir avantaj da olabilir. Çünkü tek bir büyük temel modeli çalıştırıp müşteriye özel LoRA ağırlıklarını anlık olarak uygulayabilirsiniz. LoRA ağırlıklarını tekrar temel modele birleştirirseniz, temel modelle tamamen aynı performansı elde edebilirsiniz.