495 lines
27 KiB
Plaintext
495 lines
27 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Generatyviniai tinklai\n",
|
||
"\n",
|
||
"Pasikartojantys neuroniniai tinklai (RNN) ir jų užtvarų ląstelių variantai, tokie kaip ilgos trumpalaikės atminties ląstelės (LSTM) ir užtvarų pasikartojantys vienetai (GRU), suteikė mechanizmą kalbos modeliavimui, t. y. jie gali išmokti žodžių tvarką ir pateikti prognozes apie kitą žodį sekoje. Tai leidžia mums naudoti RNN **generatyvinėms užduotims**, tokioms kaip įprastas teksto generavimas, mašininis vertimas ir net vaizdų aprašymas.\n",
|
||
"\n",
|
||
"RNN architektūroje, kurią aptarėme ankstesniame skyriuje, kiekvienas RNN vienetas generavo kitą paslėptą būseną kaip išvestį. Tačiau mes taip pat galime pridėti kitą išvestį prie kiekvieno pasikartojančio vieneto, kuris leistų mums generuoti **seką** (kuri yra tokio pat ilgio kaip pradinė seka). Be to, galime naudoti RNN vienetus, kurie kiekviename žingsnyje nepriima įvesties, o tiesiog naudoja pradinį būsenos vektorių ir tada generuoja išvesties seką.\n",
|
||
"\n",
|
||
"Šiame užrašų knygelėje mes sutelksime dėmesį į paprastus generatyvinius modelius, kurie padeda mums generuoti tekstą. Paprastumo dėlei sukurkime **simbolių lygmens tinklą**, kuris generuoja tekstą raidė po raidės. Mokymo metu mums reikia paimti tam tikrą teksto korpusą ir padalyti jį į raidžių sekas.\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": [
|
||
"## Charakterių žodyno kūrimas\n",
|
||
"\n",
|
||
"Norint sukurti generatyvinį tinklą simbolių lygiu, tekstą reikia suskaidyti į atskirus simbolius, o ne žodžius. `TextVectorization` sluoksnis, kurį naudojome anksčiau, to padaryti negali, todėl turime dvi galimybes:\n",
|
||
"\n",
|
||
"* Rankiniu būdu įkelti tekstą ir atlikti tokenizaciją „rankomis“, kaip parodyta [šiame oficialiame Keras pavyzdyje](https://keras.io/examples/generative/lstm_character_level_text_generation/)\n",
|
||
"* Naudoti `Tokenizer` klasę simbolių lygio tokenizacijai.\n",
|
||
"\n",
|
||
"Mes pasirinkome antrąjį variantą. `Tokenizer` taip pat gali būti naudojamas žodžių tokenizacijai, todėl turėtų būti gana paprasta pereiti nuo simbolių lygio prie žodžių lygio tokenizacijos.\n",
|
||
"\n",
|
||
"Norint atlikti simbolių lygio tokenizaciją, reikia perduoti parametrą `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": [
|
||
"Mes taip pat norime naudoti vieną specialų žymeklį, kuris žymėtų **sekos pabaigą**, kurį pavadinsime `<eos>`. Pridėkime jį rankiniu būdu į žodyną:\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": [
|
||
"## Generatyvios RNN mokymas kurti pavadinimus\n",
|
||
"\n",
|
||
"Štai kaip mes mokysime RNN generuoti naujienų pavadinimus. Kiekviename žingsnyje imsime vieną pavadinimą, kurį pateiksime RNN, ir kiekvienam įvesties simboliui prašysime tinklo sugeneruoti kitą išvesties simbolį:\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"Paskutiniam mūsų sekos simboliui prašysime tinklo sugeneruoti `<eos>` žymeklį.\n",
|
||
"\n",
|
||
"Pagrindinis skirtumas tarp generatyvios RNN, kurią naudojame čia, yra tas, kad imsime išvestį iš kiekvieno RNN žingsnio, o ne tik iš paskutinės ląstelės. Tai galima pasiekti nurodant `return_sequences` parametrą RNN ląstelei.\n",
|
||
"\n",
|
||
"Taigi, mokymo metu tinklo įvestis bus tam tikro ilgio užkoduotų simbolių seka, o išvestis bus tokio pat ilgio seka, bet paslinkta vienu elementu ir baigiama `<eos>`. Minipartija sudarys kelias tokias sekas, ir mums reikės naudoti **užpildymą**, kad suderintume visas sekas.\n",
|
||
"\n",
|
||
"Sukurkime funkcijas, kurios transformuos mums duomenų rinkinį. Kadangi norime užpildyti sekas minipartijos lygiu, pirmiausia sugrupuosime duomenų rinkinį naudodami `.batch()`, o tada naudosime `map`, kad atliktume transformaciją. Taigi, transformacijos funkcija priims visą minipartiją kaip parametrą:\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": [
|
||
"Keletas svarbių dalykų, kuriuos čia atliekame:\n",
|
||
"* Pirmiausia išgauname tikrąjį tekstą iš string tipo tensoriaus\n",
|
||
"* `text_to_sequences` konvertuoja tekstų sąrašą į sveikųjų skaičių tensorių sąrašą\n",
|
||
"* `pad_sequences` užpildo tuos tensorius iki jų maksimalaus ilgio\n",
|
||
"* Galiausiai atliekame vieno karšto kodavimo (one-hot encoding) procesą visiems simboliams, taip pat atliekame poslinkį ir `<eos>` pridėjimą. Netrukus paaiškinsime, kodėl mums reikia vieno karšto koduotų simbolių\n",
|
||
"\n",
|
||
"Tačiau ši funkcija yra **Pythonic**, t. y. jos negalima automatiškai paversti Tensorflow skaičiavimo grafu. Jei bandysime naudoti šią funkciją tiesiogiai `Dataset.map` funkcijoje, gausime klaidų. Turime šį Pythonic kvietimą apgaubti naudojant `py_function` apvalkalą:\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": [
|
||
"> **Pastaba**: Skirtumas tarp Pythonic ir Tensorflow transformacijos funkcijų gali atrodyti pernelyg sudėtingas, ir galbūt kyla klausimas, kodėl mes nenaudojame standartinių Python funkcijų duomenų rinkiniui transformuoti prieš perduodant jį į `fit`. Nors tai tikrai galima padaryti, naudojant `Dataset.map` yra didelis privalumas, nes duomenų transformacijos procesas vykdomas naudojant Tensorflow skaičiavimo grafiką, kuris išnaudoja GPU skaičiavimo galimybes ir sumažina poreikį perduoti duomenis tarp CPU/GPU.\n",
|
||
"\n",
|
||
"Dabar galime sukurti savo generatoriaus tinklą ir pradėti mokymą. Jis gali būti pagrįstas bet kuria pasikartojančia ląstele, kurią aptarėme ankstesniame skyriuje (paprasta, LSTM arba GRU). Mūsų pavyzdyje naudosime LSTM.\n",
|
||
"\n",
|
||
"Kadangi tinklas kaip įvestį naudoja simbolius, o žodyno dydis yra gana mažas, mums nereikia įterpimo sluoksnio – vieno karšto kodavimo (one-hot-encoded) įvestis gali tiesiogiai patekti į LSTM ląstelę. Išvesties sluoksnis būtų `Dense` klasifikatorius, kuris konvertuos LSTM išvestį į vieno karšto kodavimo simbolių numerius.\n",
|
||
"\n",
|
||
"Be to, kadangi dirbame su kintamo ilgio sekų duomenimis, galime naudoti `Masking` sluoksnį, kad sukurtume kaukę, kuri ignoruos užpildytą (padded) eilutės dalį. Tai nėra griežtai būtina, nes mums nėra labai svarbu viskas, kas yra už `<eos>` žymos, tačiau naudosime šį sluoksnį, kad įgytume patirties su šio tipo sluoksniais. `input_shape` bus `(None, vocab_size)`, kur `None` nurodo kintamo ilgio seką, o išvesties forma taip pat yra `(None, vocab_size)`, kaip matote iš `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": [
|
||
"## Generuojant rezultatą\n",
|
||
"\n",
|
||
"Dabar, kai modelis yra apmokytas, norime jį panaudoti rezultatui generuoti. Visų pirma, mums reikia būdo dekoduoti tekstą, kuris yra pateiktas kaip skaičių sekos. Tam galėtume naudoti funkciją `tokenizer.sequences_to_texts`; tačiau ji nėra labai efektyvi, kai naudojama simbolių lygmens tokenizacija. Todėl mes paimsime tokenų žodyną iš tokenizer (vadinamą `word_index`), sukursime atvirkštinį žemėlapį ir parašysime savo dekodavimo funkciją:\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": [
|
||
"Dabar pradėsime generavimą. Pirmiausia turime tam tikrą eilutę `start`, kurią užkoduojame į seką `inp`, o tada kiekviename žingsnyje kviesime savo tinklą, kad nustatytume kitą simbolį.\n",
|
||
"\n",
|
||
"Tinklo išvestis `out` yra vektorius su `vocab_size` elementų, kurie atspindi kiekvieno ženklo tikimybes. Naudodami `argmax` galime rasti labiausiai tikėtiną ženklo numerį. Tada šį simbolį pridedame prie sugeneruoto ženklų sąrašo ir tęsiame generavimą. Šis procesas, kai sugeneruojamas vienas simbolis, kartojamas `size` kartų, kad būtų sugeneruotas reikiamas simbolių skaičius, o generavimą baigiame anksčiau, jei pasiekiamas `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": [
|
||
"## Pavyzdžių generavimas treniruotės metu\n",
|
||
"\n",
|
||
"Kadangi neturime jokių naudingų metrikų, tokių kaip *tikslumas*, vienintelis būdas pamatyti, ar mūsų modelis tobulėja, yra **generuojamų eilučių pavyzdžių peržiūra** treniruotės metu. Tam naudosime **atšaukimus** (callbacks), t. y. funkcijas, kurias galime perduoti `fit` funkcijai ir kurios bus periodiškai iškviečiamos treniruotės metu.\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": [
|
||
"Šis pavyzdys jau generuoja gana gerą tekstą, tačiau jį galima dar labiau patobulinti keliais būdais:\n",
|
||
"\n",
|
||
"* **Daugiau teksto**. Mes naudojome tik antraštes savo užduočiai, tačiau galite eksperimentuoti su pilnu tekstu. Atminkite, kad RNN nėra labai gerai pritaikyti ilgiems sekų apdorojimams, todėl verta jas suskaidyti į trumpesnes sakinių dalis arba visada treniruoti fiksuoto sekos ilgio, pvz., `num_chars` (pavyzdžiui, 256). Galite pabandyti pakeisti aukščiau pateiktą pavyzdį į tokią architektūrą, naudodami [oficialų Keras vadovą](https://keras.io/examples/generative/lstm_character_level_text_generation/) kaip įkvėpimą.\n",
|
||
"\n",
|
||
"* **Daugiasluoksnis LSTM**. Verta išbandyti 2 ar 3 LSTM ląstelių sluoksnius. Kaip minėjome ankstesniame skyriuje, kiekvienas LSTM sluoksnis iš tekstų išskiria tam tikrus raštus, o simbolių lygio generatoriaus atveju galime tikėtis, kad žemesnis LSTM lygis bus atsakingas už skiemenų išskyrimą, o aukštesni lygiai - už žodžius ir jų derinius. Tai galima paprastai įgyvendinti perduodant sluoksnių skaičiaus parametrą LSTM konstruktoriui.\n",
|
||
"\n",
|
||
"* Taip pat galite eksperimentuoti su **GRU vienetais** ir pažiūrėti, kurie veikia geriau, bei su **skirtingais paslėptų sluoksnių dydžiais**. Per didelis paslėptas sluoksnis gali sukelti per didelį pritaikymą (pvz., tinklas išmoks tikslų tekstą), o mažesnis dydis gali neduoti gero rezultato.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Minkštas teksto generavimas ir temperatūra\n",
|
||
"\n",
|
||
"Ankstesnėje `generate` apibrėžtyje mes visada rinkdavomės simbolį su didžiausia tikimybe kaip kitą simbolį generuojamame tekste. Tai lėmė, kad tekstas dažnai „kartodavosi“ tarp tų pačių simbolių sekų vėl ir vėl, kaip šiame pavyzdyje:\n",
|
||
"```\n",
|
||
"today of the second the company and a second the company ...\n",
|
||
"```\n",
|
||
"\n",
|
||
"Tačiau, jei pažvelgsime į tikimybių pasiskirstymą kitam simboliui, gali būti, kad skirtumas tarp kelių didžiausių tikimybių nėra didelis, pvz., vienas simbolis gali turėti tikimybę 0.2, kitas - 0.19 ir pan. Pavyzdžiui, ieškant kito simbolio sekai '*play*', kitas simbolis gali būti tiek tarpas, tiek **e** (kaip žodyje *player*).\n",
|
||
"\n",
|
||
"Tai leidžia daryti išvadą, kad ne visada „teisinga“ pasirinkti simbolį su didesne tikimybe, nes pasirinkus antrą pagal dydį tikimybę vis tiek galime gauti prasmingą tekstą. Protingiau yra **imti mėginius** iš tikimybių pasiskirstymo, kurį pateikia tinklo išvestis.\n",
|
||
"\n",
|
||
"Šis mėginių ėmimas gali būti atliekamas naudojant `np.multinomial` funkciją, kuri įgyvendina vadinamąjį **multinominį pasiskirstymą**. Funkcija, kuri įgyvendina šį **minkštą** teksto generavimą, apibrėžta žemiau:\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": [
|
||
"Mes pristatėme dar vieną parametrą, vadinamą **temperatūra**, kuris naudojamas nurodyti, kaip stipriai turėtume laikytis didžiausios tikimybės. Jei temperatūra yra 1.0, atliekame sąžiningą multinominį mėginių ėmimą, o kai temperatūra pasiekia begalybę - visos tikimybės tampa lygios, ir mes atsitiktinai pasirenkame kitą simbolį. Žemiau pateiktame pavyzdyje galime pastebėti, kad tekstas tampa beprasmiškas, kai temperatūra per daug padidėja, ir primena „ciklinį“ sunkiai generuojamą tekstą, kai ji artėja prie 0.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"\n---\n\n**Atsakomybės apribojimas**: \nŠis dokumentas buvo išverstas naudojant AI vertimo paslaugą [Co-op Translator](https://github.com/Azure/co-op-translator). Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama naudoti profesionalų žmogaus vertimą. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus interpretavimus, atsiradusius dėl šio vertimo naudojimo.\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-31T13:42:18+00:00",
|
||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
||
"language_code": "lt"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
} |