494 lines
26 KiB
Plaintext
494 lines
26 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Generatiivsed võrgud\n",
|
|
"\n",
|
|
"Korduvad närvivõrgud (RNN-id) ja nende väratiga rakutüübid, nagu Long Short Term Memory Cells (LSTM-id) ja Gated Recurrent Units (GRU-d), pakkusid mehhanismi keele modelleerimiseks, st nad suudavad õppida sõnade järjestust ja anda ennustusi järgmise sõna kohta järjestuses. See võimaldab meil kasutada RNN-e **generatiivseteks ülesanneteks**, nagu tavaline tekstigeneratsioon, masintõlge ja isegi pildiallkirjade loomine.\n",
|
|
"\n",
|
|
"RNN arhitektuuris, mida arutasime eelmises osas, genereeris iga RNN üksus järgmise varjatud oleku väljundina. Kuid me saame lisada igale korduva üksusele veel ühe väljundi, mis võimaldab meil luua **järjestuse** (mis on sama pikk kui algne järjestus). Lisaks saame kasutada RNN üksusi, mis ei võta igal sammul sisendit, vaid kasutavad ainult algoleku vektorit ja seejärel genereerivad väljundite järjestuse.\n",
|
|
"\n",
|
|
"Selles märkmikus keskendume lihtsatele generatiivsetele mudelitele, mis aitavad meil teksti genereerida. Lihtsuse huvides loome **tähemärgi tasemel võrgu**, mis genereerib teksti täht-tähelt. Treeningu ajal peame võtma mõne tekstikorpuse ja jagama selle tähemärkide järjestusteks.\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": [
|
|
"## Tähemärkide sõnavara loomine\n",
|
|
"\n",
|
|
"Tähemärkide tasemel generatiivse võrgu loomiseks peame teksti jagama üksikuteks tähemärkideks, mitte sõnadeks. `TextVectorization` kiht, mida oleme varem kasutanud, ei suuda seda teha, seega on meil kaks võimalust:\n",
|
|
"\n",
|
|
"* Laadida tekst käsitsi ja teha tokeniseerimine \"käsitsi\", nagu [selles ametlikus Keras näites](https://keras.io/examples/generative/lstm_character_level_text_generation/)\n",
|
|
"* Kasutada `Tokenizer` klassi tähemärkide tasemel tokeniseerimiseks.\n",
|
|
"\n",
|
|
"Me valime teise variandi. `Tokenizer`-it saab kasutada ka sõnade tokeniseerimiseks, seega peaks olema lihtne vahetada tähemärkide tasemelt sõnade tasemele.\n",
|
|
"\n",
|
|
"Tähemärkide tasemel tokeniseerimiseks peame lisama parameetri `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": [
|
|
"Me tahame kasutada ka ühte spetsiaalset tokenit, et tähistada **järjestuse lõppu**, mida me nimetame `<eos>`. Lisame selle käsitsi sõnavarasse:\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": [
|
|
"Nüüd, et kodeerida teksti numbrijadadeks, saame kasutada:\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": [
|
|
"## Generatiivse RNN-i treenimine pealkirjade genereerimiseks\n",
|
|
"\n",
|
|
"RNN-i treenimine uudiste pealkirjade genereerimiseks toimub järgmiselt. Igal sammul võtame ühe pealkirja, mis sisestatakse RNN-i, ja iga sisendmärgi puhul palume võrgul genereerida järgmine väljundmärk:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"Meie järjestuse viimase märgi puhul palume võrgul genereerida `<eos>` tokeni.\n",
|
|
"\n",
|
|
"Peamine erinevus generatiivse RNN-i puhul, mida siin kasutame, seisneb selles, et võtame väljundi igast RNN-i sammust, mitte ainult viimasest rakust. Seda saab saavutada, määrates RNN-i rakule parameetri `return_sequences`.\n",
|
|
"\n",
|
|
"Seega, treeningu ajal on võrgu sisendiks teatud pikkusega kodeeritud märkide järjestus ja väljundiks sama pikkusega järjestus, mis on nihutatud ühe elemendi võrra ja lõpetatud `<eos>`-iga. Minipartii koosneb mitmest sellisest järjestusest, ja me peame kasutama **täitmist**, et kõik järjestused ühtlustada.\n",
|
|
"\n",
|
|
"Loome funktsioonid, mis muudavad meie jaoks andmekogu. Kuna soovime järjestusi täita minipartii tasemel, rühmitame esmalt andmekogu, kutsudes `.batch()`, ja seejärel rakendame `map`, et teha transformatsioon. Seega võtab transformatsioonifunktsioon parameetrina terve minipartii:\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": [
|
|
"Mõned olulised asjad, mida me siin teeme: \n",
|
|
"* Kõigepealt eraldame tegeliku teksti stringi tensorist \n",
|
|
"* `text_to_sequences` teisendab stringide loendi täisarvude tensorite loendiks \n",
|
|
"* `pad_sequences` täidab need tensorid nende maksimaalse pikkuseni \n",
|
|
"* Lõpuks kodeerime kõik tähemärgid ühekordselt (one-hot encoding), teeme nihutamise ja lisame `<eos>`. Varsti näeme, miks me vajame ühekordselt kodeeritud tähemärke \n",
|
|
"\n",
|
|
"Siiski on see funktsioon **Pythonile omane**, st seda ei saa automaatselt tõlkida Tensorflow arvutusgraafikuks. Kui proovime seda funktsiooni otse kasutada `Dataset.map` funktsioonis, saame veateateid. Peame selle Pythonile omase kõne ümbritsema, kasutades `py_function` ümbrist:\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": [
|
|
"> **Märkus**: Pythonic ja Tensorflow teisendusfunktsioonide eristamine võib tunduda veidi keeruline ning võite küsida, miks me ei teisenda andmekogumit tavaliste Pythoni funktsioonide abil enne, kui selle `fit`-i edastame. Kuigi see on kindlasti võimalik, on `Dataset.map` kasutamisel suur eelis, kuna andmete teisendamise torujuhe täidetakse Tensorflow arvutusgraafiku abil, mis kasutab ära GPU arvutusvõimsust ja vähendab vajadust andmeid CPU ja GPU vahel edasi-tagasi liigutada.\n",
|
|
"\n",
|
|
"Nüüd saame luua oma generaatori võrgu ja alustada treenimist. See võib põhineda mis tahes korduvrakul, mida arutasime eelmises osas (lihtne, LSTM või GRU). Meie näites kasutame LSTM-i.\n",
|
|
"\n",
|
|
"Kuna võrk võtab sisendiks tähemärke ja sõnavara suurus on üsna väike, ei ole meil vaja sisendkihtide jaoks embedding-kihte; üheselt kodeeritud sisend võib otse minna LSTM-rakku. Väljundkiht oleks `Dense` klassifikaator, mis teisendab LSTM-i väljundi üheselt kodeeritud tokenite numbriteks.\n",
|
|
"\n",
|
|
"Lisaks, kuna töötame muutuva pikkusega jadadega, saame kasutada `Masking` kihti, et luua mask, mis ignoreerib täiendatud stringi osi. See ei ole rangelt vajalik, kuna meid ei huvita väga see, mis jääb `<eos>` tokenist kaugemale, kuid kasutame seda kihti, et saada kogemust selle tüüpi kihiga. `input_shape` oleks `(None, vocab_size)`, kus `None` tähistab muutuva pikkusega jada, ja väljundkuju on samuti `(None, vocab_size)`, nagu näete `summary`-st:\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": [
|
|
"## Väljundi genereerimine\n",
|
|
"\n",
|
|
"Nüüd, kui oleme mudeli treeninud, tahame seda kasutada väljundi genereerimiseks. Kõigepealt vajame viisi, kuidas dekodeerida tekst, mis on esitatud tokenite numbrite jadana. Selleks võiksime kasutada funktsiooni `tokenizer.sequences_to_texts`; siiski ei tööta see hästi tähemärgi tasemel tokeniseerimisega. Seetõttu võtame tokenite sõnastiku tokeniseerijast (nimetatakse `word_index`), loome pöördkaardi ja kirjutame oma dekodeerimisfunktsiooni:\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": [
|
|
"Nüüd alustame genereerimist. Võtame alguses stringi `start`, kodeerime selle järjestuseks `inp` ja igal sammul kutsume oma võrgu välja, et tuvastada järgmine tähemärk.\n",
|
|
"\n",
|
|
"Võrgu väljund `out` on vektor, millel on `vocab_size` elementi, mis esindavad iga tokeni tõenäosust. Kõige tõenäolisema tokeni numbri saame leida, kasutades `argmax`. Seejärel lisame selle tähemärgi genereeritud tokenite loendisse ja jätkame genereerimist. Ühe tähemärgi genereerimise protsessi korratakse `size` korda, et luua vajalik arv tähemärke, ja lõpetame varakult, kui kohtame `eos_token`-i.\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": [
|
|
"## Väljundi proovivõtmine treeningu ajal\n",
|
|
"\n",
|
|
"Kuna meil puuduvad kasulikud mõõdikud, nagu *täpsus*, on ainus viis näha, et meie mudel paraneb, **proovivõtmine** genereeritud stringist treeningu ajal. Selleks kasutame **tagasiside funktsioone** ehk funktsioone, mida saame edastada `fit` funktsioonile ja mis kutsutakse treeningu käigus perioodiliselt välja.\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": [
|
|
"See näide genereerib juba üsna head teksti, kuid seda saab mitmel viisil veelgi paremaks muuta:\n",
|
|
"* **Rohkem teksti**. Oleme oma ülesande jaoks kasutanud ainult pealkirju, kuid võite katsetada täistekstiga. Pidage meeles, et RNN-id ei ole eriti head pikkade järjestuste käsitlemisel, seega on mõistlik need kas jagada lühemateks lauseteks või alati treenida fikseeritud järjestuse pikkusega, mille väärtus on eelnevalt määratud `num_chars` (näiteks 256). Võite proovida ülaltoodud näidet muuta selliseks arhitektuuriks, kasutades inspiratsiooniks [ametlikku Keras õpetust](https://keras.io/examples/generative/lstm_character_level_text_generation/).\n",
|
|
"* **Mitmekihiline LSTM**. Tasub proovida 2 või 3 LSTM-rakkude kihti. Nagu mainisime eelmises osas, iga LSTM kiht eraldab tekstist teatud mustreid, ja tähemärgi tasemel generaatori puhul võime eeldada, et madalam LSTM tase vastutab silpide eraldamise eest, ning kõrgemad tasemed - sõnade ja sõnakombinatsioonide eest. Seda saab lihtsalt rakendada, andes LSTM konstruktorile kihtide arvu parameetri.\n",
|
|
"* Võite katsetada ka **GRU üksustega** ja vaadata, millised annavad paremaid tulemusi, ning **erinevate varjatud kihtide suurustega**. Liiga suur varjatud kiht võib viia üleõppimisele (näiteks õpib võrk täpse teksti), ja väiksem suurus ei pruugi anda häid tulemusi.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Pehme teksti genereerimine ja temperatuur\n",
|
|
"\n",
|
|
"Eelmises `generate` definitsioonis valisime alati järgmise tähemärgina selle, millel oli kõrgeim tõenäosus genereeritud tekstis. See tõi sageli kaasa olukorra, kus tekst \"kordas\" samu tähemärkide jadasid ikka ja jälle, nagu selles näites:\n",
|
|
"```\n",
|
|
"today of the second the company and a second the company ...\n",
|
|
"```\n",
|
|
"\n",
|
|
"Kuid kui vaatame järgmise tähemärgi tõenäosusjaotust, võib juhtuda, et mõne kõrgeima tõenäosuse vahe ei ole suur, näiteks ühel tähemärgil võib olla tõenäosus 0,2 ja teisel 0,19 jne. Näiteks, kui otsime järgmist tähemärki jadas '*play*', võib järgmine tähemärk sama hästi olla kas tühik või **e** (nagu sõnas *player*).\n",
|
|
"\n",
|
|
"See viib meid järelduseni, et ei ole alati \"õiglane\" valida tähemärki, millel on kõrgem tõenäosus, sest ka teise kõrgeima valimine võib viia tähendusliku tekstini. Mõistlikum on **valida juhuslikult** tähemärke võrgu väljundi antud tõenäosusjaotuse põhjal.\n",
|
|
"\n",
|
|
"Seda juhuslikku valimist saab teha `np.multinomial` funktsiooni abil, mis rakendab nn **multinomiaalset jaotust**. Allpool on defineeritud funktsioon, mis rakendab seda **pehmet** teksti genereerimist:\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": [
|
|
"Oleme lisanud veel ühe parameetri nimega **temperatuur**, mida kasutatakse näitamaks, kui tugevalt peaksime järgima kõrgeimat tõenäosust. Kui temperatuur on 1.0, teeme õiglast multinomiaalse valimit, ja kui temperatuur läheneb lõpmatusele - muutuvad kõik tõenäosused võrdseks ning me valime järgmise tähemärgi juhuslikult. Allolevas näites näeme, et tekst muutub mõttetuks, kui temperatuuri liiga palju suurendame, ja meenutab \"tsüklilist\" rangelt genereeritud teksti, kui see läheneb 0-le.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Lahtiütlus**: \nSee dokument on tõlgitud AI tõlketeenuse [Co-op Translator](https://github.com/Azure/co-op-translator) abil. Kuigi püüame tagada täpsust, palume arvestada, et automaatsed tõlked võivad sisaldada vigu või ebatäpsusi. Algne dokument selle algses keeles tuleks pidada autoriteetseks allikaks. Olulise teabe puhul soovitame kasutada professionaalset inimtõlget. Me ei vastuta selle tõlke kasutamisest tulenevate arusaamatuste või valesti tõlgenduste eest.\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-10-11T12:52:46+00:00",
|
|
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
|
"language_code": "et"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |