8
This commit is contained in:
parent
fa25bcc34d
commit
219d0fc56b
338
wyk/07_Zanurzenia_slow.org
Normal file
338
wyk/07_Zanurzenia_slow.org
Normal file
@ -0,0 +1,338 @@
|
||||
* Zanurzenia słów
|
||||
|
||||
W praktyce stosowalność słowosieci okazała się zaskakująco
|
||||
ograniczona. Większy przełom w przetwarzaniu języka naturalnego przyniosły
|
||||
wielowymiarowe reprezentacje słów, inaczej: zanurzenia słów.
|
||||
|
||||
** „Wymiary” słów
|
||||
|
||||
Moglibyśmy zanurzyć (ang. /embed/) w wielowymiarowej przestrzeni, tzn. zdefiniować odwzorowanie
|
||||
$E \colon V \rightarrow \mathcal{R}^m$ dla pewnego $m$ i określić taki sposób estymowania
|
||||
prawdopodobieństw $P(u|v)$, by dla par $E(v)$ i $E(v')$ oraz $E(u)$ i $E(u')$ znajdujących się w pobliżu
|
||||
(według jakiejś metryki odległości, na przykład zwykłej odległości euklidesowej):
|
||||
|
||||
$$P(u|v) \approx P(u'|v').$$
|
||||
|
||||
$E(u)$ nazywamy zanurzeniem (embeddingiem) słowa.
|
||||
|
||||
*** Wymiary określone z góry?
|
||||
|
||||
Można by sobie wyobrazić, że $m$ wymiarów mogłoby być z góry
|
||||
określonych przez lingwistę. Wymiary te byłyby związane z typowymi
|
||||
„osiami” rozpatrywanymi w językoznawstwie, na przykład:
|
||||
|
||||
- czy słowo jest wulgarne, pospolite, potoczne, neutralne czy książkowe?
|
||||
- czy słowo jest archaiczne, wychodzące z użycia czy jest neologizmem?
|
||||
- czy słowo dotyczy kobiet, czy mężczyzn (w sensie rodzaju gramatycznego i/lub
|
||||
socjolingwistycznym)?
|
||||
- czy słowo jest w liczbie pojedynczej czy mnogiej?
|
||||
- czy słowo jest rzeczownikiem czy czasownikiem?
|
||||
- czy słowo jest rdzennym słowem czy zapożyczeniem?
|
||||
- czy słowo jest nazwą czy słowem pospolitym?
|
||||
- czy słowo opisuje konkretną rzecz czy pojęcie abstrakcyjne?
|
||||
- …
|
||||
|
||||
W praktyce okazało się jednak, że lepiej, żeby komputer uczył się sam
|
||||
możliwych wymiarów — z góry określamy tylko $m$ (liczbę wymiarów).
|
||||
|
||||
** Bigramowy model języka oparty na zanurzeniach
|
||||
|
||||
Zbudujemy teraz najprostszy model język oparty na zanurzeniach. Będzie to właściwie najprostszy
|
||||
*neuronowy model języka*, jako że zbudowany model można traktować jako prostą sieć neuronową.
|
||||
|
||||
*** Słownik
|
||||
|
||||
W typowym neuronowym modelu języka rozmiar słownika musi być z góry
|
||||
ograniczony. Zazwyczaj jest to liczba rzędu kilkudziesięciu wyrazów —
|
||||
po prostu będziemy rozpatrywać $|V|$ najczęstszych wyrazów, pozostałe zamienimy
|
||||
na specjalny token ~<unk>~ reprezentujący nieznany (/unknown/) wyraz.
|
||||
|
||||
Aby utworzyć taki słownik użyjemy gotowej klasy ~Vocab~ z pakietu torchtext:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
from itertools import islice
|
||||
import regex as re
|
||||
import sys
|
||||
from torchtext.vocab import build_vocab_from_iterator
|
||||
|
||||
|
||||
def get_words_from_line(line):
|
||||
line = line.rstrip()
|
||||
yield '<s>'
|
||||
for m in re.finditer(r'[\p{L}0-9\*]+|\p{P}+', line):
|
||||
yield m.group(0).lower()
|
||||
yield '</s>'
|
||||
|
||||
|
||||
def get_word_lines_from_file(file_name):
|
||||
with open(file_name, 'r') as fh:
|
||||
for line in fh:
|
||||
yield get_words_from_line(line)
|
||||
|
||||
vocab_size = 20000
|
||||
|
||||
vocab = build_vocab_from_iterator(
|
||||
get_word_lines_from_file('opensubtitlesA.pl.txt'),
|
||||
max_tokens = vocab_size,
|
||||
specials = ['<unk>'])
|
||||
|
||||
vocab['jest']
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
16
|
||||
:end:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
vocab.lookup_tokens([0, 1, 2, 10, 12345])
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
['<unk>', '</s>', '<s>', 'w', 'wierzyli']
|
||||
:end:
|
||||
|
||||
*** Definicja sieci
|
||||
|
||||
Naszą prostą sieć neuronową zaimplementujemy używając frameworku PyTorch.
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
from torch import nn
|
||||
import torch
|
||||
|
||||
embed_size = 100
|
||||
|
||||
class SimpleBigramNeuralLanguageModel(nn.Module):
|
||||
def __init__(self, vocabulary_size, embedding_size):
|
||||
super(SimpleBigramNeuralLanguageModel, self).__init__()
|
||||
self.model = nn.Sequential(
|
||||
nn.Embedding(vocabulary_size, embedding_size),
|
||||
nn.Linear(embedding_size, vocabulary_size),
|
||||
nn.Softmax()
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
return self.model(x)
|
||||
|
||||
model = SimpleBigramNeuralLanguageModel(vocab_size, embed_size)
|
||||
|
||||
vocab.set_default_index(vocab['<unk>'])
|
||||
ixs = torch.tensor(vocab.forward(['pies']))
|
||||
out[0][vocab['jest']]
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
:end:
|
||||
|
||||
Teraz wyuczmy model. Wpierw tylko potasujmy nasz plik:
|
||||
|
||||
#+BEGIN_SRC
|
||||
shuf < opensubtitlesA.pl.txt > opensubtitlesA.pl.shuf.txt
|
||||
#+END_SRC
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
from torch.utils.data import IterableDataset
|
||||
import itertools
|
||||
|
||||
def look_ahead_iterator(gen):
|
||||
prev = None
|
||||
for item in gen:
|
||||
if prev is not None:
|
||||
yield (prev, item)
|
||||
prev = item
|
||||
|
||||
class Bigrams(IterableDataset):
|
||||
def __init__(self, text_file, vocabulary_size):
|
||||
self.vocab = build_vocab_from_iterator(
|
||||
get_word_lines_from_file(text_file),
|
||||
max_tokens = vocabulary_size,
|
||||
specials = ['<unk>'])
|
||||
self.vocab.set_default_index(self.vocab['<unk>'])
|
||||
self.vocabulary_size = vocabulary_size
|
||||
self.text_file = text_file
|
||||
|
||||
def __iter__(self):
|
||||
return look_ahead_iterator(
|
||||
(self.vocab[t] for t in itertools.chain.from_iterable(get_word_lines_from_file(self.text_file))))
|
||||
|
||||
train_dataset = Bigrams('opensubtitlesA.pl.shuf.txt', vocab_size)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
:end:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
from torch.utils.data import DataLoader
|
||||
|
||||
next(iter(train_dataset))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
(2, 5)
|
||||
:end:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
from torch.utils.data import DataLoader
|
||||
|
||||
next(iter(DataLoader(train_dataset, batch_size=5)))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
[tensor([ 2, 5, 51, 3481, 231]), tensor([ 5, 51, 3481, 231, 4])]
|
||||
:end:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
device = 'cuda'
|
||||
model = SimpleBigramNeuralLanguageModel(vocab_size, embed_size).to(device)
|
||||
data = DataLoader(train_dataset, batch_size=5000)
|
||||
optimizer = torch.optim.Adam(model.parameters())
|
||||
criterion = torch.nn.NLLLoss()
|
||||
|
||||
model.train()
|
||||
step = 0
|
||||
for x, y in data:
|
||||
x = x.to(device)
|
||||
y = y.to(device)
|
||||
optimizer.zero_grad()
|
||||
ypredicted = model(x)
|
||||
loss = criterion(torch.log(ypredicted), y)
|
||||
if step % 100 == 0:
|
||||
print(step, loss)
|
||||
step += 1
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
|
||||
torch.save(model.state_dict(), 'model1.bin')
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
None
|
||||
:end:
|
||||
|
||||
Policzmy najbardziej prawdopodobne kontynuację dla zadanego słowa:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
device = 'cuda'
|
||||
model = SimpleBigramNeuralLanguageModel(vocab_size, embed_size).to(device)
|
||||
model.load_state_dict(torch.load('model1.bin'))
|
||||
model.eval()
|
||||
|
||||
ixs = torch.tensor(vocab.forward(['dla'])).to(device)
|
||||
|
||||
out = model(ixs)
|
||||
top = torch.topk(out[0], 10)
|
||||
top_indices = top.indices.tolist()
|
||||
top_probs = top.values.tolist()
|
||||
top_words = vocab.lookup_tokens(top_indices)
|
||||
list(zip(top_words, top_indices, top_probs))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
[('ciebie', 73, 0.1580502986907959), ('mnie', 26, 0.15395283699035645), ('<unk>', 0, 0.12862136960029602), ('nas', 83, 0.0410110242664814), ('niego', 172, 0.03281523287296295), ('niej', 245, 0.02104802615940571), ('siebie', 181, 0.020788608118891716), ('którego', 365, 0.019379809498786926), ('was', 162, 0.013852755539119244), ('wszystkich', 235, 0.01381855271756649)]
|
||||
:end:
|
||||
|
||||
Teraz zbadajmy najbardziej podobne zanurzenia dla zadanego słowa:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
vocab = train_dataset.vocab
|
||||
ixs = torch.tensor(vocab.forward(['kłopot'])).to(device)
|
||||
|
||||
out = model(ixs)
|
||||
top = torch.topk(out[0], 10)
|
||||
top_indices = top.indices.tolist()
|
||||
top_probs = top.values.tolist()
|
||||
top_words = vocab.lookup_tokens(top_indices)
|
||||
list(zip(top_words, top_indices, top_probs))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
[('.', 3, 0.404473215341568), (',', 4, 0.14222915470600128), ('z', 14, 0.10945753753185272), ('?', 6, 0.09583134204149246), ('w', 10, 0.050338443368673325), ('na', 12, 0.020703863352537155), ('i', 11, 0.016762692481279373), ('<unk>', 0, 0.014571071602404118), ('...', 15, 0.01453721895813942), ('</s>', 1, 0.011769450269639492)]
|
||||
:end:
|
||||
|
||||
#+BEGIN_SRC python :session mysession :exports both :results raw drawer
|
||||
cos = nn.CosineSimilarity(dim=1, eps=1e-6)
|
||||
|
||||
embeddings = model.model[0].weight
|
||||
|
||||
vec = embeddings[vocab['poszedł']]
|
||||
|
||||
similarities = cos(vec, embeddings)
|
||||
|
||||
top = torch.topk(similarities, 10)
|
||||
|
||||
top_indices = top.indices.tolist()
|
||||
top_probs = top.values.tolist()
|
||||
top_words = vocab.lookup_tokens(top_indices)
|
||||
list(zip(top_words, top_indices, top_probs))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:results:
|
||||
[('poszedł', 1087, 1.0), ('idziesz', 1050, 0.4907470941543579), ('przyjeżdża', 4920, 0.45242372155189514), ('pojechałam', 12784, 0.4342481195926666), ('wrócił', 1023, 0.431664377450943), ('dobrać', 10351, 0.4312002956867218), ('stałeś', 5738, 0.4258835017681122), ('poszła', 1563, 0.41979148983955383), ('trafiłam', 18857, 0.4109022617340088), ('jedzie', 1674, 0.4091658890247345)]
|
||||
:end:
|
||||
|
||||
*** Zapis przy użyciu wzoru matematycznego
|
||||
|
||||
Powyżej zaprogramowaną sieć neuronową można opisać następującym wzorem:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(CE(w_{i-1}),$$
|
||||
|
||||
gdzie:
|
||||
|
||||
- $w_{i-1}$ to pierwszy wyraz w bigramie (poprzedzający wyraz),
|
||||
- $E(w)$ to zanurzenie (embedding) wyrazy $w$ — wektor o rozmiarze $m$,
|
||||
- $C$ to macierz o rozmiarze $|V| \times m$, która rzutuje wektor zanurzenia w wektor o rozmiarze słownika,
|
||||
- $\vec{y}$ to wyjściowy wektor prawdopodobieństw o rozmiarze $|V|$.
|
||||
|
||||
**** Hiperparametry
|
||||
|
||||
Zauważmy, że nasz model ma dwa hiperparametry:
|
||||
|
||||
- $m$ — rozmiar zanurzenia,
|
||||
- $|V|$ — rozmiar słownika, jeśli zakładamy, że możemy sterować
|
||||
rozmiarem słownika (np. przez obcinanie słownika do zadanej liczby
|
||||
najczęstszych wyrazów i zamiany pozostałych na specjalny token, powiedzmy, ~<UNK>~.
|
||||
|
||||
Oczywiście możemy próbować manipulować wartościami $m$ i $|V|$ w celu
|
||||
polepszenia wyników naszego modelu.
|
||||
|
||||
*Pytanie*: dlaczego nie ma sensu wartość $m \approx |V|$ ? dlaczego nie ma sensu wartość $m = 1$?
|
||||
|
||||
*** Diagram sieci
|
||||
|
||||
Jako że mnożenie przez macierz ($C$) oznacza po prostu zastosowanie
|
||||
warstwy liniowej, naszą sieć możemy interpretować jako jednowarstwową
|
||||
sieć neuronową, co można zilustrować za pomocą następującego diagramu:
|
||||
|
||||
#+CAPTION: Diagram prostego bigramowego neuronowego modelu języka
|
||||
[[./07_Zanurzenia_slow/bigram1.drawio.png]]
|
||||
|
||||
*** Zanurzenie jako mnożenie przez macierz
|
||||
|
||||
Uzyskanie zanurzenia ($E(w)$) zazwyczaj realizowane jest na zasadzie
|
||||
odpytania (_look-up_). Co ciekawe, zanurzenie można intepretować jako
|
||||
mnożenie przez macierz zanurzeń (embeddingów) $E$ o rozmiarze $m \times |V|$ — jeśli słowo będziemy na wejściu kodowali przy użyciu
|
||||
wektora z gorącą jedynką (_one-hot encoding_), tzn. słowo $w$ zostanie
|
||||
podane na wejściu jako wektor $\vec{1_V}(w) = [0,\ldots,0,1,0\ldots,0]$ o rozmiarze $|V|$
|
||||
złożony z samych zer z wyjątkiem jedynki na pozycji odpowiadającej indeksowi wyrazu $w$ w słowniku $V$.
|
||||
|
||||
Wówczas wzór przyjmie postać:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(CE\vec{1_V}(w_{i-1})),$$
|
||||
|
||||
gdzie $E$ będzie tym razem macierzą $m \times |V|$.
|
||||
|
||||
*Pytanie*: czy $\vec{1_V}(w)$ intepretujemy jako wektor wierszowy czy kolumnowy?
|
||||
|
||||
W postaci diagramu można tę interpretację zilustrować w następujący sposób:
|
||||
|
||||
#+CAPTION: Diagram prostego bigramowego neuronowego modelu języka z wejściem w postaci one-hot
|
||||
[[./07_Zanurzenia_slow/bigram2.drawio.png]]
|
403
wyk/08_Neuronowy_ngramowy_model.org
Normal file
403
wyk/08_Neuronowy_ngramowy_model.org
Normal file
@ -0,0 +1,403 @@
|
||||
* Neuronowy n-gramowy model języka
|
||||
|
||||
Omówiony w poprzedniej części neuronowy bigramowy model języka
|
||||
warunkuje kolejny wyraz jedynie względem bezpośrednio poprzedzającego
|
||||
— jak w każdym bigramowym modelu przyjmujemy założenie, że $w_i$
|
||||
zależy tylko od $w_{i-1}$. Rzecz jasna jest to bardzo duże
|
||||
ograniczenie, w rzeczywiście bardzo często prawdopodobieństwo
|
||||
kolejnego wyrazu zależy od wyrazu dwie, trzy, cztery itd. pozycje
|
||||
wstecz czy w ogólności od wszystkich wyrazów poprzedzających (bez
|
||||
względu na ich pozycje).
|
||||
|
||||
*Pytanie*: Wskaż zależności o zasięgu większym niż 1 wyraz w zdaniu
|
||||
_Zatopieni w kłębach dymu cygar i pochyleni nad butelkami z ciemnego
|
||||
szkła obywatele tej dzielnicy, jedni zakładali się o wygranę lub
|
||||
przegranę Anglii, drudzy o bankructwo Wokulskiego; jedni nazywali
|
||||
geniuszem Bismarcka, drudzy — awanturnikiem Wokulskiego; jedni
|
||||
krytykowali postępowanie prezydenta MacMahona, inni twierdzili, że
|
||||
Wokulski jest zdecydowanym wariatem, jeżeli nie czymś gorszym…_
|
||||
|
||||
** Trigramowy neuronowy model języka
|
||||
|
||||
Spróbujmy najpierw rozszerzyć nasz model na trigramy, to znaczy
|
||||
będziemy przewidywać słowo $w_i$ na podstawie słów $w_{i-2}$ i
|
||||
$w_{i-1}$.
|
||||
|
||||
Najprostsze rozwiązanie polegałoby na zanurzeniu pary $(w_{i-2},
|
||||
w_{i-1})$ w całości i postępowaniu jak w przypadku modelu bigramowego.
|
||||
Byłoby to jednak zupełnie niepraktyczne, jako że:
|
||||
|
||||
- liczba zanurzeń do wyuczenia byłaby olbrzymia ($|V|^2$ — byłoby to
|
||||
ewentualnie akceptowalne dla modeli operujących na krótszych
|
||||
jednostkach niż słowno, np. na znakach),
|
||||
- w szczególności zanurzenia dla par $(v, u)$, $(u, v)$, $(u, u)$ i
|
||||
$(v, v)$ nie miałyby ze sobą nic wspólnego.
|
||||
|
||||
*** Konketanacja zanurzeń
|
||||
|
||||
Właściwsze rozwiązanie polega na zanurzenia dalej pojedynczych słów i
|
||||
następnie ich *konkatenowaniu*.
|
||||
|
||||
Przypomnijmy, że konkatenacja wektorów $\vec{x_1}$ i $\vec{x_2}$ to wektor o rozmiarze
|
||||
$|\vec{x_1}| + |\vec{x_2}|$ powstały ze „sklejania” wektorów $\vec{x_1}$ i $\vec{x_2}$.
|
||||
Konkatenację wektorów $\vec{x_1}$ i $\vec{x_2}$ będziemy oznaczać za pomocą $[\vec{x_1}, \vec{x_2}]$.
|
||||
|
||||
Przykład: jeśli $\vec{x_1} = [-1, 2, 0]$ i $\vec{x_2} = [3, -3]$
|
||||
wówczas $[\vec{x_1}, \vec{x_2}] = [-1, 2, 0, 3, -3]$
|
||||
|
||||
Oznacza to, że nasza macierz „kontekstowa” $C$ powinna mieć w modelu trigramowy rozmiar nie
|
||||
$|V| \times m$, lecz $|V| \times m+m$ = $|V| \times 2m$ i wyjście będę zdefiniowane za pomocą wzoru:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(C[E(w_{i-2}),E(w_{i-1})]),$$
|
||||
|
||||
co można przedstawić za pomocą następującego schematu:
|
||||
|
||||
#+CAPTION: Diagram prostego bigramowego neuronowego modelu języka
|
||||
[[./08_Neuronowy_ngramowy_model/trigram1.drawio.png]]
|
||||
|
||||
**** Rozbicie macierzy $C$
|
||||
|
||||
Zamiast mnożyć macierz $C$ przez konkatenację dwóch wektorów, można
|
||||
rozbić macierz $C$ na dwie, powiedzmy $C_{-2}$ i $C_{-1}$, przemnażać
|
||||
je osobno przez odpowiadający im wektory i następnie _dodać_ macierze,
|
||||
tak aby:
|
||||
|
||||
$$C[E(w_{i-2}),E(w_{i-1})] = C_{-2}E(w_{i-2}) + C_{-1}E(w_{i-1}).$$
|
||||
|
||||
Macierze $C_{-2}$ i $C_{-1}$ będą miały rozmiar $|V| \times m$.
|
||||
|
||||
Przy tym podejściu możemy powiedzieć, że ostatni i przedostatni wyraz
|
||||
mają swoje osobne macierze o potencjalnie różnych wagach — co ma sens,
|
||||
jako że na inne aspekty zwracamy uwagę przewidując kolejne słowo na
|
||||
podstawie wyrazu bezpośrednio poprzedzającego, a na inne — na
|
||||
podstawie słowa występującego dwie pozycje wcześniej.
|
||||
|
||||
** Uogólnienie na $n$-gramowy model języka dla dowolnego $n$
|
||||
|
||||
Łatwo uogólnić opisany wyżej trigramowy model języka dla dowolnego $n$.
|
||||
Uogólniony model można przedstawić za pomocą wzoru:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(C[E(w_{i-n+1}),\dots,E(w_{i-1})]),$$
|
||||
|
||||
gdzie macierz $C$ ma rozmiar $|V| \times nm$ lub za pomocą wzoru:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(C_{-(i-n+1)}E(w_{i-n+1}) + \dots + C_{-1}E(w_{i-1}),$$
|
||||
|
||||
gdzie macierze $C_{-(i-n+1)$, \ldots, $C_{-1}$ mają rozmiary $|V| \times m$.
|
||||
|
||||
Por. diagram:
|
||||
|
||||
#+CAPTION: Diagram prostego n-gramowego neuronowego modelu języka
|
||||
[[./08_Neuronowy_ngramowy_model/ngram.drawio.png]]
|
||||
|
||||
** Dodanie kolejnej warstwy
|
||||
|
||||
W wypadku trigramowego czy — ogólniej — n-gramowego modelu języka dla
|
||||
$n \geq 3$ warto dodać kolejną (*ukrytą*) warstwę, na którą będziemy rzutować
|
||||
skonkatenowane embeddingi, zanim zrzutujemy je do długiego wektora
|
||||
prawdopodobieństw.
|
||||
|
||||
Zakładamy, że warstwa ukryta zawiera $h$ neuronów. Wartość $h$ powinna być mniejsza
|
||||
niż $nm$ (a może nawet od $m$).
|
||||
|
||||
*Pytanie*: Dlaczego wartość $h > nm$ nie jest racjonalnym wyborem?
|
||||
|
||||
*Pytanie*: Dlaczego dodanie kolejnej warstwy nie ma sensu dla modelu bigramowego?
|
||||
|
||||
*** Funkcja aktywacji
|
||||
|
||||
Aby warstwa ukryta wnosiła coś nowego, na wyjściu z tej funkcji musimy
|
||||
zastosować nieliniową *funkcji aktywacji*. Zazwyczaj jako funkcji
|
||||
aktywacji w sieciach neuronowych używa się funkcji ReLU albo funkcji
|
||||
sigmoidalnej. W prostych neuronowych modelach języka sprawdza się też
|
||||
*tangens hiperboliczny* (tgh, w literaturze anglojęzycznej tanh):
|
||||
|
||||
$$\operatorname{tgh}(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}.$$
|
||||
|
||||
#+BEGIN_SRC python :session mysession :results file
|
||||
import matplotlib.pyplot as plt
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
x = torch.linspace(-5,5,100)
|
||||
plt.xlabel("x")
|
||||
plt.ylabel("y")
|
||||
a = torch.Tensor(x.size()[0]).fill_(2.)
|
||||
m = torch.stack([x, a])
|
||||
plt.plot(x, nn.functional.tanh(m)[0])
|
||||
fname = '08_Neuronowy_ngramowy_model/tanh.png'
|
||||
plt.savefig(fname)
|
||||
fname
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
[[file:08_Neuronowy_ngramowy_model/tanh.png]]
|
||||
|
||||
**** Tangens hiperboliczny zastosowany dla wektora
|
||||
|
||||
Tangens hiperboliczny wektora będzie po prostu wektorem tangensów
|
||||
hiperbolicznych poszczególnych wartości.
|
||||
|
||||
#+BEGIN_SRC python :session mysession :results file
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
v = torch.Tensor([-100, -2.0, 0.0, 0.5, 1000.0])
|
||||
nn.functional.tanh(v)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
[[file:tensor([-1.0000, -0.9640, 0.0000, 0.4621, 1.0000])]]
|
||||
|
||||
*** Wzór i schemat dwuwarstwowego n-gramowego neuronowego modelu języka
|
||||
|
||||
Dwuwarstwowy model języka będzie określony następującym wzorem:
|
||||
|
||||
$$\vec{y} = \operatorname{softmax}(C\operatorname{tgh}(W[E(w_{i-n+1}),\dots,E(w_{i-1})])),$$
|
||||
|
||||
gdzie:
|
||||
|
||||
- $W$ jest wyuczalną macierzą wag o rozmiarze $h \times nm$,
|
||||
- $C$ będzie macierzą o rozmiarze $|V| \times h$.
|
||||
|
||||
Zmodyfikowaną się można przedstawić za pomocą następującego schematu:
|
||||
|
||||
#+CAPTION: Dwuwarstwowy n-gramowy neuronowy model języka
|
||||
[[./08_Neuronowy_ngramowy_model/ngram-tgh.drawio.png]]
|
||||
|
||||
*** Liczba wag w modelu dwuwarstwowym
|
||||
|
||||
Na wagi w modelu dwuwarstwowym składają się:
|
||||
|
||||
- zanurzenia: $m|V|$,
|
||||
- wagi warstwy ukrytej: $hnm$,
|
||||
- wagi warstwy wyjściowej: $|V|h$,
|
||||
|
||||
a zatem łącznie:
|
||||
|
||||
$$m|V| + hnm + |V|h$$
|
||||
|
||||
Jeśli $h \approx m$ (co jest realistyczną opcją), wówczas otrzymamy oszacowanie:
|
||||
|
||||
$$O(m|V| + nm^2).$$
|
||||
|
||||
Zauważmy, że względem $n$ oznacza to bardzo korzystną złożoność
|
||||
$O(n)$! Oznacza to, że nasz model może działać dla dużo większych
|
||||
wartości $n$ niż tradycyjny n-gramowy model języka (dla którego
|
||||
wartości $n > 5$ zazwyczaj nie mają sensu).
|
||||
|
||||
** Model worka słów
|
||||
|
||||
Jak stwierdziliśmy przed chwilą, dwuwarstwowy n-gramowym modelu języka
|
||||
może działać dla stosunkowo dużego $n$. Zauważmy jednak, że istnieje
|
||||
pewna słabość tego modelu. Otóż o ile intuicyjnie ma sens odróżniać
|
||||
słowo poprzedzające, słowo występujące dwie pozycje wstecz i zapewne
|
||||
trzy pozycje wstecz, a zatem uczyć się osobnych macierzy $C_{-1}$,
|
||||
$C_{-2}$, $C_{-3}$ to zapewne różnica między wpływem słowa
|
||||
występującego cztery pozycje wstecz i pięć pozycji wstecz jest już
|
||||
raczej nieistotna; innymi słowy różnica między macierzami $C_{-4}$ i
|
||||
$C_{-5}$ będzie raczej niewielka i sieć niepotrzebnie będzie uczyła
|
||||
się dwukrotnie podobnych wag. Im dalej wstecz, tym różnica wpływu
|
||||
będzie jeszcze mniej istotna, można np. przypuszczać, że różnica
|
||||
między $C_{-10}$ i $C_{-13}$ nie powinna być duża.
|
||||
|
||||
Spróbujmy najpierw zaproponować radykalne podejście, w którym nie
|
||||
będziemy w ogóle uwzględniać pozycji słów (lub będziemy je uwzględniać
|
||||
w niewielkim stopniu), później połączymy to z omówionym wcześniej
|
||||
modelem $n$-gramowym.
|
||||
|
||||
*** Agregacja wektorów
|
||||
|
||||
Zamiast patrzeć na kilka poprzedzających słów, można przewidywać na
|
||||
cały ciąg słów poprzedzających przewidywane słowo. Zauważmy jednak, że
|
||||
sieć neuronowa musi mieć ustaloną strukturę, nie możemy zmieniać jej
|
||||
rozmiaru. Musimy zatem najpierw zagregować cały ciąg do wektora o
|
||||
*stałej* długości. Potrzebujemy zatem pewnej funkcji agregującej $A$, takiej by
|
||||
$A(w_1,\dots,w_{i-1})$ było wektorem o stałej długości, niezależnie od $i$.
|
||||
|
||||
*** Worek słów
|
||||
|
||||
Najprostszą funkcją agregującą jest po prostu… suma. Dodajemy po
|
||||
prostu zanurzenia słów:
|
||||
|
||||
$$A(w_1,\dots,w_{i-1}) = E(w_1) + \dots + E(w_{i-1}) = \sum_{j=1}^{i-1} E(w_j).$$
|
||||
|
||||
*Uwaga*: zanurzenia słów nie zależą od pozycji słowa (podobnie było w wypadku n-gramowego modelu!).
|
||||
|
||||
Jeśli rozmiar zanurzenia (embeddingu) wynosi $m$, wówczas rozmiar
|
||||
wektora uzyskanego dla całego poprzedzającego tekstu wynosi również $m$.
|
||||
|
||||
Proste dodawanie wydaje się bardzo „prostacką” metodą, a jednak
|
||||
dodawanie wektorów słów jest *zaskakująco skuteczną metodą zanurzenia
|
||||
(embedowania) całych tekstów (doc2vec)*. Prostym wariantem dodawania jest obliczanie *średniej wektorów*:
|
||||
|
||||
$$A(w_1,\dots,w_{i-1}) = \frac{E(w_1) + \dots + E(w_{i-1})}{i-1} = \frac{\sum_{j=1}^{i-1} E(w_j)}{i-1}.$$
|
||||
|
||||
Tak czy siak uzyskany wektor *nie zależy od kolejności słów*
|
||||
(dodawanie jest przemienne i łączne!). Mówimy więc o *worku słów*
|
||||
(/bag of words/, /BoW/) — co ma symbolizować fakt, że słowa są
|
||||
przemieszane, niczym produkty w torbie na zakupy.
|
||||
|
||||
**** Schemat graficzny modelu typu worek słów
|
||||
|
||||
Po zanurzeniu całego poprzedzającego tekstu postępujemy podobnie jak w
|
||||
modelu bigramowym — rzutujemy embedding na długi wektor wartości, na
|
||||
którym stosujemy funkcję softmax:
|
||||
|
||||
#+CAPTION: Model typu worek słów
|
||||
[[./08_Neuronowy_ngramowy_model/bow1.drawio.png]]
|
||||
|
||||
Odpowiada to wzorowi:
|
||||
|
||||
$$y = \operatorname{softmax}(C\sum_{j=1}^{i-1} E(w_j)).$$
|
||||
|
||||
*** Jak traktować powtarzające się słowa?
|
||||
|
||||
Według wzoru podanego wyżej, jeśli słowo w poprzedzającym tekście
|
||||
pojawia się więcej niż raz, jego embedding zostanie zsumowany odpowiednią liczbę razy.
|
||||
Na przykład embedding tekstu _to be or not to be_ będzie wynosił:
|
||||
|
||||
$$E(\mathrm{to}) + E(\mathrm{be}) + E(\mathrm{or}) + E(\mathrm{not}) + E(\mathrm{to}) + E(\mathrm{be}) = 2E(\mathrm{to}) + 2E(\mathrm{be}) + E(\mathrm{or}) + E(\mathrm{not}).$$
|
||||
|
||||
Innymi słowy, choć w worku słów nie uwzględniamy kolejności słów, to
|
||||
*liczba wystąpień* ma dla nas znaczenie. Można powiedzieć, że
|
||||
traktujemy poprzedzający tekst jako *multizbiór* (struktura
|
||||
matematyczna, w której nie uwzględnia się kolejności, choć zachowana
|
||||
jest informacja o liczbie wystąpień).
|
||||
|
||||
**** Zbiór słów
|
||||
|
||||
Oczywiście moglibyśmy przy agregowaniu zanurzeń pomijać powtarzające
|
||||
się słowa, a zatem zamiast multizbioru słów rozpatrywać po prostu ich zbiór:
|
||||
|
||||
$$A(w_1,\dots,w_{i-1}) = \sum_{w \in \{w_1,\dots,w_{i-1}\}} E(w).$$
|
||||
|
||||
Jest kwestią dyskusyjną, czy to lepsze czy gorsze podejście — w końcu
|
||||
liczba wystąpień np. słów _Ukraina_ czy _Polska_ może wpływać w jakimś
|
||||
stopniu na prawdopodobieństwo kolejnego słowa (_Kijów_ czy
|
||||
_Warszawa_?).
|
||||
|
||||
*** Worek słów a wektoryzacja tf
|
||||
|
||||
Wzór na sumę zanurzeń słów można przekształcić w taki sposób, by
|
||||
sumować po wszystkich słowach ze słownika, zamiast po słowach rzeczywiście występujących w tekście:
|
||||
|
||||
$$A(w_1,\dots,w_{i-1}) = \sum_{j=1}^{i-1} E(w_j) = \sum_{w \in V} \#wE(w)$$
|
||||
|
||||
gdzie $\#w$ to liczba wystąpień słowa $w$ (w wielu przypadkach równa zero!).
|
||||
|
||||
Jeśli teraz zanurzenia będzie reprezentować jako macierz $E$ (por. poprzedni wykład),
|
||||
wówczas sumę można przedstawić jako iloczyn macierzy $E$ i pewnego wektora:
|
||||
|
||||
$$A(w_1,\dots,w_{i-1}) = E(w) [\#w^1,\dots,\#w^{|V|}]^T.$$
|
||||
|
||||
(Odróżniamy $w^i$ jako $i$-ty wyraz w słowniku $V$ od $w_i$ jako $i$-ty wyraz w ciągu).
|
||||
|
||||
Zwróćmy uwagę, że wektor $[\#w_1,\dots,\#w_{|V|}]$ to po prostu
|
||||
reprezentacja wektora poprzedzającego tekstu (tj. ciągu
|
||||
$(w_1,\dots,w_{i-1})$) przy użyciu schematu wektoryzacji tf (_term
|
||||
frequency_). Przypomnijmy, że tf to reprezentacja tekstu przy użyciu
|
||||
wektorów o rozmiarze $|V|$ — na każdej pozycji odnotowujemy liczbę wystąpień.
|
||||
Wektory tf są *rzadkie*, tj. na wielu pozycjach zawierają zera.
|
||||
|
||||
Innymi słowy, nasz model języka _bag of words_ można przedstawić za pomocą wzoru:
|
||||
|
||||
$$y = \operatorname{softmax}(C\operatorname{tf}(w_1,\dots,w_{i-1})),$$
|
||||
|
||||
co można zilustrować w następujący sposób:
|
||||
|
||||
#+CAPTION: Model typu worek słów — alternatywna reprezentacja
|
||||
[[./08_Neuronowy_ngramowy_model/bow2.drawio.png]]
|
||||
|
||||
Można stwierdzić, że zanurzenie tekstu przekształca rzadki, długi wektor
|
||||
tf w gęsty, krótki wektor.
|
||||
|
||||
** Ważenie słów
|
||||
|
||||
Czy wszystkie słowa są tak samo istotne? Rzecz jasna, nie:
|
||||
|
||||
- jak już wiemy z naszych rozważań dotyczących n-gramowych modeli języka, słowa bezpośrednio
|
||||
poprzedzające odgadywany wyraz mają większy wpływ niż słowa wcześniejsze;
|
||||
intuicyjnie, wpływ słów stopniowo spada — tym bardziej, im bardziej słowo jest oddalone od słowa odgadywanego;
|
||||
- jak wiemy z wyszukiwania informacji, słowa, które występują w wielu tekstach czy dokumentach, powinny mieć
|
||||
mniejsze znaczenie, w skrajnym przypadku słowa występujące w prawie każdym tekście (_że_, _w_, _i_ itd.) powinny
|
||||
być praktycznie pomijane jako stop words (jeśli rozpatrywać je w „masie” worka słów — oczywiście
|
||||
to, czy słowo poprzedzające odgadywane słowo to _że_, _w_ czy _i_ ma olbrzymie znaczenie!).
|
||||
|
||||
Zamiast po prostu dodawać zanurzenia, można operować na sumie (bądź średniej) ważonej:
|
||||
|
||||
$$\sum_{j=1}^{i-1} \omega(j, w_j)E(w_j), gdzie$$
|
||||
|
||||
$\omega(j, w_j)$ jest pewną wagą, która może zależeć od pozycji $j$ lub samego słowa $w_j$.
|
||||
|
||||
*** Uwzględnienie pozycji
|
||||
|
||||
Można w pewnym stopniu złamać „workowatość” naszej sieci przez proste
|
||||
uwzględnienie pozycji słowa, np. w taki sposób:
|
||||
|
||||
$$\omega(j, w_j) = \beta^{i-j-1},$$
|
||||
|
||||
dla pewnego hiperparametru $\beta$. Na przykład jeśli $\beta=0,9$,
|
||||
wówczas słowo bezpośrednio poprzedzające dane słowo ma $1 / 0,9^9 \approx 2.58$
|
||||
większy wpływ niż słowo występujące 10 pozycji wstecz.
|
||||
|
||||
*** Odwrócona częstość dokumentowa
|
||||
|
||||
Aby większą wagę przykładać do słów występujących w mniejszej liczbie
|
||||
dokumentów, możemy użyć, znanej w wyszukiwaniu informacji
|
||||
odwrotnej częstości dokumentowej (_inverted document frequency_, _idf_):
|
||||
|
||||
$$\omega(j, w_j) = \operatorname{idf}_S(w_j) = \operatorname{log}\frac{|S|}{\operatorname{df}_S(w_j)},$$
|
||||
|
||||
gdzie:
|
||||
|
||||
- $S$ jest pewną kolekcją dokumentów czy tekstów, z którego pochodzi przedmiotowy ciąg słów,
|
||||
- $\operatorname{df}_S(w)$ to częstość dokumentowa słowa $w$ w kolekcji $S$, tzn. odpowiedź na pytanie,
|
||||
w ilu dokumentach występuje $w$.
|
||||
|
||||
Rzecz jasna, ten sposób ważenia oznacza tak naprawdę zastosowanie wektoryzacji tf-idf zamiast tf,
|
||||
nasza sieć będzie dana wzorem:
|
||||
|
||||
$$y = \operatorname{softmax}(C\operatorname{tfidf}(w_1,\dots,w_{i-1})).$$
|
||||
|
||||
*** Bardziej skomplikowane sposoby ważenia słów
|
||||
|
||||
Można oczywiście połączyć odwrotną częstość dokumentową z uwzględnieniem pozycji słowa:
|
||||
|
||||
$$\omega(j, w_j) = \beta^{i-j-1}\operatorname{idf}_S(w_j).$$
|
||||
|
||||
*Uwaga*: „wagi” $\omega(j, w_j)$ nie są tak naprawdę wyuczalnymi
|
||||
wagami (parametrami) naszej sieci neuronowej, terminologia może być
|
||||
tutaj myląca. Z punktu widzenia sieci neuronowej $\omega(j, w_j)$ są
|
||||
stałe i są optymalizowane w procesie propagacji wstecznej. Innymi
|
||||
słowy, tak zdefiniowane $\omega(j, w_j)$ zależą tylko od:
|
||||
|
||||
- hiperparametru $\beta$, który może być optymalizowany już poza siecią (w procesie *hiperoptymalizacji*),
|
||||
- wartości $\operatorname{idf}_S(w_j)$ wyliczanych wcześniej na podstawie kolekcji $S$.
|
||||
|
||||
*Pytanie*: czy wagi $\omega(j, w_j)$ mogłyby sensownie uwzględniać
|
||||
jakieś parametry wyuczalne z całą siecią?
|
||||
|
||||
** Modelowanie języka przy użyciu bardziej złożonych neuronowych sieci _feed-forward_
|
||||
|
||||
Można połączyć zalety obu ogólnych podejść (n-gramowego modelu i worka
|
||||
słów) — można _równocześnie_ traktować w specjalny sposób (na
|
||||
przykład) dwa poprzedzające wyrazy, zaś wszystkie inne wyrazy
|
||||
reprezentować jako „tło” modelowane za pomocą worka słów lub podobnej
|
||||
reprezentacji. Osiągamy to poprzez konkatenację wektora
|
||||
poprzedzającego słowa, słowa występującego dwie pozycje wstecz oraz
|
||||
zagregowanego zanurzenia całego wcześniejszego tekstu:
|
||||
|
||||
$$y = \operatorname{softmax}(C[E(w_{i-1}),E(w_{i-2}),A(w_1,\dots,w_{i-3})]),$$
|
||||
|
||||
lepiej z dodatkową warstwą ukrytą:
|
||||
|
||||
$$y = \operatorname{softmax}(C\operatorname{tg}(W[E(w_{i-1}),E(w_{i-2}),A(w_1,\dots,w_{i-3})])),$$
|
||||
|
||||
W tak uzyskanym dwuwarstwowym neuronowym modelu języka, łączącym model
|
||||
trigramowy z workiem słów, macierz $W$ ma rozmiar $h \times 3m$.
|
||||
|
||||
** Literatura
|
||||
|
||||
Skuteczny n-gramowy neuronowy model języka opisano po raz pierwszy
|
||||
w pracy [[https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf][A Neural Probabilistic Language Model]] autorstwa Yoshua Bengio i in.
|
1
wyk/08_Neuronowy_ngramowy_model/bow1.drawio
Normal file
1
wyk/08_Neuronowy_ngramowy_model/bow1.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-04-23T08:10:01.287Z" agent="5.0 (X11)" etag="DuwX-avzVRfuxOlr24Vt" version="17.4.6" type="device"><diagram id="UNyY5TJjaPirS19H5Hif" name="Page-1">7VpZd9o4GP01PJLjDWM/BgKZmaaTtjmnU+alR8XCVjCWI4sY8utHQjLexNKwk3kB6Wr/tvvJdsPsTmb3BMTBZ+zBsGFo3qxh3jUMw7V09suBuQB027UE4hPkSSwHntAblKAm0SnyYFLqSDEOKYrL4BBHERzSEgYIwWm52wiH5VVj4MMa8DQEYR39B3k0EKhjtHP8D4j8IFuZHVC0TEDWWU6RBMDDqYAWhzN7DbNLMKaiNJl1YciFl8lFSKC/onW5MQIjutWAbu/xCwqcTz//fvZerAc4TN6aUhkJnWcHhh47v6xiQgPs4wiEvRztEDyNPMhn1Vgt7/OAccxAnYHPkNK5VCaYUsyggE5C2QpniP7gw29asjaQk/Hy3axYmWeViJL5j2JlkM/Aq/mwRS0bN8IRlRvhIu+I8/JDrhRjpi88JUPZ6+vj5/Txfjy+f/gz+vbS96nuPDQNaY6A+JCukbG+VDbzEognkO2PjSMwBBS9lvcBpLn6y365RllBKlWt4HWbfAXhVK5U03iuT66cNEAUPsVgcfSUOXVZdyvF9QoJhbMCVD+xbDU06dsyJpiurKe5g+mmxIKCc2XY3oVkKoRkh2zVjodeWdGni5MzZ7HSn412BzGxtu8EkPVkC5c6V4TMZEPLkkwowWPYxSEmDIlwxH1rhMKwAoEQ+RGrDpnEIcM7XNKIRahb2TBBnrdwTJXqys66B+1ZFe1ZTl179jGV515KCHt/pLHrkUbZz1FGt1OFHvv8Qo/ulo1Xb9WNd2nQR7Fe/QIZOCfdQTbfGgZ+v9k7W5q9bp6V3Tvnb/enN3ttJeWijENDjMfNaVwgWHT99GrrFXq1Tkyvej2DTPCITsDsepVgVZSga4oMVTuqFrZKUQl+Gze6rYZjAI/LgIDUwzH+heACtRKaAn4ZD/nvGHCw0/Wgjxv87ijSW8TLrS6K2P/39SmuIkUW0C9SRT5Kdmw4BmPHou0sQ13Bdgy3dRjbUd4/zYvLMJYpxTHv+EPsPPe/uoM++itwv7eM3sTrZLI7mzv+uk2eU8LR0k94x1cK6ePm2ftLi+XQLxixJXJdt91yytKu6FB4mRxVfEK5aSKjMpFww9pEt4SAeaFbzDskv7FhS/u9fZX7s4LYQW6cS+G+315Vt+f1z6T0D/tMqmW1K6x7zKdSSkKoh+ArCzf7Id30SXvRSWwPevff/gWfsNW3ps3sPc+5kO66TZ4T6Zp22QmOSrpKIV1e6nkppGsZbjXkvZd2FVMdiHgVK22g3o0jdiZfpd3Wyffm5uZ6+dPcIls/FHsq5d9WBFeR6ehZhnOtujDM02UySl04/8fwA8XwpR53jeC1iQ4Uv2vrbIjeG/rvHLuVWWHrUux1Pxn0QTLjFWRsVmhC287M9qVZVcotLrpclCWd2y9TnDU0k4WQb1kHZuKzvDG/GBefU4u5VlyZ2S5RnKwig4JBgCQWn6ON0IwbVmcFDyj0u/VrCdOsU4OloAbrUJfc9qW42mkvuUrZbftNh72jK++k4MN8wrGTE1QvuUb7iJdcpZDq7/tTQOSrthBFCPPSGaeru8UkqxyTDMXrrn29KmXV/HNZQSr5R8dm7z8=</diagram></mxfile>
|
1
wyk/08_Neuronowy_ngramowy_model/bow2.drawio
Normal file
1
wyk/08_Neuronowy_ngramowy_model/bow2.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-04-23T09:02:43.180Z" agent="5.0 (X11)" etag="6a48B_aLc62Epg4yxUQr" version="17.4.6" type="device"><diagram id="UNyY5TJjaPirS19H5Hif" name="Page-1">5Vpdc+I2FP01nmkfkkGyAftxcYC2m22ym5lt05cdrS1sgbGIEDHw6ythGX/IEDYECOQBkI6vJOueo6srDYbpjud9hibhF+rjyIANf26YNwaEjgXEtwQWKQBajpUiASO+wnLggSyxAhsKnREfT0uGnNKIk0kZ9GgcY4+XMMQYTcpmAxqVR52gAGvAg4ciHf2H+DxMURu2c/wPTIIwG1lMMH0yRpmx6mIaIp8mKbSanNk1TJdRytPSeO7iSDov80vqgd6Gp+sXYzjmuzT4evclueuPRv3bP+NvT72AA/v2ykx7eUbRTE3YgK1I9NfxybMoBrJoQMGZlfww2h1yBY32TQpklmLIkvFqsnyReZDjucRDPo4EAERxyhkdYZdGlAkkprGw7AxIFFUgFJEgFlVPzBALvPOMGSeCm0/qwZj4vhymk4SE44cJ8uSYiVCiwBidxT6Wk2+sX6voLeVA2SeeFyDlvT6mY8zZQpiop1ZLaVJp2bJVPcmFkZmEBU2YCkNKisG655wtUVCE/QJ5juZr7AvxqiplPKQBjVHUzdGKV3KbW0onip4h5nyhViKacVomD88J/1c2v26q2qPqTJZv5sXK4iXnT+mMeXjLFFtqySMWYL7Fzk7t5Py3UslwhDh5Li/uNyemVbOqKkzlPIAN+i34/A3EC5yyeEFTF+9a0EdRL7DORb7C62xRaCSrj1l/spI3W9X2l729o+yB+a50b79/3Z9e9lBz0pQO+BjNL3jnBJXg09BZWGPHYWGnxIfR5chwm4YNkS99wFDi0wn9SfAKtaY8QTK5jeT3CEmw4/o4oIbMxdKkichy0yWx+P2+PXGqSbxS6CerIh8l5xKZtoi5Re1cAV070GkeRjsetYe9r85jj/wVOt+bsDv2O7W7+/acGXzYnLlptSv8HTNrTh4aT4BNWo/d/rf/0Gdq9axZduQ5q7TDcpxfSTxWtXvMiPCYFMF2NivJQzntAG737p6E9ucffw/9J+sWe9NlevDYI8lQTe8pEa+S7xLQqWqlXRFBmjipdsWz7stdwUpX6SS1rj4xhhYFs4k0mGqiW8/69TrUw8j19fXlRgKzkgOYzonjQLsmjKcxG2Sx+lK5gObpYnJtQGmeS0we0JirDqWDOxsi6AtnvmMGVbOy7Bq7xcGXO6qKYUNsfkW4rHVP+1wk8trbggNKa9dbtNaeEtwrBhzm0kwLijUe3LxntcpxErZrzq3mMQOlfsOSIKaOoRGJCV2VfnN/f9eb116kWFY5EMGaAyGAxyTF0UgRI7nFD6jU5QdusKmzPdQnG2uVebqNky+46m2dWZOYHOy6rpbbTFxnlKbvF/Iq2/zJU0MANAISPOKULZbIG8poxweXS4el35+YOiEHuzutZ0S/wV6ieMaWOCZY4EM0khegtRtT9wNtTGYNU/C4TOm33GyJ/JG8k04X0eWyUT2u1MSxIy8bSyMjMFzLcBzh/o9HSG0u/UaEiGr+v5r0AJr/O8ns/g8=</diagram></mxfile>
|
BIN
wyk/08_Neuronowy_ngramowy_model/bow2.drawio.png
Normal file
BIN
wyk/08_Neuronowy_ngramowy_model/bow2.drawio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
1
wyk/08_Neuronowy_ngramowy_model/ngram-tgh.drawio
Normal file
1
wyk/08_Neuronowy_ngramowy_model/ngram-tgh.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-04-23T07:25:35.437Z" agent="5.0 (X11)" etag="wQ0k74k1QtIDXs4Ob3ey" version="17.4.6" type="device"><diagram id="UNyY5TJjaPirS19H5Hif" name="Page-1">7Vpbc5s4FP41PCZjxMXwWBzb6W4y3TQz3c2+dFSjgGoZUVkOdn99pSDMTb6kviVxZzKxdDi68J2PcxEYVm8yHzKYxrc0RMQAnXBuWFcGAKYNOuJHShZK4ttWLokYDpWsFNzjn0gJ1cBohkM0rSlySgnHaV04okmCRrwmg4zRrK72SEl91RRGqCW4H0HSlv6LQx7nUg90S/k1wlFcrGy6fn5lAgtlNcU0hiHNctHzzVl9w+oxSnnemsx7iEj0ClxyBAYrri43xlDCtxlw9+k2+zQcj4c3H5PPPwYRN72bC5DP8gTJTN2w2ixfFAgwOktCJCcxDSvIYszRfQpH8momjC5kMZ8Qdbm9KbXPJ8Q4mldEapNDRCeIs4VQUVeBpUyvKANs1c9K/M1CJ65gX8igMnm0nLpERTQUMC8AydKA5BKxahDiJ9GM+POd2+Iv+2p0Ayxg7V7lgkJTLFxTboAssOF1JKec0THqUUKZkCQ0EZrBIyakIYIER4nojgTiSMgDiTQWBP6gLkxwGMpltKYrjdvZj/WWT7yynmW1rece03h+C2sUiidcdSnjMY1oAkm/lDZQKXVuKE2Veb4jzhfKXcEZp3XjoTnm/8nhl47qPajJZPtqXu0sNoE/pTM2Qmtu0VV+EbII8TV6Xq4n73+tKRkikOOnugfcu2HcV+h6OnXyXjht8treMdlr2m+FvgJ1tqgMkt2HYj7ZKYc993anvbcl7U3rVfHeewO8N09P/M7KoIuLKEooHV/M0kqIxe8/wLp2Iz3yTxxgTbNlqQyyKc+gEBKcYCpb79UcdjNb7Wiy1c5R7dHO6af0kU/g/B1bATQd2OnNsFXVwOjPsdFzDA/AUILAYBbSlH7D6Flqq8coJPL/GEph0AtRRA15x3nFgWXb6eFE/H5ZX3VoqpZc9I01JedSsAAfiISlRp7l4UOFPMB3DkOeEfW+D+78hwH+K/a/OKA/CQNtxXniHMEx6ygdtSzXgnS+qfH+Mlk19B+KxRKlrb1GEQ8aNsxzczWqeua0YSLQbUyUJ++tiT4wBhcVtVQqTLffcJEUbb2vur5o5DsoybkE9/f5qit41x8jmWd7jOQ4DQYe8RiJumlggX7wlc5ur3vh3dXH61FxUHoqZwOO5W0armVjZZ7dd36YLHUf+sPP/8O/qT2wZxfFQX2lMteCeqw6fN0mX1OMtbwTxlgtSNafGHugGGvbfiPv/O0o257qUHFWs9KGSLtxxM6xVsvbdqy9vLx8v+HSah4KaRzHocKlFv/ui3MdUb0G55vvALfhC46Y72gN6P1x/Ady/MsD213dfnOiQzn91jobXP4G/Z0dvjaV7J4HX1+anq9Ou7dIz50d+b9TwXWY9LzlkTUIro6yTt1Jm5pzQrN7zKrUfSus3yN7nTZ7V39fcCr2Oi328ihuG4sQnE5XJRkVyOE0zT9ue8Rzabp9sLn5zkT3ylfDZftQXG6/F5+N2YLLFx9v633iblaxukW9VPUqzn68iuiWHxzmobf8btPq/wI=</diagram></mxfile>
|
BIN
wyk/08_Neuronowy_ngramowy_model/ngram-tgh.drawio.png
Normal file
BIN
wyk/08_Neuronowy_ngramowy_model/ngram-tgh.drawio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
1
wyk/08_Neuronowy_ngramowy_model/ngram.drawio
Normal file
1
wyk/08_Neuronowy_ngramowy_model/ngram.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-04-23T06:52:34.125Z" agent="5.0 (X11)" etag="F7oHlS30BOIVpfAPOky4" version="17.1.3" type="device"><diagram id="UNyY5TJjaPirS19H5Hif" name="Page-1">7VpZc9owEP41fkwGn9iPhQA90mmTzKRNXzoqVmwV4XWFiKG/vhKW4zMYypUmfQHp0+r6dtlDg2b2p4sRQ3H4EXxMNaPjLzTzQjMMz9LFpwSWKaA7npUiASO+wnLghvzGCuwodE58PCsJcgDKSVwGxxBFeMxLGGIMkrLYPdDyrjEKcA24GSNaR78Qn4cp6hrdHH+LSRBmO4sLpiNTlAmrJWYh8iFJodXlzIFm9hkAT1vTRR9TSV7GS8rA8InRx4MxHPFNJlx9+ph8Gk0mo8t30fWvYcB19/LMSFd5QHSuLqwOy5cZAwzmkY/lIrpm9pKQcHwTo7EcTYTOBRbyKVXD9UOpcz5gxvGiAKlDjjBMMWdLIaJGDVOpXpmMYal+kvOvZzJhgfsMQ0rlwePSOSuioYjZgiSzgSSHil17PnkQzYCvbi4M20q+a90eEbR2L1IgkxQbl4QrJAtueJnJGWcwwX2gwAQSQSQke/eE0gqEKAki0R0LxrHAe5JpIgz4jRqYEt+X2zSqLlduZz/as4yy9kyzrj3nmMrzalxjX/zCVRcYDyGACNFBjlZYyWUuAWKlnp+Y86VyV2jOoaw8vCD8q5x+bqvenVpMti8Wxc6yjfwZzNkYr7mio/wiYgHma+TcVE7ef60qGaaIk4eyB9y7Ypzn53p0r2y8ul03Xss9pvXq1r9ivoJ1tixMkt27bD3Zyaeterubvbuh2evms7J79/nb/enNvvNkyCVZDKUAk7N5XAiw5OWHV8eqJEfeicOrrtc0lSA24wkSICURAdl6qeqwqrlqpyFX7RxVH/WMfgb3fIoWL1gLeiVsn14LG5UMDH5PtL6tuQbyJQcMJT7E8IPgFWqpX5FP5ecESbDX93EAmkyy03KDyLbdJ5H4vl1fcjSULCn0g1WR11KtiEJeZCtF23kMPQXbMTz7MLYzBvfn8Mq7G5L3oXdrG4Op32usNk+cH9h6maSjluSNJL3etHh/Waya+hmI2CLXtVsp4I2KDtO8XM0qvje1LGR0KwuliXttoTeMoWVBLJYCs80PnKVEG5+rLC8a6Qly43wk9+/ttanYXf+EpL/aJyTbrljgEZ+QkpvOL53Fzt1gdP0NfQBraM3P7NM6G2PbN6SKi2itrhsvnT22t1XXzo5eaCfN1IuPfcTKmqk2MPik9ZruCWNlI0nm64iV7Va/91hpWV4lffzraFlf6lDxsmGnlojZOmPnmNlot/WYeX5+/qzD3m6Oo/q00+A4jhr2ulvnLKII7f3TectOCjScii84dd7i/nf8B3L8hrenIqm60KGcfm2fFpffIr+twxfd/I8OqXj+dxFz8Ac=</diagram></mxfile>
|
BIN
wyk/08_Neuronowy_ngramowy_model/ngram.drawio.png
Normal file
BIN
wyk/08_Neuronowy_ngramowy_model/ngram.drawio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
wyk/08_Neuronowy_ngramowy_model/tanh.png
Normal file
BIN
wyk/08_Neuronowy_ngramowy_model/tanh.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
1
wyk/08_Neuronowy_ngramowy_model/trigram1.drawio
Normal file
1
wyk/08_Neuronowy_ngramowy_model/trigram1.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-04-22T20:26:07.083Z" agent="5.0 (X11)" etag="6MNvURN8OzIm5K8R91Ac" version="17.1.3" type="device"><diagram id="UNyY5TJjaPirS19H5Hif" name="Page-1">5VldU+IwFP01fdTpJ5RHQXB3R8d1ndldn3YiiW0k7WVDsOCv34SmtKWBRVERfYHk5Puec3OT1PJ6yeyMo3F8AZgwy7XxzPJOLdft+I78VcA8B5xWx8+RiFOssRK4po9Eg7ZGpxSTSa2iAGCCjuvgENKUDEUNQ5xDVq92B6w+6hhFpAFcDxFror8oFnGOhm67xL8QGsXFyHKBeUmCisq6i0mMMGQ5tFic17e8HgcQeSqZ9QhTxivskltgsKZ0OTFOUrFNgyGE94Orzs2Afos7PwO3n+DukV7GRMyLBRMs16+zwEUMEaSI9Uu0y2GaYqJ6tWWurHMOMJagI8F7IsRck4mmAiQUi4TpUjKj4nclfaO7UunTWTUzLzKp4HPVxD4OiuxN0YPKlM0WuaJdvjq1pLVGK9iBKR/qWleXF9nl2Wh0dv41/fF3EAknPD9ytfgQj4jYUK+1pFb6BIGEyPnIdpwwJOhDfR5IizNa1iv5kwlNoZnOTZN8QGyqR2rwW7KnjJfFVJDrMVosPZMuXGdqrbkeCBdkVoGaK9alnq09We8Arq/zWelOjqexuOJKBbaLkYyab9rkDTWvBXwoqve2VL27o+oXTU84R/NKhTHQVEwqPX9XQEVaraAmLa++A8pE3mMpleXUnu9insHFWkzapovpg0xGYsGAjHJ+9sdqd6m0Tfs0B4qacuBa5RU5Ss8SdfVMBIcR6QEDLpEUUqXJO8rYCoQYjVKZHUqiicS7yk+pjGYnuiChGC8EbXL8ushfwvd920hQ1fdbr+T6RvI6h+L6z/fY1pYeGxp3iX0Frtb7C1zFeaoQrxM0xeu7b6lexz8U+e4WuZ4j+3BL2Tveu9J9+P51v3/Z22tDLi1iKAMYHU3HlQBLP354DZyVo3W45/DqOA2mMsQnIkMSZDSloFIflQ7fW6HDNtx07Dflo3kfnMCdSNDsA7Ow4hTO/lnY6srA4XFk9QIrdBFWNuAowzCGW0oWqK+9CDP1O0IK7PYwicBSm3F+3aAqHfRoKv9/br5yGK4sOXTLV5HPcltxQ/e4fqFchp6KdtxO8DraMb5VmKSz+/mgYROD5bbf5vb+oPNJjsX/f9DZ9QGm8cLih/6x+Y1l2Ul+MtftSiK36Mptr3SVH94bXT31WcgwUsd+6tzqLXZ+SjLq1nTp3fyU5BzyU9Juu06wRocvf9aV2fKrTM51+W3L6/8D</diagram></mxfile>
|
BIN
wyk/08_Neuronowy_ngramowy_model/trigram1.drawio.png
Normal file
BIN
wyk/08_Neuronowy_ngramowy_model/trigram1.drawio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Loading…
Reference in New Issue
Block a user