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

497 lines
28 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Rangkaian Generatif\n",
"\n",
"Recurrent Neural Networks (RNNs) dan varian sel berpagar seperti Long Short Term Memory Cells (LSTMs) dan Gated Recurrent Units (GRUs) menyediakan mekanisme untuk pemodelan bahasa, iaitu mereka boleh mempelajari susunan perkataan dan memberikan ramalan untuk perkataan seterusnya dalam satu urutan. Ini membolehkan kita menggunakan RNN untuk **tugas generatif**, seperti penjanaan teks biasa, terjemahan mesin, dan juga kapsyen imej.\n",
"\n",
"Dalam seni bina RNN yang kita bincangkan dalam unit sebelumnya, setiap unit RNN menghasilkan keadaan tersembunyi seterusnya sebagai output. Walau bagaimanapun, kita juga boleh menambah satu lagi output kepada setiap unit berulang, yang membolehkan kita menghasilkan **urutan** (yang sama panjang dengan urutan asal). Selain itu, kita boleh menggunakan unit RNN yang tidak menerima input pada setiap langkah, dan hanya mengambil beberapa vektor keadaan awal, kemudian menghasilkan urutan output.\n",
"\n",
"Dalam notebook ini, kita akan memberi tumpuan kepada model generatif mudah yang membantu kita menjana teks. Untuk kesederhanaan, mari bina **rangkaian peringkat aksara**, yang menjana teks huruf demi huruf. Semasa latihan, kita perlu mengambil beberapa korpus teks, dan membahagikannya kepada urutan huruf.\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": [
"## Membina Perbendaharaan Kata Karakter\n",
"\n",
"Untuk membina rangkaian generatif pada tahap karakter, kita perlu memecahkan teks kepada karakter individu dan bukannya perkataan. Lapisan `TextVectorization` yang telah kita gunakan sebelum ini tidak dapat melakukannya, jadi kita mempunyai dua pilihan:\n",
"\n",
"* Memuatkan teks secara manual dan melakukan tokenisasi 'secara manual', seperti dalam [contoh rasmi Keras ini](https://keras.io/examples/generative/lstm_character_level_text_generation/)\n",
"* Menggunakan kelas `Tokenizer` untuk tokenisasi pada tahap karakter.\n",
"\n",
"Kita akan memilih pilihan kedua. `Tokenizer` juga boleh digunakan untuk tokenisasi kepada perkataan, jadi seseorang boleh beralih daripada tokenisasi tahap karakter kepada tahap perkataan dengan mudah.\n",
"\n",
"Untuk melakukan tokenisasi pada tahap karakter, kita perlu memberikan 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": [
"Kami juga ingin menggunakan satu token khas untuk menandakan **akhir jujukan**, yang akan kami panggil `<eos>`. Mari tambahkannya secara manual ke dalam perbendaharaan kata:\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": [
"Sekarang, untuk mengekod teks ke dalam urutan nombor, kita boleh menggunakan:\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": [
"## Melatih RNN Generatif untuk Menjana Tajuk\n",
"\n",
"Cara kita akan melatih RNN untuk menjana tajuk berita adalah seperti berikut. Pada setiap langkah, kita akan mengambil satu tajuk, yang akan dimasukkan ke dalam RNN, dan untuk setiap aksara input, kita akan meminta rangkaian untuk menjana aksara output seterusnya:\n",
"\n",
"![Imej menunjukkan contoh penjanaan RNN untuk perkataan 'HELLO'.](../../../../../translated_images/ms/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"Untuk aksara terakhir dalam urutan kita, kita akan meminta rangkaian untuk menjana token `<eos>`.\n",
"\n",
"Perbezaan utama antara RNN generatif yang kita gunakan di sini adalah bahawa kita akan mengambil output dari setiap langkah RNN, dan bukan hanya dari sel terakhir. Ini boleh dicapai dengan menetapkan parameter `return_sequences` pada sel RNN.\n",
"\n",
"Oleh itu, semasa latihan, input kepada rangkaian adalah urutan aksara yang telah dikodkan dengan panjang tertentu, dan output adalah urutan dengan panjang yang sama, tetapi digeser satu elemen dan diakhiri dengan `<eos>`. Minibatch akan terdiri daripada beberapa urutan seperti ini, dan kita perlu menggunakan **padding** untuk menyelaraskan semua urutan.\n",
"\n",
"Mari kita cipta fungsi-fungsi yang akan mengubah dataset untuk kita. Oleh kerana kita ingin menambah padding pada tahap minibatch, kita akan terlebih dahulu mengelompokkan dataset dengan memanggil `.batch()`, dan kemudian `map` untuk melakukan transformasi. Jadi, fungsi transformasi akan mengambil keseluruhan minibatch sebagai 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": [
"Beberapa perkara penting yang kita lakukan di sini:\n",
"* Kita mula-mula mengekstrak teks sebenar daripada tensor string\n",
"* `text_to_sequences` menukar senarai string kepada senarai tensor integer\n",
"* `pad_sequences` menambah padding pada tensor tersebut sehingga panjang maksimum\n",
"* Akhirnya, kita melakukan pengekodan satu-hot untuk semua aksara, serta melakukan pergeseran dan penambahan `<eos>`. Kita akan segera melihat mengapa kita memerlukan aksara yang dikodkan satu-hot\n",
"\n",
"Namun, fungsi ini adalah **Pythonic**, iaitu ia tidak boleh diterjemahkan secara automatik ke dalam graf pengiraan Tensorflow. Kita akan mendapat ralat jika cuba menggunakan fungsi ini secara langsung dalam fungsi `Dataset.map`. Kita perlu membungkus panggilan Pythonic ini dengan menggunakan pembungkus `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": [
"> **Nota**: Membezakan antara fungsi transformasi Pythonic dan Tensorflow mungkin kelihatan agak kompleks, dan anda mungkin tertanya-tanya mengapa kita tidak mengubah dataset menggunakan fungsi Python standard sebelum menghantarnya ke `fit`. Walaupun ini sememangnya boleh dilakukan, menggunakan `Dataset.map` mempunyai kelebihan besar, kerana saluran transformasi data dilaksanakan menggunakan graf pengiraan Tensorflow, yang memanfaatkan pengiraan GPU, dan meminimumkan keperluan untuk memindahkan data antara CPU/GPU.\n",
"\n",
"Sekarang kita boleh membina rangkaian penjana kita dan memulakan latihan. Ia boleh berdasarkan mana-mana sel berulang yang telah kita bincangkan dalam unit sebelumnya (simple, LSTM atau GRU). Dalam contoh kita, kita akan menggunakan LSTM.\n",
"\n",
"Oleh kerana rangkaian mengambil aksara sebagai input, dan saiz kosa kata agak kecil, kita tidak memerlukan lapisan embedding, input yang dikodkan satu-panas (one-hot-encoded) boleh terus masuk ke dalam sel LSTM. Lapisan output akan menjadi pengklasifikasi `Dense` yang akan menukar output LSTM kepada nombor token yang dikodkan satu-panas.\n",
"\n",
"Selain itu, memandangkan kita berurusan dengan jujukan panjang berubah, kita boleh menggunakan lapisan `Masking` untuk mencipta topeng yang akan mengabaikan bahagian rentetan yang dipadatkan. Ini tidak semestinya diperlukan, kerana kita tidak begitu berminat dengan segala-galanya yang melangkaui token `<eos>`, tetapi kita akan menggunakannya demi mendapatkan pengalaman dengan jenis lapisan ini. `input_shape` akan menjadi `(None, vocab_size)`, di mana `None` menunjukkan jujukan panjang berubah, dan bentuk output juga `(None, vocab_size)`, seperti yang anda boleh lihat daripada `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": [
"## Menjana output\n",
"\n",
"Sekarang kita telah melatih model, kita ingin menggunakannya untuk menghasilkan beberapa output. Pertama sekali, kita memerlukan cara untuk menyahkod teks yang diwakili oleh urutan nombor token. Untuk melakukan ini, kita boleh menggunakan fungsi `tokenizer.sequences_to_texts`; namun, ia tidak berfungsi dengan baik dengan pengekodan token peringkat aksara. Oleh itu, kita akan mengambil kamus token daripada tokenizer (dipanggil `word_index`), membina peta terbalik, dan menulis fungsi penyahkodan kita sendiri:\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": [
"Sekarang, mari kita lakukan penjanaan. Kita akan bermula dengan beberapa string `start`, mengekodnya ke dalam urutan `inp`, dan kemudian pada setiap langkah kita akan memanggil rangkaian kita untuk menyimpulkan aksara seterusnya.\n",
"\n",
"Output daripada rangkaian `out` adalah vektor dengan elemen sebanyak `vocab_size` yang mewakili kebarangkalian setiap token, dan kita boleh mencari nombor token yang paling mungkin dengan menggunakan `argmax`. Kemudian, kita tambahkan aksara ini ke senarai token yang dijana, dan teruskan proses penjanaan. Proses ini, iaitu penjanaan satu aksara, diulang sebanyak `size` kali untuk menjana jumlah aksara yang diperlukan, dan kita akan berhenti lebih awal apabila `eos_token` ditemui.\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": [
"## Menyampel output semasa latihan\n",
"\n",
"Oleh kerana kita tidak mempunyai metrik berguna seperti *ketepatan*, satu-satunya cara untuk melihat bahawa model kita semakin baik adalah dengan **menyampel** string yang dihasilkan semasa latihan. Untuk melakukannya, kita akan menggunakan **callback**, iaitu fungsi yang boleh kita serahkan kepada fungsi `fit`, dan yang akan dipanggil secara berkala semasa latihan.\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": [
"Contoh ini sudah menghasilkan teks yang cukup baik, tetapi ia boleh diperbaiki lagi dalam beberapa cara:\n",
"\n",
"* **Lebih banyak teks**. Kita hanya menggunakan tajuk untuk tugas kita, tetapi anda mungkin ingin mencuba dengan teks penuh. Ingat bahawa RNN tidak terlalu bagus dalam mengendalikan urutan panjang, jadi adalah masuk akal untuk membahagikannya kepada ayat yang lebih pendek, atau sentiasa melatih pada panjang urutan tetap dengan nilai yang telah ditetapkan `num_chars` (contohnya, 256). Anda boleh cuba mengubah contoh di atas kepada seni bina seperti ini, menggunakan [tutorial rasmi Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) sebagai inspirasi.\n",
"\n",
"* **LSTM berlapis-lapis**. Adalah masuk akal untuk mencuba 2 atau 3 lapisan sel LSTM. Seperti yang disebutkan dalam unit sebelumnya, setiap lapisan LSTM mengekstrak corak tertentu daripada teks, dan dalam kes penjana peringkat aksara, kita boleh menjangkakan lapisan LSTM yang lebih rendah bertanggungjawab untuk mengekstrak suku kata, dan lapisan yang lebih tinggi - untuk perkataan dan kombinasi perkataan. Ini boleh dilaksanakan dengan mudah dengan memberikan parameter bilangan lapisan kepada pembina LSTM.\n",
"\n",
"* Anda juga mungkin ingin bereksperimen dengan **unit GRU** dan melihat mana yang memberikan prestasi lebih baik, serta dengan **saiz lapisan tersembunyi yang berbeza**. Lapisan tersembunyi yang terlalu besar mungkin menyebabkan overfitting (contohnya, rangkaian akan belajar teks secara tepat), dan saiz yang lebih kecil mungkin tidak menghasilkan keputusan yang baik.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Penjanaan teks lembut dan suhu\n",
"\n",
"Dalam definisi `generate` sebelum ini, kita sentiasa memilih aksara dengan kebarangkalian tertinggi sebagai aksara seterusnya dalam teks yang dijana. Ini menyebabkan teks sering \"berulang\" antara urutan aksara yang sama berulang kali, seperti dalam contoh ini:\n",
"```\n",
"today of the second the company and a second the company ...\n",
"```\n",
"\n",
"Namun, jika kita melihat pada taburan kebarangkalian untuk aksara seterusnya, mungkin perbezaan antara beberapa kebarangkalian tertinggi tidak begitu besar, contohnya satu aksara boleh mempunyai kebarangkalian 0.2, manakala yang lain - 0.19, dan sebagainya. Sebagai contoh, apabila mencari aksara seterusnya dalam urutan '*play*', aksara seterusnya boleh jadi sama ada ruang, atau **e** (seperti dalam perkataan *player*).\n",
"\n",
"Ini membawa kita kepada kesimpulan bahawa tidak selalu \"adil\" untuk memilih aksara dengan kebarangkalian lebih tinggi, kerana memilih yang kedua tertinggi masih boleh menghasilkan teks yang bermakna. Lebih bijak untuk **sampel** aksara daripada taburan kebarangkalian yang diberikan oleh output rangkaian.\n",
"\n",
"Pensampelan ini boleh dilakukan menggunakan fungsi `np.multinomial` yang melaksanakan apa yang dipanggil **taburan multinomial**. Fungsi yang melaksanakan penjanaan teks **lembut** ini ditakrifkan di bawah:\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": [
"Kami telah memperkenalkan satu lagi parameter yang dipanggil **temperature**, yang digunakan untuk menunjukkan sejauh mana kita harus berpegang kepada kebarangkalian tertinggi. Jika temperature adalah 1.0, kita melakukan pensampelan multinomial yang adil, dan apabila temperature meningkat ke infiniti - semua kebarangkalian menjadi sama, dan kita memilih aksara seterusnya secara rawak. Dalam contoh di bawah, kita dapat melihat bahawa teks menjadi tidak bermakna apabila kita meningkatkan temperature terlalu tinggi, dan ia menyerupai teks \"berkitar\" yang dihasilkan secara keras apabila ia menjadi lebih dekat kepada 0.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Penafian**: \nDokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Walaupun kami berusaha untuk memastikan ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat penting, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.\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:40:35+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "ms"
}
},
"nbformat": 4,
"nbformat_minor": 4
}