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

497 lines
28 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Jaringan Generatif\n",
"\n",
"Recurrent Neural Networks (RNNs) dan varian sel bergerbang seperti Long Short Term Memory Cells (LSTMs) dan Gated Recurrent Units (GRUs) menyediakan mekanisme untuk pemodelan bahasa, yaitu mereka dapat mempelajari urutan kata dan memberikan prediksi untuk kata berikutnya dalam sebuah urutan. Hal ini memungkinkan kita menggunakan RNN untuk **tugas generatif**, seperti pembuatan teks biasa, terjemahan mesin, dan bahkan pembuatan keterangan gambar.\n",
"\n",
"Dalam arsitektur RNN yang kita bahas di unit sebelumnya, setiap unit RNN menghasilkan keadaan tersembunyi berikutnya sebagai output. Namun, kita juga dapat menambahkan output lain ke setiap unit rekuren, yang memungkinkan kita menghasilkan sebuah **urutan** (yang panjangnya sama dengan urutan aslinya). Selain itu, kita dapat menggunakan unit RNN yang tidak menerima input di setiap langkah, dan hanya mengambil vektor keadaan awal, lalu menghasilkan urutan output.\n",
"\n",
"Di notebook ini, kita akan fokus pada model generatif sederhana yang membantu kita menghasilkan teks. Untuk kesederhanaan, mari kita membangun **jaringan tingkat karakter**, yang menghasilkan teks huruf demi huruf. Selama pelatihan, kita perlu mengambil korpus teks dan membaginya menjadi 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": [
"## Membangun Kosakata Karakter\n",
"\n",
"Untuk membangun jaringan generatif tingkat karakter, kita perlu membagi teks menjadi karakter individu, bukan kata. Lapisan `TextVectorization` yang telah kita gunakan sebelumnya tidak dapat melakukan itu, jadi kita memiliki dua opsi:\n",
"\n",
"* Memuat teks secara manual dan melakukan tokenisasi 'secara manual', seperti dalam [contoh resmi Keras ini](https://keras.io/examples/generative/lstm_character_level_text_generation/)\n",
"* Menggunakan kelas `Tokenizer` untuk tokenisasi tingkat karakter.\n",
"\n",
"Kita akan memilih opsi kedua. `Tokenizer` juga dapat digunakan untuk tokenisasi menjadi kata, sehingga seseorang dapat dengan mudah beralih dari tokenisasi tingkat karakter ke tingkat kata.\n",
"\n",
"Untuk melakukan tokenisasi tingkat 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 khusus untuk menandakan **akhir dari urutan**, yang akan kami sebut `<eos>`. Mari kita tambahkan secara manual ke kosakata:\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 mengkodekan teks menjadi urutan angka, kita dapat 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 Membuat Judul\n",
"\n",
"Cara kita melatih RNN untuk menghasilkan judul berita adalah sebagai berikut. Pada setiap langkah, kita akan mengambil satu judul, yang akan dimasukkan ke dalam RNN, dan untuk setiap karakter input, kita akan meminta jaringan untuk menghasilkan karakter output berikutnya:\n",
"\n",
"![Gambar yang menunjukkan contoh RNN menghasilkan kata 'HELLO'.](../../../../../translated_images/id/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"Untuk karakter terakhir dari urutan kita, kita akan meminta jaringan untuk menghasilkan token `<eos>`.\n",
"\n",
"Perbedaan utama antara RNN generatif yang kita gunakan di sini adalah bahwa kita akan mengambil output dari setiap langkah RNN, bukan hanya dari sel terakhir. Hal ini dapat dicapai dengan menentukan parameter `return_sequences` pada sel RNN.\n",
"\n",
"Jadi, selama pelatihan, input ke jaringan akan berupa urutan karakter yang telah dikodekan dengan panjang tertentu, dan outputnya akan berupa urutan dengan panjang yang sama, tetapi digeser satu elemen dan diakhiri dengan `<eos>`. Minibatch akan terdiri dari beberapa urutan seperti itu, dan kita perlu menggunakan **padding** untuk menyelaraskan semua urutan.\n",
"\n",
"Mari kita buat fungsi-fungsi yang akan mengubah dataset untuk kita. Karena kita ingin melakukan padding pada tingkat minibatch, kita akan terlebih dahulu membuat batch dataset dengan memanggil `.batch()`, lalu menggunakan `map` untuk melakukan transformasi. Jadi, fungsi transformasi akan mengambil seluruh 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 hal penting yang kami lakukan di sini:\n",
"* Pertama, kami mengekstrak teks sebenarnya dari tensor string\n",
"* `text_to_sequences` mengubah daftar string menjadi daftar tensor integer\n",
"* `pad_sequences` menambahkan padding pada tensor tersebut hingga panjang maksimum\n",
"* Akhirnya, kami melakukan one-hot encoding pada semua karakter, serta melakukan pergeseran dan menambahkan `<eos>`. Kita akan segera melihat mengapa kita membutuhkan karakter yang di-encode dengan one-hot\n",
"\n",
"Namun, fungsi ini bersifat **Pythonic**, yaitu tidak dapat secara otomatis diterjemahkan ke dalam grafik komputasi Tensorflow. Kita akan mendapatkan error jika mencoba 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": [
"> **Note**: Membedakan antara fungsi transformasi Pythonic dan Tensorflow mungkin terasa terlalu rumit, dan Anda mungkin bertanya-tanya mengapa kita tidak mengubah dataset menggunakan fungsi Python standar sebelum meneruskannya ke `fit`. Meskipun hal ini tentu saja bisa dilakukan, menggunakan `Dataset.map` memiliki keuntungan besar, karena pipeline transformasi data dieksekusi menggunakan grafik komputasi Tensorflow, yang memanfaatkan perhitungan GPU, dan meminimalkan kebutuhan untuk memindahkan data antara CPU/GPU.\n",
"\n",
"Sekarang kita dapat membangun jaringan generator kita dan mulai pelatihan. Jaringan ini dapat didasarkan pada sel rekuren apa pun yang telah kita bahas di unit sebelumnya (simple, LSTM, atau GRU). Dalam contoh kita, kita akan menggunakan LSTM.\n",
"\n",
"Karena jaringan menerima karakter sebagai input, dan ukuran kosakata cukup kecil, kita tidak memerlukan lapisan embedding, input yang dienkode satu-hot dapat langsung masuk ke sel LSTM. Lapisan output akan menjadi classifier `Dense` yang akan mengubah output LSTM menjadi angka token yang dienkode satu-hot.\n",
"\n",
"Selain itu, karena kita berurusan dengan urutan dengan panjang variabel, kita dapat menggunakan lapisan `Masking` untuk membuat mask yang akan mengabaikan bagian string yang diisi (padded). Ini sebenarnya tidak terlalu diperlukan, karena kita tidak terlalu tertarik pada apa pun yang melampaui token `<eos>`, tetapi kita akan menggunakannya demi mendapatkan pengalaman dengan jenis lapisan ini. `input_shape` akan menjadi `(None, vocab_size)`, di mana `None` menunjukkan urutan dengan panjang variabel, dan bentuk output juga `(None, vocab_size)`, seperti yang dapat Anda lihat dari `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": [
"## Menghasilkan Output\n",
"\n",
"Sekarang setelah kita melatih model, kita ingin menggunakannya untuk menghasilkan output. Pertama-tama, kita membutuhkan cara untuk mendekode teks yang direpresentasikan oleh urutan angka token. Untuk melakukan ini, kita bisa menggunakan fungsi `tokenizer.sequences_to_texts`; namun, fungsi ini tidak bekerja dengan baik pada tokenisasi tingkat karakter. Oleh karena itu, kita akan mengambil kamus token dari tokenizer (disebut `word_index`), membangun peta balik, dan menulis fungsi dekode 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 mulai dengan beberapa string `start`, mengkodekannya menjadi sebuah urutan `inp`, dan kemudian pada setiap langkah kita akan memanggil jaringan kita untuk menyimpulkan karakter berikutnya.\n",
"\n",
"Output dari jaringan `out` adalah sebuah vektor dengan `vocab_size` elemen yang merepresentasikan probabilitas dari setiap token, dan kita dapat menemukan nomor token yang paling mungkin dengan menggunakan `argmax`. Kemudian kita menambahkan karakter ini ke daftar token yang dihasilkan, dan melanjutkan proses generasi. Proses menghasilkan satu karakter ini diulangi sebanyak `size` kali untuk menghasilkan jumlah karakter yang diperlukan, dan kita akan menghentikan proses lebih awal ketika `eos_token` ditemukan.\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": [
"## Mengambil sampel output selama pelatihan\n",
"\n",
"Karena kita tidak memiliki metrik yang berguna seperti *akurasi*, satu-satunya cara untuk melihat bahwa model kita semakin baik adalah dengan **mengambil sampel** string yang dihasilkan selama pelatihan. Untuk melakukannya, kita akan menggunakan **callback**, yaitu fungsi yang dapat kita berikan ke fungsi `fit`, dan yang akan dipanggil secara berkala selama pelatihan.\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 masih bisa ditingkatkan dalam beberapa cara:\n",
"\n",
"* **Lebih banyak teks**. Kita hanya menggunakan judul untuk tugas ini, tetapi Anda mungkin ingin bereksperimen dengan teks lengkap. Ingatlah bahwa RNN tidak terlalu baik dalam menangani urutan panjang, jadi masuk akal untuk membaginya menjadi kalimat pendek, atau selalu melatih pada panjang urutan tetap dengan nilai yang telah ditentukan sebelumnya `num_chars` (misalnya, 256). Anda dapat mencoba mengubah contoh di atas menjadi arsitektur seperti itu, menggunakan [tutorial resmi Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) sebagai inspirasi.\n",
"\n",
"* **LSTM multilayer**. Ada baiknya mencoba 2 atau 3 lapisan sel LSTM. Seperti yang disebutkan dalam unit sebelumnya, setiap lapisan LSTM mengekstrak pola tertentu dari teks, dan dalam kasus generator tingkat karakter, kita dapat mengharapkan tingkat LSTM yang lebih rendah bertanggung jawab untuk mengekstrak suku kata, dan tingkat yang lebih tinggi - untuk kata dan kombinasi kata. Ini dapat diimplementasikan dengan mudah dengan memberikan parameter jumlah lapisan ke konstruktor LSTM.\n",
"\n",
"* Anda juga mungkin ingin bereksperimen dengan **unit GRU** dan melihat mana yang memberikan hasil lebih baik, serta dengan **ukuran lapisan tersembunyi yang berbeda**. Lapisan tersembunyi yang terlalu besar dapat menyebabkan overfitting (misalnya, jaringan akan mempelajari teks secara persis), dan ukuran yang lebih kecil mungkin tidak menghasilkan hasil yang baik.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generasi teks lunak dan suhu\n",
"\n",
"Dalam definisi `generate` sebelumnya, kita selalu memilih karakter dengan probabilitas tertinggi sebagai karakter berikutnya dalam teks yang dihasilkan. Hal ini menyebabkan teks sering \"berulang\" pada urutan karakter yang sama berulang kali, seperti dalam contoh berikut:\n",
"```\n",
"today of the second the company and a second the company ...\n",
"```\n",
"\n",
"Namun, jika kita melihat distribusi probabilitas untuk karakter berikutnya, bisa jadi perbedaan antara beberapa probabilitas tertinggi tidak terlalu besar, misalnya satu karakter memiliki probabilitas 0.2, sementara karakter lain - 0.19, dan sebagainya. Sebagai contoh, ketika mencari karakter berikutnya dalam urutan '*play*', karakter berikutnya bisa saja berupa spasi, atau **e** (seperti dalam kata *player*).\n",
"\n",
"Hal ini membawa kita pada kesimpulan bahwa tidak selalu \"adil\" untuk memilih karakter dengan probabilitas lebih tinggi, karena memilih karakter dengan probabilitas tertinggi kedua masih bisa menghasilkan teks yang bermakna. Akan lebih bijaksana untuk **mengambil sampel** karakter dari distribusi probabilitas yang diberikan oleh output jaringan.\n",
"\n",
"Pengambilan sampel ini dapat dilakukan menggunakan fungsi `np.multinomial` yang mengimplementasikan apa yang disebut sebagai **distribusi multinomial**. Fungsi yang mengimplementasikan generasi teks **lunak** ini didefinisikan 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 parameter lagi yang disebut **temperature**, yang digunakan untuk menunjukkan seberapa ketat kita harus berpegang pada probabilitas tertinggi. Jika temperature adalah 1.0, kita melakukan sampling multinomial yang adil, dan ketika temperature mendekati tak hingga - semua probabilitas menjadi sama, dan kita secara acak memilih karakter berikutnya. Dalam contoh di bawah ini, kita dapat mengamati bahwa teks menjadi tidak bermakna ketika kita meningkatkan temperature terlalu tinggi, dan teks tersebut menyerupai teks \"berulang\" yang dihasilkan secara kaku ketika mendekati 0.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Penafian**: \nDokumen ini telah diterjemahkan menggunakan layanan penerjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Meskipun kami berupaya untuk memberikan hasil yang akurat, harap diperhatikan bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang berwenang. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa penerjemahan manusia profesional. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari 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:39:45+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "id"
}
},
"nbformat": 4,
"nbformat_minor": 4
}