1 puan yazan GN⁺ 2024-01-23 | 1 yorum | WhatsApp'ta paylaş
  • 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

 
GN⁺ 2024-01-23
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

    • Ben de aynı durumdayım. Asıl işim makine öğrenimi olmasına rağmen, hatta belki de tam bu yüzden, bağlamın neredeyse hiç olmadığı yerlerde bu kısaltmayı her gördüğümde bir an duraksıyorum
      Özellikle de HN ana sayfası gibi iki anlamın da doğal göründüğü yerlerde
    • “Low-Rank Adaptation” dışında başka ne anlama geliyor? Aradaki farkı aratmak bile zor
    • İnsanlar fazla uzmanlaşıp kendi balonlarının dışında neler olduğuna dikkat etmeyince böyle şeyler oluyor
    • Yazılım tarafındaki insanların donanımla ilgili isimleri alıp kullanma eğiliminden hoşlanmıyorum
    • Şimdiye kadar birbiriyle ilgisiz iki teknolojinin aynı kısaltmayı kullanır hale gelmiş olması üzücü
  • 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

    • “Birkaç farklı değer deneyip en iyi çalışanı kullanalım” yaklaşımı, değer bulmak için Monte Carlo simülasyonu kullanmaya benzemiyor mu?
      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
    • Bu, mühendislik yoluyla inşa edilen şeylerle keşfedilen şeyler arasındaki fark gibi geliyor
      Sektörde şimdiye kadarki şeylerin çoğu mühendislik ürünü olarak tasarlanmıştı; LLM’ler ise keşfedilmiş bir şeye daha yakın
    • Bu tür aşağıdan yukarı yamalama, Dijkstra’nın da gözlemlediği gibi, bilgisayar biliminin Amerika’da başlamasına da benziyor: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD06xx/E...
      İ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
    • Minsky ve başkalarının, perceptronların doğrusal olmayan fonksiyonları modelleyemediğini söyleyerek onları küçümsemesinin de büyük etkisi oldu. Modern CPU ve GPU’lar olmadan LLM’lerin ortaya çıkması zaten zordu ama bu, önceden daha iyi bir teorik temel oluşturulamayacağı anlamına gelmiyor
      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
    • Stable Diffusion ayarlarını araştırmak da buna benziyor. İnsanın kısa sürede fark ettiği şey, işin içinde bolca tahmin olduğu
  • İ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?

    • Makine öğrenmesindeki pek çok şeyde olduğu gibi, hangi katmanın kullanılacağı teoriden çok ampirik kanıtlar tarafından belirlenir. Genel LoRA eğitim hattında temel model sabit tutulur ve yalnızca LoRA katmanları ayarlanır
      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

  • İ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?

    • Eğitim sırasında, geri yayılımda yalnızca bazı parametreler güncellendiği için tam ince ayardan daha verimlidir
      Çı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.