ML Atlas

08 · LLM · 4 min czytania · Interaktywne · aktualizacja

Jak LLM przewiduje następne słowo i jak generuje cały tekst?

W skrócie

LLM dla każdego miejsca w tekście liczy rozkład prawdopodobieństwa następnego tokenu. Uczy się go entropią krzyżową, a tekst tworzy, losując token po tokenie.

Co to jest

Przewidywanie następnego tokenu to zadanie, na którym trenuje się modele językowe typu GPT: na podstawie wszystkich dotychczasowych tokenów model ma podać prawdopodobieństwo każdego tokenu ze słownika jako kolejnego. Formalnie model szacuje P(token_t | token_1, …, token_(t−1)). Generowanie tekstu to powtarzanie tego kroku: wybierz token, dopisz go do wejścia, policz rozkład od nowa.

To podejście nazywa się autoregresyjnym — każdy krok zależy od poprzednich wyjść modelu. Z reguły łańcuchowej prawdopodobieństwa wynika, że prawdopodobieństwo całego tekstu to iloczyn prawdopodobieństw kolejnych tokenów. Model, który dobrze przewiduje następny token, jest więc pełnym modelem prawdopodobieństwa tekstu.

Brzmi skromnie, ale to zadanie jest wymagające. Przewidzenie ostatniego słowa w zdaniu „Po trzech godzinach poszukiwań detektyw w końcu zrozumiał, że mordercą był…” wymaga śledzenia całej historii.

Mechanizm — dlaczego tak działa

Od logitów do prawdopodobieństw. Ostatnia warstwa modelu daje wektor logitów — po jednej liczbie na token słownika. Funkcja softmax zamienia je na prawdopodobieństwa: p_i = e^(z_i) / Σ e^(z_j). Wysoki logit to wysokie prawdopodobieństwo, ale żaden token nie dostaje dokładnie zera.

Strata: entropia krzyżowa. Gdy prawdziwym następnym tokenem jest y, kara wynosi −log p_y. Jeśli model dał poprawnemu tokenowi 0,9, kara to 0,11; jeśli 0,01 — aż 4,61. Logarytm sprawia, że pewność siebie przy błędzie kosztuje bardzo dużo. Minimalizacja tej straty jest równoważna metodzie największej wiarygodności: szukamy wag, przy których obserwowany tekst jest najbardziej prawdopodobny.

Wiele przykładów z jednego zdania. Dzięki masce przyczynowej w samouwadze pozycja t widzi tylko pozycje wcześniejsze. Dlatego jeden fragment o długości N tokenów daje w jednym przebiegu N przykładów treningowych naraz: z „Ala” przewidujemy „ma”, z „Ala ma” — „kota” i tak dalej. W treningu model zawsze dostaje prawdziwy poprzedni tekst (teacher forcing), nie własne zgadywania.

Perpleksja. Średnią stratę często podaje się jako perpleksję: e^(średnia strata). Perpleksja 20 znaczy, że model jest średnio tak niepewny, jakby wybierał spośród 20 równie prawdopodobnych tokenów. Model losowy na słowniku 50 257 tokenów ma stratę ln 50 257 ≈ 10,82 — od tego poziomu zaczyna się trening.

Generowanie i jego pułapki. Przy generowaniu model karmi się własnymi wyjściami. Błąd w jednym tokenie zostaje w kontekście i wpływa na resztę — nie ma przycisku „cofnij”. Wybór zawsze najbardziej prawdopodobnego tokenu (dekodowanie zachłanne) prowadzi często do nudnych, zapętlonych tekstów, dlatego zwykle się losuje (zob. temperatura i próbkowanie). Ważne zastrzeżenie: model optymalizuje prawdopodobieństwo tekstu, a nie prawdziwość. Fałsz napisany typowym stylem może mieć wysokie prawdopodobieństwo.

Na przykładzie

Kontekst: „Stolicą Polski jest”. Załóżmy, że dla czterech kandydatów model dał logity: „ Warszawa” 3,0, „ Kraków” 1,5, „ miasto” 0,5, „ pies” −1,0 (pomijamy resztę słownika). Softmax daje prawdopodobieństwa 0,756; 0,169; 0,062 i 0,014 — suma 1.

Jeśli w danych treningowych dalej stało „Warszawa”, strata wynosi −ln 0,756 = 0,28 (perpleksja 1,32). Gdyby jednak w tym tekście stało „Kraków” (np. w tekście o czasach Jagiellonów), strata wynosi 1,78, a dla „pies” aż 4,28. Gradient tej straty podnosi logit prawdziwego tokenu i obniża pozostałe proporcjonalnie do ich prawdopodobieństw. Powtórzone na bilionach tokenów, takie drobne korekty składają się na wiedzę modelu.

Ta ilustracja działa w przeglądarce z włączonym JavaScriptem: dla zdania „Kot siedzi na …” suwak temperatury zmienia rozkład prawdopodobieństw następnego słowa: przy T = 1 „parapecie” ma 35%, przy T = 0,1 już 95%.

W praktyce

  • W PyTorch strata to torch.nn.functional.cross_entropy(logits.view(-1, V), targets.view(-1)), gdzie cele to wejście przesunięte o jedną pozycję.
  • W transformers wystarczy podać labels=input_ids do modelu AutoModelForCausalLM — przesunięcie robi się wewnątrz.
  • Perpleksję porównuj tylko między modelami z tym samym tokenizerem; różny podział tekstu zmienia liczbę tokenów i samą skalę.
  • Do generowania służy model.generate z parametrami max_new_tokens, do_sample, temperature, top_p.
  • Typowy błąd: liczenie straty także na tokenach wypełnienia (padding) — maskuj je wartością -100.

Najczęstsze pytania

Czy model planuje całą odpowiedź z góry?
Nie jawnie — wybiera jeden token naraz. Badania interpretowalności pokazują jednak, że stany ukryte niosą informację o dalszych fragmentach, np. o rymie na końcu wersu. „Plan” istnieje więc w reprezentacjach, ale nie jako osobny etap.
Dlaczego ta sama treść daje różne odpowiedzi?
Bo przy generowaniu z rozkładu się losuje. Przy temperaturze 0 (wybór najbardziej prawdopodobnego tokenu) odpowiedź jest prawie deterministyczna, choć drobne różnice numeryczne na GPU mogą ją czasem zmienić.
Czy przewidywanie następnego tokenu wystarczy do rozumowania?
To otwarte pytanie. Zadanie wymusza modelowanie wielu zależności i wiele umiejętności wyłania się z samej skali. Jednocześnie model generuje odpowiedź w jednym przebiegu na token, więc trudne problemy rozwiązuje lepiej, gdy może „myśleć na głos” (łańcuch myśli).

Źródła

  • Bengio Y. i in., 2003, „A Neural Probabilistic Language Model”, Journal of Machine Learning Research 3.
  • Radford A. i in., 2018, „Improving Language Understanding by Generative Pre-Training”, raport techniczny OpenAI.
  • Radford A. i in., 2019, „Language Models are Unsupervised Multitask Learners”, raport techniczny OpenAI.
  • Goodfellow I., Bengio Y., Courville A., 2016, „Deep Learning”, MIT Press, rozdz. 12.4 (modele językowe).
  • Jurafsky D., Martin J. H., „Speech and Language Processing”, 3rd ed. (wersja robocza online), rozdz. 3 (n-gramy i perpleksja).

Zobacz też