Merge branch 'master' of git.wmi.amu.edu.pl:filipg/aitech-moj
This commit is contained in:
commit
4d30d0c2f4
File diff suppressed because one or more lines are too long
@ -37,15 +37,19 @@ nie tylko od pozycji $k$ czy słowa $w_k$. W naszym uproszczonym przypadku
|
|||||||
jako kontekst możemy rozpatrywać słowo bezpośrednio poprzedzające
|
jako kontekst możemy rozpatrywać słowo bezpośrednio poprzedzające
|
||||||
odgadywane słowa (kontekstem jest $w_{i-1}$).
|
odgadywane słowa (kontekstem jest $w_{i-1}$).
|
||||||
|
|
||||||
Wygodnie również przyjąć, że $\sum_{k=1}^j \omega_k = 1$, wówczas mamy do czynienia ze średnią ważoną.
|
Wygodnie również przyjąć, że $\sum_{k=1}^j \omega_k = 1$ i $\omega_k
|
||||||
|
\in (0,1)$, wówczas mamy do czynienia ze średnią ważoną.
|
||||||
|
|
||||||
*** Nieznormalizowane wagi atencji
|
*** Nieznormalizowane wagi atencji
|
||||||
|
|
||||||
Będziemy liczyć nieznormalizowane **wagi atencji**
|
Będziemy liczyć nieznormalizowane **wagi atencji**
|
||||||
$\hat{\alpha}_{k,j}$. Określają one, jak bardzo słowo $w_j$ „zwraca
|
$\hat{\alpha}_{k,j}$. Określają one, jak bardzo słowo $w_j$ „zwraca
|
||||||
uwagę” na poszczególne, inne słowa. Innymi słowy, wagi opisują, jak
|
uwagę” na poszczególne, inne słowa. Innymi słowy, wagi atencji opisują, jak
|
||||||
bardzo słowo $w_k$ pasuje do naszego kontekstu, czyli słowa $w_j$.
|
bardzo słowo $w_k$ pasuje do naszego kontekstu, czyli słowa $w_j$.
|
||||||
|
|
||||||
|
*Uwaga*: (nieznormalizowane czy znormalizowane) wagi atencji nie należą do wyuczalnych
|
||||||
|
wag (parametrów) modelu.
|
||||||
|
|
||||||
Najprostszy sposób mierzenia dopasowania to po prostu iloczyn skalarny:
|
Najprostszy sposób mierzenia dopasowania to po prostu iloczyn skalarny:
|
||||||
|
|
||||||
$$\hat{\alpha}_{k,j} = E(w_k)E(w_j),$$
|
$$\hat{\alpha}_{k,j} = E(w_k)E(w_j),$$
|
||||||
@ -86,67 +90,6 @@ słowo odgadywane.
|
|||||||
#+CAPTION: Atencja użyta w prostym neuronowym modelu języka
|
#+CAPTION: Atencja użyta w prostym neuronowym modelu języka
|
||||||
[[./10_Atencja/simple-attention.drawio.png]]
|
[[./10_Atencja/simple-attention.drawio.png]]
|
||||||
|
|
||||||
** Atencja jako „miękka” baza danych
|
|
||||||
|
|
||||||
O atencji można myśleć metaforycznie jako o odpytywaniu „miękkiej”, wektorowej
|
|
||||||
bazy danych. Możemy sobie wyobrazić, że słowa $w_1,\dots,w_{j-1}$ są
|
|
||||||
naszą bazą danych, a słowo $w_j$ (z którego kierujemy „snop” uwagi)
|
|
||||||
jest *zapytaniem* (/query/). To zapytanie dopasowujemy do *kluczy*
|
|
||||||
(/keys/), w najprostszym ujęciu po prostu słów $w_1,\dots,w_{j-1}$ (a
|
|
||||||
właściwie ich zanurzeń). Jeśli klucz pasuje do zapytania, odpowiednia
|
|
||||||
wartość (/value/) jest wydobywana z bazy. Nasza baza jest jednak
|
|
||||||
„miękka”, nie — zerojedynkowa, zapytanie pasuje klucza w pewnym
|
|
||||||
stopniu, mniej lub bardziej.
|
|
||||||
|
|
||||||
W najprostszym ujęciu wartości są tym samym co klucze, czyli z naszej
|
|
||||||
bazy wydobywamy te same zanurzenia słów, których używamy jako kluczy.
|
|
||||||
Można jednak skomplikować schemat rozróżniając klucze i wartości —
|
|
||||||
mogą one powstawać przez rzutowanie podstawowe zanurzenia różnymi
|
|
||||||
macierzami:
|
|
||||||
|
|
||||||
$$\vec{k_i} = W_k E(w_i),$$
|
|
||||||
|
|
||||||
$$\vec{v_i} = W_v E(w_i).$$
|
|
||||||
|
|
||||||
Również samo zapytanie może powstać przez rzutowanie:
|
|
||||||
|
|
||||||
$$\vec{q_i} = W_q E(w_i).$$
|
|
||||||
|
|
||||||
Jeśli zanurzenie $E(w_i)$ o rozmiarze $m$ przedstawimy w postaci
|
|
||||||
kolumnowej, wówczas macierze będą $W_k$ i $W_q$ będą miały rozmiar
|
|
||||||
$d_k \times m$, gdzie $d_k$ jest rozmiarem kluczy i zapytań (dlaczego
|
|
||||||
wektory kluczy i zapytań powinny mieć raczej ten sam rozmiar?), zaś macierz
|
|
||||||
$W_v$ — $d_v \times m$, gdzie $d_v$ to rozmiar zanurzenia wektora wartości.
|
|
||||||
Zazwyczaj $d_k = d_v = m$, ale nie jest to obligatoryjne.
|
|
||||||
|
|
||||||
Teraz nieznormalizowane wagi atencji przyjmą postać:
|
|
||||||
|
|
||||||
$$\hat{\alpha}_{i,j} = \vec{q_i}^T\vec{k_j} = (W_q E(w_i))(W_k E(k_j)).$$
|
|
||||||
|
|
||||||
Zauważmy, że ciąg $\hat{\alpha}_{1,j},\dots,\hat{\alpha}_{j-1,j}$ można potraktować jako wektor
|
|
||||||
$\hat{\vec{\alpha}_{*,j}}$ i wyliczać w postaci zwartej:
|
|
||||||
|
|
||||||
$$\hat{\vec{\alpha}_{*,j}} = \vec{k_j}^T K$$
|
|
||||||
|
|
||||||
gdzie $K$ to macierz kluczy złożona z wektorów
|
|
||||||
$\vec{k_1},\dots,\vec{k_{j-1}}$, tj. macierz o rozmiarze $d_k \times (j-1)$.
|
|
||||||
|
|
||||||
Wektor znormalizowanych wag atencji będzie miał wówczas postać:
|
|
||||||
|
|
||||||
$$\vec{\alpha}_{*,j} = \operatorname{softmax}(\vec{k_j}^T K).$$
|
|
||||||
|
|
||||||
Dokonajmy teraz agregacji wartości — obliczeniamy średnią wektorów
|
|
||||||
wartości (\vec{v_i}) ważoną atencją:
|
|
||||||
|
|
||||||
$$A(w_1,\dots,j-1) = \alpha_{1,j} \vec{v_1} + \dots + \alpha_{j-1,j} \vec{v_{j-1}} = \sum_{i=1}^{j-1} \alpha_{i,j} v_i.$$
|
|
||||||
|
|
||||||
Jeśli $j-1$ wektorów wartości ułożyłem w macierz $V$ (o rozmiarze
|
|
||||||
$(j-1) \times d_v$), powyższy wzór będziemy mogli zapisać jako iloczyn wektora wag atencji i macierzy $V$:
|
|
||||||
|
|
||||||
$$A(w_1,\dots,j-1) = \vec{\alpha}_{*,j}^T V = \operatorname{softmax}(\vec{k_j}^T K)^T V.$$
|
|
||||||
|
|
||||||
Sposób patrzenia na atencję przez pryzmat trójki
|
|
||||||
zapytania-klucze-wartości okaże się niezwykle ważny w wypadku modelu Transformer (zob. kolejny wykład).
|
|
||||||
|
|
||||||
** Atencja jako składnik sieci rekurencyjnej
|
** Atencja jako składnik sieci rekurencyjnej
|
||||||
|
|
||||||
@ -171,7 +114,7 @@ $$P_M(w_j|w_1,\dots,w_{j-1}) = ?.$$
|
|||||||
|
|
||||||
Załóżmy, że mamy pewien początek (*prefiks*) tekstu o długości $p$:
|
Załóżmy, że mamy pewien początek (*prefiks*) tekstu o długości $p$:
|
||||||
$w_1,\dots,w_p$. Powiedzmy, że naszym celem jest *wygenerowanie*
|
$w_1,\dots,w_p$. Powiedzmy, że naszym celem jest *wygenerowanie*
|
||||||
dokończenia czy kontynuacji tego tekstu (nie określamy z góry tej
|
dokończenia czy kontynuacji tego tekstu (nie określamy z góry
|
||||||
długości tej kontynuacji).
|
długości tej kontynuacji).
|
||||||
|
|
||||||
Najprostszy sposób wygenerowania pierwszego wyrazu dokończenia polega
|
Najprostszy sposób wygenerowania pierwszego wyrazu dokończenia polega
|
||||||
@ -179,7 +122,7 @@ na wzięciu wyrazu maksymalizującego prawdopodobieństwo według modelu języka
|
|||||||
|
|
||||||
$$w_{p+1} = \operatorname{argmax}_w P_M(w|w_1,\dots,w_p).$$
|
$$w_{p+1} = \operatorname{argmax}_w P_M(w|w_1,\dots,w_p).$$
|
||||||
|
|
||||||
*Pytanie*: Dlaczego \operatorname{argmax}, a nie \operatorname{max}?
|
*Pytanie*: Dlaczego $\operatorname{argmax}$, a nie $\operatorname{max}$?
|
||||||
|
|
||||||
Słowo $w_{p+1}$ możemy dołączyć do prefiksu i powtórzyć procedurę:
|
Słowo $w_{p+1}$ możemy dołączyć do prefiksu i powtórzyć procedurę:
|
||||||
|
|
||||||
@ -205,9 +148,9 @@ przedstawić jako zadanie generowania tekstu. Przykładem jest tłumaczenie masz
|
|||||||
|
|
||||||
W tłumaczeniu maszynowym (tłumaczeniu automatycznym, ang. /machine
|
W tłumaczeniu maszynowym (tłumaczeniu automatycznym, ang. /machine
|
||||||
translation/) na wejściu podawany jest tekst (na ogół pojedyncze
|
translation/) na wejściu podawany jest tekst (na ogół pojedyncze
|
||||||
zdanie) źródłowy (/source sentence/) $S = (u_1,\dots,u_|S|)$, celem
|
zdanie) źródłowy (/source sentence/) $S = (u_1,\dots,u_{|S|})$, celem
|
||||||
jest uzyskanie tekstu docelowego (/target sentence/)
|
jest uzyskanie tekstu docelowego (/target sentence/)
|
||||||
$T=(w_1,\dots,w_|T|). Zakładamy, że $S$ jest tekstem w pewnym języku
|
$T=(w_1,\dots,w_{|T|})$. Zakładamy, że $S$ jest tekstem w pewnym języku
|
||||||
źródłowym (/source language/), zaś $T$ — w innym języku, języku
|
źródłowym (/source language/), zaś $T$ — w innym języku, języku
|
||||||
docelowym (/target language/).
|
docelowym (/target language/).
|
||||||
|
|
||||||
@ -229,8 +172,8 @@ The 'new Member States' - actually, the name continues to be sort of conditional
|
|||||||
The number of armed attacks also rose by 200% overall. Także liczba ataków zbrojnych wzrosła łącznie o 200 %.
|
The number of armed attacks also rose by 200% overall. Także liczba ataków zbrojnych wzrosła łącznie o 200 %.
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
Zauważmy, że możemy taki tekst modelować po prostu traktując jako
|
Zauważmy, że możemy taki (bi)tekst modelować po prostu traktując jako
|
||||||
jeden. Innymi słowy, nie modelujemy tekstu angielskiego ani polskiego,
|
jeden ciągły tekst. Innymi słowy, nie modelujemy tekstu angielskiego ani polskiego,
|
||||||
tylko angielsko-polską mieszankę, to znaczy uczymy model, który najpierw modeluje prawdopodobieństwo
|
tylko angielsko-polską mieszankę, to znaczy uczymy model, który najpierw modeluje prawdopodobieństwo
|
||||||
po stronie źródłowej (powiedzmy — angielskiej):
|
po stronie źródłowej (powiedzmy — angielskiej):
|
||||||
|
|
||||||
@ -239,7 +182,7 @@ The number of armed attacks also ?
|
|||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
W momencie napotkania specjalnego tokenu końca zdania źródłowego (powiedzmy ~<eoss>~) model
|
W momencie napotkania specjalnego tokenu końca zdania źródłowego (powiedzmy ~<eoss>~) model
|
||||||
powinien nauczyć się, że musi przerzucić się na modelowanie tekstu w języku docelowym (powiedzmy — polskim):
|
powinien nauczyć się, że musi przełączyć się na modelowanie tekstu w języku docelowym (powiedzmy — polskim):
|
||||||
|
|
||||||
#+BEGIN_SRC
|
#+BEGIN_SRC
|
||||||
The number of armed attacks also rose by 200% overall.<eoss>Także liczba ataków ?
|
The number of armed attacks also rose by 200% overall.<eoss>Także liczba ataków ?
|
||||||
@ -254,10 +197,10 @@ tłumaczone zdanie jako prefiks, doklejając tylko token ~<eoss>~.
|
|||||||
|
|
||||||
**** Neuronowe modele języka jako translatory
|
**** Neuronowe modele języka jako translatory
|
||||||
|
|
||||||
Jako że N-gramowego modelu języka ani modelu opartego na worku słów
|
Jako że n-gramowego modelu języka ani modelu opartego na worku słów
|
||||||
nie da się użyć w omawiany sposób w tłumaczeniu maszynowym
|
nie da się użyć w omawiany sposób w tłumaczeniu maszynowym
|
||||||
(dlaczego?), jako pierwszych użyto w neuronowym tłumaczeniu maszynowym
|
(dlaczego?), jako pierwszych użyto w neuronowym tłumaczeniu maszynowym
|
||||||
sieci LSTM, przy użyciu omawianego wyżej sposobu.
|
sieci LSTM, przy zastosowaniu omawianego wyżej sposobu.
|
||||||
|
|
||||||
System tłumaczenia oparte na sieciach LSTM działały zaskakująco
|
System tłumaczenia oparte na sieciach LSTM działały zaskakująco
|
||||||
dobrze, zważywszy na to, że cała informacja o zdaniu źródłowym musi
|
dobrze, zważywszy na to, że cała informacja o zdaniu źródłowym musi
|
||||||
|
281
wyk/11_Transformer.org
Normal file
281
wyk/11_Transformer.org
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
|
||||||
|
* Transformer
|
||||||
|
|
||||||
|
** Atencja jako „miękka” baza danych
|
||||||
|
|
||||||
|
O atencji można myśleć metaforycznie jako o odpytywaniu „miękkiej”, wektorowej
|
||||||
|
bazy danych. Możemy sobie wyobrazić, że słowa $w_1,\dots,w_{j-1}$ są
|
||||||
|
naszą bazą danych, a słowo $w_j$ (z którego kierujemy „snop” uwagi)
|
||||||
|
jest *zapytaniem* (/query/). To zapytanie dopasowujemy do *kluczy*
|
||||||
|
(/keys/), w najprostszym ujęciu po prostu słów $w_1,\dots,w_{j-1}$ (a
|
||||||
|
właściwie ich zanurzeń). Jeśli klucz pasuje do zapytania, odpowiednia
|
||||||
|
wartość (/value/) jest wydobywana z bazy. Nasza baza jest jednak
|
||||||
|
„miękka”, nie — zerojedynkowa, zapytanie pasuje do klucza w pewnym
|
||||||
|
stopniu, mniej lub bardziej.
|
||||||
|
|
||||||
|
W najprostszym ujęciu wartości są tym samym co klucze, czyli z naszej
|
||||||
|
bazy wydobywamy te same zanurzenia słów, których używamy jako kluczy.
|
||||||
|
Można jednak skomplikować schemat rozróżniając klucze i wartości —
|
||||||
|
mogą one powstawać przez rzutowanie podstawowych zanurzeń różnymi
|
||||||
|
macierzami:
|
||||||
|
|
||||||
|
$$\vec{k_i} = W_k E(w_i),$$
|
||||||
|
|
||||||
|
$$\vec{v_i} = W_v E(w_i).$$
|
||||||
|
|
||||||
|
Również samo zapytanie może powstać przez rzutowanie:
|
||||||
|
|
||||||
|
$$\vec{q_i} = W_q E(w_i).$$
|
||||||
|
|
||||||
|
Jeśli zanurzenie $E(w_i)$ o rozmiarze $m$ przedstawimy w postaci
|
||||||
|
kolumnowej, wówczas macierze będą $W_k$ i $W_q$ będą miały rozmiar
|
||||||
|
$d_k \times m$, gdzie $d_k$ jest rozmiarem kluczy i zapytań (dlaczego
|
||||||
|
wektory kluczy i zapytań powinny mieć raczej ten sam rozmiar?), zaś macierz
|
||||||
|
$W_v$ — $d_v \times m$, gdzie $d_v$ to rozmiar zanurzenia wektora wartości.
|
||||||
|
Zazwyczaj $d_k = d_v = m$, ale nie jest to obligatoryjne.
|
||||||
|
|
||||||
|
Teraz nieznormalizowane wagi atencji przyjmą postać:
|
||||||
|
|
||||||
|
$$\hat{\alpha}_{i,j} = \vec{q_i}^T\vec{k_j} = (W_q E(w_i))(W_k E(k_j)).$$
|
||||||
|
|
||||||
|
Zauważmy, że ciąg $\hat{\alpha}_{1,j},\dots,\hat{\alpha}_{j-1,j}$ można potraktować jako wektor
|
||||||
|
$\hat{\vec{\alpha}_{*,j}}$ i wyliczać w postaci zwartej:
|
||||||
|
|
||||||
|
$$\hat{\vec{\alpha}_{*,j}} = \vec{q_j}^T K$$
|
||||||
|
|
||||||
|
gdzie $K$ to macierz kluczy złożona z wektorów
|
||||||
|
$\vec{k_1},\dots,\vec{k_{j-1}}$, tj. macierz o rozmiarze $d_k \times (j-1)$.
|
||||||
|
|
||||||
|
Wektor znormalizowanych wag atencji będzie miał wówczas postać:
|
||||||
|
|
||||||
|
$$\vec{\alpha}_{*,j} = \operatorname{softmax}(\vec{q_j}^T K).$$
|
||||||
|
|
||||||
|
Dokonajmy teraz agregacji wartości — obliczamy średnią wektorów
|
||||||
|
wartości ($\vec{v_i}$) ważoną atencją:
|
||||||
|
|
||||||
|
$$A(w_1,\dots,j-1) = \alpha_{1,j} \vec{v_1} + \dots + \alpha_{j-1,j} \vec{v_{j-1}} = \sum_{i=1}^{j-1} \alpha_{i,j} v_i.$$
|
||||||
|
|
||||||
|
Jeśli $j-1$ wektorów wartości ułożyłem w macierz $V$ (o rozmiarze
|
||||||
|
$(j-1) \times d_v$), powyższy wzór będziemy mogli zapisać jako iloczyn wektora wag atencji i macierzy $V$:
|
||||||
|
|
||||||
|
$$A(w_1,\dots,j-1) = \vec{\alpha}_{*,j}^T V = \operatorname{softmax}(\vec{q_j}^T K)^T V.$$
|
||||||
|
|
||||||
|
Sposób patrzenia na atencję przez pryzmat trójki
|
||||||
|
zapytania-klucze-wartości okaże się niezwykle ważny w wypadku modelu Transformer.
|
||||||
|
|
||||||
|
** Model Transformer — historia
|
||||||
|
|
||||||
|
Architekturę Transformer opracowano, pierwotnie, na potrzeby
|
||||||
|
tłumaczenia automatycznego (rok 2017, artykuł [Attention Is All You
|
||||||
|
Need](https://arxiv.org/abs/1706.03762)). Szybko okazało się, że
|
||||||
|
podobnie jak w wypadku modelu ELMo dla sieci LSTM, można *pretrenować*
|
||||||
|
duże modele Transformer (po prostu na dużych korpusach tekstowych, w
|
||||||
|
sposób nienadzorowany), a potem dostrajać pod konkretne zadanie
|
||||||
|
przetwarzania języka naturalnego. Jednym z pierwszych przykładów
|
||||||
|
takiego podejścia był model BERT (rok 2018, artykuł [BERT:
|
||||||
|
Pre-training of Deep Bidirectional Transformers for Language
|
||||||
|
Understanding](https://arxiv.org/abs/1810.04805)). To podejście było
|
||||||
|
później rozwinięte w postaci różnych modeli Transformer, również dla innych
|
||||||
|
języków niż angielski (RoBERTa, XLM, Polish RoBERTa itd.).
|
||||||
|
|
||||||
|
Na tym wykładzie my skupimy się na innej odnodze modeli Transformer —
|
||||||
|
modelach generatywnych, takich jak na przykład GPT-2 czy GPT-3. To
|
||||||
|
podejście jest bliższe duchowi czystego modelowania języka — model
|
||||||
|
języka jest używany wprost jako generator.
|
||||||
|
|
||||||
|
** GPT-2 — przykład działania
|
||||||
|
|
||||||
|
Dokonajmy najpierw tokenizacji:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("gpt2")
|
||||||
|
text = "The World War III will begin in"
|
||||||
|
encoded_input = tokenizer(text, return_tensors='pt')
|
||||||
|
encoded_input
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
{'input_ids': tensor([[ 464, 2159, 1810, 6711, 481, 2221, 287]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1]])}
|
||||||
|
:end:
|
||||||
|
|
||||||
|
Możemy podejrzeć uzyskane tokeny:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
[tokenizer.decode(i) for i in encoded_input.input_ids[0]]
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
['The', ' World', ' War', ' III', ' will', ' begin', ' in']
|
||||||
|
:end:
|
||||||
|
|
||||||
|
Zwróćmy uwagę, że w GPT-2 tokeny obejmują spacje!
|
||||||
|
|
||||||
|
Teraz uruchommy zasadniczy model:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
from transformers import AutoModelForCausalLM
|
||||||
|
model = AutoModelForCausalLM.from_pretrained("gpt2")
|
||||||
|
outputs = model(**encoded_input)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
:end:
|
||||||
|
|
||||||
|
Z modelu GPT-2 otrzymamy rozkład prawdopodobieństwa kolejnego wyrazu, najpierw w postaci
|
||||||
|
nieznormalizowanych *logitów*:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
logits = outputs[0][0][-1]
|
||||||
|
logits
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
tensor([-130.2947, -129.5677, -136.4030, ..., -138.3791, -138.8967,
|
||||||
|
-131.6319], grad_fn=<SelectBackward0>)
|
||||||
|
:end:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
from torch import softmax, topk
|
||||||
|
|
||||||
|
k = 20
|
||||||
|
|
||||||
|
t = topk(softmax(logits, -1), k)
|
||||||
|
|
||||||
|
tb = [[tokenizer.decode(t.indices[ix]), t.values[ix].item()] for ix in range(k)]
|
||||||
|
tb
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
[[' earnest', 0.07378227263689041], [' the', 0.06698606163263321], [' 1945', 0.043497972190380096], [' September', 0.024068640545010567], [' March', 0.0228887926787138], [' October', 0.02232857048511505], [' Europe', 0.02032744698226452], [' 2020', 0.018564637750387192], [' Japan', 0.018423961475491524], [' December', 0.016560807824134827], [' January', 0.015074416995048523], [' July', 0.014139187522232533], [' April', 0.013183596543967724], [' November', 0.012901309877634048], [' 20', 0.012770282104611397], [' Afghanistan', 0.012765118852257729], [' 1944', 0.01266297698020935], [' June', 0.012072316370904446], [' 1914', 0.011765970848500729], [' May', 0.011659453622996807]]
|
||||||
|
:end:
|
||||||
|
|
||||||
|
*** Generowanie tekstu za pomocą GPT-2
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||||
|
from transformers import pipeline
|
||||||
|
generator = pipeline('text-generation', model='gpt2')
|
||||||
|
generator('Hello, I\'m a language model,', max_length=30, num_return_sequences=1)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
:end:
|
||||||
|
|
||||||
|
** Model Transformer — podstawowa idea
|
||||||
|
|
||||||
|
Model Transformer sprowadza się właściwie do atencji; nie posiada
|
||||||
|
żadnego komponentu rekurencyjnego, ani nawet nie stosujemy czegoś w
|
||||||
|
rodzaju połączenia modelu worka słów i modelu n-gramowego.
|
||||||
|
|
||||||
|
W pierwszym przybliżeniu przy obliczaniu rozkładu prawdopodobieństwa
|
||||||
|
dla kolejnego wyrazu, to jest:
|
||||||
|
|
||||||
|
$$P(w_j|w_1\dots w_{j-1})$$
|
||||||
|
|
||||||
|
na $j$-tym miejscu (w miejscu przewidywanego wyrazu) doklejamy
|
||||||
|
specjalny token, powiedzmy ~<mask>~. Token ten będzie „atendował” do
|
||||||
|
innych wszystkich wcześniejszych tokenów w zdaniu:
|
||||||
|
|
||||||
|
$$\vec{\alpha}_{*,j}^T V = \operatorname{softmax}(\vec{q_j}^T K)^T V.$$
|
||||||
|
|
||||||
|
Samo to byłoby oczywiście zbyt proste:
|
||||||
|
|
||||||
|
1. Otrzymalibyśmy model (ważonego) worka słów, w dodatku każde słowo
|
||||||
|
miałoby zawsze taką samą wagę! — Token $w_j$, który atenduje jest
|
||||||
|
zawsze ten sam (~<mask>~). Musimy wzbogacić reprezentację wektorową
|
||||||
|
słów i specjalnego tokenu (~<mask>~).
|
||||||
|
|
||||||
|
2. Model Transformer w swojej podstawowej postaci w ogóle nie jest
|
||||||
|
wyposażony w pojęcie sekwencji — w przeciwieństwie do sieci
|
||||||
|
rekurencyjnych, które w sposób inherentny operują krok po kroku, w
|
||||||
|
sekwencji (w czasie). Musimy pozycję tokenów wprowadzić do sieci
|
||||||
|
Transformer nie przez modyfikację jej architektury, lecz przez dołączenie
|
||||||
|
informacji pozycyjnej do początkowych zanurzeń.
|
||||||
|
|
||||||
|
3. Model Transformer nie powinien mieć żadnych tokenów OOV/UNK. Musimy
|
||||||
|
wrócić do kwestii tokenizacji tekstu i wprowadzić podział rzadszych
|
||||||
|
tokenów na mniejsze, *podwyrazowe* jednostki.
|
||||||
|
|
||||||
|
** Atencja wsobna
|
||||||
|
|
||||||
|
Jeśli chodzi problem (1), rozwiążemy go przez wprowadzenie
|
||||||
|
**skontekstualizowanych reprezentacji** tokenów.
|
||||||
|
|
||||||
|
Na przykład słowo /mysz/ ma jedno wejściowe (/statyczne/) zanurzenie
|
||||||
|
(embedding) — bez względu na to, czy chodzi o zwierzę czy urządzenie
|
||||||
|
peryferyjne, tymczasem dość łatwo ustalić na podstawie kontekstu, o
|
||||||
|
które znaczenie chodzi.
|
||||||
|
|
||||||
|
Rozwiązanie polega na tym, że tokenom będziemy przypisywać kolejne
|
||||||
|
zanurzenia skontekstualizowane — zależne od innych wyrazów w zdaniu. W
|
||||||
|
tym celu zastosujemy atencję wsobną (samo-atencję, /self-attention/).
|
||||||
|
Każdy token będzie atendował potencjalnie do każdego innego tokenu,
|
||||||
|
również do samego siebie (!).
|
||||||
|
|
||||||
|
*** Wzory
|
||||||
|
|
||||||
|
Rozpatrywać zatem będziemy nie tylko pojedynczy wektor znormalizowanych atencji
|
||||||
|
|
||||||
|
$$\vec{\alpha}_{*,j}^T V = \operatorname{softmax}(\vec{q_j}^T K)^T V$$,
|
||||||
|
|
||||||
|
lecz całą serię wektorów:
|
||||||
|
|
||||||
|
$$\vec{\alpha}_{*,1},\dots,\vec{\alpha}_{*,i},\dots,\vec{\alpha}_{*,j}$$
|
||||||
|
|
||||||
|
gdzie:
|
||||||
|
|
||||||
|
$$\vec{\alpha}_{*,i} = \operatorname{softmax}(\vec{q_i}^T K)$$
|
||||||
|
|
||||||
|
i $K$ jest macierzą kluczy o rozmiarze $d_k \times j$ (tym razem obejmuje również sam $i$-ty token).
|
||||||
|
|
||||||
|
Nowa, skontekstualizowana reprezentacja $i$-tego tokenu będzie po prostu średnią wszystkich
|
||||||
|
wektorów ważoną atencją:
|
||||||
|
|
||||||
|
$$E_1(w_i) = \operatorname{softmax}(\vec{q_i}^T K)^T V,$$
|
||||||
|
|
||||||
|
gdzie:
|
||||||
|
|
||||||
|
- $E_1(w_i)$ — skontekstualizowane zanurzenie $i$-tego tokenu; używając indeksu $_1$
|
||||||
|
zaznaczamy, że to jest pierwszy skonstekstualizowany embedding, rekurencyjnie będziemy budowali
|
||||||
|
kolejne $E_2(w_i)$, $E_3(w_i)$ itd. (zaś wejściowy statyczny embedding możemy oznaczyć przez $E_0(w_i)$);
|
||||||
|
- $V$ to macierz wartości o rozmiarze $j \times d_v$.
|
||||||
|
|
||||||
|
**** Zwarta postać macierzowa atencji wsobnej
|
||||||
|
|
||||||
|
Z praktycznych powodów (szybkość obliczeń na kartach graficznych) dużą
|
||||||
|
zaletą atencji wsobnej jest to, że wyliczenie skonstekstualizowanych zanurzeń dla wszystkich tokenów
|
||||||
|
w tekście da się zapisać w postaci zwartego wzoru macierzowego:
|
||||||
|
|
||||||
|
$$E_1 = \operatorname{Attention}(Q, K, V) = \operatorname{softmax}(QK)^T V,$$
|
||||||
|
|
||||||
|
gdzie $Q$ to macierz wszystkich zapytań o rozmiarze $j \times d_k$ (wektory ułożone poziomo).
|
||||||
|
|
||||||
|
**** Skalowanie atencji
|
||||||
|
|
||||||
|
Twórcy modelu Transformer odkryli, że lepsze wyniki daje skalowanie atencji
|
||||||
|
przez stałą zależną od rozmiaru wektora klucza/zapytania $d_k$:
|
||||||
|
|
||||||
|
$\operatorname{Attention}(Q, K, V) = \operatorname{softmax}(\frac{QK}{d_k})^T V,$$
|
||||||
|
|
||||||
|
** Wielogłowicowa atencja
|
||||||
|
|
||||||
|
Od samego początku w Transformerze zamiast jednej atencji zaproponowano wiele **głowic atencji**
|
||||||
|
$(\operatorname{head}_1,\dots,\operatorname{head}_h$, każda głowica atencji działa w następujący sposób:
|
||||||
|
|
||||||
|
$$\operatorname{head_i} = \operatorname{Attention}(QW_i^Q, KW_i^K,VW_i^V),$$
|
||||||
|
|
||||||
|
to znaczy każda głowica atencji działa tak samo, tylko przed jej zastosowaniem mnożymy
|
||||||
|
wektory zapytań, kluczy i wartości przez różne wyuczalne macierze, odpowiednio,
|
||||||
|
W_i^Q, W_i^K,W_i^V. Otrzymamy w ten sposób $h$ wektorów, konkatenujemy po prostu i mnożymy
|
||||||
|
przez dodatkową wyuczalną macierz $W^O$:
|
||||||
|
|
||||||
|
$$\operatorname{MultiHead}(Q, K, V) = [\operatorname{head}_1,...,\operatorname{head}_n]W^O.$$
|
||||||
|
|
||||||
|
Przyjmujemy, że $d_k = d_v = m/h$, wtedy rozmiary macierzy $W_i^Q$ i $W_i^K$ będą wynosiły
|
||||||
|
$m \times d_k$, macierzy $W_i^V$ — $m \times d_v$, $W^O$ — $hd_v \times m$.
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
@ -7,7 +8,7 @@
|
|||||||
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
|
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
|
||||||
"<div class=\"alert alert-block alert-info\">\n",
|
"<div class=\"alert alert-block alert-info\">\n",
|
||||||
"<h1> Modelowanie języka</h1>\n",
|
"<h1> Modelowanie języka</h1>\n",
|
||||||
"<h2> 2. <i>Języki</i> [wykład]</h2> \n",
|
"<h2> 10. <i>Atencja</i> [wykład]</h2> \n",
|
||||||
"<h3> Filip Graliński (2022)</h3>\n",
|
"<h3> Filip Graliński (2022)</h3>\n",
|
||||||
"</div>\n",
|
"</div>\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user