forked from filipg/aitech-eks-pub
Merge branch 'master' of git.wmi.amu.edu.pl:filipg/aitech-eks
This commit is contained in:
commit
9d96c9ec4f
@ -375,13 +375,13 @@ Definicja w PyTorchu:
|
|||||||
z_plus = torch.exp(z)
|
z_plus = torch.exp(z)
|
||||||
return z_plus / torch.sum(z_plus)
|
return z_plus / torch.sum(z_plus)
|
||||||
|
|
||||||
softmax(torch.tensor([3., -1., 0., 5.]))
|
softmax(torch.tensor([3., 1., -1., 1.]))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
:results:
|
:results:
|
||||||
# Out[75]:
|
# Out[3]:
|
||||||
: tensor([0.1182, 0.0022, 0.0059, 0.8737])
|
: tensor([7.8678e-01, 1.0648e-01, 2.6393e-04, 1.0648e-01])
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
#+CAPTION: Softmax
|
#+CAPTION: Softmax
|
||||||
|
523
wyk/11_rnn.ipynb
523
wyk/11_rnn.ipynb
File diff suppressed because one or more lines are too long
@ -87,7 +87,7 @@ $$s^k = \sigma(W\langle\vec{v}(t^k), \vec{s^{k-1}}\rangle + \vec{b}),$$
|
|||||||
gdzie:
|
gdzie:
|
||||||
|
|
||||||
- $\langle\vec{x},\vec{y}\rangle$ to konkatenacja dwóch wektorów,
|
- $\langle\vec{x},\vec{y}\rangle$ to konkatenacja dwóch wektorów,
|
||||||
- $W \in \mathcal{R}^m \times \mathcal{R}^{n+m} $ — macierz wag,
|
- $W \in \mathcal{R}^m \times \mathcal{R}^{n+m}$ — macierz wag,
|
||||||
- $b \in \mathcal{R}^m$ — wektor obciążeń (/biases/).
|
- $b \in \mathcal{R}^m$ — wektor obciążeń (/biases/).
|
||||||
|
|
||||||
Taką sieć RNN można przedstawić schematycznie w następujący sposób:
|
Taką sieć RNN można przedstawić schematycznie w następujący sposób:
|
||||||
@ -181,7 +181,7 @@ selektywnie wygaszać pozycje wektora, np. tutaj wyzerowaliśmy 2. i 5. pozycję
|
|||||||
|
|
||||||
Co więcej, za pomocą bramki możemy selektywnie kontrolować, co
|
Co więcej, za pomocą bramki możemy selektywnie kontrolować, co
|
||||||
zapamiętujemy, a co zapominamy. Rozpatrzmy mianowicie wektor zer i
|
zapamiętujemy, a co zapominamy. Rozpatrzmy mianowicie wektor zer i
|
||||||
jedynek $\vec{g} \in \{0,1}^m$, dla stanu (pamięci) $\vec{s}$ i nowej informacji
|
jedynek $\vec{g} \in \{0,1\}^m$, dla stanu (pamięci) $\vec{s}$ i nowej informacji
|
||||||
$\vec{x}$ możemy dokonywać aktualizacji w następujący sposób:
|
$\vec{x}$ możemy dokonywać aktualizacji w następujący sposób:
|
||||||
|
|
||||||
$$\vec{s} \leftarrow \vec{g} \odot \vec{x} + (1 - \vec{g}) \odot \vec{s}$$
|
$$\vec{s} \leftarrow \vec{g} \odot \vec{x} + (1 - \vec{g}) \odot \vec{s}$$
|
||||||
@ -259,7 +259,7 @@ $$\vec{i} = \sigma(W_i\langle\vec{v}(t^k),\vec{h^{k-1}}\rangle)$$
|
|||||||
|
|
||||||
$$\vec{f} = \sigma(W_f\langle\vec{v}(t^k),\vec{h^{k-1}}\rangle)$$
|
$$\vec{f} = \sigma(W_f\langle\vec{v}(t^k),\vec{h^{k-1}}\rangle)$$
|
||||||
|
|
||||||
$$\vec{o} = \sigma(W_f\langle\vec{v}(t^k),\vec{h^{k-1}}\rangle)$$
|
$$\vec{o} = \sigma(W_o\langle\vec{v}(t^k),\vec{h^{k-1}}\rangle)$$
|
||||||
|
|
||||||
Jak widać, wzory różnią się tylko macierzami wag $W_*$.
|
Jak widać, wzory różnią się tylko macierzami wag $W_*$.
|
||||||
|
|
||||||
@ -279,10 +279,10 @@ Ostateczne wyjście może być wyliczane na podstawie wektora $\vec{h^k}$:
|
|||||||
|
|
||||||
$$O(\vec{s}) = O(\langle\vec{c},\vec{h}\rangle) = \vec{h}$$
|
$$O(\vec{s}) = O(\langle\vec{c},\vec{h}\rangle) = \vec{h}$$
|
||||||
|
|
||||||
*Pytanie*: Ile wag/parametrów ma sieć RNN o rozmiarze wejścia $n$ i
|
*Pytanie*: Ile wag/parametrów ma sieć RNN o rozmiarze wejścia $n$ i rozmiarze warstwy ukrytej $m$?
|
||||||
|
|
||||||
|
|
||||||
** Literatura
|
** Literatura
|
||||||
|
|
||||||
Yoav Goldberg, /Neural Network Methods for Natural Language
|
Yoav Goldberg, /Neural Network Methods for Natural Language Processing/,
|
||||||
Processing/, Morgan & Claypool Publishers, 2017
|
Morgan & Claypool Publishers, 2017
|
||||||
|
839
wyk/12_bpe.ipynb
Normal file
839
wyk/12_bpe.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -36,7 +36,7 @@ Ile jest różnych form fleksyjnych w języku polskim? Zobaczmy w słowniku Poli
|
|||||||
|
|
||||||
Tak naprawdę form jest jeszcze więcej, oczywiście PoliMorf nie wyczerpuje zbioru…
|
Tak naprawdę form jest jeszcze więcej, oczywiście PoliMorf nie wyczerpuje zbioru…
|
||||||
|
|
||||||
*Pytanie* Podaj przykłady „oczywistych” wyrazów, których w PoliMorfie. Jak w sposób systematyczny szukać takich wyrazów?
|
*Pytanie* Podaj przykłady „oczywistych” wyrazów, których nie ma w PoliMorfie. Jak w sposób systematyczny szukać takich wyrazów?
|
||||||
|
|
||||||
Z drugiej strony, w PoliMorfie jest dużo dziwnych, „sztucznych” wyrazów.
|
Z drugiej strony, w PoliMorfie jest dużo dziwnych, „sztucznych” wyrazów.
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ nie pokryje on sporej części tekstów przetwarzanych w czasie inferencji.
|
|||||||
Zobaczmy, ilu wyrazów ze zbioru deweloperskiego nie będzie w słowniku.
|
Zobaczmy, ilu wyrazów ze zbioru deweloperskiego nie będzie w słowniku.
|
||||||
|
|
||||||
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
! cat petite-difference-challenge2/dev-0/in.tsv.xz | perl -C -ne 'print "$&\n" while/\p{L}+/g;' | sort -u | comm vocab.txt - -13 | wc -l
|
! cat petite-difference-challenge2/dev-0/in.tsv | perl -C -ne 'print "$&\n" while/\p{L}+/g;' | sort -u | comm vocab.txt - -13 | wc -l
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
Takie wyrazy nazywamy wyrazami *OOV* (/out-of-vocabulary/).
|
Takie wyrazy nazywamy wyrazami *OOV* (/out-of-vocabulary/).
|
||||||
@ -112,7 +112,7 @@ Daje to lepszy efekt niż można się spodziewać. Odrzucamy w ten sposób
|
|||||||
tylko bardzo rzadkie słowa (albo takie, które wystąpiły tylko raz w
|
tylko bardzo rzadkie słowa (albo takie, które wystąpiły tylko raz w
|
||||||
korpusie — tzw. /hapax legomena/), choć tych słów jest bardzo dużo.
|
korpusie — tzw. /hapax legomena/), choć tych słów jest bardzo dużo.
|
||||||
|
|
||||||
*Zagadka*: 50000 najczęstszych słów (1,9\% *typów*) pokrywa jaki odsetek *wystąpień*?
|
*Zagadka*: 50000 najczęstszych słów (1,9% *typów*) pokrywa jaki odsetek *wystąpień*?
|
||||||
|
|
||||||
Rozkład normalny w języku nie jest… normalny — nie spotkamy się z nim
|
Rozkład normalny w języku nie jest… normalny — nie spotkamy się z nim
|
||||||
badając języki. W tekstach dominują „skrzywione” rozkłady z długimi,
|
badając języki. W tekstach dominują „skrzywione” rozkłady z długimi,
|
||||||
@ -244,7 +244,7 @@ momentu traktujemy go jako całostkę (wkładamy go do „pudełka”).
|
|||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
:results:
|
:results:
|
||||||
# Out[4]:
|
# Out[1]:
|
||||||
: ['e$', 'to', 'to$', 'be$', 't$', 'th', 'or', 'or$', 'no', 'not$']
|
: ['e$', 'to', 'to$', 'be$', 't$', 'th', 'or', 'or$', 'no', 'not$']
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
@ -256,11 +256,15 @@ na którym słownik był wyuczony:
|
|||||||
d = list(d.replace(' ', '$') + '$')
|
d = list(d.replace(' ', '$') + '$')
|
||||||
vocab_set = set(vocab)
|
vocab_set = set(vocab)
|
||||||
|
|
||||||
|
modified = True
|
||||||
|
while modified:
|
||||||
ix = 0
|
ix = 0
|
||||||
|
modified = False
|
||||||
while ix < len(d) - 1:
|
while ix < len(d) - 1:
|
||||||
bigram = d[ix] + d[ix+1]
|
bigram = d[ix] + d[ix+1]
|
||||||
if bigram in vocab_set:
|
if bigram in vocab_set:
|
||||||
d[ix:ix+2] = [bigram]
|
d[ix:ix+2] = [bigram]
|
||||||
|
modified = True
|
||||||
else:
|
else:
|
||||||
ix += 1
|
ix += 1
|
||||||
|
|
||||||
@ -272,7 +276,7 @@ na którym słownik był wyuczony:
|
|||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
:results:
|
:results:
|
||||||
# Out[5]:
|
# Out[5]:
|
||||||
: 'to$ b e$ or$ no t$ to$ b e$ th a t$ i s $ th e$ q u e s t i o n $'
|
: 'to$ be$ or$ not$ to$ be$ th a t$ i s $ th e$ q u e s t i o n $'
|
||||||
:end:
|
:end:
|
||||||
|
|
||||||
Zauważmy, że oprócz jednostek podwyrazowych zostały izolowane litery,
|
Zauważmy, że oprócz jednostek podwyrazowych zostały izolowane litery,
|
||||||
@ -289,6 +293,12 @@ Słownik jednostek podwyrazowych można stosować dla dowolnego tekstu:
|
|||||||
' '.join(apply_bpe_vocab(vocab1, 'tom will be the best'))
|
' '.join(apply_bpe_vocab(vocab1, 'tom will be the best'))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
# Out[6]:
|
||||||
|
: 'to m $ w i l l $ be$ th e$ b e s t$'
|
||||||
|
:end:
|
||||||
|
|
||||||
Jak można zauważyć algorytm BPE daje dwa rodzaje jednostek podwyrazowych:
|
Jak można zauważyć algorytm BPE daje dwa rodzaje jednostek podwyrazowych:
|
||||||
|
|
||||||
- jednostki, które mogą doklejane na początku wyrazu;
|
- jednostki, które mogą doklejane na początku wyrazu;
|
||||||
|
113
wyk/13_generative_approach.ipynb
Normal file
113
wyk/13_generative_approach.ipynb
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Ekstrakcja informacji a podejście generatywne\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Podejście generatywne\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Do tej pory zadanie ekstrakcji informacji traktowaliśmy jako zadanie etykietowania sekwencji, tzn. uczyliśmy system zaznaczać tokeny składające się na ekstrahowane informacje.\n",
|
||||||
|
"\n",
|
||||||
|
"![img](./ie-seqlab.png)\n",
|
||||||
|
"\n",
|
||||||
|
"Możliwe jest inne podeście, **generatywne**, w którym podchodzimy do problemu ekstrakcji informacji jak do swego rodzaju **tłumaczenia maszynowego** — „tłumaczymy” tekst (wraz z pytaniem lub etykietą) na informację.\n",
|
||||||
|
"\n",
|
||||||
|
"![img](./ie-gener.png)\n",
|
||||||
|
"\n",
|
||||||
|
"To podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne.\n",
|
||||||
|
"\n",
|
||||||
|
"Zalety:\n",
|
||||||
|
"\n",
|
||||||
|
"- informacja nie musi być dosłownie zapisana w tekście, ekstraktor może nauczyć się również normalizacji czy parafrazowania,\n",
|
||||||
|
"- nie wprowadzamy wielu kroków przetwarzania (gdzie błędy mogą się\n",
|
||||||
|
" namnażać), system działa na zasadzie *end-to-end*.\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Atencja\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Pierwsze systemu neuronowego tłumaczenia maszynowego używały siecie LSTM. Dopiero jednak dodanie tzw. atencji (*attention*) umożliwiło duży przeskok jakościowy. Najpierw atencję dodano do sieci rekurencyjnych, później powstały sieci oparte *wyłącznie* na atencji — modele Transformer.\n",
|
||||||
|
"\n",
|
||||||
|
"Idea atencji polega na tym, że sieć może kierować selektywnie „snop” uwagi na wyrazy na wejściu lub do tej pory wygenerowane wyrazy.\n",
|
||||||
|
"\n",
|
||||||
|
"Mechanizm atencji korzysta z:\n",
|
||||||
|
"\n",
|
||||||
|
"- z poprzedniego stanu sieci $\\vec{s^{k-1}}$ (to jest „miejsce”, z którego „kierujemy” atencję),\n",
|
||||||
|
"- z wektora reprezentującego słowo $\\vec{v}(t_i)$ (to jest „miejsce”, na które kierujemy atencję), gdzie\n",
|
||||||
|
" $\\vec{v}(t_i)$ to reprezentacja wektorowa wyrazu $t_i$ (statyczny embedding lub reprezentacja wektorowa\n",
|
||||||
|
" z poprzedniej warstwy dla sieci wielowarstwowej),\n",
|
||||||
|
"\n",
|
||||||
|
"aby wytworzyć wektor kontekstu $\\vec{\\xi^k}$ (który z kolei będzie w jakiś sposób wnosił wkład do wyliczenia nowej wartości stanu $\\vec{s^k}$ lub wyjścia $y^k$.\n",
|
||||||
|
"\n",
|
||||||
|
"Najpierw wyliczymy skalarne wartości atencji, tzn. liczby, które będą sygnalizowały, jak bardzo wektor $\\vec{v}(t_i)$ „pasuje” do $\\vec{s^{k-1}}$, w najprostszej wersji można po prostu skorzystać z iloczynu skalarnego (o ile $n=m$),\n",
|
||||||
|
"\n",
|
||||||
|
"$$a(\\vec{s^{k-1}}, \\vec{v}(t_i)) = \\vec{s^{k-1}}\\vec{v}(t_i).$$\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: co jeśli $n$ nie jest równe $m$, tzn. rozmiar embeddingu nie jest równy rozmiarowi wektora stanu?\n",
|
||||||
|
"\n",
|
||||||
|
"W przypadku sieci LSTM korzysta się częściej z bardziej skomplikowanego wzoru zawierającego dodatkowe wyuczalne wagi:\n",
|
||||||
|
"\n",
|
||||||
|
"$$a(\\vec{s^{k-1}}, \\vec{v}(t_i)) = \\vec{w_a}\\operatorname{tanh}(W_a\\vec{s^{k-1}} + U_a\\vec{v}(t_i))$$\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: jakie rozmiary mają macierze $W_a$, $U_a$ i wektor $w_a$?\n",
|
||||||
|
"\n",
|
||||||
|
"Powtórzmy, że wartości $a$ są wartościami skalarnymi, natomiast nie są one znormalizowane (nie sumują się do jedynki), normalizujemy je używając schematu podobnego do softmaxa:\n",
|
||||||
|
"\n",
|
||||||
|
"$$\\alpha_{i} = \\frac{e^{a(\\vec{s^{k-1}}, \\vec{v}(t_i))}}{\\sum_j e^{a(\\vec{s^{k-1}}, \\vec{v}(t_j))}}$$\n",
|
||||||
|
"\n",
|
||||||
|
"Wektor kontekstu $\\vec{\\xi^k}$ będzie po prostu średnią ważoną wektorowych reprezentacji słów:\n",
|
||||||
|
"\n",
|
||||||
|
"$$\\vec{\\xi^k} = \\sum_i \\alpha_i\\vec{v}(t_i)$$\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: zasadniczo atencja jest środkiem do celu (żeby sieć się sprawniej uczyła), czy można atencja sama w sobie może być do czegoś przydatna?\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.9.2"
|
||||||
|
},
|
||||||
|
"org": null
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
55
wyk/13_generative_approach.org
Normal file
55
wyk/13_generative_approach.org
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
* Ekstrakcja informacji a podejście generatywne
|
||||||
|
** Podejście generatywne
|
||||||
|
|
||||||
|
Do tej pory zadanie ekstrakcji informacji traktowaliśmy jako zadanie etykietowania sekwencji, tzn. uczyliśmy system zaznaczać tokeny składające się na ekstrahowane informacje.
|
||||||
|
|
||||||
|
[[./ie-seqlab.png]]
|
||||||
|
|
||||||
|
Możliwe jest inne podeście, *generatywne*, w którym podchodzimy do problemu ekstrakcji informacji jak do swego rodzaju *tłumaczenia maszynowego* — „tłumaczymy” tekst (wraz z pytaniem lub etykietą) na informację.
|
||||||
|
|
||||||
|
[[./ie-gener.png]]
|
||||||
|
|
||||||
|
To podejście może się wydawać trudniejsze niż etykietowanie sekwencji, ale wystarczająco zaawansowanej architekturze sieci, jest wykonalne.
|
||||||
|
|
||||||
|
Zalety:
|
||||||
|
|
||||||
|
- informacja nie musi być dosłownie zapisana w tekście, ekstraktor może nauczyć się również normalizacji czy parafrazowania,
|
||||||
|
- nie wprowadzamy wielu kroków przetwarzania (gdzie błędy mogą się
|
||||||
|
namnażać), system działa na zasadzie /end-to-end/.
|
||||||
|
|
||||||
|
** Atencja
|
||||||
|
|
||||||
|
Pierwsze systemu neuronowego tłumaczenia maszynowego używały siecie LSTM. Dopiero jednak dodanie tzw. atencji (/attention/) umożliwiło duży przeskok jakościowy. Najpierw atencję dodano do sieci rekurencyjnych, później powstały sieci oparte /wyłącznie/ na atencji — modele Transformer.
|
||||||
|
|
||||||
|
Idea atencji polega na tym, że sieć może kierować selektywnie „snop” uwagi na wyrazy na wejściu lub do tej pory wygenerowane wyrazy.
|
||||||
|
|
||||||
|
Mechanizm atencji korzysta z:
|
||||||
|
|
||||||
|
- z poprzedniego stanu sieci $\vec{s^{k-1}}$ (to jest „miejsce”, z którego „kierujemy” atencję),
|
||||||
|
- z wektora reprezentującego słowo $\vec{v}(t_i)$ (to jest „miejsce”, na które kierujemy atencję), gdzie
|
||||||
|
$\vec{v}(t_i)$ to reprezentacja wektorowa wyrazu $t_i$ (statyczny embedding lub reprezentacja wektorowa
|
||||||
|
z poprzedniej warstwy dla sieci wielowarstwowej),
|
||||||
|
|
||||||
|
aby wytworzyć wektor kontekstu $\vec{\xi^k}$ (który z kolei będzie w jakiś sposób wnosił wkład do wyliczenia nowej wartości stanu $\vec{s^k}$ lub wyjścia $y^k$.
|
||||||
|
|
||||||
|
Najpierw wyliczymy skalarne wartości atencji, tzn. liczby, które będą sygnalizowały, jak bardzo wektor $\vec{v}(t_i)$ „pasuje” do $\vec{s^{k-1}}$, w najprostszej wersji można po prostu skorzystać z iloczynu skalarnego (o ile $n=m$),
|
||||||
|
|
||||||
|
$$a(\vec{s^{k-1}}, \vec{v}(t_i)) = \vec{s^{k-1}}\vec{v}(t_i).$$
|
||||||
|
|
||||||
|
*Pytanie*: co jeśli $n$ nie jest równe $m$, tzn. rozmiar embeddingu nie jest równy rozmiarowi wektora stanu?
|
||||||
|
|
||||||
|
W przypadku sieci LSTM korzysta się częściej z bardziej skomplikowanego wzoru zawierającego dodatkowe wyuczalne wagi:
|
||||||
|
|
||||||
|
$$a(\vec{s^{k-1}}, \vec{v}(t_i)) = \vec{w_a}\operatorname{tanh}(W_a\vec{s^{k-1}} + U_a\vec{v}(t_i))$$
|
||||||
|
|
||||||
|
*Pytanie*: jakie rozmiary mają macierze $W_a$, $U_a$ i wektor $w_a$?
|
||||||
|
|
||||||
|
Powtórzmy, że wartości $a$ są wartościami skalarnymi, natomiast nie są one znormalizowane (nie sumują się do jedynki), normalizujemy je używając schematu podobnego do softmaxa:
|
||||||
|
|
||||||
|
$$\alpha_{i} = \frac{e^{a(\vec{s^{k-1}}, \vec{v}(t_i))}}{\sum_j e^{a(\vec{s^{k-1}}, \vec{v}(t_j))}}$$
|
||||||
|
|
||||||
|
Wektor kontekstu $\vec{\xi^k}$ będzie po prostu średnią ważoną wektorowych reprezentacji słów:
|
||||||
|
|
||||||
|
$$\vec{\xi^k} = \sum_i \alpha_i\vec{v}(t_i)$$
|
||||||
|
|
||||||
|
*Pytanie*: zasadniczo atencja jest środkiem do celu (żeby sieć się sprawniej uczyła), czy można atencja sama w sobie może być do czegoś przydatna?
|
338
wyk/14_pretrenowanie.ipynb
Normal file
338
wyk/14_pretrenowanie.ipynb
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Pretrenowanie modeli\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"System AlphaZero uczy się grając sam ze sobą — wystarczy 24 godziny,\n",
|
||||||
|
"by system nauczył się grać w szachy lub go na nadludzkim poziomie.\n",
|
||||||
|
"\n",
|
||||||
|
"**Pytanie**: Dlaczego granie samemu ze sobą nie jest dobrym sposobem\n",
|
||||||
|
" nauczenia się grania w szachy dla człowieka, a dla maszyny jest?\n",
|
||||||
|
"\n",
|
||||||
|
"Co jest odpowiednikiem grania samemu ze sobą w świecie przetwarzania tekstu?\n",
|
||||||
|
"Tzn. **pretrenowanie** (*pretraining*) na dużym korpusie tekstu. (Tekst jest tani!)\n",
|
||||||
|
"\n",
|
||||||
|
"Jest kilka sposobów na pretrenowanie modelu, w każdym razie sprowadza\n",
|
||||||
|
"się do odgadywania następnego bądź zamaskowanego słowa.\n",
|
||||||
|
"W każdym razie zawsze stosujemy softmax (być może ze „sztuczkami” takimi jak\n",
|
||||||
|
"negatywne próbkowanie albo hierarchiczny softamx) na pewnej **representecji kontekstowej**:\n",
|
||||||
|
"\n",
|
||||||
|
"$$\\vec{p} = \\operatorname{softmax}(f(\\vec{c})).$$\n",
|
||||||
|
"\n",
|
||||||
|
"Model jest karany używając funkcji log loss:\n",
|
||||||
|
"\n",
|
||||||
|
"$$-\\log(p_j),$$\n",
|
||||||
|
"\n",
|
||||||
|
"gdzie $w_j$ jest wyrazem, który pojawił się rzeczywiście w korpusie.\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Przewidywanie słowa (GPT-2)\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Jeden ze sposobów pretrenowania modelu to po prostu przewidywanie\n",
|
||||||
|
"następnego słowa.\n",
|
||||||
|
"\n",
|
||||||
|
"Zainstalujmy najpierw bibliotekę transformers.\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"! pip install transformers"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"50257\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[('Ġon', 0.6786560416221619),\n",
|
||||||
|
" ('Ġupon', 0.04339785501360893),\n",
|
||||||
|
" ('Ġheavily', 0.02208443358540535),\n",
|
||||||
|
" ('Ġin', 0.021049050614237785),\n",
|
||||||
|
" (',', 0.020188499242067337),\n",
|
||||||
|
" ('Ġa', 0.01833895780146122),\n",
|
||||||
|
" ('Ġvery', 0.017935041338205338),\n",
|
||||||
|
" ('Ġentirely', 0.017528969794511795),\n",
|
||||||
|
" ('Ġlargely', 0.016769640147686005),\n",
|
||||||
|
" ('Ġto', 0.01009418722242117),\n",
|
||||||
|
" ('Ġgreatly', 0.010009866207838058),\n",
|
||||||
|
" ('Ġnot', 0.009016563184559345),\n",
|
||||||
|
" ('Ġmore', 0.005853226874023676),\n",
|
||||||
|
" ('Ġprimarily', 0.005203146021813154),\n",
|
||||||
|
" ('Ġstrongly', 0.0034501152113080025),\n",
|
||||||
|
" ('Ġpartly', 0.0033184229396283627),\n",
|
||||||
|
" ('Ġmuch', 0.0033095215912908316),\n",
|
||||||
|
" ('Ġmostly', 0.0032150144688785076),\n",
|
||||||
|
" ('Ġmainly', 0.0030899408739060163),\n",
|
||||||
|
" ('Ġfor', 0.003034428460523486),\n",
|
||||||
|
" ('.', 0.0028878094162791967),\n",
|
||||||
|
" ('Ġboth', 0.0028405177872627974),\n",
|
||||||
|
" ('Ġsomewhat', 0.0028194624464958906),\n",
|
||||||
|
" ('Ġcru', 0.002263976726680994),\n",
|
||||||
|
" ('Ġas', 0.00221616611815989),\n",
|
||||||
|
" ('Ġof', 0.0022000609897077084),\n",
|
||||||
|
" ('Ġalmost', 0.001968063646927476),\n",
|
||||||
|
" ('Ġat', 0.0018015997484326363),\n",
|
||||||
|
" ('Ġhighly', 0.0017461496172472835),\n",
|
||||||
|
" ('Ġcompletely', 0.001692073536105454)]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import torch\n",
|
||||||
|
"from transformers import GPT2Tokenizer, GPT2LMHeadModel\n",
|
||||||
|
"tokenizer = GPT2Tokenizer.from_pretrained('gpt2-large')\n",
|
||||||
|
"model = GPT2LMHeadModel.from_pretrained('gpt2-large')\n",
|
||||||
|
"text = \"This issue depends\"\n",
|
||||||
|
"encoded_input = tokenizer(text, return_tensors='pt')\n",
|
||||||
|
"output = model(**encoded_input)\n",
|
||||||
|
"next_token_probs = torch.softmax(output[0][:, -1, :][0], dim=0)\n",
|
||||||
|
"\n",
|
||||||
|
"next_token_probs\n",
|
||||||
|
"nb_of_tokens = next_token_probs.size()[0]\n",
|
||||||
|
"print(nb_of_tokens)\n",
|
||||||
|
"\n",
|
||||||
|
"_, top_k_indices = torch.topk(next_token_probs, 30, sorted=True)\n",
|
||||||
|
"\n",
|
||||||
|
"words = tokenizer.convert_ids_to_tokens(top_k_indices)\n",
|
||||||
|
"\n",
|
||||||
|
"top_probs = []\n",
|
||||||
|
"\n",
|
||||||
|
"for ix in range(len(top_k_indices)):\n",
|
||||||
|
" top_probs.append((words[ix], next_token_probs[top_k_indices[ix]].item()))\n",
|
||||||
|
"\n",
|
||||||
|
"top_probs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zalety tego podejścia:\n",
|
||||||
|
"\n",
|
||||||
|
"- prostota,\n",
|
||||||
|
"- dobra podstawa do strojenia systemów generowania tekstu zwłaszcza\n",
|
||||||
|
" „otwartego” (systemy dialogowe, generowanie (fake) newsów, streszczanie tekstu),\n",
|
||||||
|
" ale niekoniecznie tłumaczenia maszynowego,\n",
|
||||||
|
"- zaskakująca skuteczność przy uczeniu *few-shot* i *zero-shot*.\n",
|
||||||
|
"\n",
|
||||||
|
"Wady:\n",
|
||||||
|
"\n",
|
||||||
|
"- asymetryczność, przetwarzanie tylko z lewej do prawej, preferencja\n",
|
||||||
|
" dla lewego kontekstu,\n",
|
||||||
|
"- mniejsza skuteczność przy dostrajaniu do zadań klasyfikacji i innych zadań\n",
|
||||||
|
" niepolegających na prostym generowaniu.\n",
|
||||||
|
"\n",
|
||||||
|
"Przykłady modeli: GPT, GPT-2, GPT-3, DialoGPT.\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Maskowanie słów (BERT)\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Inną metodą jest maskowanie słów (*Masked Language Modeling*, *MLM*).\n",
|
||||||
|
"\n",
|
||||||
|
"W tym podejściu losowe wybrane zastępujemy losowe słowa specjalnym\n",
|
||||||
|
"tokenem (`[MASK]`) i każemy modelowi odgadywać w ten sposób\n",
|
||||||
|
"zamaskowane słowa (z uwzględnieniem również prawego kontekstu!).\n",
|
||||||
|
"\n",
|
||||||
|
"Móciąc ściśle, w jednym z pierwszych modeli tego typu (BERT)\n",
|
||||||
|
"zastosowano schemat, w którym również niezamaskowane słowa są odgadywane (!):\n",
|
||||||
|
"\n",
|
||||||
|
"- wybieramy losowe 15% wyrazów do odgadnięcia\n",
|
||||||
|
"- 80% z nich zastępujemy tokenem `[MASK]`,\n",
|
||||||
|
"- 10% zastępujemy innym losowym wyrazem,\n",
|
||||||
|
"- 10% pozostawiamy bez zmian.\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"# Out[3]:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from transformers import AutoModelWithLMHead, AutoTokenizer\n",
|
||||||
|
"import torch\n",
|
||||||
|
"\n",
|
||||||
|
"tokenizer = AutoTokenizer.from_pretrained(\"xlm-roberta-large\")\n",
|
||||||
|
"model = AutoModelWithLMHead.from_pretrained(\"xlm-roberta-large\")\n",
|
||||||
|
"\n",
|
||||||
|
"sequence = f'II wojna światowa zakończyła się w {tokenizer.mask_token} roku.'\n",
|
||||||
|
"\n",
|
||||||
|
"input_ids = tokenizer.encode(sequence, return_tensors=\"pt\")\n",
|
||||||
|
"mask_token_index = torch.where(input_ids == tokenizer.mask_token_id)[1]\n",
|
||||||
|
"\n",
|
||||||
|
"token_logits = model(input_ids)[0]\n",
|
||||||
|
"mask_token_logits = token_logits[0, mask_token_index, :]\n",
|
||||||
|
"mask_token_logits = torch.softmax(mask_token_logits, dim=1)\n",
|
||||||
|
"\n",
|
||||||
|
"top_10 = torch.topk(mask_token_logits, 10, dim=1)\n",
|
||||||
|
"top_10_tokens = zip(top_10.indices[0].tolist(), top_10.values[0].tolist())\n",
|
||||||
|
"\n",
|
||||||
|
"for token, score in top_10_tokens:\n",
|
||||||
|
" print(sequence.replace(tokenizer.mask_token, tokenizer.decode([token])), f\"(score: {score})\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Przykłady: BERT, RoBERTa (również Polish RoBERTa).\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Podejście generatywne (koder-dekoder).\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"System ma wygenerować odpowiedź na różne pytania (również\n",
|
||||||
|
"odpowiadające zadaniu MLM), np.:\n",
|
||||||
|
"\n",
|
||||||
|
"- \"translate English to German: That is good.\" => \"Das ist gut.\"\n",
|
||||||
|
"- \"cola sentence: The course is jumping well.\" => \"not acceptable\"\n",
|
||||||
|
"- \"summarize: state authorities dispatched emergency crews tuesday to survey the damage after an onslaught of severe weather in mississippi…\"\n",
|
||||||
|
" => \"six people hospitalized after a storm in attala county\"\n",
|
||||||
|
"- \"Thank you for <X> me to your party <Y> week.\" => <X> for inviting <Y> last <Z>\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from transformers import T5Tokenizer, T5Config, T5ForConditionalGeneration\n",
|
||||||
|
"\n",
|
||||||
|
"T5_PATH = 't5-base'\n",
|
||||||
|
"\n",
|
||||||
|
"t5_tokenizer = T5Tokenizer.from_pretrained(T5_PATH)\n",
|
||||||
|
"t5_config = T5Config.from_pretrained(T5_PATH)\n",
|
||||||
|
"t5_mlm = T5ForConditionalGeneration.from_pretrained(T5_PATH, config=t5_config)\n",
|
||||||
|
"\n",
|
||||||
|
"slot = '<extra_id_0>'\n",
|
||||||
|
"\n",
|
||||||
|
"text = f'Warsaw is the {slot} of Poland.'\n",
|
||||||
|
"\n",
|
||||||
|
"encoded = t5_tokenizer.encode_plus(text, add_special_tokens=True, return_tensors='pt')\n",
|
||||||
|
"input_ids = encoded['input_ids']\n",
|
||||||
|
"\n",
|
||||||
|
"outputs = t5_mlm.generate(input_ids=input_ids,\n",
|
||||||
|
" num_beams=200, num_return_sequences=5,\n",
|
||||||
|
" max_length=5)\n",
|
||||||
|
"\n",
|
||||||
|
"_0_index = text.index(slot)\n",
|
||||||
|
"_result_prefix = text[:_0_index]\n",
|
||||||
|
"_result_suffix = text[_0_index+len(slot):]\n",
|
||||||
|
"\n",
|
||||||
|
"def _filter(output, end_token='<extra_id_1>'):\n",
|
||||||
|
" _txt = t5_tokenizer.decode(output[2:], skip_special_tokens=False, clean_up_tokenization_spaces=False)\n",
|
||||||
|
" if end_token in _txt:\n",
|
||||||
|
" _end_token_index = _txt.index(end_token)\n",
|
||||||
|
" return _result_prefix + _txt[:_end_token_index] + _result_suffix\n",
|
||||||
|
" else:\n",
|
||||||
|
" return _result_prefix + _txt + _result_suffix\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"results = [_filter(out) for out in outputs]\n",
|
||||||
|
"results"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"(Zob. [https://arxiv.org/pdf/1910.10683.pdf](https://arxiv.org/pdf/1910.10683.pdf))\n",
|
||||||
|
"\n",
|
||||||
|
"Przykład: T5, mT5\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.9.2"
|
||||||
|
},
|
||||||
|
"org": null
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
212
wyk/14_pretrenowanie.org
Normal file
212
wyk/14_pretrenowanie.org
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
* Pretrenowanie modeli
|
||||||
|
|
||||||
|
System AlphaZero uczy się grając sam ze sobą — wystarczy 24 godziny,
|
||||||
|
by system nauczył się grać w szachy lub go na nadludzkim poziomie.
|
||||||
|
|
||||||
|
*Pytanie*: Dlaczego granie samemu ze sobą nie jest dobrym sposobem
|
||||||
|
nauczenia się grania w szachy dla człowieka, a dla maszyny jest?
|
||||||
|
|
||||||
|
Co jest odpowiednikiem grania samemu ze sobą w świecie przetwarzania tekstu?
|
||||||
|
Tzn. *pretrenowanie* (/pretraining/) na dużym korpusie tekstu. (Tekst jest tani!)
|
||||||
|
|
||||||
|
Jest kilka sposobów na pretrenowanie modelu, w każdym razie sprowadza
|
||||||
|
się do odgadywania następnego bądź zamaskowanego słowa.
|
||||||
|
W każdym razie zawsze stosujemy softmax (być może ze „sztuczkami” takimi jak
|
||||||
|
negatywne próbkowanie albo hierarchiczny softamx) na pewnej *representecji kontekstowej*:
|
||||||
|
|
||||||
|
$$\vec{p} = \operatorname{softmax}(f(\vec{c})).$$
|
||||||
|
|
||||||
|
Model jest karany używając funkcji log loss:
|
||||||
|
|
||||||
|
$$-\log(p_j),$$
|
||||||
|
|
||||||
|
gdzie $w_j$ jest wyrazem, który pojawił się rzeczywiście w korpusie.
|
||||||
|
|
||||||
|
** Przewidywanie słowa (GPT-2)
|
||||||
|
|
||||||
|
Jeden ze sposobów pretrenowania modelu to po prostu przewidywanie
|
||||||
|
następnego słowa.
|
||||||
|
|
||||||
|
Zainstalujmy najpierw bibliotekę transformers.
|
||||||
|
|
||||||
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
|
! pip install transformers
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
|
import torch
|
||||||
|
from transformers import GPT2Tokenizer, GPT2LMHeadModel
|
||||||
|
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-large')
|
||||||
|
model = GPT2LMHeadModel.from_pretrained('gpt2-large')
|
||||||
|
text = "Warsaw is the capital city of"
|
||||||
|
encoded_input = tokenizer(text, return_tensors='pt')
|
||||||
|
output = model(**encoded_input)
|
||||||
|
next_token_probs = torch.softmax(output[0][:, -1, :][0], dim=0)
|
||||||
|
|
||||||
|
nb_of_tokens = next_token_probs.size()[0]
|
||||||
|
|
||||||
|
_, top_k_indices = torch.topk(next_token_probs, 30, sorted=True)
|
||||||
|
top_k_indices
|
||||||
|
# words = tokenizer.convert_ids_to_tokens(top)
|
||||||
|
|
||||||
|
# top_probs = []
|
||||||
|
|
||||||
|
# for ix in range(len(top)):
|
||||||
|
# top_probs.append((words[ix], next_token_probs[top[ix]].item()))
|
||||||
|
|
||||||
|
# top_probs
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
# Out[8]:
|
||||||
|
#+BEGIN_EXAMPLE
|
||||||
|
[('Ġthe', 0.4415026307106018),
|
||||||
|
('ĠPoland', 0.236798495054245),
|
||||||
|
('ĠBelarus', 0.10114768147468567),
|
||||||
|
('ĠUkraine', 0.058283545076847076),
|
||||||
|
('Ġeastern', 0.020564062520861626),
|
||||||
|
('ĠEastern', 0.011137397028505802),
|
||||||
|
('ĠPolish', 0.010205904021859169),
|
||||||
|
('ĠWestern', 0.00833223108202219),
|
||||||
|
('Ġwestern', 0.006872199941426516),
|
||||||
|
('Ġa', 0.004939113277941942),
|
||||||
|
('ĠSlovakia', 0.003553805174306035),
|
||||||
|
('ĠLithuania', 0.003335304092615843),
|
||||||
|
('ĠRussia', 0.002872465644031763),
|
||||||
|
('Ġcentral', 0.002493523992598057),
|
||||||
|
('Ġmodern', 0.0022767107002437115),
|
||||||
|
('ĠCzech', 0.0022264323197305202),
|
||||||
|
('ĠPr', 0.002146221464499831),
|
||||||
|
('Ġformer', 0.0021054286044090986),
|
||||||
|
('Ġwhat', 0.0017435317859053612),
|
||||||
|
('ĠSlov', 0.0014634730760008097),
|
||||||
|
('ĠUkrainian', 0.0014347084797918797),
|
||||||
|
('ĠCentral', 0.0013676199596375227),
|
||||||
|
('ĠSouth', 0.0013484350638464093),
|
||||||
|
('Ġone', 0.001204205909743905),
|
||||||
|
('ĠNorthern', 0.0011802552035078406),
|
||||||
|
('ĠWest', 0.001175572513602674),
|
||||||
|
('ĠEast', 0.0011596156982704997),
|
||||||
|
('Ġsouthern', 0.0011580033460631967),
|
||||||
|
('Ġnorthern', 0.001110077602788806),
|
||||||
|
('Ġ"', 0.0010494199814274907)]
|
||||||
|
#+END_EXAMPLE
|
||||||
|
:end:
|
||||||
|
|
||||||
|
Zalety tego podejścia:
|
||||||
|
|
||||||
|
- prostota,
|
||||||
|
- dobra podstawa do strojenia systemów generowania tekstu zwłaszcza
|
||||||
|
„otwartego” (systemy dialogowe, generowanie (fake) newsów, streszczanie tekstu),
|
||||||
|
ale niekoniecznie tłumaczenia maszynowego,
|
||||||
|
- zaskakująca skuteczność przy uczeniu /few-shot/ i /zero-shot/.
|
||||||
|
|
||||||
|
Wady:
|
||||||
|
|
||||||
|
- asymetryczność, przetwarzanie tylko z lewej do prawej, preferencja
|
||||||
|
dla lewego kontekstu,
|
||||||
|
- mniejsza skuteczność przy dostrajaniu do zadań klasyfikacji i innych zadań
|
||||||
|
niepolegających na prostym generowaniu.
|
||||||
|
|
||||||
|
Przykłady modeli: GPT, GPT-2, GPT-3, DialoGPT.
|
||||||
|
|
||||||
|
** Maskowanie słów (BERT)
|
||||||
|
|
||||||
|
Inną metodą jest maskowanie słów (/Masked Language Modeling/, /MLM/).
|
||||||
|
|
||||||
|
W tym podejściu losowe wybrane zastępujemy losowe słowa specjalnym
|
||||||
|
tokenem (~[MASK]~) i każemy modelowi odgadywać w ten sposób
|
||||||
|
zamaskowane słowa (z uwzględnieniem również prawego kontekstu!).
|
||||||
|
|
||||||
|
Móciąc ściśle, w jednym z pierwszych modeli tego typu (BERT)
|
||||||
|
zastosowano schemat, w którym również niezamaskowane słowa są odgadywane (!):
|
||||||
|
|
||||||
|
- wybieramy losowe 15% wyrazów do odgadnięcia
|
||||||
|
- 80% z nich zastępujemy tokenem ~[MASK]~,
|
||||||
|
- 10% zastępujemy innym losowym wyrazem,
|
||||||
|
- 10% pozostawiamy bez zmian.
|
||||||
|
|
||||||
|
|
||||||
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
|
from transformers import AutoModelWithLMHead, AutoTokenizer
|
||||||
|
import torch
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("xlm-roberta-large")
|
||||||
|
model = AutoModelWithLMHead.from_pretrained("xlm-roberta-large")
|
||||||
|
|
||||||
|
sequence = f'II wojna światowa zakończyła się w {tokenizer.mask_token} roku.'
|
||||||
|
|
||||||
|
input_ids = tokenizer.encode(sequence, return_tensors="pt")
|
||||||
|
mask_token_index = torch.where(input_ids == tokenizer.mask_token_id)[1]
|
||||||
|
|
||||||
|
token_logits = model(input_ids)[0]
|
||||||
|
mask_token_logits = token_logits[0, mask_token_index, :]
|
||||||
|
mask_token_logits = torch.softmax(mask_token_logits, dim=1)
|
||||||
|
|
||||||
|
top_10 = torch.topk(mask_token_logits, 10, dim=1)
|
||||||
|
top_10_tokens = zip(top_10.indices[0].tolist(), top_10.values[0].tolist())
|
||||||
|
|
||||||
|
for token, score in top_10_tokens:
|
||||||
|
print(sequence.replace(tokenizer.mask_token, tokenizer.decode([token])), f"(score: {score})")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
# Out[3]:
|
||||||
|
:end:
|
||||||
|
|
||||||
|
|
||||||
|
Przykłady: BERT, RoBERTa (również Polish RoBERTa).
|
||||||
|
|
||||||
|
** Podejście generatywne (koder-dekoder).
|
||||||
|
|
||||||
|
System ma wygenerować odpowiedź na różne pytania (również
|
||||||
|
odpowiadające zadaniu MLM), np.:
|
||||||
|
|
||||||
|
- "translate English to German: That is good." => "Das ist gut."
|
||||||
|
- "cola sentence: The course is jumping well." => "not acceptable"
|
||||||
|
- "summarize: state authorities dispatched emergency crews tuesday to survey the damage after an onslaught of severe weather in mississippi..."
|
||||||
|
=> "six people hospitalized after a storm in attala county"
|
||||||
|
- "Thank you for <X> me to your party <Y> week." => <X> for inviting <Y> last <Z>
|
||||||
|
|
||||||
|
#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer
|
||||||
|
from transformers import T5Tokenizer, T5Config, T5ForConditionalGeneration
|
||||||
|
|
||||||
|
T5_PATH = 't5-base'
|
||||||
|
|
||||||
|
t5_tokenizer = T5Tokenizer.from_pretrained(T5_PATH)
|
||||||
|
t5_config = T5Config.from_pretrained(T5_PATH)
|
||||||
|
t5_mlm = T5ForConditionalGeneration.from_pretrained(T5_PATH, config=t5_config)
|
||||||
|
|
||||||
|
slot = '<extra_id_0>'
|
||||||
|
|
||||||
|
text = f'Warsaw is the {slot} of Poland.'
|
||||||
|
|
||||||
|
encoded = t5_tokenizer.encode_plus(text, add_special_tokens=True, return_tensors='pt')
|
||||||
|
input_ids = encoded['input_ids']
|
||||||
|
|
||||||
|
outputs = t5_mlm.generate(input_ids=input_ids,
|
||||||
|
num_beams=200, num_return_sequences=5,
|
||||||
|
max_length=5)
|
||||||
|
|
||||||
|
_0_index = text.index(slot)
|
||||||
|
_result_prefix = text[:_0_index]
|
||||||
|
_result_suffix = text[_0_index+len(slot):]
|
||||||
|
|
||||||
|
def _filter(output, end_token='<extra_id_1>'):
|
||||||
|
_txt = t5_tokenizer.decode(output[2:], skip_special_tokens=False, clean_up_tokenization_spaces=False)
|
||||||
|
if end_token in _txt:
|
||||||
|
_end_token_index = _txt.index(end_token)
|
||||||
|
return _result_prefix + _txt[:_end_token_index] + _result_suffix
|
||||||
|
else:
|
||||||
|
return _result_prefix + _txt + _result_suffix
|
||||||
|
|
||||||
|
|
||||||
|
results = [_filter(out) for out in outputs]
|
||||||
|
results
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
(Zob. https://arxiv.org/pdf/1910.10683.pdf)
|
||||||
|
|
||||||
|
Przykład: T5, mT5
|
BIN
wyk/bpe.png
Normal file
BIN
wyk/bpe.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
1
wyk/ie-gener.drawio
Normal file
1
wyk/ie-gener.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2021-06-09T07:54:35.721Z" agent="5.0 (X11)" etag="NciLNBJF1axAiSJ0r0sv" version="14.7.3" type="device"><diagram id="HvCQlNLg7fWOxGx64C6g" name="Page-1">3Vjbbts4EP0aAe2DF9bNiR9jO9lisVekQLF9Y8SxRJsSVYqKrHz9Di+SJctF0m6TtvGDRB2RM+QcnhnKXrjOD79KUmZ/CArcC+b04IUbLwiWkY9XDbQWiMPQAqlk1EL+EbhlD+DAuUNrRqEadVRCcMXKMZiIooBEjTAipWjG3baCj72WJIUJcJsQPkU/MKoyi14GF0f8HbA06zz7i6V9k5Ous1tJlREqmgEUXnvhWgqhbCs/rIHr2HVxseNuPvO2n5iEQj1lgPgrjt7/+du/G76THw8f5Wyxv545K/eE127BXrDgaG+V4atFqlsdUpWk0OtQrQvO4lOtJ7+6I8k+laIu6CwRXEgvvMJ+Mr17E8Sxp6e1xutJ++1xfOfoHRDKirTzh0uxLsfTQHg6t/LFJ/u7kJDr8JZVre/UGEOPTOmtl4Oyo3FjVrgxQdX6LS6wZBVLzDLnwJnrVQE1NjTI6ioX+lFBXhqbrEgYZbQutOlaXzi5Q/+6t+p8g9l0aUG0G84+1eSXxyM5iFswCleg4GC2gco5Aj42t4zztQ3ZphAF2CibpYSb+Pj0XpQIzDB84arJmIJbxLXVBjMEYuIe5JYbKWSMUigQM4SA3ql6VKWk2EPnywvCufn100QDOL3P6sDv1YVZCQRSIVvs0g24dIJ0GclfuufmqO8gclg20rYDicspaW/7KDtsOOV9gQqDiQoV7CvNbAM7bx17y1XCRNM+gaRx6BxNZ5jDHZJi4DcJRg0QX+mYMsx7V+5FjtRoN2cpHNP1LUjxHyflHCfBc1ESnkmMJ8HHhF7q5pbD4UqXGgwFFNQ1NwknFSp9TI81AnRSdB4N1CAQ8ZlAdJgEThS7H5s/Fx3n4W/BTFZxPERRPOIBpTc2UYlaJuBGDavNiaHYf8SQIjIFNTFkyOqX/fX8RRP+tKIk2Sc7nSBNlnwgFaEPDEymtymRdfkQiZwpMcPbIFuyL8iWP6kQo8WJEC++sxCXEyK7SquLXV19XeH6llF/1moVh2M++kAP+Fi+JB9doh4Q0rR9kYJOLXey08qbprXSy0RDCjDHma2QOUl28Pb1Cik+PWYspsT1Ve9lmDtX0yxblN13dP1Tm7MnVP3B0gtvpqwOsuJg8P8TI4et+oGlODk4Rk88OD4fo9MqV7aKFFqGN6DaPQNFXq/E/PkJIeF3rlXdmWeUGwfJrzUfdfZkb0ia53XF9A0f1pF3eWE84PLb5KHAoz9GQ1QKv6rsV+KO7PXqrJVByn2tBMfLk+J3+Xw5FB+P/8XYU+jxD63w+j8=</diagram></mxfile>
|
BIN
wyk/ie-gener.png
Normal file
BIN
wyk/ie-gener.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
1
wyk/ie-seqlab.drawio
Normal file
1
wyk/ie-seqlab.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2021-06-09T07:51:04.277Z" agent="5.0 (X11)" etag="tdTX7mJTGI1dKBKJk9w0" version="14.7.3" type="device"><diagram id="HvCQlNLg7fWOxGx64C6g" name="Page-1">7Vhtk5MwEP41zOiHOhQKd/14bc+3Uet4zjj6LSVbyDUQDOEo/no3EEp5uempd+qc9kMbHpLd7PNkl6WWu4z3LyRJo7eCArccm+4td2U5znw2xW8NlDXguW4NhJLRGpq2wBX7Bga0DZozCllnohKCK5Z2wUAkCQSqgxEpRdGdthW86zUlIQyAq4DwIfqJURXV6Llz1uIvgYVR43nqz+s7MWkmm0iyiFBRHEHupeUupRCqHsX7JXDNXcNLve75LXcPG5OQqLssEGtv9vHd688rfi2/7L/Iib+7nBgrN4TnJmDL8TnaW0R4yw/1qEGylCQ6DlUacvyvud78YkOCXShFntBJILiQlnuB82S4eeJ4nqW3tcTv3vhpu75x9BIIZUnY+MNQapfdbSA83Fv62zf7RkiINb1plutfWhlDj0zpoxeDqlfjwczwYILK9V0MMGUZC6owbeDMzMqAVjY0yPIsFvpSQZxWNlkSMMponmjTuf7iZIP+9WzV+Ibq0IUJ0W44+5qTZ6eZPOLN6dDlKNhXx0DFHIEpDreM82VN2SoRCdQsV6G4K6+9+ihSBCZIn7soIqbgCnFttcAKgZi4AbnlVSpEjFJIEKsEAX1S9apMSbGDxpfluHb1OWwTDeD2bs2D6SG7sCqBQClkiVOaBecmIU1Fmvrmumjz25kZLOrktgGJqSnhwXabdjgwmfcDWegMslDBLtPKFnBtLT1rvgiYKMo7iNSlzsg0ohyekBCJXwXIGiC+0JwyrHsX5kaM0mg3oxJ25boPUaY9Uc6Gooxp4jyUJO5IYeyRjwU91cMth/2FftQgFZBQM1wFnGSY6V15aiNABw+dk0QdEeGNENFgEjhR7KZrfowd4+G9YFVVMTrMvK4OA4IzkcsAzKrjp03PkOecMKSIDEENDFViHcL+ef1mA/1AlTsGShQkYfB4M2nm/2WZ5P1vMR5Bi/EAQXvTkZj7rcwtOvU7nI3sq7MVVSjbOttaR0ssYAx0yO+gGPrHXxLrxEw2WTp6ba9Pz7nLmtswezFZrd+sP+Do1WG0PmKijqwb7TD+/z3fUVH0vDv0fP5Yzzd7qLLo/5sNxrl7Tw3G3P6zDcbZQL9Uikzp0lWUVGzKQHcZdtXI54+33Tif/WXtxnygS/+R8jNF7z5Zf9BKN+/nl+0N9Jj/Tj2aF7sjQYry8FILwwfYk6LUOSNJpFt1qHqTrZAxCa7h6eNNpPnZ6UfU4S35F5XDy/Z/x7ogtn/eupffAQ==</diagram></mxfile>
|
BIN
wyk/ie-seqlab.png
Normal file
BIN
wyk/ie-seqlab.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
1
wyk/rnn-seq.drawio
Normal file
1
wyk/rnn-seq.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2021-06-01T16:04:31.943Z" agent="5.0 (X11)" etag="_GtJ7cj7F7SQ6oQHAF32" version="14.6.13" type="device"><diagram id="Q_5Aon-lI3fA6Ftl2Xdk" name="Page-1">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</diagram></mxfile>
|
BIN
wyk/rnn-seq.png
Normal file
BIN
wyk/rnn-seq.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
1
wyk/rnn.drawio
Normal file
1
wyk/rnn.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2021-06-01T15:52:54.501Z" agent="5.0 (X11)" etag="o_4DnBy9wLtBbjAQzQYJ" version="14.6.13" type="device"><diagram id="Q_5Aon-lI3fA6Ftl2Xdk" name="Page-1">5Vltj5s4EP41SO2HXcUYwuZjQ3J3H1pdpb3TtffNBRfcAI6M88L++hsH8w45qk2W7FbarDyPX7Bn5pkZjIHd+Pi7INvwE/dpZJgz/2jglWGaCwvBfwVkOYDmjpkjgWC+xirgkT1RDc40umM+TRsDJeeRZNsm6PEkoZ5sYEQIfmgO+86j5lO3JKAd4NEjURf9h/kyzNEH06nwPygLwuLJaL7Ie2JSDNZLpCHx+SGHTofDawO7gnOZt+KjSyOlvEIvuQZ+G+gtNyZoIsdM+Fu6u39ttrGyB2edrZxPf338cadX2ZNopw+sNyuzQgOC7xKfqkVmBl4eQibp45Z4qvcANgcslHEEEoKmXo4KSY+D+0Tl6cFtKI+pFBkM0ROwpU1fuAzW8qHSP9JnnYV13TsaJNrmQbl2pRZoaM38hJbmHaVQH7xEi1zIkAc8IdG6QpdNtVVjPnK+1cr6QaXMtMuTneRNVdIjk1/U9HtbS1/1Yqq9OtaFrBASOG5tkhK/FuspoZp2kop5+fnUoc4bDXTAd8KjZ3SlHUgSEVB5ZhzudwJBIyLZvrmPixvU7HF7C/6kYa83ebNjcvBo2bRQKgXfUJdHXACS8ETZ/TuLohZEIhYkIHqgTAr4UvGDQYz5oDti5vsnp+ljV9ORLkGwhybB8KJLMKuHX/ha9LJfC70uSBM8kiZoPiVPcIcnNP5GfZ8lAcCG7b6D3556hrPcG87q3Yk/7wF7fyaNoJdJIwjdm3bT0a2eTOI49/YL+nqRuKZxdlR39dLx/y+X1DNJLbFcP5c4r4IkzkAySYEMQIwNFFnO6q0nlaL6LLhmWvaopGJei2jIPmOWN5/jbXxj5ig5f/NJ/gZqaDQfG/icKQNfsc0axQ5EpPJADHMeKSJ9E9AKVCtiCeOqY+qywG7WBGZPTbB4yeIXLV4fMSYrCNDoisCekhgmfn02nS7YjbVpfjc1WbAbKvPgbSdlQUwGSorJA9xsXIC7Xubv6uRGyXBBp362r+qpnzmDR5fGtWatu9FZy2o5ifSsluHKbTzDlkMXZ3/eqPejken9et4/9BqS/QqvIe2rRmfcTePVrIFHfO/wdmJfeixN/A/qK5JSaUTSlHnPDzM+ScPyAUr4TCQYKzkh5gxdOL0OVEI1E9g9JiiwZwYsu/Uxp2PafP+dgNVZyGwvZI2LfGA9ktWGbdWA9MyGF/0bHtqX3YrId/b58e1z3KHGeGjkO75o2MbdsJ1uxZPhWsZiYbi2sXRpwiiMeIJfQlKZd22TLAZgA7GHUdXynkjKDwp8sxEL99uncWd8oZgFYvX5N7d19REdr/8D</diagram></mxfile>
|
BIN
wyk/rnn.png
Normal file
BIN
wyk/rnn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
wyk/word-distribution.png
Normal file
BIN
wyk/word-distribution.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
Loading…
Reference in New Issue
Block a user