AI-For-Beginners/translations/sk/lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb

492 lines
27 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Generatívne siete\n",
"\n",
"Rekurentné neurónové siete (RNN) a ich varianty s bránkovými bunkami, ako sú bunky s dlhodobou a krátkodobou pamäťou (LSTMs) a bránkové rekurentné jednotky (GRUs), poskytujú mechanizmus na modelovanie jazyka, t.j. dokážu sa naučiť poradie slov a poskytovať predpovede pre nasledujúce slovo v sekvencii. To nám umožňuje používať RNN pre **generatívne úlohy**, ako je bežná generácia textu, strojový preklad a dokonca aj popisovanie obrázkov.\n",
"\n",
"V architektúre RNN, ktorú sme diskutovali v predchádzajúcej jednotke, každá jednotka RNN produkovala ako výstup nasledujúci skrytý stav. Avšak môžeme tiež pridať ďalší výstup ku každej rekurentnej jednotke, čo nám umožní generovať **sekvenciu** (ktorá má rovnakú dĺžku ako pôvodná sekvencia). Navyše môžeme použiť jednotky RNN, ktoré neprijímajú vstup na každom kroku, ale len berú nejaký počiatočný stavový vektor a potom produkujú sekvenciu výstupov.\n",
"\n",
"V tomto notebooku sa zameriame na jednoduché generatívne modely, ktoré nám pomáhajú generovať text. Pre jednoduchosť vytvorme **sieť na úrovni znakov**, ktorá generuje text písmeno po písmene. Počas tréningu musíme vziať nejaký textový korpus a rozdeliť ho na sekvencie písmen.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"import tensorflow_datasets as tfds\n",
"import numpy as np\n",
"\n",
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vytváranie slovníka znakov\n",
"\n",
"Na vytvorenie generatívnej siete na úrovni znakov je potrebné rozdeliť text na jednotlivé znaky namiesto slov. Vrstva `TextVectorization`, ktorú sme používali predtým, to nedokáže, takže máme dve možnosti:\n",
"\n",
"* Ručne načítať text a vykonať tokenizáciu „ručne“, ako je uvedené v [tomto oficiálnom príklade Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/)\n",
"* Použiť triedu `Tokenizer` na tokenizáciu na úrovni znakov.\n",
"\n",
"Zvolíme druhú možnosť. `Tokenizer` sa dá použiť aj na tokenizáciu do slov, takže by malo byť pomerne jednoduché prepnúť z tokenizácie na úrovni znakov na tokenizáciu na úrovni slov.\n",
"\n",
"Na vykonanie tokenizácie na úrovni znakov je potrebné odovzdať parameter `char_level=True`:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def extract_text(x):\n",
" return x['title']+' '+x['description']\n",
"\n",
"def tupelize(x):\n",
" return (extract_text(x),x['label'])\n",
"\n",
"tokenizer = keras.preprocessing.text.Tokenizer(char_level=True,lower=False)\n",
"tokenizer.fit_on_texts([x['title'].numpy().decode('utf-8') for x in ds_train])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Chceme tiež použiť jeden špeciálny token na označenie **konca sekvencie**, ktorý nazveme `<eos>`. Pridajme ho manuálne do slovníka:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"eos_token = len(tokenizer.word_index)+1\n",
"tokenizer.word_index['<eos>'] = eos_token\n",
"\n",
"vocab_size = eos_token + 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[48, 2, 10, 10, 5, 44, 1, 25, 5, 8, 10, 13, 78]]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer.texts_to_sequences(['Hello, world!'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Trénovanie generatívnej RNN na generovanie nadpisov\n",
"\n",
"Spôsob, akým budeme trénovať RNN na generovanie nadpisov správ, je nasledovný. V každom kroku vezmeme jeden nadpis, ktorý bude poskytnutý RNN, a pre každý vstupný znak požiadame sieť, aby vygenerovala nasledujúci výstupný znak:\n",
"\n",
"![Obrázok zobrazujúci príklad generovania slova 'HELLO' pomocou RNN.](../../../../../translated_images/sk/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"Pre posledný znak našej sekvencie požiadame sieť, aby vygenerovala token `<eos>`.\n",
"\n",
"Hlavný rozdiel medzi generatívnou RNN, ktorú tu používame, je ten, že vezmeme výstup z každého kroku RNN, a nie len z poslednej bunky. To je možné dosiahnuť nastavením parametra `return_sequences` pre bunku RNN.\n",
"\n",
"Takže počas trénovania bude vstupom do siete sekvencia zakódovaných znakov určitej dĺžky a výstupom bude sekvencia rovnakej dĺžky, ale posunutá o jeden prvok a ukončená tokenom `<eos>`. Minibatch bude pozostávať z viacerých takýchto sekvencií, a bude potrebné použiť **padding**, aby sa všetky sekvencie zarovnali.\n",
"\n",
"Vytvorme funkcie, ktoré nám transformujú dataset. Pretože chceme sekvencie dopĺňať na úrovni minibatchu, najskôr dataset zoskupíme pomocou `.batch()`, a potom ho upravíme pomocou `map`, aby sme vykonali transformáciu. Transformačná funkcia teda bude brať celý minibatch ako parameter:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def title_batch(x):\n",
" x = [t.numpy().decode('utf-8') for t in x]\n",
" z = tokenizer.texts_to_sequences(x)\n",
" z = tf.keras.preprocessing.sequence.pad_sequences(z)\n",
" return tf.one_hot(z,vocab_size), tf.one_hot(tf.concat([z[:,1:],tf.constant(eos_token,shape=(len(z),1))],axis=1),vocab_size)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Niekoľko dôležitých vecí, ktoré tu robíme:\n",
"* Najskôr extrahujeme skutočný text zo stringového tenzora\n",
"* `text_to_sequences` konvertuje zoznam reťazcov na zoznam celočíselných tenzorov\n",
"* `pad_sequences` doplní tieto tenzory na ich maximálnu dĺžku\n",
"* Nakoniec všetky znaky zakódujeme pomocou one-hot kódovania, a tiež vykonáme posun a pridanie `<eos>`. Čoskoro uvidíme, prečo potrebujeme znaky zakódované pomocou one-hot.\n",
"\n",
"Táto funkcia je však **Pythonická**, t.j. nemôže byť automaticky preložená do výpočtového grafu Tensorflow. Ak sa pokúsime použiť túto funkciu priamo vo funkcii `Dataset.map`, dostaneme chyby. Musíme túto Pythonickú výzvu obaliť použitím obalu `py_function`:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def title_batch_fn(x):\n",
" x = x['title']\n",
" a,b = tf.py_function(title_batch,inp=[x],Tout=(tf.float32,tf.float32))\n",
" return a,b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Poznámka**: Rozlíšiť medzi Pythonickými a Tensorflow transformačnými funkciami sa môže zdať príliš zložité, a možno sa pýtate, prečo dataset netransformujeme pomocou štandardných Python funkcií predtým, ako ho odovzdáme do `fit`. Aj keď to určite možné je, použitie `Dataset.map` má obrovskú výhodu, pretože dátová transformačná pipeline je vykonávaná pomocou Tensorflow výpočtového grafu, ktorý využíva výpočty na GPU a minimalizuje potrebu prenášať dáta medzi CPU a GPU.\n",
"\n",
"Teraz môžeme vytvoriť našu generátorovú sieť a začať trénovať. Môže byť založená na akejkoľvek rekurentnej bunke, ktorú sme preberali v predchádzajúcej jednotke (jednoduchá, LSTM alebo GRU). V našom príklade použijeme LSTM.\n",
"\n",
"Keďže sieť prijíma znaky ako vstup a veľkosť slovníka je pomerne malá, nepotrebujeme embedding vrstvu, jednohotovo zakódovaný vstup môže ísť priamo do LSTM bunky. Výstupná vrstva bude `Dense` klasifikátor, ktorý premení výstup LSTM na jednohotovo zakódované čísla tokenov.\n",
"\n",
"Okrem toho, keďže pracujeme so sekvenciami s premenlivou dĺžkou, môžeme použiť vrstvu `Masking` na vytvorenie masky, ktorá bude ignorovať doplnené časti reťazca. Toto nie je striktne potrebné, pretože nás veľmi nezaujíma všetko, čo presahuje token `<eos>`, ale použijeme to kvôli získaniu skúseností s týmto typom vrstvy. `input_shape` bude `(None, vocab_size)`, kde `None` označuje sekvenciu s premenlivou dĺžkou, a výstupný tvar je taktiež `(None, vocab_size)`, ako môžete vidieť zo `summary`:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"masking (Masking) (None, None, 84) 0 \n",
"_________________________________________________________________\n",
"lstm (LSTM) (None, None, 128) 109056 \n",
"_________________________________________________________________\n",
"dense (Dense) (None, None, 84) 10836 \n",
"=================================================================\n",
"Total params: 119,892\n",
"Trainable params: 119,892\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n",
"15000/15000 [==============================] - 229s 15ms/step - loss: 1.5385\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7fa40c1245e0>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.Masking(input_shape=(None,vocab_size)),\n",
" keras.layers.LSTM(128,return_sequences=True),\n",
" keras.layers.Dense(vocab_size,activation='softmax')\n",
"])\n",
"\n",
"model.summary()\n",
"model.compile(loss='categorical_crossentropy')\n",
"\n",
"model.fit(ds_train.batch(8).map(title_batch_fn))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generovanie výstupu\n",
"\n",
"Teraz, keď sme model natrénovali, chceme ho použiť na generovanie výstupu. V prvom rade potrebujeme spôsob, ako dekódovať text reprezentovaný sekvenciou čísel tokenov. Na tento účel by sme mohli použiť funkciu `tokenizer.sequences_to_texts`; tá však nefunguje dobre s tokenizáciou na úrovni znakov. Preto si vezmeme slovník tokenov z tokenizéra (nazývaný `word_index`), vytvoríme reverznú mapu a napíšeme si vlastnú dekódovaciu funkciu:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"reverse_map = {val:key for key, val in tokenizer.word_index.items()}\n",
"\n",
"def decode(x):\n",
" return ''.join([reverse_map[t] for t in x])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Teraz začneme generovanie. Začneme s nejakým reťazcom `start`, zakódujeme ho do sekvencie `inp`, a potom v každom kroku zavoláme našu sieť, aby sme odvodili nasledujúci znak.\n",
"\n",
"Výstup siete `out` je vektor s `vocab_size` prvkami, ktoré predstavujú pravdepodobnosti každého tokenu, a najpravdepodobnejší token môžeme nájsť pomocou `argmax`. Tento znak potom pridáme do generovaného zoznamu tokenov a pokračujeme v generovaní. Tento proces generovania jedného znaku sa opakuje `size` krát, aby sme vygenerovali požadovaný počet znakov, a predčasne ukončíme, keď sa objaví `eos_token`.\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Today #39;s lead to strike for the strike for the strike for the strike (AFP)'"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def generate(model,size=100,start='Today '):\n",
" inp = tokenizer.texts_to_sequences([start])[0]\n",
" chars = inp\n",
" for i in range(size):\n",
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
" nc = tf.argmax(out)\n",
" if nc==eos_token:\n",
" break\n",
" chars.append(nc.numpy())\n",
" inp = inp+[nc]\n",
" return decode(chars)\n",
" \n",
"generate(model)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vzorkovanie výstupu počas tréningu\n",
"\n",
"Keďže nemáme žiadne užitočné metriky, ako napríklad *presnosť*, jediný spôsob, ako môžeme vidieť, že náš model sa zlepšuje, je **vzorkovanie** generovaného reťazca počas tréningu. Na tento účel použijeme **callbacky**, teda funkcie, ktoré môžeme odovzdať funkcii `fit` a ktoré budú pravidelne volané počas tréningu.\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/3\n",
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.2703\n",
"Today #39;s a lead in the company for the strike\n",
"Epoch 2/3\n",
"15000/15000 [==============================] - 227s 15ms/step - loss: 1.2057\n",
"Today #39;s the Market Service on Security Start (AP)\n",
"Epoch 3/3\n",
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.1752\n",
"Today #39;s a line on the strike to start for the start\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7fa40c74e3d0>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sampling_callback = keras.callbacks.LambdaCallback(\n",
" on_epoch_end = lambda batch, logs: print(generate(model))\n",
")\n",
"\n",
"model.fit(ds_train.batch(8).map(title_batch_fn),callbacks=[sampling_callback],epochs=3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tento príklad už generuje pomerne dobrý text, ale dá sa ešte vylepšiť viacerými spôsobmi:\n",
"* **Viac textu**. Použili sme iba nadpisy pre našu úlohu, ale môžete experimentovať s plným textom. Pamätajte, že RNN nie sú príliš dobré pri spracovaní dlhých sekvencií, takže má zmysel buď rozdeliť text na kratšie vety, alebo vždy trénovať na pevnej dĺžke sekvencie s nejakou preddefinovanou hodnotou `num_chars` (napríklad 256). Môžete skúsiť zmeniť vyššie uvedený príklad na takúto architektúru, pričom sa môžete inšpirovať [oficiálnym tutoriálom Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/).\n",
"* **Viacvrstvové LSTM**. Má zmysel vyskúšať 2 alebo 3 vrstvy LSTM buniek. Ako sme spomenuli v predchádzajúcej jednotke, každá vrstva LSTM extrahuje určité vzory z textu, a v prípade generátora na úrovni znakov môžeme očakávať, že nižšia úroveň LSTM bude zodpovedná za extrahovanie slabík, a vyššie úrovne - za slová a kombinácie slov. Toto sa dá jednoducho implementovať pomocou parametra počtu vrstiev v konštruktore LSTM.\n",
"* Môžete tiež experimentovať s **GRU jednotkami** a zistiť, ktoré fungujú lepšie, a s **rôznymi veľkosťami skrytých vrstiev**. Príliš veľká skrytá vrstva môže viesť k pretrénovaniu (napr. sieť sa naučí presný text), a menšia veľkosť nemusí produkovať dobrý výsledok.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generovanie mäkkého textu a teplota\n",
"\n",
"V predchádzajúcej definícii `generate` sme vždy vyberali znak s najvyššou pravdepodobnosťou ako nasledujúci znak v generovanom texte. To malo za následok, že text často \"cykloval\" medzi rovnakými sekvenciami znakov znova a znova, ako v tomto príklade:\n",
"```\n",
"today of the second the company and a second the company ...\n",
"```\n",
"\n",
"Ak sa však pozrieme na rozdelenie pravdepodobností pre nasledujúci znak, môže sa stať, že rozdiel medzi niekoľkými najvyššími pravdepodobnosťami nie je veľký, napríklad jeden znak môže mať pravdepodobnosť 0,2, iný 0,19 atď. Napríklad pri hľadaní nasledujúceho znaku v sekvencii '*play*' môže byť nasledujúcim znakom rovnako dobre medzera alebo **e** (ako v slove *player*).\n",
"\n",
"To nás vedie k záveru, že nie je vždy \"spravodlivé\" vybrať znak s vyššou pravdepodobnosťou, pretože výber druhého najvyššieho môže stále viesť k zmysluplnému textu. Je rozumnejšie **vzorkovať** znaky z rozdelenia pravdepodobností, ktoré poskytuje výstup siete.\n",
"\n",
"Toto vzorkovanie je možné vykonať pomocou funkcie `np.multinomial`, ktorá implementuje takzvané **multinomiálne rozdelenie**. Funkcia, ktorá implementuje toto **mäkké** generovanie textu, je definovaná nižšie:\n"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- Temperature = 0.3\n",
"Today #39;s strike #39; to start at the store return\n",
"On Sunday PO to Be Data Profit Up (Reuters)\n",
"Moscow, SP wins straight to the Microsoft #39;s control of the space start\n",
"President olding of the blast start for the strike to pay &lt;b&gt;...&lt;/b&gt;\n",
"Little red riding hood ficed to the spam countered in European &lt;b&gt;...&lt;/b&gt;\n",
"\n",
"--- Temperature = 0.8\n",
"Today countie strikes ryder missile faces food market blut\n",
"On Sunday collores lose-toppy of sale of Bullment in &lt;b&gt;...&lt;/b&gt;\n",
"Moscow, IBM Diffeiting in Afghan Software Hotels (Reuters)\n",
"President Ol Luster for Profit Peaced Raised (AP)\n",
"Little red riding hood dace on depart talks #39; bank up\n",
"\n",
"--- Temperature = 1.0\n",
"Today wits House buiting debate fixes #39; supervice stake again\n",
"On Sunday arling digital poaching In for level\n",
"Moscow, DS Up 7, Top Proble Protest Caprey Mamarian Strike\n",
"President teps help of roubler stepted lessabul-Dhalitics (AFP)\n",
"Little red riding hood signs on cash in Carter-youb\n",
"\n",
"--- Temperature = 1.3\n",
"Today wits flawer ro, pSIA figat's co DroftwavesIs Talo up\n",
"On Sunday hround elitwing wint EU Powerburlinetien\n",
"Moscow, Bazz #39;s sentries olymen winnelds' next for Olympite Huc?\n",
"President lost securitys from power Elections in Smiltrials\n",
"Little red riding hood vides profit, exponituity, profitmainalist-at said listers\n",
"\n",
"--- Temperature = 1.8\n",
"Today #39;It: He deat: N.KA Asside\n",
"On Sunday i arry Par aldeup patient Wo stele1\n"
]
},
{
"ename": "KeyError",
"evalue": "0",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"\\n--- Temperature = {i}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerate_soft\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m300\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mstart\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwords\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtemperature\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36mgenerate_soft\u001b[0;34m(model, size, start, temperature)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mchars\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0minp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minp\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchars\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mwords\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'Today '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'On Sunday '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Moscow, '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'President '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Little red riding hood '\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m: 0"
]
}
],
"source": [
"def generate_soft(model,size=100,start='Today ',temperature=1.0):\n",
" inp = tokenizer.texts_to_sequences([start])[0]\n",
" chars = inp\n",
" for i in range(size):\n",
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
" probs = tf.exp(tf.math.log(out)/temperature).numpy().astype(np.float64)\n",
" probs = probs/np.sum(probs)\n",
" nc = np.argmax(np.random.multinomial(1,probs,1))\n",
" if nc==eos_token:\n",
" break\n",
" chars.append(nc)\n",
" inp = inp+[nc]\n",
" return decode(chars)\n",
"\n",
"words = ['Today ','On Sunday ','Moscow, ','President ','Little red riding hood ']\n",
" \n",
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
" print(f\"\\n--- Temperature = {i}\")\n",
" for j in range(5):\n",
" print(generate_soft(model,size=300,start=words[j],temperature=i))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Zaviedli sme ďalší parameter nazývaný **teplota**, ktorý sa používa na určenie, ako striktne by sme sa mali držať najvyššej pravdepodobnosti. Ak je teplota 1.0, vykonávame spravodlivé multinomiálne vzorkovanie, a keď teplota dosiahne nekonečno - všetky pravdepodobnosti sa stanú rovnakými a náhodne vyberáme ďalší znak. V príklade nižšie môžeme pozorovať, že text sa stáva nezmyselným, keď príliš zvýšime teplotu, a pripomína „cyklický“ ťažko generovaný text, keď sa teplota blíži k 0.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Upozornenie**: \nTento dokument bol preložený pomocou služby AI prekladu [Co-op Translator](https://github.com/Azure/co-op-translator). Hoci sa snažíme o presnosť, prosím, berte na vedomie, že automatizované preklady môžu obsahovať chyby alebo nepresnosti. Pôvodný dokument v jeho rodnom jazyku by mal byť považovaný za autoritatívny zdroj. Pre kritické informácie sa odporúča profesionálny ľudský preklad. Nenesieme zodpovednosť za akékoľvek nedorozumenia alebo nesprávne interpretácie vyplývajúce z použitia tohto prekladu.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
},
"kernelspec": {
"display_name": "Python 3.8.12 ('py38')",
"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.8.12"
},
"coopTranslator": {
"original_hash": "9fbb7d5fda708537649f71f5f646fcde",
"translation_date": "2025-08-30T00:33:36+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "sk"
}
},
"nbformat": 4,
"nbformat_minor": 4
}