RoPE od podstaw i jak YaRN rozciąga kontekst modelu
Jak rotacyjne embeddingi pozycji kodują pozycję jako obrót, co długość fali każdego wymiaru oznacza dla długiego kontekstu i jak interpolacja pozycji, skalowanie NTK-aware i YaRN rozciągają model trenowany na 32K w stronę 262K.
- deep dive
- RoPE
- długi kontekst
- atencja
Sama atencja nie ma pojęcia, gdzie jest token: przestaw wejścia, a tak samo przestawisz wyjścia. Pozycję trzeba dodać. Prawie każdy dzisiejszy otwarty model robi to za pomocą rotacyjnych embeddingów pozycji (RoPE). To, jak działa RoPE, decyduje o tym, jak daleko poza kontekst z treningu da się model wypchnąć.
Pozycja jako obrót
RoPE (Su i in., 2021) dzieli każdy wektor zapytania i klucza na pary wymiarów i obraca parę i o kąt proporcjonalny do pozycji tokenu m:
θ_i = base^(−2i/d) i = 0 … d/2 − 1, d = wymiar głowicy
[x_2i, x_2i+1] → obróć o m · θ_i
Przydatna własność: obrót q o mθ i k o nθ sprawia, że ich iloczyn skalarny zależy tylko od m − n. Atencja widzi pozycję względną za darmo, przez kąt między dwoma wektorami. Nie dodaje się żadnego wektora pozycji i niczego nie trzeba się uczyć per pozycja.
Każdy wymiar ma długość fali
Para i wykonuje pełny obrót co λ_i = 2π / θ_i = 2π · base^(2i/d) tokenów. Przy wymiarze głowicy 128:
| Baza | Najszybsza para | Najwolniejsza para | Pary wolniejsze niż 32K tokenów |
|---|---|---|---|
| 10 000 | 6,3 tokenu | 54 410 tokenów | 4 z 64 |
| 1 000 000 | 6,3 tokenu | 5 063 256 tokenów | 24 z 64 |
Szybkie pary kodują drobny, lokalny porządek: czy ten token jest 3, czy 4 pozycje wstecz? Wolne pary kodują zgrubną pozycję dalekiego zasięgu.
Problem z ekstrapolacją siedzi w wolnych parach. Jeśli długość fali pary jest dłuższa niż kontekst z treningu, model nigdy nie widział więcej niż ułamek jej obrotu. Po przekroczeniu długości z treningu ta para daje kąty, których model nigdy nie widział, i atencja się psuje. Dlatego nowsze modele podnoszą bazę: Llama 3 używa 500 000, a Qwen2.5 używa 1 000 000. To rozciąga wolne wymiary, kosztem tego, że więcej z nich nigdy nie wykonuje pełnego obrotu w trakcie treningu.
Trzy sposoby rozciągania kontekstu
Interpolacja pozycji (Chen i in., 2023). Podziel każdą pozycję przez współczynnik skali s = L_new / L_train, więc pozycja 262K wygląda jak pozycja 32K. To proste, ale ściska też szybkie pary, co kosztuje rozdzielczość lokalną: tokeny 3 i 4 pozycje wstecz wyglądają teraz na bliższe sobie, niż model się nauczył. Odrobienie tej straty wymaga fine-tuningu.
Skalowanie NTK-aware. Zmień bazę zamiast pozycji: base' = base · s^(d / (d − 2)). Szybkie pary prawie się nie zmieniają, a wolne rozciągają się najbardziej. Bez fine-tuningu działa wyraźnie lepiej niż zwykła interpolacja, ale wszystkie wymiary traktuje jednym wzorem.
YaRN (Peng i in., 2023). Traktuj każdą parę według jej długości fali w stosunku do długości z treningu:
- pary, które w kontekście z treningu wykonują wiele obrotów, zostają nietknięte, bo już generalizują;
- pary, które wykonują mniej niż około jednego obrotu, są interpolowane pełnym współczynnikiem
s; - pary pomiędzy nimi dostają liniową rampę.
YaRN dodaje też temperaturę atencji. Zapytania i klucze są skalowane przez √(1/t) = 0,1 · ln(s) + 1, bo dłuższy kontekst rozkłada atencję na więcej tokenów i spłaszcza softmax. Przejście z 32K na 262K daje s = 8, czyli współczynnik 1,208, więc logity atencji są mnożone przez około 1,46.
Jak modele naprawdę dochodzą do 262K
Zwykły przepis to trening wstępny na krótszym kontekście, rozszerzenie skalowaniem w stylu YaRN, a potem dalszy trening na długich dokumentach, żeby model nauczył się korzystać z dodatkowego zakresu. Opublikowane konfiguracje pokazują skalowanie wprost: kilka wydań Qwen ma natywne okno 32K i współczynnik YaRN 4, żeby dojść do 131K. Nowsze deklarują natywnie 262 144 tokeny.
W llama.cpp skalowanie zwykle pochodzi z metadanych GGUF. Możesz je nadpisać przez --rope-scaling yarn, --rope-scale i --yarn-orig-ctx.
Dwie rzeczy, których skalowanie RoPE nie zmienia:
- Koszt cache KV. Cache rośnie liniowo z kontekstem, niezależnie od tego, jak kodowane są pozycje. Liczby na token są w notatce o cache KV.
- Czy model potrafi rozumować na podstawie całości. Znalezienie igły przy 200K to nie to samo, co wykorzystanie informacji sprzed 200K tokenów. Długi kontekst oceniaj na własnych zadaniach.
Zasady, których się trzymam
- Nie wychodź poza deklarowany kontekst bez metody skalowania, z którą model był trenowany albo testowany. „Ładuje się” to nie „działa”.
- Sprawdź metadane GGUF pod kątem bazy RoPE i skalowania, zanim obwinisz model o porażki na długim kontekście.
- Mierz przy takiej długości, z jaką naprawdę będziesz pracować. Jakość, szybkość i rozmiar cache zmieniają się z kontekstem.
- Przedkładaj modele trenowane na długim kontekście nad modele do niego rozciągnięte, gdy zadanie tego wymaga.
Źródła: Su i in., RoFormer (2021). Chen i in., Extending Context Window of Large Language Models via Positional Interpolation (2023). Peng i in., YaRN (2023). Skalowanie NTK-aware jako pierwsza opisała społeczność open source (bloc97, 2023). Długości fal są policzone ze wzoru powyżej.