07 · Architektury · 5 min czytania · aktualizacja
Czym jest kodowanie pozycyjne w transformerze i dlaczego jest potrzebne?
W skrócie
Samouwaga nie widzi kolejności słów, więc transformer dodaje do każdego tokenu sygnał jego pozycji: sinusoidy, uczone wektory albo obrót zapytań i kluczy.
Co to jest
Kodowanie pozycyjne to sposób przekazania transformerowi informacji o tym, na którym miejscu w sekwencji stoi każdy token. W najprostszej wersji do wektora (embeddingu) tokenu dodaje się wektor zależny tylko od jego pozycji: pierwszy token dostaje jeden „znaczek”, drugi inny, i tak dalej. Bez tego model traktowałby tekst jak worek słów.
Intuicja: wyobraź sobie, że ktoś rozsypał wyrazy zdania na stole. Wiesz, jakie słowa padły, ale nie wiesz, czy „pies gryzie człowieka”, czy „człowiek gryzie psa”. Kodowanie pozycyjne to numerki doklejone do wyrazów — z tą różnicą, że zamiast jednej liczby jest to cały wektor, z którego sieci łatwo odczytać i pozycję bezwzględną, i odległość między słowami.
Stosuje się trzy główne rodziny: sinusoidalne kodowanie z oryginalnego transformera (Vaswani i in., 2017), uczone wektory pozycji (GPT-2, BERT) oraz kodowania względne, z których dziś najpopularniejsze jest RoPE — obrotowe kodowanie pozycji używane m.in. w modelach z rodziny LLaMA.
Mechanizm — dlaczego tak działa
Problem bierze się z samej samouwagi. Wynik dla tokenu to średnia ważona wartości wszystkich tokenów, a wagi zależą tylko od par wektorów zapytanie–klucz. Jeśli przestawimy tokeny, każdy dostanie dokładnie ten sam wynik co wcześniej — tylko w innym miejscu. Samouwaga jest ekwiwariantna względem permutacji, a więc ślepa na kolejność. Sieci RNN nie miały tego problemu, bo czytały tekst krok po kroku; splot widzi kolejność lokalnie przez układ filtra.
Kodowanie sinusoidalne definiuje się wzorem: PE(pos, 2i) = sin(pos / 10000^(2i/d)) i PE(pos, 2i+1) = cos(pos / 10000^(2i/d)). Każda para wymiarów to „wskazówka zegara” obracająca się z inną prędkością: pierwsze wymiary zmieniają się szybko (okres 2π, czyli ok. 6 tokenów), ostatnie bardzo wolno (okres sięgający 10 000·2π). Razem tworzą coś w rodzaju licznika z wieloma tarczami — każda pozycja ma unikalny wzór, a sąsiednie pozycje mają podobne wektory.
Dlaczego sinusy, a nie po prostu liczba „pos”? Liczba rosłaby bez ograniczeń i zagłuszała treść słowa; sinusy mieszczą się w przedziale [−1, 1]. Ważniejsze jest jednak, że dla każdego przesunięcia k wektor PE(pos + k) jest liniową funkcją PE(pos) — obrotem każdej pary wymiarów o stały kąt. Dzięki temu model może łatwo nauczyć się relacji typu „patrz na token dwa miejsca wcześniej”, niezależnie od tego, gdzie w tekście jesteśmy. Skutek uboczny: iloczyn skalarny PE(pos)·PE(pos + k) zależy tylko od odległości k, a nie od pos.
Uczone pozycje to po prostu macierz parametrów: jeden wektor na każdą pozycję do maksymalnej długości. Działa równie dobrze w zakresie treningu, ale nie ma czego użyć dla pozycji dłuższych niż widziane w treningu. RoPE zamiast dodawać wektor, obraca zapytania i klucze o kąt proporcjonalny do pozycji. Wtedy iloczyn q·k zależy od różnicy pozycji, co wprost koduje odległość względną. Inną drogą jest ALiBi: kara za odległość dodawana bezpośrednio do wyników uwagi.
Zastrzeżenie: żadne kodowanie nie daje automatycznie dobrego działania na tekstach dłuższych niż treningowe. Rozszerzanie okna kontekstu wymaga zwykle dodatkowych zabiegów (np. skalowania częstotliwości RoPE) i krótkiego dotrenowania.
Na przykładzie
Dla małego wymiaru d = 4 sinusoidalne kodowanie daje (kolejność: sin, cos szybkiej tarczy, sin, cos wolnej): pozycja 0 → [0; 1; 0; 1], pozycja 1 → [0,841; 0,540; 0,010; 1,000], pozycja 2 → [0,909; −0,416; 0,020; 1,000], pozycja 3 → [0,141; −0,990; 0,030; 1,000]. Pierwsza para wymiarów obraca się o 1 radian na token, druga o 0,01 radiana. Szybka para po 6 tokenach wraca prawie do punktu wyjścia (pozycja 6 → sin 6 ≈ −0,28, cos 6 ≈ 0,96), więc dalekie pozycje odróżnia dopiero wolna para — stąd potrzeba wielu tarcz o różnych prędkościach.
Dla d = 512, jak w oryginalnym transformerze, policzyliśmy iloczyny skalarne. PE(10)·PE(11) = 249,1 i PE(100)·PE(101) = 249,1; PE(10)·PE(15) = 189,6 i PE(100)·PE(105) = 189,6; przy odstępie 40 wynik spada do 137,0 (maksimum, dla tej samej pozycji, to 256). Podobieństwo zależy więc wyłącznie od odległości i z grubsza maleje wraz z nią. Dla porównania: uczone pozycje w GPT-2 small to macierz 1024×768, czyli 786 432 parametry — i sztywny limit 1024 tokenów.
W praktyce
- Sinusoidy liczy się raz i rejestruje jako bufor (
self.register_buffer("pe", pe)), a dodaje do embeddingów:x = emb(tokens) + pe[:n]. - Uczone pozycje:
nn.Embedding(max_len, d)indeksowanetorch.arange(n). - RoPE implementuje się wewnątrz warstwy uwagi, na Q i K po projekcji — nie na wejściu modelu.
- W oryginalnym transformerze embeddingi tokenów mnoży się przez √d przed dodaniem pozycji, żeby sygnał pozycji ich nie zagłuszał.
- Częsty błąd: przekroczenie maksymalnej długości przy uczonych pozycjach — model zwraca błąd indeksu albo, przy obcinaniu, po cichu gubi koniec tekstu.
Najczęstsze pytania
- Dlaczego pozycję się dodaje, a nie dokleja jako dodatkowe wymiary?
- Dodawanie nie zwiększa wymiaru modelu, a w przestrzeni setek wymiarów sieć i tak potrafi oddzielić treść od pozycji. Doklejanie też działa, ale zwiększa koszt każdej warstwy.
- Które kodowanie pozycyjne jest najlepsze?
- We współczesnych dużych modelach językowych dominuje RoPE, bo koduje odległość względną i dobrze współpracuje z rozszerzaniem kontekstu. Sinusoidy i uczone pozycje wciąż spotyka się w mniejszych modelach i w transformerach wizyjnych.
- Czy model bez kodowania pozycyjnego jest bezużyteczny?
- Dla zadań, gdzie kolejność jest ważna — jak język — tak, prawie zawsze. Wyjątkiem są modele z maską przyczynową, które częściowo odtwarzają pozycję z samej maski, ale i one zwykle działają lepiej z jawnym kodowaniem.
Źródła
- Vaswani i in. „Attention Is All You Need”, NeurIPS 2017, arXiv:1706.03762 (sekcja 3.5).
- Shaw, Uszkoreit, Vaswani „Self-Attention with Relative Position Representations”, NAACL 2018.
- Su i in. „RoFormer: Enhanced Transformer with Rotary Position Embedding”, arXiv:2104.09864, 2021.
- Press, Smith, Lewis „Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation”, ICLR 2022.
- Zhang i in. „Dive into Deep Learning”, d2l.ai, rozdz. 11.6 („Self-Attention and Positional Encoding”).