Add notebooks for zajecia3
This commit is contained in:
parent
9c3140fec0
commit
f853ab3d68
68
03_zadania.ipynb
Normal file
68
03_zadania.ipynb
Normal 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
|
||||
}
|
341
03_zadania_helpful_codeblocks.ipynb
Normal file
341
03_zadania_helpful_codeblocks.ipynb
Normal 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['<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
|
||||
}
|
Loading…
Reference in New Issue
Block a user