AI-For-Beginners/translations/my/lessons/5-NLP/16-RNN/RNNTF.ipynb

460 lines
42 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ပြန်လည်ထပ်ခါတလဲလဲ နယူးရယ်နက်ဝက်များ\n",
"\n",
"ယခင် module တွင်၊ စာသားများ၏ အဓိပ္ပါယ်ဆိုင်ရာ သက်သေခံမှုများကို လေ့လာခဲ့ပါသည်။ ကျွန်ုပ်တို့အသုံးပြုနေသော architecture သည် စာကြောင်းတစ်ကြောင်းအတွင်းရှိ စကားလုံးများ၏ ပေါင်းစည်းထားသော အဓိပ္ပါယ်ကို ဖမ်းဆီးနိုင်သည်။ သို့သော် စကားလုံးများ၏ **အစီအစဉ်** ကို မထည့်သွင်းစဉ်းစားနိုင်ပါ၊ အကြောင်းမှာ embedding များကို လိုက်နာပြီး aggregation လုပ်ငန်းစဉ်သည် မူလစာသားမှ အချက်အလက်များကို ဖယ်ရှားလိုက်သောကြောင့် ဖြစ်သည်။ စကားလုံးအစီအစဉ်ကို ကိုယ်စားပြုနိုင်မှုမရှိသောကြောင့်၊ မိမိတို့သည် စာသားထုတ်လုပ်ခြင်း သို့မဟုတ် မေးခွန်းဖြေဆိုခြင်းကဲ့သို့သော ပိုမိုရှုပ်ထွေးသော သို့မဟုတ် မရှင်းလင်းသော လုပ်ငန်းများကို ဖြေရှင်းနိုင်မည်မဟုတ်ပါ။\n",
"\n",
"စာသားအစီအစဉ်၏ အဓိပ္ပါယ်ကို ဖမ်းဆီးရန်၊ **recurrent neural network** (RNN) ဟုခေါ်သော နယူးရယ်နက်ဝက် architecture ကို အသုံးပြုမည်ဖြစ်သည်။ RNN ကို အသုံးပြုသောအခါ၊ ကျွန်ုပ်တို့၏ စာကြောင်းကို network အတွင်းသို့ token တစ်ခုစီဖြင့် အဆင့်ဆင့် ဖြတ်သန်းပြီး၊ network သည် **state** တစ်ခုကို ထုတ်ပေးမည်ဖြစ်သည်။ ထို state ကို နောက် token နှင့်အတူ network သို့ ပြန်လည်ထည့်သွင်းမည်ဖြစ်သည်။\n",
"\n",
"![Recurrent neural network ထုတ်လုပ်မှု၏ ဥပမာကို ပြသသော ပုံ။](../../../../../translated_images/my/rnn.27f5c29c53d727b5.webp)\n",
"\n",
"tokens များ၏ input အစီအစဉ် $X_0,\\dots,X_n$ ကို ပေးသောအခါ၊ RNN သည် နယူးရယ်နက်ဝက် block များ၏ အစီအစဉ်တစ်ခုကို ဖန်တီးပြီး၊ ထိုအစီအစဉ်ကို backpropagation အသုံးပြု၍ အဆုံးမှ အဆုံးသို့ လေ့ကျင့်သည်။ network block တစ်ခုစီသည် $(X_i,S_i)$ ကို input အနေဖြင့် လက်ခံပြီး၊ $S_{i+1}$ ကို ရလဒ်အဖြစ် ထုတ်ပေးသည်။ နောက်ဆုံး state $S_n$ သို့မဟုတ် output $Y_n$ ကို linear classifier သို့ ပေးပို့ပြီး ရလဒ်ကို ထုတ်ယူသည်။ network block အားလုံးသည် တူညီသော weight များကို မျှဝေထားပြီး၊ တစ်ကြိမ်တည်းသော backpropagation pass ဖြင့် အဆုံးမှ အဆုံးသို့ လေ့ကျင့်သည်။\n",
"\n",
"> အထက်ပါပုံတွင် RNN ကို unrolled ပုံစံ (ဘယ်ဖက်တွင်) နှင့် ပိုမိုချုပ်ငြိ RNN ကိုယ်စားပြုမှု (ညာဖက်တွင်) အနေဖြင့် ပြထားသည်။ RNN Cells အားလုံးတွင် **မျှဝေနိုင်သော weight များ** ရှိသည်ကို နားလည်ရန် အရေးကြီးသည်။\n",
"\n",
"state vectors $S_0,\\dots,S_n$ များကို network အတွင်း ဖြတ်သန်းပေးသောကြောင့်၊ RNN သည် စကားလုံးများအကြား အစီအစဉ်ဆိုင်ရာ အချိတ်အဆက်များကို သင်ယူနိုင်သည်။ ဥပမာအားဖြင့်၊ စာကြောင်းတစ်ခုအတွင်း *not* ဟူသော စကားလုံးတစ်လုံး ပေါ်လာသောအခါ၊ state vector အတွင်းရှိ အချို့သော အရာများကို ငြင်းဆိုရန် သင်ယူနိုင်သည်။\n",
"\n",
"RNN cell တစ်ခုစီအတွင်းတွင် weight matrix နှစ်ခု $W_H$ နှင့် $W_I$၊ နှင့် bias $b$ တို့ ပါဝင်သည်။ RNN အဆင့်တစ်ခုစီတွင်၊ input $X_i$ နှင့် input state $S_i$ ကို ပေးသောအခါ၊ output state ကို $S_{i+1} = f(W_H\\times S_i + W_I\\times X_i+b)$ အဖြစ်တွက်ချက်သည်၊ ဤတွင် $f$ သည် activation function (အများအားဖြင့် $\\tanh$) ဖြစ်သည်။\n",
"\n",
"> စာသားထုတ်လုပ်မှု (ကျွန်ုပ်တို့သည် နောက်ထပ် unit တွင် လေ့လာမည့်အရာ) သို့မဟုတ် စက်ဖြင့်ဘာသာပြန်ခြင်းကဲ့သို့သော ပြဿနာများအတွက်၊ RNN အဆင့်တစ်ခုစီတွင် output တန်ဖိုးတစ်ခုကိုလည်း ရရှိလိုသည်။ ဤအခါတွင် $W_O$ ဟုခေါ်သော matrix တစ်ခုလည်း ရှိပြီး၊ output ကို $Y_i=f(W_O\\times S_i+b_O)$ အဖြစ်တွက်ချက်သည်။\n",
"\n",
"ယခု RNN များက ကျွန်ုပ်တို့၏ သတင်းဒေတာစုပေါင်းကို မည်သို့ ခွဲခြားနိုင်မည်ကို ကြည့်ကြရအောင်။\n",
"\n",
"> sandbox ပတ်ဝန်းကျင်အတွက်၊ လိုအပ်သော library ကို install လုပ်ပြီး၊ ဒေတာကို ကြိုတင်ရယူထားရန် အောက်ပါ cell ကို run လိုက်ရမည်ဖြစ်သည်။ သင်သည် local တွင် run လုပ်နေပါက၊ အောက်ပါ cell ကို ကျော်သွားနိုင်သည်။\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"!{sys.executable} -m pip install --quiet tensorflow_datasets==4.4.0\n",
"!cd ~ && wget -q -O - https://mslearntensorflowlp.blob.core.windows.net/data/tfds-ag-news.tgz | tar xz"
]
},
{
"cell_type": "code",
"execution_count": 2,
"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",
"# We are going to be training pretty large models. In order not to face errors, we need\n",
"# to set tensorflow option to grow GPU memory allocation when required\n",
"physical_devices = tf.config.list_physical_devices('GPU') \n",
"if len(physical_devices)>0:\n",
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
"\n",
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
]
},
{
"cell_type": "markdown",
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
},
"source": [
"အကြီးမားသောမော်ဒယ်များကိုလေ့ကျင့်နေစဉ် GPU မှတ်ဉာဏ်အသုံးပြုမှုသည်ပြဿနာဖြစ်နိုင်ပါသည်။ ဒါ့အပြင် GPU မှတ်ဉာဏ်ထဲသို့ဒေတာကိုသင့်တော်စွာထည့်နိုင်ရန်နှင့်လေ့ကျင့်မှုအမြန်နှုန်းလုံလောက်စေရန် မီနီဘတ်ချ်အရွယ်အစားများကိုစမ်းသပ်ရန်လိုအပ်နိုင်ပါသည်။ သင်၏ကိုယ်ပိုင် GPU စက်ပေါ်တွင်ဤကုဒ်ကိုအလုပ်လုပ်နေပါက လေ့ကျင့်မှုအမြန်နှုန်းကိုမြှင့်တင်ရန် မီနီဘတ်ချ်အရွယ်အစားကိုချိန်ညှိခြင်းကိုစမ်းသပ်နိုင်ပါသည်။\n",
"\n",
"> **Note**: NVidia driver အချို့ဗားရှင်းများသည် မော်ဒယ်ကိုလေ့ကျင့်ပြီးနောက်မှတ်ဉာဏ်ကိုလွှတ်မပေးကြောင်းသိရှိထားပါသည်။ ဤ notebook တွင် ဥပမာများစွာကိုအလုပ်လုပ်နေပြီး သင့် notebook တွင်ကိုယ်ပိုင်စမ်းသပ်မှုများပြုလုပ်နေပါက အချို့သော setup များတွင်မှတ်ဉာဏ်ကုန်ခန်းနိုင်ပါသည်။ မော်ဒယ်ကိုလေ့ကျင့်ရန်စတင်သောအခါ အဆင်မပြေသောအမှားများကြုံတွေ့ပါက notebook kernel ကိုပြန်လည်စတင်ရန်လိုအပ်နိုင်ပါသည်။\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true,
"jupyter": {
"outputs_hidden": false,
"source_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
}
},
"outputs": [],
"source": [
"batch_size = 16\n",
"embed_size = 64"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ရိုးရှင်းသော RNN ခွဲခြားသူ\n",
"\n",
"ရိုးရှင်းသော RNN ၏အခြေအနေတွင်၊ တစ်ခုချင်းစီသော recurrent unit သည် ရိုးရှင်းသော linear network တစ်ခုဖြစ်ပြီး၊ input vector နှင့် state vector တို့ကို လက်ခံပြီး၊ state vector အသစ်တစ်ခုကို ထုတ်ပေးသည်။ Keras တွင်၊ ၎င်းကို `SimpleRNN` layer ဖြင့် ကိုယ်စားပြုနိုင်သည်။\n",
"\n",
"RNN layer သို့ one-hot encoded tokens များကို တိုက်ရိုက်ပို့နိုင်သော်လည်း၊ ၎င်းတို့၏ အတိုင်းအတာမြင့်မားမှုကြောင့် ၎င်းသည် ကောင်းမွန်သော အကြံမဟုတ်ပါ။ ထို့ကြောင့်၊ စကားလုံး vector များ၏ အတိုင်းအတာကို လျှော့ချရန် embedding layer တစ်ခုကို အသုံးပြုမည်ဖြစ်ပြီး၊ ထို့နောက် RNN layer တစ်ခုနှင့် နောက်ဆုံးတွင် `Dense` ခွဲခြားသူတစ်ခုကို အသုံးပြုမည်ဖြစ်သည်။\n",
"\n",
"> **Note**: အတိုင်းအတာမမြင့်မားသည့် အခြေအနေများတွင်၊ ဥပမာအားဖြင့် character-level tokenization ကို အသုံးပြုသောအခါ၊ one-hot encoded tokens များကို RNN cell ထဲသို့ တိုက်ရိုက်ပို့ခြင်းသည် make sense ဖြစ်နိုင်ပါသည်။\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"text_vectorization (TextVect (None, None) 0 \n",
"_________________________________________________________________\n",
"embedding (Embedding) (None, None, 64) 1280000 \n",
"_________________________________________________________________\n",
"simple_rnn (SimpleRNN) (None, 16) 1296 \n",
"_________________________________________________________________\n",
"dense (Dense) (None, 4) 68 \n",
"=================================================================\n",
"Total params: 1,281,364\n",
"Trainable params: 1,281,364\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"vocab_size = 20000\n",
"\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(\n",
" max_tokens=vocab_size,\n",
" input_shape=(1,))\n",
"\n",
"model = keras.models.Sequential([\n",
" vectorizer,\n",
" keras.layers.Embedding(vocab_size, embed_size),\n",
" keras.layers.SimpleRNN(16),\n",
" keras.layers.Dense(4,activation='softmax')\n",
"])\n",
"\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **မှတ်ချက်:** ဒီနေရာမှာ ကျွန်တော်တို့ အလွယ်တကူ အသုံးပြုနိုင်ဖို့ untrained embedding layer ကို သုံးထားပါတယ်၊ ဒါပေမယ့် ပိုမိုကောင်းမွန်တဲ့ရလဒ်ရဖို့ Word2Vec ကို အသုံးပြုပြီး pretrained embedding layer ကို သုံးနိုင်ပါတယ်၊ အရင်ယူနစ်မှာ ဖော်ပြထားသလိုပဲ။ Pretrained embeddings ကို အသုံးပြုဖို့ ဒီကုဒ်ကို ပြောင်းလဲဖို့ ကြိုးစားကြည့်တာက သင့်အတွက် ကောင်းမွန်တဲ့လေ့ကျင့်ခန်းတစ်ခု ဖြစ်နိုင်ပါတယ်။\n",
"\n",
"အခုတော့ ကျွန်တော်တို့ရဲ့ RNN ကို လေ့ကျင့်ကြည့်ရအောင်။ RNN တွေကို အထွေထွေ လေ့ကျင့်ဖို့ ခက်ခဲတတ်ပါတယ်၊ အကြောင်းကတော့ RNN cells တွေကို sequence length အတိုင်း unroll လုပ်ပြီးရင် backpropagation အတွက် ပါဝင်တဲ့ layer အရေအတွက်က အလွန်များလာတတ်လို့ပါပဲ။ ဒါကြောင့် learning rate ကို သေးငယ်တဲ့တန်ဖိုးတစ်ခုရွေးချယ်ရပြီး၊ ကောင်းမွန်တဲ့ရလဒ်ရဖို့ dataset ကြီးတစ်ခုမှာ network ကို လေ့ကျင့်ရပါတယ်။ ဒါကြောင့် အချိန်အတော်ကြာတတ်ပြီး GPU ကို အသုံးပြုရင် ပိုမိုအဆင်ပြေပါတယ်။\n",
"\n",
"အချိန်ကို လျှော့ချဖို့ RNN မော်ဒယ်ကို သတင်းခေါင်းစဉ်များပေါ်မှာသာ လေ့ကျင့်မှာဖြစ်ပြီး၊ ဖော်ပြချက်ကို မပါဝင်စေပါဘူး။ သင်ဖော်ပြချက်နဲ့အတူ လေ့ကျင့်ကြည့်ပြီး မော်ဒယ်ကို လေ့ကျင့်နိုင်မလား စမ်းကြည့်နိုင်ပါတယ်။\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n"
]
}
],
"source": [
"def extract_title(x):\n",
" return x['title']\n",
"\n",
"def tupelize_title(x):\n",
" return (extract_title(x),x['label'])\n",
"\n",
"print('Training vectorizer')\n",
"vectorizer.adapt(ds_train.take(2000).map(extract_title))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7500/7500 [==============================] - 82s 11ms/step - loss: 0.6629 - acc: 0.7623 - val_loss: 0.5559 - val_acc: 0.7995\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f3e0030d350>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize_title).batch(batch_size),validation_data=ds_test.map(tupelize_title).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
},
"source": [
"**မှတ်ချက်** သတင်းခေါင်းစဉ်များပေါ်တွင်သာလေ့ကျင့်နေသောကြောင့် တိကျမှုနည်းနိုင်ပါသည်။\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Variable Sequences ကို ပြန်လည်ဆန်းစစ်ခြင်း\n",
"\n",
"`TextVectorization` layer သည် minibatch အတွင်းရှိ အလျားအစား မတူညီသော sequence များကို အလိုအလျောက် pad token များဖြင့် ဖြည့်စွက်ပေးမည်ဖြစ်သည်ကို သတိရပါ။ သို့သော်၊ ထို token များသည်လည်း training အတွင်း ပါဝင်လာပြီး၊ model ၏ convergence ကို ရှုပ်ထွေးစေနိုင်ပါသည်။\n",
"\n",
"Padding အရေအတွက်ကို လျှော့ချရန်အတွက် ကျွန်ုပ်တို့ လုပ်ဆောင်နိုင်သည့် နည်းလမ်းအချို့ ရှိပါသည်။ ထိုနည်းလမ်းများထဲမှ တစ်ခုမှာ dataset ကို sequence အလျားအစားအလိုက် ပြန်လည်စီစဉ်ပြီး၊ အရွယ်အစားတူ sequence များကို အုပ်စုဖွဲ့ခြင်းဖြစ်သည်။ ၎င်းကို `tf.data.experimental.bucket_by_sequence_length` function ကို အသုံးပြု၍ ပြုလုပ်နိုင်ပါသည် (အချက်အလက်များကို [documentation](https://www.tensorflow.org/api_docs/python/tf/data/experimental/bucket_by_sequence_length) တွင် ကြည့်ရှုနိုင်ပါသည်)။\n",
"\n",
"အခြားနည်းလမ်းတစ်ခုမှာ **masking** ကို အသုံးပြုခြင်းဖြစ်သည်။ Keras တွင် layer အချို့သည် training အတွင်း အဘယ် token များကို အရေးထားရမည်ကို ပြသသည့် အပို input ကို ပံ့ပိုးပေးပါသည်။ Masking ကို model အတွင်း ထည့်သွင်းရန်အတွက်၊ `Masking` layer ([docs](https://keras.io/api/layers/core_layers/masking/)) ကို သီးခြားထည့်သွင်းနိုင်သလို၊ `Embedding` layer ၏ `mask_zero=True` parameter ကို သတ်မှတ်နိုင်ပါသည်။\n",
"\n",
"> **Note**: ဒီ training ကို dataset အပြည့်အစုံအတွက် တစ်ခါ epoch ပြီးမြောက်ရန် ၅ မိနစ်ခန့် ကြာမြင့်မည်ဖြစ်သည်။ သည်းမခံနိုင်လျှင် training ကို မည်သည့်အချိန်တွင်မဆို ရပ်တန့်နိုင်ပါသည်။ ထို့အပြင် training အတွက် အသုံးပြုမည့် data အရေအတွက်ကို ကန့်သတ်လိုပါက `ds_train` နှင့် `ds_test` dataset များအပြီးတွင် `.take(...)` clause ကို ထည့်သွင်းနိုင်ပါသည်။\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7500/7500 [==============================] - 371s 49ms/step - loss: 0.5401 - acc: 0.8079 - val_loss: 0.3780 - val_acc: 0.8822\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f3dec118850>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"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",
"model = keras.models.Sequential([\n",
" vectorizer,\n",
" keras.layers.Embedding(vocab_size,embed_size,mask_zero=True),\n",
" keras.layers.SimpleRNN(16),\n",
" keras.layers.Dense(4,activation='softmax')\n",
"])\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ယခု Masking ကို အသုံးပြုနေသောကြောင့်၊ ခေါင်းစဉ်များနှင့် ဖော်ပြချက်များ၏ အချက်အလက်စုစည်းမှုအားလုံးကို အသုံးပြု၍ မော်ဒယ်ကို လေ့ကျင့်နိုင်ပါပြီ။\n",
"\n",
"> **Note**: သတိထားမိပါသလား၊ ကျွန်ုပ်တို့သည် သတင်းခေါင်းစဉ်များပေါ်တွင် လေ့ကျင့်ထားသော vectorizer ကို အသုံးပြုနေပြီး၊ ဆောင်းပါး၏ အပြည့်အစုံကို မဟုတ်ပါ။ အခြား token အချို့ကို မသိသာစေခြင်း ဖြစ်နိုင်ပြီး၊ vectorizer ကို ပြန်လည်လေ့ကျင့်ခြင်းက ပိုမိုကောင်းမွန်နိုင်ပါသည်။ သို့သော်၊ ၎င်းသည် အလွန်သေးငယ်သော အကျိုးသက်ရောက်မှုသာ ရှိနိုင်ပြီး၊ ရိုးရှင်းမှုအတွက် ယခင်လေ့ကျင့်ထားသော vectorizer ကို ဆက်လက်အသုံးပြုမည်ဖြစ်သည်။\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LSTM: ရေရှည်-အတိုချုပ် မှတ်ဉာဏ်\n",
"\n",
"RNNs ရဲ့ အဓိကပြဿနာတစ်ခုက **gradient ပျောက်ဆုံးမှု** ဖြစ်ပါတယ်။ RNNs ဟာ အလွန်ရှည်လျားနိုင်ပြီး၊ backpropagation လုပ်စဉ်မှာ network ရဲ့ ပထမဆုံးအလွှာထိ gradient တွေကို ပြန်ပို့ဖို့ အခက်အခဲရှိနိုင်ပါတယ်။ ဒီလိုဖြစ်တဲ့အခါမှာ၊ network ဟာ အဝေးက token တွေကြားက ဆက်နွယ်မှုတွေကို သင်ယူလို့မရနိုင်ပါဘူး။ ဒီပြဿနာကို ရှောင်ရှားဖို့နည်းလမ်းတစ်ခုက **state ကို ထိန်းချုပ်မှု** ကို **gate** တွေ အသုံးပြုပြီး ထည့်သွင်းပေးတာပါ။ Gate တွေကို ထည့်သွင်းပေးတဲ့ architecture တွေထဲမှာ အများဆုံးတွေ့ရတာက **long short-term memory** (LSTM) နဲ့ **gated relay unit** (GRU) ဖြစ်ပါတယ်။ ဒီမှာတော့ LSTM တွေကို ဖော်ပြပါမယ်။\n",
"\n",
"![ရေရှည်-အတိုချုပ် မှတ်ဉာဏ် cell ရဲ့ ဥပမာပုံ](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)\n",
"\n",
"LSTM network ဟာ RNN နဲ့ ဆင်တူတဲ့ ပုံစံနဲ့ စီမံထားပြီး၊ အလွှာတစ်ခုကနေ နောက်တစ်ခုဆီကို state $c$ နဲ့ hidden vector $h$ ဆိုတဲ့ state နှစ်ခုကို ပို့ပေးပါတယ်။ Unit တစ်ခုစီမှာ hidden vector $h_{t-1}$ ကို input $x_t$ နဲ့ ပေါင်းစပ်ပြီး၊ **gate** တွေက state $c_t$ နဲ့ output $h_{t}$ ကို ထိန်းချုပ်ပေးပါတယ်။ Gate တစ်ခုစီမှာ sigmoid activation (output $[0,1]$ အတွင်း) ရှိပြီး၊ state vector ကို မျှတစွာ mask လုပ်ပေးတဲ့အခါမှာ အလုပ်လုပ်ပါတယ်။ LSTM တွေမှာ အောက်ပါ gate တွေရှိပါတယ် (အပုံမှာ ဘယ်မှညာအတိုင်း):\n",
"* **forget gate** - vector $c_{t-1}$ ရဲ့ ဘယ် components တွေကို မေ့ပစ်ရမလဲ၊ ဘယ် components တွေကို ဆက်လက်အသုံးပြုရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
"* **input gate** - input vector နဲ့ hidden vector ရဲ့ အရင်းအမြစ်တွေကို state vector ထဲမှာ ဘယ်လောက်ထိ ထည့်သွင်းရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
"* **output gate** - အသစ်ရရှိတဲ့ state vector ကိုယူပြီး၊ hidden vector $h_t$ ထုတ်လုပ်ဖို့ ဘယ် components တွေကို အသုံးပြုရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
"\n",
"State $c$ ရဲ့ components တွေကို flag တွေလို switch on/off လုပ်နိုင်ပါတယ်။ ဥပမာ၊ sequence ထဲမှာ *Alice* ဆိုတဲ့နာမည်ကိုတွေ့တဲ့အခါ၊ အမျိုးသမီးနာမည်ဖြစ်တယ်လို့ ခန့်မှန်းပြီး၊ sentence ထဲမှာ အမျိုးသမီးနာမည်ရှိတယ်ဆိုတဲ့ flag ကို state ထဲမှာတင်ထားပါတယ်။ နောက်ပိုင်းမှာ *and Tom* ဆိုတဲ့စကားလုံးတွေကိုတွေ့တဲ့အခါ၊ plural noun ရှိတယ်ဆိုတဲ့ flag ကိုတင်ပေးပါတယ်။ ဒီလို state ကို ထိန်းချုပ်ခြင်းအားဖြင့် sentence ရဲ့ သဒ္ဒါဆိုင်ရာ အကျဉ်းချုပ်တွေကို ထိန်းသိမ်းနိုင်ပါတယ်။\n",
"\n",
"> **Note**: LSTM ရဲ့ အတွင်းပိုင်းကို နားလည်ဖို့အတွက် အလွန်ကောင်းတဲ့ resource တစ်ခုက [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) by Christopher Olah ဖြစ်ပါတယ်။\n",
"\n",
"LSTM cell ရဲ့ အတွင်းပိုင်းဖွဲ့စည်းပုံဟာ ရှုပ်ထွေးနေပေမယ့်၊ Keras က `LSTM` layer ထဲမှာ ဒီ implementation ကို ဖုံးကွယ်ထားပါတယ်။ အထက်ပါဥပမာမှာ recurrent layer ကို အစားထိုးပေးရုံသာ လိုအပ်ပါတယ်။\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"15000/15000 [==============================] - 188s 13ms/step - loss: 0.5692 - acc: 0.7916 - val_loss: 0.3441 - val_acc: 0.8870\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f3d6af5c350>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" vectorizer,\n",
" keras.layers.Embedding(vocab_size, embed_size),\n",
" keras.layers.LSTM(8),\n",
" keras.layers.Dense(4,activation='softmax')\n",
"])\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(8),validation_data=ds_test.map(tupelize).batch(8))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## နှစ်ဖက်သို့လှည့်နိုင်သောနှင့် အလွှာများပါဝင်သော RNN များ\n",
"\n",
"ယခင်ဥပမာများတွင်၊ recurrent network များသည် အစမှ အဆုံးအထိ အစဉ်အတိုင်း လုပ်ဆောင်သည်။ ၎င်းသည် ကျွန်ုပ်တို့အတွက် သဘာဝကျသောအရာဖြစ်သည်၊ အကြောင်းမှာ ကျွန်ုပ်တို့ ဖတ်ခြင်း သို့မဟုတ် စကားနားထောင်ခြင်း၏ လမ်းကြောင်းနှင့် တူသော လမ်းကြောင်းကို လိုက်နာသောကြောင့်ဖြစ်သည်။ သို့သော်၊ input sequence ကို random access လုပ်ရန်လိုအပ်သော အခြေအနေများအတွက်၊ recurrent computation ကို နှစ်ဖက်လုံးတွင် လုပ်ဆောင်ခြင်းသည် ပိုမိုသင့်တော်သည်။ နှစ်ဖက်လုံးတွင် လုပ်ဆောင်နိုင်သော RNN များကို **bidirectional** RNN များဟုခေါ်ပြီး၊ ၎င်းတို့ကို `Bidirectional` layer အထူးလွှာဖြင့် recurrent layer ကို wrap လုပ်ခြင်းအားဖြင့် ဖန်တီးနိုင်သည်။\n",
"\n",
"> **Note**: `Bidirectional` layer သည် ၎င်းအတွင်းရှိ layer ကို မိတ္တူနှစ်ခု ဖန်တီးပြီး၊ မိတ္တူတစ်ခု၏ `go_backwards` property ကို `True` သတ်မှတ်ကာ sequence အတိုင်း လမ်းကြောင်းဆန့်ကျင်ဘက်သို့ သွားစေသည်။\n",
"\n",
"Recurrent network များ၊ unidirectional ဖြစ်စေ bidirectional ဖြစ်စေ၊ sequence အတွင်းရှိ pattern များကို ဖမ်းဆီးပြီး state vector များအဖြစ် သိမ်းဆည်းသို့မဟုတ် output အဖြစ် ပြန်လည်ပေးသည်။ Convolutional network များနှင့်တူပင်၊ ပထမ layer မှ အနိမ့်ဆုံး level pattern များကို ဖမ်းဆီးပြီး၊ အမြင့်ဆုံး level pattern များကို ဖမ်းဆီးရန် ပိုမိုမြင့်မားသော recurrent layer တစ်ခုကို တည်ဆောက်နိုင်သည်။ ၎င်းသည် **multi-layer RNN** ၏ အယူအဆသို့ ဦးတည်ပြီး၊ ၎င်းသည် recurrent network နှစ်ခု သို့မဟုတ် အများကြီးပါဝင်ပြီး၊ ယခင် layer ၏ output ကို နောက် layer ၏ input အဖြစ် ပေးပို့သည်။\n",
"\n",
"![Multilayer long-short-term-memory- RNN ကို ပြသထားသော ပုံ](../../../../../translated_images/my/multi-layer-lstm.dd975e29bb2a59fe.webp)\n",
"\n",
"*Fernando López ရေးသားထားသော [ဤအလွန်အမိုက်ဆုံး post](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) မှ ရိုက်ယူထားသော ပုံ။*\n",
"\n",
"Keras သည် network များကို တည်ဆောက်ရန် လွယ်ကူစေသည်၊ အကြောင်းမှာ model တွင် recurrent layer များကို ပေါင်းထည့်ရုံသာ လိုအပ်သည်။ နောက်ဆုံး layer ကို မပါဘဲ အခြား layer များအတွက် `return_sequences=True` parameter ကို သတ်မှတ်ရန်လိုအပ်သည်၊ အကြောင်းမှာ recurrent computation ၏ နောက်ဆုံး state ကိုသာမက၊ အလယ်အလတ် state များအားလုံးကို layer မှ ပြန်လည်ပေးရန်လိုအပ်သည်။\n",
"\n",
"အမျိုးအစားခွဲခြင်းပြဿနာအတွက် နှစ်လွှာ bidirectional LSTM တစ်ခုကို တည်ဆောက်ကြစို့။\n",
"\n",
"> **Note** ဤ code သည် ပြန်လည်လုပ်ဆောင်ရန် အချိန်ကြာမြင့်သော်လည်း၊ ယခင် accuracy များထက် အမြင့်ဆုံး accuracy ကို ရရှိစေသည်။ ထို့ကြောင့် အချိန်စောင့်ပြီး ရလဒ်ကို ကြည့်ရှုရန် တန်ဖိုးရှိနိုင်သည်။\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5044/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r5045/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706"
]
}
],
"source": [
"model = keras.models.Sequential([\n",
" vectorizer,\n",
" keras.layers.Embedding(vocab_size, 128, mask_zero=True),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(64,return_sequences=True)),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(64)), \n",
" keras.layers.Dense(4,activation='softmax')\n",
"])\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),\n",
" validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## RNN များကို အခြားအလုပ်များအတွက် အသုံးပြုခြင်း\n",
"\n",
"ယခုအချိန်အထိ RNN များကို စာသားအတိုင်းအတာများကို အမျိုးအစားခွဲရန်အတွက် အသုံးပြုခြင်းကို အဓိကထားခဲ့ပါသည်။ သို့သော် RNN များသည် စာသားဖန်တီးခြင်းနှင့် ဘာသာပြန်ခြင်းကဲ့သို့သော အလုပ်များကိုလည်း လုပ်ဆောင်နိုင်ပါသည် — အဲဒီအလုပ်များကို နောက်ယူနစ်တွင် ဆွေးနွေးမည်ဖြစ်သည်။\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များကို အသုံးပြု၍ ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
]
}
],
"metadata": {
"kernel_info": {
"name": "conda-env-py37_tensorflow-py"
},
"kernelspec": {
"display_name": "py37_tensorflow",
"language": "python",
"name": "conda-env-py37_tensorflow-py"
},
"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.7.9"
},
"nteract": {
"version": "nteract-front-end@1.0.0"
},
"coopTranslator": {
"original_hash": "81351e61f619b432ff51010a4f993194",
"translation_date": "2025-08-30T10:29:34+00:00",
"source_file": "lessons/5-NLP/16-RNN/RNNTF.ipynb",
"language_code": "my"
}
},
"nbformat": 4,
"nbformat_minor": 4
}