\n",
"\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Neuronowy n-gramowy model języka\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Omówiony w poprzedniej części neuronowy bigramowy model języka\n",
"warunkuje kolejny wyraz jedynie względem bezpośrednio poprzedzającego\n",
"— jak w każdym bigramowym modelu przyjmujemy założenie, że $w_i$\n",
"zależy tylko od $w_{i-1}$. Rzecz jasna jest to bardzo duże\n",
"ograniczenie, w rzeczywistości bardzo często prawdopodobieństwo\n",
"kolejnego wyrazu zależy od wyrazu dwie, trzy, cztery itd. pozycje\n",
"wstecz czy w ogólności od wszystkich wyrazów poprzedzających (bez\n",
"względu na ich pozycje).\n",
"\n",
"**Pytanie**: Wskaż zależności o zasięgu większym niż 1 wyraz w zdaniu\n",
"/Zatopieni w kłębach dymu cygar i pochyleni nad butelkami z ciemnego\n",
"szkła obywatele tej dzielnicy, jedni zakładali się o wygranę lub\n",
"przegranę Anglii, drudzy o bankructwo Wokulskiego; jedni nazywali\n",
"geniuszem Bismarcka, drudzy — awanturnikiem Wokulskiego; jedni\n",
"krytykowali postępowanie prezydenta MacMahona, inni twierdzili, że\n",
"Wokulski jest zdecydowanym wariatem, jeżeli nie czymś gorszym…/\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Trigramowy neuronowy model języka\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Spróbujmy najpierw rozszerzyć nasz model na trigramy, to znaczy\n",
"będziemy przewidywać słowo $w_i$ na podstawie słów $w_{i-2}$ i\n",
"$w_{i-1}$.\n",
"\n",
"Najprostsze rozwiązanie polegałoby na zanurzeniu pary $(w_{i-2},\n",
"w_{i-1})$ w całości i postępowaniu jak w przypadku modelu bigramowego.\n",
"Byłoby to jednak zupełnie niepraktyczne, jako że:\n",
"\n",
"- liczba zanurzeń do wyuczenia byłaby olbrzymia ($|V|^2$ — byłoby to\n",
" ewentualnie akceptowalne dla modeli operujących na krótszych\n",
" jednostkach niż słowa, np. na znakach),\n",
"- w szczególności zanurzenia dla par $(v, u)$, $(u, v)$, $(u, u)$ i\n",
" $(v, v)$ nie miałyby ze sobą nic wspólnego.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Konketanacja zanurzeń\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Właściwsze rozwiązanie polega na zanurzeniu dalej pojedynczych słów i\n",
"następnie ich **konkatenowaniu**.\n",
"\n",
"Przypomnijmy, że konkatenacja wektorów $\\vec{x_1}$ i $\\vec{x_2}$ to wektor o rozmiarze\n",
"$|\\vec{x_1}| + |\\vec{x_2}|$ powstały ze „sklejania” wektorów $\\vec{x_1}$ i $\\vec{x_2}$.\n",
"Konkatenację wektorów $\\vec{x_1}$ i $\\vec{x_2}$ będziemy oznaczać za pomocą $[\\vec{x_1}, \\vec{x_2}]$.\n",
"\n",
"Przykład: jeśli $\\vec{x_1} = [-1, 2, 0]$ i $\\vec{x_2} = [3, -3]$,\n",
"wówczas $[\\vec{x_1}, \\vec{x_2}] = [-1, 2, 0, 3, -3]$\n",
"\n",
"Oznacza to, że nasza macierz „kontekstowa” $C$ powinna mieć w modelu trigramowym rozmiar nie\n",
"$|V| \\times m$, lecz $|V| \\times (m+m)$ = $|V| \\times 2m$ i wyjście będzie zdefiniowane za pomocą wzoru:\n",
"\n",
"$$\\vec{y} = \\operatorname{softmax}(C[E(w_{i-2}),E(w_{i-1})]),$$\n",
"\n",
"co można przedstawić za pomocą następującego schematu:\n",
"\n",
"![img](./08_Neuronowy_ngramowy_model/trigram1.drawio.png \"Diagram prostego bigramowego neuronowego modelu języka\")\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Rozbicie macierzy $C$\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Zamiast mnożyć macierz $C$ przez konkatenację dwóch wektorów, można\n",
"rozbić macierz $C$ na dwie, powiedzmy $C_{-2}$ i $C_{-1}$, przemnażać\n",
"je osobno przez odpowiadające im wektory i następnie **dodać** macierze,\n",
"tak aby:\n",
"\n",
"$$C[E(w_{i-2}),E(w_{i-1})] = C_{-2}E(w_{i-2}) + C_{-1}E(w_{i-1}).$$\n",
"\n",
"Macierze $C_{-2}$ i $C_{-1}$ będą miały rozmiar $|V| \\times m$.\n",
"\n",
"Przy tym podejściu możemy powiedzieć, że ostatni i przedostatni wyraz\n",
"mają swoje osobne macierze o potencjalnie różnych wagach — co ma sens,\n",
"jako że na inne aspekty zwracamy uwagę przewidując kolejne słowo na\n",
"podstawie wyrazu bezpośrednio poprzedzającego, a na inne — na\n",
"podstawie słowa występującego dwie pozycje wcześniej.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Uogólnienie na $n$-gramowy model języka dla dowolnego $n$\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Łatwo uogólnić opisany wyżej trigramowy model języka dla dowolnego $n$.\n",
"Uogólniony model można przedstawić za pomocą wzoru:\n",
"\n",
"$$\\vec{y} = \\operatorname{softmax}(C[E(w_{i-n+1}),\\dots,E(w_{i-1})]),$$\n",
"\n",
"gdzie macierz $C$ ma rozmiar $|V| \\times nm$ lub za pomocą wzoru:\n",
"\n",
"$$\\vec{y} = \\operatorname{softmax}(C_{-(n-1)}E(w_{i-n+1}) + \\dots + C_{-1}E(w_{i-1}),$$\n",
"\n",
"gdzie macierze $C_{-(n-1)}$, …, $C_{-1}$ mają rozmiary $|V| \\times m$.\n",
"\n",
"Por. diagram:\n",
"\n",
"![img](./08_Neuronowy_ngramowy_model/ngram.drawio.png \"Diagram prostego n-gramowego neuronowego modelu języka\")\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Dodanie kolejnej warstwy\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"W wypadku trigramowego czy — ogólniej — n-gramowego modelu języka dla\n",
"$n \\geq 3$ warto dodać kolejną (**ukrytą**) warstwę, na którą będziemy rzutować\n",
"skonkatenowane embeddingi, zanim zrzutujemy je do długiego wektora\n",
"prawdopodobieństw.\n",
"\n",
"Zakładamy, że warstwa ukryta zawiera $h$ neuronów. Wartość $h$ powinna być mniejsza\n",
"niż $nm$ (a może nawet od $m$).\n",
"\n",
"**Pytanie**: Dlaczego wartość $h > nm$ nie jest racjonalnym wyborem?\n",
"\n",
"**Pytanie**: Dlaczego dodanie kolejnej warstwy nie ma sensu dla modelu bigramowego?\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Funkcja aktywacji\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aby warstwa ukryta wnosiła coś nowego, na wyjściu z tej funkcji musimy (dlaczego?)\n",
"zastosować nieliniową **funkcji aktywacji**. Zazwyczaj jako funkcji\n",
"aktywacji w sieciach neuronowych używa się funkcji ReLU albo funkcji\n",
"sigmoidalnej. W prostych neuronowych modelach języka sprawdza się też\n",
"**tangens hiperboliczny** (tgh, w literaturze anglojęzycznej tanh):\n",
"\n",
"$$\\operatorname{tgh}(x) = \\frac{e^x - e^{-x}}{e^x + e^{-x}}.$$\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/media/kuba/ssdsam/anaconda3/envs/lmzajecia/lib/python3.10/site-packages/torch/nn/functional.py:1933: UserWarning: nn.functional.tanh is deprecated. Use torch.tanh instead.\n",
" warnings.warn(\"nn.functional.tanh is deprecated. Use torch.tanh instead.\")\n"
]
},
{
"data": {
"text/plain": [
"'08_Neuronowy_ngramowy_model/tanh.png'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"