---
title: "Anatomia LLM: LoRA i dotrenowywanie modeli"
date: 2026-06-21
description: "Jak wyspecjalizować gotowy model, nie ruszając miliardów jego wag: hipoteza niskiego rzędu i sztuczka LoRA, cała rodzina metod oszczędnego dotrenowywania (PEFT), kwantyzacja i QLoRA, a na końcu - po co w ogóle dotrenowywać, czyli jak z surowego modelu robi się asystent przez instruction tuning i RLHF."
tags: ["anatomia llm", "ai", "llm", "fine-tuning", "deep-dive"]
---

## 🚀 Intro

W [poprzednim przystanku tej serii](/posty/llm-blok-transformera) - jednej z gałęzi [przeglądowego wpisu „Anatomia LLM"](/posty/anatomia-llm) - złożyliśmy z klocków całą maszynę: blok Transformera, stos kilkudziesięciu takich bloków, warstwę wyjściową, która zamienia wektor liczb z powrotem w słowo. Mamy gotowy model. Tyle że jego wytrenowanie od zera kosztowało miliony dolarów i pochłonęło bilion tokenów - a my chcielibyśmy go teraz tylko trochę **wyspecjalizować**. Nauczyć prawniczego żargonu, własnej wiedzy domenowej, konkretnego tonu obsługi klienta.

Naiwna odpowiedź brzmi: dotrenuj go. Weź gotowy model i ucz dalej, na swoich danych. Problem w tym, że „dotrenuj" oznacza zaktualizować **wszystkie** miliardy parametrów - a to wymaga prawie tyle samo sprzętu, co trening od zera. Dla modelu rzędu 70 miliardów wag to wciąż rachunek, którego większość ludzi i firm nie udźwignie.

Ten wpis jest o sprytnej drodze naokoło. Okaże się, że żeby nauczyć olbrzymi model nowej sztuczki, wcale nie trzeba ruszać całego olbrzyma - wystarczy doczepić mu malutki „dodatek" liczący ułamek procenta jego wag. A dlaczego to w ogóle działa, kryje w sobie jedną z bardziej zaskakujących obserwacji o naturze tych modeli: że nowa umiejętność ma **zdumiewająco mały rozmiar**. To ostatni przystanek serii - i zarazem ten, który najlepiej pokazuje, jak wiele z tego, co model „umie", siedzi w nim już, zanim go o cokolwiek dopytamy.

> 💡 **Jak czytać ten tekst.** Główny wątek jest opisowy i samowystarczalny. Wzory chowam w rozwijanych blokach „dla dociekliwych" - jeśli lubisz matematykę, rozwiń; jeśli nie, pomiń bez straty dla zrozumienia. Wszystkie twierdzenia mają przypisy do prac źródłowych na końcu.


## 📋 TL;DR

- **Pełne dotrenowanie jest drogie.** Aktualizacja wszystkich wag modelu 70B wymaga niemal tyle sprzętu, co trening od zera. LoRA powstała wprost jako odpowiedź na nieopłacalność tego podejścia w skali GPT-3.
- **LoRA: ucz tylko poprawki.** Zamrażamy oryginalne wagi i uczymy maleńkiej, „niskorzędowej" poprawki zapisanej jako iloczyn dwóch chudych macierzy. W skali GPT-3 175B to około **10 000× mniej** trenowanych parametrów i około **3× mniej** pamięci GPU - przy jakości na poziomie pełnego dotrenowania.
- **Bez kosztu w użyciu.** Po treningu poprawkę można **wtopić** z powrotem w wagi, więc gotowy model działa dokładnie tak szybko jak przedtem - w odróżnieniu od starszych „adapterów", które spowalniały inferencję.
- **Dlaczego to w ogóle działa.** Bo dostrojenie do nowego zadania ma **niski wymiar wewnętrzny**: w jednym eksperymencie zaledwie **200 parametrów** wystarczyło, by osiągnąć 90% wyniku pełnego dotrenowania. Skoro samo zadanie jest „małe", to i poprawka może być mała.
- **Cała rodzina PEFT.** LoRA to jeden z wielu sposobów oszczędnego dotrenowywania (adaptery, prefix/prompt tuning, BitFit). Wszystkie ruszają ułamek wag, dając wynik bliski pełnemu dotrenowaniu.
- **QLoRA: jeszcze taniej.** Kwantyzujemy zamrożony model do 4 bitów i uczymy adapterów na tak ściśniętej wersji - pozwala to dostroić model 65B na **jednej** karcie 48 GB, bez utraty jakości.
- **Po co dotrenowywać.** To właśnie dotrenowywanie zamienia surowy model „dokańczający tekst" w **asystenta**: instruction tuning uczy słuchać poleceń, a RLHF - dostrajać się do ludzkich preferencji. Dostrojenie do intencji potrafi bić sam rozmiar.

👉 **Pobaw się:** na stronie interaktywnej masz [sekcję o LoRA](/llm/anatomia#lora) - zobacz, jak zamrożona macierz dostaje tani „boczny tor" z dwóch cienkich macierzy i ile na tym oszczędzamy.


## 🧊 LoRA: ucz się tylko poprawki

Zacznijmy od samej sztuczki. Wyobraź sobie wielką, wytrenowaną macierz wag $W_0$ - jedną z tysięcy w modelu. Pełne dotrenowanie powiedziałoby: zmień ją całą, każdą z milionów jej liczb. **LoRA** (Low-Rank Adaptation; Hu i in., 2021) mówi co innego: zostaw $W_0$ **zamrożoną**, w ogóle jej nie dotykaj, a obok dołóż drobną **poprawkę** $\Delta W$ (czytaj „delta W"), której się nauczysz[^hu].

Cały spryt jest w tym, jak tę poprawkę zapisujemy. Zamiast trzymać ją jako kolejną pełną, gęstą macierz (równie dużą jak $W_0$ - więc bez żadnej oszczędności), rozkładamy ją na **iloczyn dwóch chudych macierzy**: $B$ i $A$. Jeśli oryginał ma wymiary, powiedzmy, 4096 na 4096, to zamiast uczyć poprawki o ponad 16 milionach liczb, uczymy dwóch wąskich pasków - jeden wysoki i chudy, drugi niski i szeroki - które po przemnożeniu dają macierz tego samego kształtu, ale „przewężoną" w środku do raptem kilku wymiarów. Ta liczba wymiarów w przewężeniu to **rank** (rząd), oznaczany $r$ - zwykle 8 albo 16. To on decyduje, ile w ogóle nowych parametrów dokładamy.

Liczby z oryginalnej pracy robią wrażenie. Względem pełnego dotrenowania GPT-3 175B optymalizatorem Adam, LoRA redukuje liczbę trenowanych parametrów około **10 000 razy**, a zapotrzebowanie na pamięć GPU około **3 razy** - osiągając przy tym wyniki na poziomie pełnego dotrenowania lub lepsze[^hu]. Dla porównania ze stroną interaktywną: przy wymiarze 4096 i randze 8 wychodzi z tego około **256× mniej** parametrów poprawki.

Jest jeszcze jedna, kluczowa zaleta nad starszymi metodami. Skoro poprawka to po prostu coś, co **dodajemy** do $W_0$, to po skończonym treningu można ją z powrotem **wtopić** w oryginalną macierz - policzyć raz $W_0 + \Delta W$ i zapamiętać jako jedną macierz. W efekcie gotowy, dostrojony model ma dokładnie tę samą strukturę i tę samą szybkość co model wyjściowy: **zero dodatkowego opóźnienia** w użyciu[^hu]. To właśnie odróżnia LoRA od „adapterów", o których za chwilę - tamte dokładały nowe warstwy, które trzeba liczyć przy każdym zapytaniu.

W praktyce nie dokleja się LoRA do każdej macierzy w modelu. Twórcy zauważyli, że przy ustalonym budżecie parametrów najwięcej daje dostrojenie macierzy **zapytań i wartości** w mechanizmie uwagi (tych $W_q$ i $W_v$ z [wpisu o uwadze](/posty/llm-mechanizm-uwagi)) - i stąd wzięła się domyślna konwencja[^hu]. Ciekawe było też drugie ustalenie: lepiej dostroić **więcej** macierzy przy **niższej** randze niż mniej macierzy przy wyższej[^hu].

<details>
<summary>📐 Dla dociekliwych: rozkład niskiego rzędu i liczba parametrów</summary>

LoRA zamraża wytrenowaną macierz $W_0 \in \mathbb{R}^{d \times k}$ i uczy tylko niskorzędowej poprawki, rozłożonej na dwie macierze:

$$W = W_0 + \Delta W = W_0 + \frac{\alpha}{r}\,BA, \qquad B \in \mathbb{R}^{d \times r},\ A \in \mathbb{R}^{r \times k},\ r \ll \min(d,k)$$

Dla wejścia $x$ wartość warstwy to suma drogi głównej (zamrożonej) i taniego bocznego toru:

$$h = W_0\,x + \frac{\alpha}{r}\,B(A x)$$

Tu $\alpha$ (alfa) to skala wpływu poprawki, a $r$ to rank - szerokość przewężenia. Skąd oszczędność? Pełna poprawka $\Delta W$ ma $d \times k$ liczb; rozkład na $B$ i $A$ ma ich $d \times r + r \times k = r(d+k)$. Dla macierzy kwadratowej $d \times d$ daje to $2dr$ zamiast $d^2$, czyli redukcję o czynnik $\frac{d}{2r}$ - dla $d = 4096$ i $r = 8$ to około 256× mniej[^hu].

</details>


## 🔬 Hipoteza niskiego rzędu: dlaczego to w ogóle działa

Tu pojawia się pytanie, które łatwo przeoczyć w zachwycie nad oszczędnością: **dlaczego** poprawka niskiego rzędu w ogóle wystarcza? Przecież ściskamy zmianę wag do raptem kilku wymiarów - intuicja podpowiada, że musimy przez to coś tracić. A jednak nie tracimy prawie nic. Dlaczego?

Odpowiedź sięga obserwacji starszej niż sama LoRA. Aghajanyan i współpracownicy (2020) zbadali coś, co nazwali **wewnętrznym wymiarem** zadania (intrinsic dimensionality). Pytanie brzmiało: ile naprawdę „stopni swobody" potrzeba, żeby dostroić wielki model do nowego zadania? Wynik był zaskakujący. Okazało się, że optymalizacja zaledwie **200 parametrów** - rzutowanych potem losowo w pełną, wielomilionową przestrzeń wag - wystarczyła, by model RoBERTa osiągnął **90% wyniku** pełnego dotrenowania na pewnym zadaniu językowym[^aghajanyan]. Dwieście liczb. Nie dwieście milionów.

To jest sedno. Skoro samo **zadanie** ma niski wymiar wewnętrzny - skoro jego „kształt" da się opisać garstką liczb - to i potrzebna zmiana wag $\Delta W$ może być niskiego rzędu. LoRA nie zgaduje na ślepo, że poprawka jest „mała"; opiera się na empirycznym odkryciu, że dostrojenie wielkiego, wytrenowanego modelu **naprawdę** mieszka w zaskakująco ciasnej przestrzeni. Wielki model nie uczy się nowego zadania od zera - on raczej **przesuwa się** o drobny krok w przestrzeni, którą już opanował.

Jest jeszcze elegancki szczegół techniczny, który pokazuje, jak ostrożnie zaprojektowano tę metodę. Na starcie treningu chcemy, żeby poprawka **niczego nie psuła** - model musi zacząć dokładnie od swoich wytrenowanych wag. Dlatego jedną z macierzy ($A$) inicjalizuje się losowo, a drugą ($B$) **zerami**. Iloczyn z zerem to zero, więc na początku $\Delta W = 0$: model startuje nietknięty i dopiero w trakcie nauki delikatnie odchyla się od oryginału[^hu].

<details>
<summary>📐 Dla dociekliwych: wewnętrzny wymiar przez losowe rzutowanie</summary>

Pomiar wewnętrznego wymiaru polega na tym, że zamiast optymalizować pełny wektor parametrów $\theta \in \mathbb{R}^{D}$ (gdzie $D$ idzie w miliony), optymalizuje się malutki wektor $\theta^{(d)} \in \mathbb{R}^{d}$ w przestrzeni o wymiarze $d \ll D$, a potem rzutuje go z powrotem stałą, losową macierzą $P$:

$$\theta = \theta_0 + P\,\theta^{(d)}$$

Tu $\theta_0$ (theta zero) to zamrożone wagi wyjściowe, a $P \in \mathbb{R}^{D \times d}$ jest losowa i ustalona (nie uczymy jej). „Wewnętrzny wymiar" to najmniejsze $d$, przy którym model osiąga zadany procent wyniku pełnego dotrenowania. Odkrycie Aghajanyana: dla wielu zadań to $d$ jest rzędu setek, nie milionów[^aghajanyan]. To właśnie obserwacja, na której opiera się intuicja LoRA - że $\Delta W$ może być niskiego rzędu.

</details>


## 🧰 Cała rodzina PEFT

LoRA nie wzięła się znikąd - jest najbardziej znaną przedstawicielką szerszej rodziny metod zwanej **PEFT** (Parameter-Efficient Fine-Tuning, czyli „dotrenowywanie oszczędne parametrowo"). Wspólny mianownik całej rodziny: zamiast ruszać wszystkie wagi, dostrajamy **niewielką** ich część (albo dokładamy garstkę nowych), uzyskując wynik porównywalny z pełnym dotrenowaniem[^peft]. Warto poznać kilku kuzynów LoRA, bo każdy atakuje ten sam problem z innej strony:

- **Adaptery** (Houlsby i in., 2019) - historycznie pierwsze. Wstawiają małe, trenowalne moduły **pomiędzy** istniejące warstwy, resztę zamrażając. Na zestawie testów GLUE schodziły do **0,4%** od pełnego dotrenowania, dokładając tylko **3,6%** parametrów na zadanie[^houlsby]. Wada, którą LoRA później wyeliminowała: te dodatkowe moduły to realne warstwy, które trzeba liczyć przy każdym zapytaniu, więc **spowalniają** model w użyciu[^hu].
- **Prefix tuning** (Li i Liang, 2021) - zamiast ruszać wagi, dokleja na początek krótki, **uczony** ciąg „wirtualnych tokenów", który steruje zachowaniem modelu. Trenuje raptem **0,1%** parametrów[^liliang].
- **Prompt tuning** (Lester i in., 2021) - pokrewny pomysł: uczy „miękkich poleceń" (soft prompts) przy całkowicie zamrożonym modelu. Ciekawa obserwacja: im większy model, tym bardziej ta lekka metoda **domyka lukę** do pełnego dotrenowania[^lester].
- **BitFit** (Ben-Zaken i in., 2021) - chyba najbardziej minimalistyczny: modyfikuje **wyłącznie wyrazy biasu** (te stałe przesunięcia, które każdy neuron dodaje do swojej sumy). Mimo to bywa konkurencyjny z pełnym dotrenowaniem dla mniejszych zbiorów danych[^bitfit].

Wszystkie te metody łączy ta sama, głęboka obserwacja z poprzedniej sekcji: wielki model jest już tak bogato „uformowany" przez pretrening, że do nowego zadania trzeba go tylko **leciutko** szturchnąć. Oficjalna biblioteka HuggingFace PEFT zbiera dziś kilkanaście takich metod pod wspólnym interfejsem - LoRA jest wśród nich domyślnym punktem wyjścia[^peft].


## 🗜️ QLoRA i kwantyzacja: jeszcze niżej

LoRA radykalnie zbiła koszt **trenowania** poprawki. Ale jest jeszcze drugi koszt, który nie znika: żeby cokolwiek dotrenować, zamrożony model bazowy i tak trzeba **załadować** do pamięci karty graficznej. A model 65B w zwykłej precesji 16-bitowej to grubo ponad sto gigabajtów - więcej, niż mieści pojedyncza karta. Tu wkracza **kwantyzacja**.

Kwantyzacja to po prostu **zmniejszanie precyzji** liczb przechowujących wagi. Zamiast trzymać każdą wagę w 16 bitach, pakujemy ją w 8, a nawet 4 bity - jak zapis tej samej fotografii w mniejszej rozdzielczości. Mniej bitów to mniej pamięci i szybsze liczenie, kosztem pewnej utraty dokładności. Sztuka polega na tym, żeby tę utratę zminimalizować. Dwie ważne prace pokazały, że da się to zrobić niemal bezboleśnie: **LLM.int8()** (Dettmers i in., 2022) skompresował wagi do 8 bitów **bez utraty jakości**, sprytnie obchodząc się z nielicznymi „wystającymi" wartościami, które psułyby naiwną kwantyzację[^llmint8]. **GPTQ** (Frantar i in., 2022) poszedł do 3-4 bitów, kwantyzując model 175B w kilka godzin i przyspieszając jego inferencję ponad trzykrotnie[^gptq].

**QLoRA** (Dettmers i in., 2023) genialnie połączył oba światy: kwantyzację i LoRA. Pomysł - zamroź model bazowy i skompresuj go aż do **4 bitów**, a potem ucz na nim adapterów LoRA, przepuszczając gradienty przez tę 4-bitową wersję[^qlora]. Bazowy olbrzym leży w pamięci ciasno upakowany, a uczy się tylko chudy dodatek. Efekt? Model 65B da się dostroić na **jednej** karcie 48 GB - przy zachowaniu jakości pełnego, 16-bitowego dotrenowania[^qlora]. Dla skali: rodzina modeli **Guanaco** wytrenowana tą metodą osiągnęła **99,3%** poziomu ChatGPT przy zaledwie **24 godzinach** dostrajania na jednym GPU[^qlora]. Dotrenowywanie wielkich modeli przestało być domeną wyłącznie wielkich laboratoriów.

<details>
<summary>📐 Dla dociekliwych: jak upakować wagę w 4 bity</summary>

Kwantyzacja liniowa odwzorowuje liczby zmiennoprzecinkowe na małą, dyskretną siatkę liczb całkowitych. W uproszczeniu dla bloku wag liczymy współczynnik skali $s$ z największej co do wartości bezwzględnej wagi w bloku, a potem:

$$w_{\text{int}} = \mathrm{round}\!\left(\frac{w}{s}\right), \qquad w \approx s \cdot w_{\text{int}}$$

przy czym $w_{\text{int}}$ mieści się w zakresie dozwolonym dla danej liczby bitów (dla 4 bitów to raptem 16 poziomów). Współczynnik $s$ pełni rolę „kroku siatki". QLoRA dokłada do tego dwie sztuczki: typ danych **NF4** (4-bit NormalFloat), którego poziomy rozłożono optymalnie dla wag o rozkładzie zbliżonym do normalnego, oraz **podwójną kwantyzację** - kwantyzuje same współczynniki skali, oszczędzając jeszcze około 0,37 bita na parametr[^qlora]. Gradienty w treningu płyną przez tę 4-bitową drogę do adapterów LoRA, które pozostają w wyższej precyzji.

</details>


## 🧬 Po LoRA: warianty rodziny

LoRA okazała się tak udana, że szybko obrosła ulepszeniami. Nie trzeba ich znać, by używać LoRA - ale warto wiedzieć, że to żywa, rozwijająca się rodzina, a nie zamknięty przepis:

- **DoRA** (Liu i in., 2024) - rozkłada każdą wagę na **wielkość** i **kierunek**, a LoRA stosuje tylko do kierunku. Poprawia zdolność uczenia bez dodatkowego kosztu w użyciu[^dora].
- **LoRA+** (Hayou i in., 2024) - zauważa, że dwie macierze poprawki ($A$ i $B$) powinny uczyć się z **różną** prędkością. Drobna zmiana, a daje poprawę i nawet **dwukrotne** przyspieszenie treningu[^loraplus].
- **AdaLoRA** (Zhang i in., 2023) - zamiast dawać każdej macierzy ten sam rank, **rozdziela budżet** rang tam, gdzie najbardziej się przydają, przycinając mało istotne kierunki[^adalora].
- **rsLoRA** (Kalajdzievski, 2023) - wraca do drobnego, lecz brzemiennego szczegółu: jak skalować poprawkę. Dowodzi, że przy właściwym czynniku skali wyższe rangi zaczynają wreszcie pomagać tak, jak powinny[^rslora].

<details>
<summary>📐 Dla dociekliwych: czynnik skali w rsLoRA</summary>

Oryginalna LoRA skaluje poprawkę przez $\frac{\alpha}{r}$ (alfa przez r). rsLoRA argumentuje, że to skalowanie „dusi" gradienty przy większych rangach, i proponuje zamiast tego dzielić przez **pierwiastek** z rangi:

$$\Delta W = \frac{\alpha}{\sqrt{r}}\,BA$$

Intuicja jest taka sama jak za czynnikiem $\sqrt{d_k}$ w [mechanizmie uwagi](/posty/llm-mechanizm-uwagi): pierwiastek stabilizuje wariancję, gdy zwiększamy liczbę sumowanych składników. Przy poprawnym czynniku wyższe rangi przestają szkodzić i zaczynają dawać lepsze dotrenowanie[^rslora].

</details>


## 🧭 Kiedy co: dotrenowanie, RAG czy samo polecenie

Zanim sięgniesz po LoRA, warto cofnąć się o krok i zapytać, czy w ogóle potrzebujesz dotrenowywania. Bo to tylko jedno z czterech narzędzi do „naginania" modelu do swoich potrzeb - i często nie to właściwe. Nie ma tu jednej kanonicznej pracy porównawczej; poniżej praktyczna synteza:

- **Samo polecenie (prompting / few-shot)** - bez żadnego treningu. Jeśli zadanie da się opisać instrukcją albo pokazać na kilku przykładach w samym zapytaniu - zacznij stąd. Najtańsze i natychmiastowe, ograniczone tylko rozmiarem okna kontekstu.
- **RAG** (dokładanie wiedzy z wyszukiwania) - gdy potrzebujesz **aktualnej lub firmowej wiedzy faktograficznej**. RAG dokłada modelowi odpowiednie dokumenty do kontekstu, zamiast zmieniać jego wagi. Nie uczy nowych zachowań ani stylu - daje **fakty**.
- **PEFT (LoRA/QLoRA/...)** - gdy trzeba zmienić **zachowanie, styl albo format** odpowiedzi, albo dostroić model do specyficznej domeny, mając ograniczony sprzęt i wiele zadań (lekkie, wymienne adaptery)[^hu][^qlora].
- **Pełne dotrenowanie** - maksymalna pojemność uczenia, gdy masz duże zasoby i dużo danych. Dla modeli 70B+ kosztowne - i to właśnie ten koszt powołał LoRA do życia[^hu].

Reguła kciuka, którą warto zapamiętać: **brakuje wiedzy → RAG; brakuje zachowania → dotrenowanie.** Mylenie tych dwóch to najczęstszy błąd - dotrenowywanie modelu, żeby „znał fakty", jest zwykle droższe i gorsze niż po prostu podanie mu tych faktów w kontekście.


## 🎓 Po co w ogóle dotrenowywać: od surowego modelu do asystenta

Jest jeszcze jedno zastosowanie dotrenowywania - najważniejsze ze wszystkich, bo bez niego nie byłoby ChatGPT ani Claude'a takim, jakim go znasz. Surowy model po pretreningu, który złożyliśmy w poprzednich wpisach, umie tylko jedno: **dokańczać tekst**, przewidywać kolejny token. Zapytany „Jaka jest stolica Polski?" równie chętnie dopisze „A jaka jest stolica Francji?" - bo statystycznie tak właśnie wyglądają teksty z pytaniami. On nie wie, że ma **odpowiadać**. To dopiero dotrenowanie zamienia takiego „dokańczacza" w **asystenta**.

Dzieje się to w dwóch krokach. Pierwszy to **instruction tuning** - dotrenowanie na zbiorze poleceń i ich poprawnych wykonań. Praca FLAN (Wei i in., 2021) pokazała coś zaskakującego: model dostrojony na ponad **60 różnych zadaniach** ujętych jako instrukcje nagle robi się lepszy w zadaniach, których **nigdy nie widział**. Sama forma „to jest polecenie, masz je wykonać" okazała się umiejętnością, która się **uogólnia**[^flan].

Drugi krok jest jeszcze ciekawszy: **RLHF** (Reinforcement Learning from Human Feedback - uczenie ze wzmocnieniem na podstawie ludzkich preferencji). Tu już nie pokazujemy modelowi „poprawnych odpowiedzi", bo dla wielu pytań nie istnieje jedna poprawna - chcemy odpowiedzi *pomocnej*, *bezpiecznej*, *w dobrym tonie*. Więc zamiast tego pokazujemy mu **ludzkie oceny**: które z dwóch odpowiedzi człowiek wolał. Z tych preferencji trenuje się model nagrody, a potem dostraja główny model tak, by tę nagrodę maksymalizował. Wynik bywa uderzający: w pracy InstructGPT (Ouyang i in., 2022) model **1,3-miliardowy** dostrojony przez RLHF był przez ludzi **preferowany** nad surowy model **175-miliardowy** - ponad stukrotnie większy[^instructgpt]. Dostrojenie do ludzkich intencji pobiło sam rozmiar.

I tu wszystko się spina: LoRA i QLoRA są w praktyce **częstym mechanizmem realizacji** instruction tuningu i RLHF na ograniczonym sprzęcie. Wspomniane Guanaco to dokładnie taki przypadek - asystent dostrojony przez QLoRA[^qlora]. Sprytna oszczędność z początku tego wpisu okazuje się więc nie ciekawostką inżynierską, lecz tym, co **demokratyzuje** budowę asystentów: tę ostatnią, najważniejszą warstwę „bycia pomocnym" da się dziś dołożyć małym kosztem.

<details>
<summary>📐 Dla dociekliwych: cel optymalizacji w RLHF</summary>

W RLHF najpierw uczy się model nagrody $r_\phi$, który z preferencji ludzi (odpowiedź wygrana vs przegrana) uczy się przypisywać tekstom liczbową „jakość". Potem dostraja się główny model $\pi_\theta$ tak, by maksymalizował oczekiwaną nagrodę, ale **nie odpływał za daleko** od modelu wyjściowego $\pi_{\text{ref}}$:

$$\max_{\theta}\ \mathbb{E}\big[\,r_\phi(x, y)\,\big] - \beta\,\mathrm{KL}\!\big(\pi_\theta \,\|\, \pi_{\text{ref}}\big)$$

Drugi składnik to kara za rozbieżność (dywergencja Kullbacka-Leiblera) między dostrajanym a wyjściowym modelem, ważona współczynnikiem $\beta$ (beta). Bez niej model „przegiąłby" w stronę modelu nagrody, generując dziwne teksty, które sztucznie nabijają punkty (tzw. reward hacking). Kara KL trzyma go blisko sensownego języka, którego nauczył się w pretreningu[^instructgpt].

</details>


## 🌗 Wiedza, która już tam była

Zatrzymajmy się na koniec, bo cała ta historia o oszczędności skrywa coś dziwniejszego, niż się z pozoru wydaje. Pozornie LoRA to po prostu sprytna inżynieria - trick, który oszczędza pamięć. Ale przypomnij sobie liczbę z hipotezy niskiego rzędu: **dwieście parametrów** wystarczyło, by olbrzymi model nauczył się nowego zadania w 90%. Nie dwieście milionów. Dwieście.

Pomyśl, co to właściwie znaczy. W [drugim wpisie serii](/posty/llm-sieci-parametry-trening) zachwycaliśmy się **miliardami** parametrów, kolosalnym kosztem treningu, bilionami tokenów. A teraz okazuje się, że żeby tego olbrzyma **przestawić** na nowe zadanie, wystarczy poruszyć garstkę liczb. Jak to możliwe? Najprostsze wyjaśnienie jest też najgłębsze: bo nowej umiejętności tak naprawdę **nie dokładamy**. Ona w jakiejś formie **już tam jest** - utajona w wagach, które chłonęły niemal cały zapisany ludzki tekst. Dotrenowanie nie tyle *uczy* model od zera, ile **odnajduje i uwypukla** to, co pretrening już w nim ułożył. Mały dodatek wystarcza, bo nie buduje nowej zdolności - on tylko obraca reflektor ku tej, która czekała w ciemności.

To jest może najcichszy, a najgłębszy morał całej tej serii. Rozkładaliśmy LLM część po części - neuron, sieć, token, uwaga, blok - szukając, *gdzie* siedzi to, co model potrafi. A LoRA pokazuje, że ta zdolność nie jest zlokalizowana w żadnym konkretnym miejscu, które dało się dotrenować osobno; jest **rozsmarowana** po całej tej wytrenowanej geometrii tak gęsto, że nowe zachowanie da się z niej wydobyć ledwie muśnięciem. Anatomia dobiega końca - rozebraliśmy mechanizm do ostatniej śrubki. A pytanie, *jak* w tej zamrożonej tkance zmieściło się tyle utajonych zdolności, że wystarczy ją lekko szturchnąć, by wyłoniła kolejną - to już pytanie, które wykracza poza sam plan budowy. Zostawiam je [osobnemu esejowi o rezonansie człowiek-LLM](/posty/rezonans-czlowiek-llm-kwantowe-lustro), bo tam jest jego właściwe miejsce.


## 🎯 Co dalej: koniec drogi od neuronu do LoRA

To był ostatni przystanek. Zaczęliśmy od [jednego neuronu](/posty/llm-neuron-i-aktywacje) - progu, sumy ważonej, funkcji aktywacji - i doszliśmy aż tutaj: do sztuczki, która pozwala wziąć gotowego, wartego miliony olbrzyma i wyspecjalizować go na własnej karcie graficznej, ruszając ułamek procenta jego wag. Po drodze złożyliśmy [sieci i trening](/posty/llm-sieci-parametry-trening), [tokeny i embeddingi](/posty/llm-tokeny-embeddingi), [mechanizm uwagi](/posty/llm-mechanizm-uwagi) i [cały blok Transformera](/posty/llm-blok-transformera). Siedem przystanków, jeden mechanizm - rozebrany do ostatniej śrubki.

I tu domyka się klamra z [przeglądowego wpisu](/posty/anatomia-llm), od którego zaczęła się ta podróż. Poznaliśmy *jak* to jest zbudowane - z zaskakująco prostych, powtarzalnych klocków. Ale im dokładniej rozbieraliśmy maszynę, tym wyraźniej widać było, że *dlaczego* z tej prostoty wyrasta coś, co rozumuje, tłumaczy i prowadzi rozmowę, wciąż pozostaje otwarte. Anatomia nie odebrała tajemnicy - tylko pokazała, gdzie dokładnie ona mieszka.

Jeśli wolisz teraz **dotknąć** zamiast czytać, [interaktywna strona „Anatomia LLM"](/llm/anatomia#lora) pozwala pobawić się każdym z tych klocków - od neuronu po LoRA. A jeśli ciągnie cię to, co naprawdę *wyłania się* z tej maszynerii - i dlaczego rozmowa z modelem potrafi przypominać rezonans z drugim umysłem - [pisałem o tym osobno](/posty/rezonans-czlowiek-llm-kwantowe-lustro). Tam ta seria znajduje swoje dopowiedzenie.


[^hu]: E. J. Hu et al. (2021). *LoRA: Low-Rank Adaptation of Large Language Models* (zamrożenie $W_0$, poprawka niskiego rzędu $\frac{\alpha}{r}BA$, ~10 000× mniej parametrów i ~3× mniej pamięci dla GPT-3, brak opóźnienia inferencji przez scalanie, konwencja $W_q$/$W_v$). arXiv:2106.09685. <https://arxiv.org/abs/2106.09685>
[^aghajanyan]: A. Aghajanyan, L. Zettlemoyer, S. Gupta (2020). *Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning* (niski wymiar wewnętrzny zadań; 200 parametrów → 90% wyniku na MRPC dla RoBERTa). arXiv:2012.13255. <https://arxiv.org/abs/2012.13255>
[^peft]: HuggingFace PEFT - dokumentacja (Parameter-Efficient Fine-Tuning; metody dostrajają niewielką część parametrów przy jakości bliskiej pełnemu dotrenowaniu; zbiór metod m.in. LoRA, AdaLoRA, DoRA, prefix/prompt/p-tuning). <https://huggingface.co/docs/peft/index>
[^houlsby]: N. Houlsby et al. (2019). *Parameter-Efficient Transfer Learning for NLP* (adaptery; w granicach 0,4% pełnego dotrenowania na GLUE przy 3,6% parametrów na zadanie). ICML. arXiv:1902.00751. <https://arxiv.org/abs/1902.00751>
[^liliang]: X. L. Li, P. Liang (2021). *Prefix-Tuning: Optimizing Continuous Prompts for Generation* (uczony ciągły prefiks, ~0,1% parametrów). ACL. arXiv:2101.00190. <https://arxiv.org/abs/2101.00190>
[^lester]: B. Lester, R. Al-Rfou, N. Constant (2021). *The Power of Scale for Parameter-Efficient Prompt Tuning* (soft prompts przy zamrożonym modelu; większy model domyka lukę). EMNLP. arXiv:2104.08691. <https://arxiv.org/abs/2104.08691>
[^bitfit]: E. Ben-Zaken, S. Ravfogel, Y. Goldberg (2021). *BitFit: Simple Parameter-efficient Fine-tuning for Transformer-based Masked Language-models* (modyfikacja tylko wyrazów biasu). arXiv:2106.10199. <https://arxiv.org/abs/2106.10199>
[^llmint8]: T. Dettmers et al. (2022). *LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale* (kwantyzacja INT8 bez utraty jakości, obsługa „emergent outlier features"). NeurIPS. arXiv:2208.07339. <https://arxiv.org/abs/2208.07339>
[^gptq]: E. Frantar et al. (2022). *GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers* (kwantyzacja modelu 175B do 3-4 bitów w ~4 h GPU, przyspieszenie inferencji ~3,25×). ICLR. arXiv:2210.17323. <https://arxiv.org/abs/2210.17323>
[^qlora]: T. Dettmers et al. (2023). *QLoRA: Efficient Finetuning of Quantized LLMs* (4-bit NormalFloat, podwójna kwantyzacja, paged optimizers; dostrojenie 65B na jednym 48 GB GPU; Guanaco 99,3% poziomu ChatGPT w 24 h). NeurIPS. arXiv:2305.14314. <https://arxiv.org/abs/2305.14314>
[^dora]: S.-Y. Liu et al. (2024). *DoRA: Weight-Decomposed Low-Rank Adaptation* (rozkład wagi na wielkość i kierunek; LoRA tylko do kierunku). ICML. arXiv:2402.09353. <https://arxiv.org/abs/2402.09353>
[^loraplus]: S. Hayou, N. Ghosh, B. Yu (2024). *LoRA+: Efficient Low Rank Adaptation of Large Models* (różne tempo uczenia dla $A$ i $B$; poprawa 1-2% i przyspieszenie do 2×). ICML. arXiv:2402.12354. <https://arxiv.org/abs/2402.12354>
[^adalora]: Q. Zhang et al. (2023). *AdaLoRA: Adaptive Budget Allocation for Parameter-Efficient Fine-Tuning* (adaptacyjny rozdział budżetu rang wg ważności, parametryzacja w formie SVD). ICLR. arXiv:2303.10512. <https://arxiv.org/abs/2303.10512>
[^rslora]: D. Kalajdzievski (2023). *A Rank Stabilization Scaling Factor for Fine-Tuning with LoRA* (skalowanie $\frac{\alpha}{\sqrt{r}}$ zamiast $\frac{\alpha}{r}$; przy poprawnym czynniku wyższe rangi pomagają). arXiv:2312.03732. <https://arxiv.org/abs/2312.03732>
[^flan]: J. Wei et al. (2021). *Finetuned Language Models Are Zero-Shot Learners* (FLAN; instruction tuning na 60+ zadaniach poprawia zero-shot; przewyższa GPT-3 175B na 20 z 25 zadań). ICLR. arXiv:2109.01652. <https://arxiv.org/abs/2109.01652>
[^instructgpt]: L. Ouyang et al. (2022). *Training language models to follow instructions with human feedback* (InstructGPT; SFT + RLHF; model 1,3B preferowany nad GPT-3 175B; cel z karą KL). NeurIPS. arXiv:2203.02155. <https://arxiv.org/abs/2203.02155>