497 lines
28 KiB
Plaintext
497 lines
28 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Generatív hálózatok\n",
|
|
"\n",
|
|
"A Rekurrens Neurális Hálózatok (RNN-ek) és azok kapuzott cellaváltozatai, mint például a Hosszú Rövid Távú Memóriacellák (LSTM-ek) és a Kapuzott Rekurrens Egységek (GRU-k), lehetőséget nyújtanak a nyelvi modellezésre, azaz képesek megtanulni a szavak sorrendjét, és előrejelzéseket adni a következő szóra egy sorozatban. Ez lehetővé teszi, hogy az RNN-eket **generatív feladatokra** használjuk, például egyszerű szöveggenerálásra, gépi fordításra, sőt akár képaláírások készítésére is.\n",
|
|
"\n",
|
|
"Az előző egységben tárgyalt RNN architektúrában minden RNN egység a következő rejtett állapotot adta ki eredményként. Azonban hozzáadhatunk egy másik kimenetet is minden rekurrens egységhez, amely lehetővé teszi, hogy egy **sorozatot** adjunk ki (amely az eredeti sorozattal azonos hosszúságú). Továbbá használhatunk olyan RNN egységeket is, amelyek nem fogadnak bemenetet minden lépésnél, hanem csak egy kezdeti állapotvektort vesznek, és ezután egy kimeneti sorozatot generálnak.\n",
|
|
"\n",
|
|
"Ebben a jegyzetfüzetben egyszerű generatív modellekre összpontosítunk, amelyek segítenek szöveget generálni. Az egyszerűség kedvéért építsünk egy **karakter-szintű hálózatot**, amely betűről betűre generál szöveget. Az edzés során szükségünk lesz egy szövegkorpuszra, amelyet betűsorozatokra bontunk.\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": [
|
|
"## Karakter szintű szókincs létrehozása\n",
|
|
"\n",
|
|
"Ahhoz, hogy karakter szintű generatív hálózatot építsünk, a szöveget szavak helyett egyedi karakterekre kell bontanunk. A korábban használt `TextVectorization` réteg erre nem képes, így két lehetőségünk van:\n",
|
|
"\n",
|
|
"* Kézzel betölteni a szöveget és manuálisan elvégezni a tokenizálást, ahogy [ebben az hivatalos Keras példában](https://keras.io/examples/generative/lstm_character_level_text_generation/) látható.\n",
|
|
"* A `Tokenizer` osztályt használni karakter szintű tokenizáláshoz.\n",
|
|
"\n",
|
|
"Mi a második lehetőséget választjuk. A `Tokenizer` szavakra történő tokenizálásra is használható, így könnyen válthatunk karakter szintű és szó szintű tokenizálás között.\n",
|
|
"\n",
|
|
"A karakter szintű tokenizáláshoz a `char_level=True` paramétert kell megadnunk:\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": [
|
|
"Azt is szeretnénk, hogy egy speciális token jelölje a **sorozat végét**, amelyet `<eos>`-nek fogunk nevezni. Adjuk hozzá manuálisan a szókincshez:\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": [
|
|
"Most pedig, hogy a szöveget számsorozatokká kódoljuk, használhatjuk:\n"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"## Generatív RNN betanítása címek létrehozására\n",
|
|
"\n",
|
|
"Az RNN betanításának módja a hírcímek generálására a következő. Minden lépésben veszünk egy címet, amelyet betáplálunk egy RNN-be, és minden bemeneti karakterhez megkérjük a hálózatot, hogy generálja a következő kimeneti karaktert:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"A szekvenciánk utolsó karakterénél megkérjük a hálózatot, hogy generálja a `<eos>` tokent.\n",
|
|
"\n",
|
|
"A generatív RNN, amelyet itt használunk, fő különbsége az, hogy az RNN minden lépésének kimenetét felhasználjuk, nem csak az utolsó celláét. Ezt úgy érhetjük el, hogy az RNN cellának megadjuk a `return_sequences` paramétert.\n",
|
|
"\n",
|
|
"Így a betanítás során a hálózat bemenete egy adott hosszúságú kódolt karakterekből álló szekvencia lesz, a kimenet pedig ugyanolyan hosszúságú szekvencia, de egy elemmel eltolva és `<eos>`-szal lezárva. Egy minibatch több ilyen szekvenciából fog állni, és **kitöltést** kell használnunk, hogy az összes szekvenciát igazítsuk.\n",
|
|
"\n",
|
|
"Hozzunk létre olyan függvényeket, amelyek átalakítják számunkra az adathalmazt. Mivel a szekvenciákat minibatch szinten szeretnénk kitölteni, először az adathalmazt `.batch()` hívással csoportosítjuk, majd `map`-pel átalakítjuk. Így az átalakító függvény egy teljes minibatch-et fog paraméterként kapni:\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": [
|
|
"Néhány fontos dolog, amit itt csinálunk:\n",
|
|
"* Először kinyerjük a tényleges szöveget a string tenzorból\n",
|
|
"* A `text_to_sequences` átalakítja a sztringek listáját egész szám tenzorok listájává\n",
|
|
"* A `pad_sequences` kitölti ezeket a tenzorokat a maximális hosszúságukig\n",
|
|
"* Végül egy-hot kódoljuk az összes karaktert, valamint elvégezzük az eltolást és a `<eos>` hozzáfűzést. Hamarosan meglátjuk, miért van szükségünk egy-hot kódolt karakterekre\n",
|
|
"\n",
|
|
"Ez a függvény azonban **Pythonos**, azaz nem fordítható automatikusan Tensorflow számítási gráffá. Hibákat kapunk, ha megpróbáljuk közvetlenül használni ezt a függvényt a `Dataset.map` függvényben. Be kell csomagolnunk ezt a Pythonos hívást a `py_function` wrapper használatával:\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": [
|
|
"> **Megjegyzés**: A Python-alapú és Tensorflow-alapú transzformációs függvények közötti különbségtétel elsőre túl bonyolultnak tűnhet, és talán azon gondolkodsz, miért nem alakítjuk át az adathalmazt standard Python függvényekkel, mielőtt átadnánk a `fit` függvénynek. Bár ez valóban lehetséges, a `Dataset.map` használatának óriási előnye van, mivel az adattranszformációs folyamat a Tensorflow számítási gráf segítségével történik, amely kihasználja a GPU számítási kapacitását, és minimalizálja az adatátvitelt a CPU és GPU között.\n",
|
|
"\n",
|
|
"Most felépíthetjük a generátor hálózatunkat és elkezdhetjük a tanítást. Ez bármelyik rekurrens cellán alapulhat, amelyet az előző egységben tárgyaltunk (egyszerű, LSTM vagy GRU). Példánkban LSTM-et fogunk használni.\n",
|
|
"\n",
|
|
"Mivel a hálózat karaktereket kap bemenetként, és a szókincs mérete viszonylag kicsi, nincs szükség beágyazási rétegre, az egy-hot kódolt bemenet közvetlenül az LSTM cellába kerülhet. A kimeneti réteg egy `Dense` osztályozó lesz, amely az LSTM kimenetét egy-hot kódolt token számokká alakítja.\n",
|
|
"\n",
|
|
"Ezenkívül, mivel változó hosszúságú szekvenciákkal dolgozunk, használhatunk `Masking` réteget, hogy létrehozzunk egy maszkot, amely figyelmen kívül hagyja a szöveg kitöltött részeit. Ez nem feltétlenül szükséges, mivel nem igazán érdekel minket minden, ami a `<eos>` tokenen túl van, de a tapasztalatszerzés érdekében használni fogjuk ezt a rétegtípust. Az `input_shape` `(None, vocab_size)` lesz, ahol a `None` a változó hosszúságú szekvenciát jelzi, és a kimeneti alakzat szintén `(None, vocab_size)`, ahogy azt a `summary` mutatja:\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": [
|
|
"## Kimenet generálása\n",
|
|
"\n",
|
|
"Most, hogy betanítottuk a modellt, szeretnénk használni, hogy kimenetet generáljunk. Először is szükségünk van egy módszerre, amely dekódolja a token számok sorozatával reprezentált szöveget. Ehhez használhatnánk a `tokenizer.sequences_to_texts` függvényt; azonban ez nem működik jól karakter szintű tokenizálás esetén. Ezért a tokenizálóból (amit `word_index`-nek hívunk) veszünk egy token szótárt, készítünk egy fordított térképet, és megírjuk a saját dekódoló függvényünket:\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": [
|
|
"Most kezdjük el a generálást. Elindulunk egy `start` nevű sztringgel, amelyet egy `inp` nevű szekvenciává kódolunk, majd minden lépésben meghívjuk a hálózatunkat, hogy megállapítsuk a következő karaktert.\n",
|
|
"\n",
|
|
"A hálózat kimenete, `out`, egy `vocab_size` elemű vektor, amely az egyes tokenek valószínűségeit reprezentálja. A legvalószínűbb token számát az `argmax` segítségével találhatjuk meg. Ezután hozzáadjuk ezt a karaktert a generált tokenek listájához, és folytatjuk a generálást. Ez a folyamat, amely során egy karaktert generálunk, `size` alkalommal ismétlődik, hogy előállítsuk a szükséges számú karaktert, és korábban befejezzük, ha az `eos_token` megjelenik.\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": [
|
|
"## Mintavételezés az edzés során\n",
|
|
"\n",
|
|
"Mivel nincsenek hasznos metrikáink, mint például *pontosság*, az egyetlen módja annak, hogy lássuk, javul-e a modellünk, az az, ha **mintát veszünk** az edzés során generált szövegből. Ehhez **visszahívásokat** (callbacks) fogunk használni, vagyis olyan függvényeket, amelyeket átadhatunk a `fit` függvénynek, és amelyek az edzés során időszakosan meghívásra kerülnek.\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": [
|
|
"Ez a példa már most is elég jó szöveget generál, de többféleképpen tovább javítható:\n",
|
|
"\n",
|
|
"* **Több szöveg**. Csak címeket használtunk a feladatunkhoz, de érdemes lehet teljes szövegekkel is kísérletezni. Ne feledd, hogy az RNN-ek nem túl jók a hosszú szekvenciák kezelésében, ezért érdemes lehet azokat rövidebb mondatokra bontani, vagy mindig egy előre meghatározott `num_chars` értékű fix szekvenciahosszon tanítani (például 256). Próbáld meg a fenti példát ilyen architektúrává alakítani, a [hivatalos Keras oktatóanyag](https://keras.io/examples/generative/lstm_character_level_text_generation/) inspirációjával.\n",
|
|
"\n",
|
|
"* **Többrétegű LSTM**. Érdemes lehet 2 vagy 3 rétegű LSTM cellákat kipróbálni. Ahogy az előző egységben említettük, az LSTM minden rétege bizonyos mintákat von ki a szövegből, és karakter-szintű generátor esetén elvárható, hogy az alsóbb LSTM szint a szótagokért, a magasabb szintek pedig a szavakért és szókapcsolatokért feleljenek. Ezt egyszerűen megvalósíthatod az LSTM konstruktorának rétegszám-paraméterének átadásával.\n",
|
|
"\n",
|
|
"* Érdemes lehet kísérletezni **GRU egységekkel** is, hogy lásd, melyik teljesít jobban, valamint **különböző rejtett réteg méretekkel**. A túl nagy rejtett réteg túltanuláshoz vezethet (például a hálózat pontosan megtanulja a szöveget), míg a kisebb méret nem biztos, hogy jó eredményt hoz.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Lágy szöveggenerálás és hőmérséklet\n",
|
|
"\n",
|
|
"Az előző `generate` definícióban mindig a legnagyobb valószínűségű karaktert választottuk ki következő karakterként a generált szövegben. Ennek eredményeként a szöveg gyakran \"ismételte\" ugyanazokat a karakter-szekvenciákat újra és újra, mint ebben a példában:\n",
|
|
"```\n",
|
|
"today of the second the company and a second the company ...\n",
|
|
"```\n",
|
|
"\n",
|
|
"Azonban, ha megnézzük a következő karakter valószínűségi eloszlását, előfordulhat, hogy a legnagyobb valószínűségek közötti különbség nem túl nagy, például egy karakter valószínűsége lehet 0.2, míg egy másiké 0.19, stb. Például, amikor a '*play*' szekvencia következő karakterét keressük, a következő karakter lehet egyaránt szóköz vagy **e** (mint a *player* szóban).\n",
|
|
"\n",
|
|
"Ez arra a következtetésre vezet minket, hogy nem mindig \"igazságos\" a magasabb valószínűségű karaktert választani, mert a második legnagyobb valószínűségű karakter választása is értelmes szöveghez vezethet. Bölcsebb dolog **mintavételezni** a karaktereket az ideghálózat kimenete által adott valószínűségi eloszlásból.\n",
|
|
"\n",
|
|
"Ez a mintavételezés a `np.multinomial` függvénnyel végezhető el, amely az úgynevezett **multinomiális eloszlást** valósítja meg. Az alábbiakban definiálva van egy függvény, amely ezt a **lágy** szöveggenerálást megvalósítja:\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 <b>...</b>\n",
|
|
"Little red riding hood ficed to the spam countered in European <b>...</b>\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 <b>...</b>\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": [
|
|
"Bevezettünk egy újabb paramétert, amelyet **hőmérsékletnek** nevezünk, és amely azt jelzi, mennyire ragaszkodjunk a legnagyobb valószínűséghez. Ha a hőmérséklet 1,0, akkor tisztességes multinomiális mintavételt végzünk, és amikor a hőmérséklet végtelenhez közelít - minden valószínűség egyenlővé válik, és véletlenszerűen választjuk ki a következő karaktert. Az alábbi példában megfigyelhetjük, hogy a szöveg értelmetlenné válik, amikor túlzottan növeljük a hőmérsékletet, és \"ciklusos\" keményen generált szövegre hasonlít, amikor közelebb kerül a 0-hoz.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Felelősség kizárása**: \nEz a dokumentum az AI fordítási szolgáltatás [Co-op Translator](https://github.com/Azure/co-op-translator) segítségével lett lefordítva. Bár törekszünk a pontosságra, kérjük, vegye figyelembe, hogy az automatikus fordítások hibákat vagy pontatlanságokat tartalmazhatnak. Az eredeti dokumentum az eredeti nyelvén tekintendő hiteles forrásnak. Kritikus információk esetén javasolt professzionális emberi fordítást igénybe venni. Nem vállalunk felelősséget semmilyen félreértésért vagy téves értelmezésért, amely a fordítás használatából eredhet.\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-29T15:42:35+00:00",
|
|
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
|
"language_code": "hu"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |