Add notebooks for zajecia3

This commit is contained in:
Ryszard Staruch 2024-05-09 11:25:34 +02:00
parent 9c3140fec0
commit f853ab3d68
2 changed files with 409 additions and 0 deletions

68
03_zadania.ipynb Normal file
View File

@ -0,0 +1,68 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Rozwiązania do zadań proszę umieszczać w nowych komórkach pomiędzy zadaniami\n",
"Zadania (jeżeli wymagają napisania programu) piszemy w języku Python\n",
"\n",
"\n",
"Funkcje wspomagające wykonanie zadań znajdują się w materiałach wykładowych:\n",
"\n",
"https://git.wmi.amu.edu.pl/pms/moj-2024/src/branch/main/wyk\n",
"\n",
"oraz dla zajęć 03 bardzo pomocny będzie notebook:\n",
"\n",
"https://git.wmi.amu.edu.pl/filipg/aitech-moj-2023/src/branch/master/wyk/09_Zanurzenia_slow.ipynb"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Zadanie 1 (110 punktów)\n",
"\n",
"Na podstawie zbioru danych z poprzednich zajęć (https://git.wmi.amu.edu.pl/ryssta/moj-2024-ns-cw/src/branch/main/challenging_america_50k_texts.zip) stwórz tetragramowy (czyli wykorzystujący 3 słowa do predykcji czwartego słowa) neuronowy model języka bazujący na zanurzeniach słów. Zadanie proszę wykonać przy użyciu biblioteki torch (warto wykorzystać również bibliotekę torchtext) w języku Python. Kroki wymagane do wykonania zadania:\n",
"\n",
"1. Zamiana wielkich liter na małe oraz usunięcie wszystkich znaków niebędących literami od \"a\" do \"z\" lub spacją - 5 punktów\n",
"2. Stworzenie słownika składającego się z 20000 najczęściej występujących słów + token <unk> dla pozostałych słów (uwaga - token <unk> też posiada swoje zanurzenie) - 5 punktów\n",
"3. Poprawne zaimplementowanie architektury tetragramowego modelu bazującego na zanurzeniach o rozmiarze 200 przyjmującego na wejściu 3 tokeny - 40 punktów.\n",
"4. Wytrenowanie modelu na 3 epokach na całym korpusie z malejącą wartością funkcji straty w czasie trenowania (jeżeli będzie widać, że wartość funkcji straty nie maleje na przestrzeni treningu, to znaczy że coś jest nie tak - wtedy punkty nie zostaną przyznane) - 60 punktów"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Zadanie 2 (40 punktów)\n",
"\n",
"Za pomocą modelu z zadania 1, wygeneruj zdania (bazując na dodawaniu do sekwencji najbardziej prawdopodobnego tokenu) o długości 15 tokenów (słów) bez uwzględniania tokenu <unk> jako potencjalnie kolejny nowy token, zakładając następujące wejście do modelu:\n",
"1. it will be\n",
"2. they went for\n",
"3. (tutaj proszę wybrać samemu 3 słowa ze słownika i przeprowadzić proces generowania sekwencji)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "python39",
"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.18"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,341 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Funkcja build_vocab_from_iterator automatycznie tworzy słownik na podstawie najczęściej występujących słów, jednocześnie traktując pozostałe słowa jako <unk>"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\ryssta\\AppData\\Local\\anaconda3\\envs\\python39\\lib\\site-packages\\torchtext\\vocab\\__init__.py:4: UserWarning: \n",
"/!\\ IMPORTANT WARNING ABOUT TORCHTEXT STATUS /!\\ \n",
"Torchtext is deprecated and the last released version will be 0.18 (this one). You can silence this warning by calling the following at the beginnign of your scripts: `import torchtext; torchtext.disable_torchtext_deprecation_warning()`\n",
" warnings.warn(torchtext._TORCHTEXT_DEPRECATION_MSG)\n",
"c:\\Users\\ryssta\\AppData\\Local\\anaconda3\\envs\\python39\\lib\\site-packages\\torchtext\\utils.py:4: UserWarning: \n",
"/!\\ IMPORTANT WARNING ABOUT TORCHTEXT STATUS /!\\ \n",
"Torchtext is deprecated and the last released version will be 0.18 (this one). You can silence this warning by calling the following at the beginnign of your scripts: `import torchtext; torchtext.disable_torchtext_deprecation_warning()`\n",
" warnings.warn(torchtext._TORCHTEXT_DEPRECATION_MSG)\n"
]
}
],
"source": [
"from torchtext.vocab import build_vocab_from_iterator\n",
"import io\n",
"import zipfile\n",
"import torch\n",
"\n",
"\n",
"with zipfile.ZipFile(\"challenging_america_50k_texts.zip\") as zf:\n",
" with io.TextIOWrapper(zf.open(\"challenging_america_50k_texts.txt\"), encoding=\"utf-8\") as f:\n",
" data = f.readlines()\n",
"\n",
"def get_words_from_line(line):\n",
" line = line.rstrip()\n",
" for t in line.split():\n",
" yield t\n",
"\n",
"\n",
"def get_word_lines_from_list(data):\n",
" for line in data:\n",
" yield get_words_from_line(line)\n",
"\n",
"vocab_size = 3000\n",
"vocab = build_vocab_from_iterator(\n",
" get_word_lines_from_list(data),\n",
" max_tokens = vocab_size,\n",
" specials = ['<unk>'])\n",
"vocab.set_default_index(vocab['<unk>'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Dostęp do par słowo, indeks ze słownika"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<unk> 0\n",
"witness 1755\n",
"Supreme 2520\n",
"seems 577\n",
"her 51\n",
"! 503\n",
"were 40\n",
"Messrs. 1911\n",
"small 282\n",
"council 2064\n",
"but 35\n"
]
}
],
"source": [
"vocab_dict = vocab.get_stoi()\n",
"for x, key in enumerate(vocab_dict):\n",
" print(key, vocab_dict[key])\n",
" if x == 10:\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Słownik dla podanego słowa w postaci stringa zwraca indeks w słowniku, który będzie wykorzystywany przez sieć neuronową (słowa nie znajdujące się w słowniku mapowane są na token unk, który posiada indeks 0 - zostało to zdefiniowane poprzez metodę vocab.set_default_index(vocab['&lt;unk>']))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5\n",
"1\n",
"208\n",
"0\n",
"0\n",
"Dla listy słów:\n",
"[5, 1]\n"
]
}
],
"source": [
"print(vocab[\"a\"])\n",
"print(vocab[\"the\"])\n",
"print(vocab[\"John\"])\n",
"print(vocab[\"awnifnawonf\"])\n",
"print(vocab[\"Poznań\"])\n",
"\n",
"print(\"Dla listy słów:\")\n",
"print(vocab.lookup_indices([\"a\", \"the\"]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Operacja odwrota (czyli odczytanie słowa na podstawie indeksu)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"the\n",
"attempt\n",
"Dla listy indeksów:\n",
"['<unk>', 'the', 'attempt', 'drew']\n"
]
}
],
"source": [
"print(vocab.lookup_token(1))\n",
"print(vocab.lookup_token(1000))\n",
"\n",
"print(\"Dla listy indeksów:\")\n",
"print(vocab.lookup_tokens([0, 1, 1000, 2000]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Aby przekazać dane słowo (lub słowa) do sieci neuronowej, należy utworzyć na podstawie indeksu danego słowa Tensor"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor(1)\n",
"tensor([ 1, 2020])\n"
]
}
],
"source": [
"input_to_neural_network = torch.tensor(vocab[\"the\"])\n",
"print(input_to_neural_network)\n",
"\n",
"input_to_neural_network = torch.tensor(vocab.lookup_indices([\"the\", \"current\"]))\n",
"print(input_to_neural_network)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Zanurzenia słów uzyskujemy poprzez wykorzystanie warstwy torch.nn.Embedding"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Uzyskanie wartości embeddingów dla tokenu o indeksie 1 oraz tokenu o indeksie 5\n",
"tensor([[-1.0945, -0.1461, 1.2927],\n",
" [-0.0303, 0.5213, 1.1486]], grad_fn=<EmbeddingBackward0>)\n",
"##########################################################\n",
"Uzyskanie wartości embeddingów dla batcha z tokenami\n",
"tensor([[[-1.0945, -0.1461, 1.2927],\n",
" [ 0.2963, 0.1083, 0.0797]],\n",
"\n",
" [[-0.9783, 1.1639, 0.3828],\n",
" [ 1.1856, 1.1943, -0.5562]],\n",
"\n",
" [[-0.3472, 0.5670, -1.2830],\n",
" [-1.0945, -0.1461, 1.2927]]], grad_fn=<EmbeddingBackward0>)\n"
]
}
],
"source": [
"vocab_size = 10\n",
"embedding_size = 3\n",
"embedding_layer = torch.nn.Embedding(vocab_size, embedding_size)\n",
"input_to_embedding_layer = torch.IntTensor([1, 5])\n",
"print(\"Uzyskanie wartości embeddingów dla tokenu o indeksie 1 oraz tokenu o indeksie 5\")\n",
"print(embedding_layer((input_to_embedding_layer)))\n",
"\n",
"batched_input_to_embedding_layer = torch.IntTensor([[1, 4],\n",
" [2, 9],\n",
" [3, 1]])\n",
"print(\"##########################################################\")\n",
"print(\"Uzyskanie wartości embeddingów dla batcha z tokenami\")\n",
"print(embedding_layer((batched_input_to_embedding_layer)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Aby połączyć ze sobą zanurzenia kilku słów (podczas trenowania modelu ngramowego innego niż unigramowy/bigramowy), należy użyć konkatenacji. W torchu do tego wykorzystujemy funkcję torch.cat"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([0.5000, 0.2000, 0.2000, 0.9100, 0.9200, 0.9300])\n"
]
}
],
"source": [
"first_embedding = torch.Tensor([0.5, 0.2, 0.2])\n",
"second_embedding = torch.Tensor([0.91, 0.92, 0.93])\n",
"\n",
"concatenated_embeddings = torch.cat([first_embedding, second_embedding])\n",
"print(concatenated_embeddings)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### W przypadku korzystania z batchy musimy zwrócić uwagę na właściwą oś (axis) po której będziemy dokonywać konkatenacji"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Nieprawidłowa konkatenacja embeddingów (stworzenie 4 tensorów o wymiarze 3, zamiast 2 tensorów o wymiarze 6)\n",
"tensor([[0.5000, 0.2000, 0.2000],\n",
" [0.5100, 0.2100, 0.2100],\n",
" [0.9100, 0.9200, 0.9300],\n",
" [0.9110, 0.9220, 0.9330]])\n",
"#########################################################################\n",
"Prawidłowa konkatenacja embeddingów dzięki właściwej wartości parametru axis\n",
"Wtedy pierwsze 3 wartości (czyli dla pierwszego Tensora są to wartości 0.5000, 0.2000, 0.2000) reprezentują embedding pierwszego słowa\n",
"a kolejne 3 wartości reprezentują embedding drugiego słowa (czyli 0.9100, 0.9200, 0.9300)\n",
"tensor([[0.5000, 0.2000, 0.2000, 0.9100, 0.9200, 0.9300],\n",
" [0.5100, 0.2100, 0.2100, 0.9110, 0.9220, 0.9330]])\n"
]
}
],
"source": [
"first_batched_embedding = torch.Tensor([[0.5, 0.2, 0.2], \n",
" [0.51, 0.21, 0.21]])\n",
"second_batched_embedding = torch.Tensor([[0.91, 0.92, 0.93],\n",
" [0.911, 0.922, 0.933]])\n",
"\n",
"concatenated_embeddings = torch.cat([first_batched_embedding, second_batched_embedding])\n",
"print(\"Nieprawidłowa konkatenacja embeddingów (stworzenie 4 tensorów o wymiarze 3, zamiast 2 tensorów o wymiarze 6)\")\n",
"print(concatenated_embeddings)\n",
"\n",
"properly_concatenated_embeddings = torch.cat([first_batched_embedding, second_batched_embedding], axis=1)\n",
"\n",
"print(\"#########################################################################\")\n",
"print(\"Prawidłowa konkatenacja embeddingów dzięki właściwej wartości parametru axis\")\n",
"print(\"Wtedy pierwsze 3 wartości (czyli dla pierwszego Tensora są to wartości 0.5000, 0.2000, 0.2000) reprezentują embedding pierwszego słowa\")\n",
"print(\"a kolejne 3 wartości reprezentują embedding drugiego słowa (czyli 0.9100, 0.9200, 0.9300)\")\n",
"print(properly_concatenated_embeddings)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "python39",
"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.18"
}
},
"nbformat": 4,
"nbformat_minor": 2
}