aitech-moj-2023/wyk/10_Neuronowy_ngramowy_model.ipynb

370 lines
23 KiB
Plaintext
Raw Normal View History

2022-07-06 08:18:08 +02:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Modelowanie języka</h1>\n",
"<h2> 10. <i>Neuronowy n-gramowy model języka</i> [wykład]</h2> \n",
"<h3> Filip Graliński (2022)</h3>\n",
"</div>\n",
"\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)\n",
"\n"
]
},
2022-07-06 08:28:27 +02:00
{
"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](./10_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)}$, &hellip;, $C_{-1}$ mają rozmiary $|V| \\times m$.\n",
"\n",
"Por. diagram:\n",
"\n",
"![img](./10_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": 1,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<matplotlib.figure.Figure>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import torch\n",
"import torch.nn as nn\n",
"\n",
"x = torch.linspace(-5,5,100)\n",
"plt.xlabel(\"x\")\n",
"plt.ylabel(\"y\")\n",
"a = torch.Tensor(x.size()[0]).fill_(2.)\n",
"m = torch.stack([x, a])\n",
"plt.plot(x, nn.functional.tanh(m)[0])\n",
"fname = '10_Neuronowy_ngramowy_model/tanh.png'\n",
"plt.savefig(fname)\n",
"fname"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Tangens hiperboliczny zastosowany dla wektora\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tangens hiperboliczny wektora będzie po prostu wektorem tangensów\n",
"hiperbolicznych poszczególnych wartości.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import torch.nn as nn\n",
"\n",
"v = torch.Tensor([-100, -2.0, 0.0, 0.5, 1000.0])\n",
"nn.functional.tanh(v)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[[tensor](tensor)([-1.0000, -0.9640, 0.0000, 0.4621, 1.0000])]]\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Wzór i schemat dwuwarstwowego n-gramowego neuronowego modelu języka\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dwuwarstwowy model języka będzie określony następującym wzorem:\n",
"\n",
"$$\\vec{y} = \\operatorname{softmax}(C\\operatorname{tgh}(W[E(w_{i-n+1}),\\dots,E(w_{i-1})])),$$\n",
"\n",
"gdzie:\n",
"\n",
"- $W$ jest wyuczalną macierzą wag o rozmiarze $h \\times nm$,\n",
"- $C$ będzie macierzą o rozmiarze $|V| \\times h$.\n",
"\n",
"Zmodyfikowaną sieć można przedstawić za pomocą następującego schematu:\n",
"\n",
"![img](./10_Neuronowy_ngramowy_model/ngram-tgh.drawio.png \"Dwuwarstwowy n-gramowy neuronowy model języka\")\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Liczba wag w modelu dwuwarstwowym\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Na wagi w modelu dwuwarstwowym składają się:\n",
"\n",
"- zanurzenia: $m|V|$,\n",
"- wagi warstwy ukrytej: $hnm$,\n",
"- wagi warstwy wyjściowej: $|V|h$,\n",
"\n",
"a zatem łącznie:\n",
"\n",
"$$m|V| + hnm + |V|h$$\n",
"\n",
"Jeśli $h \\approx m$ (co jest realistyczną opcją), wówczas otrzymamy oszacowanie:\n",
"\n",
"$$O(m|V| + nm^2).$$\n",
"\n",
"Zauważmy, że względem $n$ oznacza to bardzo korzystną złożoność\n",
"$O(n)$! Oznacza to, że nasz model może działać dla dużo większych\n",
"wartości $n$ niż tradycyjny, statystyczny n-gramowy model języka (dla którego\n",
"wartości $n > 5$ zazwyczaj nie mają sensu).\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.5"
},
"org": null
},
"nbformat": 4,
"nbformat_minor": 1
}