* Modele Transformer ** Atencja Atencję w modelach Transformer można interpretować jako rodzaj „miękkiego” odpytywania swego rodzaju bazy danych, w której przechowywane są pary klucz-wartość. Mamy trzy rodzaje wektorów (a właściwie macierzy, bo wektory są od razu upakowane w macierze): - $Q$ - macierz zapytań, - $K$ - macierz kluczy, - $V$ - macierz wartości odpowiadających kluczom $K$. W atencji modeli Transformer patrzymy jak bardzo zapytania $Q$ pasują do kluczy $K$ i na tej podstawie zwracamy wartości $V$ (im bardziej *klucz* pasuje do *zapytania*, tym większy wkład wnosi odpowiednia *wartość*). Ten rodzaj odpytywania można zrealizować z pomocą mnożenia macierzy i funkcji softmax: $$\operatorname{Atention}(Q,K,V) = \operatorname{softmax}(QK^T)V$$ *** Uproszczony przykład Załóżmy, że rozmiar embeddingu wynosi 4, w macierzach rozpatrywać będziemy po 3 wektory naraz (możemy sobie wyobrazić, że zdanie zawiera 3 wyrazy). #+BEGIN_SRC ipython :session mysession :exports both :results raw drawer import torch Q = torch.tensor([ [0.3, -2.0, 0.4, 6.0], [-1.0, 1.5, 0.2, 3.0], [0.3, -1.0, 0.2, 1.0]]) K = torch.tensor([ [-0.5, 1.7, 0.3, 4.0], [0.4, -1.5, 0.3, 5.5], [-1.0, -3.5, 1.0, 4.0]]) M = Q @ torch.transpose(K, 0, 1) M #+END_SRC #+RESULTS: :results: # Out[11]: #+BEGIN_EXAMPLE tensor([[20.5700, 36.2400, 31.1000], [15.1100, 13.9100, 7.9500], [ 2.2100, 7.1800, 7.4000]]) #+END_EXAMPLE :end: Jak widać, najbardziej pierwszy wektor $Q$ pasuje do drugiego wektora $K$. Znormalizujmy te wartości używać funkcji softmax. #+BEGIN_SRC ipython :session mysession :exports both :results raw drawer import torch Mn = torch.softmax(M, 1) Mn #+END_SRC #+RESULTS: :results: # Out[12]: #+BEGIN_EXAMPLE tensor([[1.5562e-07, 9.9418e-01, 5.8236e-03], [7.6807e-01, 2.3134e-01, 5.9683e-04], [3.0817e-03, 4.4385e-01, 5.5307e-01]]) #+END_EXAMPLE :end: Drugi wektor zapytania najbardziej pasuje do pierwszego klucza, trochę mniej do drugiego klucza, o wiele mniej do trzeciego klucza. Te wektory to oczywiście wektory atencji (drugie słowo najbardziej „patrzy” na pierwsze słowo). Teraz będziemy przemnażać przez wektory wartości: #+BEGIN_SRC ipython :session mysession :exports both :results raw drawer import torch V = torch.tensor([ [0.0, 9.0, 0.0, -5.0], [4.0, 0.1, 0.1, 0.1], [-0.3, 0.0, 0.3, 10.0]]) Mn @ V #+END_SRC #+RESULTS: :results: # Out[13]: #+BEGIN_EXAMPLE tensor([[ 3.9750, 0.0994, 0.1012, 0.1577], [ 0.9252, 6.9357, 0.0233, -3.8112], [ 1.6095, 0.0721, 0.2103, 5.5597]]) #+END_EXAMPLE :end: *** Dodatkowa normalizacja W praktyce dobrze jest znormalizować pierwszy iloczyn przez $\sqrt{d_k}$, gdzie $d_k$ to rozmiar wektora klucza. $$\operatorname{Atention}(Q,K,V) = \operatorname{softmax}(\frac{QK^T}{d^k})V$$ *** Skąd się biorą Q, K i V? Wektory (macierze) $Q$, $K$ i $V$ w pierwszej warstwie pochodzą z embeddingów tokenów $E$ (właściwie jednostek BPE). - $Q$ = $EW^Q$ - $K$ = $EW^K$ - $V$ = $EW^V$ W kolejnych warstwach zamiast $E$ wykorzystywane jest wyjście z poprzedniej warstwy. ** Literatura https://arxiv.org/pdf/1706.03762.pdf