460 lines
40 KiB
Plaintext
460 lines
40 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# पुनरावर्ती न्युरल नेटवर्कहरू\n",
|
|
"\n",
|
|
"अघिल्लो मोड्युलमा, हामीले पाठको समृद्ध अर्थपूर्ण प्रतिनिधित्वहरू कभर गरेका थियौं। हामीले प्रयोग गरिरहेको आर्किटेक्चरले वाक्यमा शब्दहरूको समग्र अर्थलाई समेट्छ, तर यो शब्दहरूको **क्रम**लाई ध्यानमा राख्दैन, किनभने एम्बेडिङ पछि हुने समग्र अपरेशनले मूल पाठबाट यो जानकारी हटाउँछ। यी मोडेलहरूले शब्दहरूको क्रमबद्धता प्रतिनिधित्व गर्न नसक्ने भएकाले, तिनीहरूले पाठ उत्पादन वा प्रश्न उत्तरजस्ता जटिल वा अस्पष्ट कार्यहरू समाधान गर्न सक्दैनन्।\n",
|
|
"\n",
|
|
"पाठ अनुक्रमको अर्थ समेट्न, हामी **पुनरावर्ती न्युरल नेटवर्क** भनिने न्युरल नेटवर्क आर्किटेक्चर प्रयोग गर्नेछौं। RNN प्रयोग गर्दा, हामी हाम्रो वाक्यलाई नेटवर्कमा एक पटकमा एक टोकन पास गर्छौं, र नेटवर्कले केही **स्थिति** उत्पादन गर्छ, जुन हामी अर्को टोकनसँग फेरि नेटवर्कमा पास गर्छौं।\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"टोकनहरूको इनपुट अनुक्रम $X_0,\\dots,X_n$ दिइएको अवस्थामा, RNN ले न्युरल नेटवर्क ब्लकहरूको अनुक्रम सिर्जना गर्छ, र यो अनुक्रमलाई ब्याकप्रोपोगेसन प्रयोग गरेर अन्त-देखि-अन्तसम्म प्रशिक्षण गर्छ। प्रत्येक नेटवर्क ब्लकले $(X_i,S_i)$ जोडीलाई इनपुटको रूपमा लिन्छ, र परिणामस्वरूप $S_{i+1}$ उत्पादन गर्छ। अन्तिम स्थिति $S_n$ वा आउटपुट $Y_n$ लाई रैखिक वर्गीकरणकर्तामा पठाइन्छ ताकि परिणाम उत्पादन गर्न सकियोस्। सबै नेटवर्क ब्लकहरूले समान तौलहरू साझा गर्छन्, र एक ब्याकप्रोपोगेसन पास प्रयोग गरेर अन्त-देखि-अन्तसम्म प्रशिक्षण गरिन्छ।\n",
|
|
"\n",
|
|
"> माथिको चित्रले पुनरावर्ती न्युरल नेटवर्कलाई अनरोल गरिएको रूप (बायाँतिर) र थप संक्षिप्त पुनरावर्ती प्रतिनिधित्व (दायाँतिर) मा देखाउँछ। सबै RNN सेलहरूले समान **साझा गर्न मिल्ने तौलहरू** भएको कुरा बुझ्न महत्त्वपूर्ण छ।\n",
|
|
"\n",
|
|
"किनकि स्थिति भेक्टरहरू $S_0,\\dots,S_n$ नेटवर्कमार्फत पास गरिन्छन्, RNN ले शब्दहरू बीचको क्रमबद्ध निर्भरता सिक्न सक्षम हुन्छ। उदाहरणका लागि, जब *not* शब्द अनुक्रममा कतै देखा पर्छ, यसले स्थिति भेक्टरभित्रका केही तत्वहरूलाई नकार्न सिक्न सक्छ।\n",
|
|
"\n",
|
|
"भित्र, प्रत्येक RNN सेलमा दुई तौल म्याट्रिक्स $W_H$ र $W_I$, र बायस $b$ हुन्छ। प्रत्येक RNN चरणमा, इनपुट $X_i$ र इनपुट स्थिति $S_i$ दिइएको अवस्थामा, आउटपुट स्थिति $S_{i+1} = f(W_H\\times S_i + W_I\\times X_i+b)$ को रूपमा गणना गरिन्छ, जहाँ $f$ सक्रियता फलन हो (प्रायः $\\tanh$)।\n",
|
|
"\n",
|
|
"> पाठ उत्पादन (जसलाई हामी अर्को युनिटमा कभर गर्नेछौं) वा मेसिन अनुवादजस्ता समस्याहरूको लागि, हामी प्रत्येक RNN चरणमा केही आउटपुट मान पनि प्राप्त गर्न चाहन्छौं। यस अवस्थामा, अर्को म्याट्रिक्स $W_O$ पनि हुन्छ, र आउटपुट $Y_i=f(W_O\\times S_i+b_O)$ को रूपमा गणना गरिन्छ।\n",
|
|
"\n",
|
|
"अब हेरौं, पुनरावर्ती न्युरल नेटवर्कहरूले हाम्रो समाचार डेटासेटलाई वर्गीकृत गर्न कसरी मद्दत गर्न सक्छ।\n",
|
|
"\n",
|
|
"> स्यान्डबक्स वातावरणको लागि, हामीले सुनिश्चित गर्न निम्न सेल चलाउन आवश्यक छ कि आवश्यक लाइब्रेरी स्थापना गरिएको छ, र डेटा प्रिफेच गरिएको छ। यदि तपाईं स्थानीय रूपमा चलाइरहनुभएको छ भने, तपाईं निम्न सेललाई छोड्न सक्नुहुन्छ।\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 ड्राइभरका केही संस्करणहरूले मोडेल प्रशिक्षणपछि मेमोरी रिलिज नगर्ने कुरा थाहा छ। हामीले यस नोटबुकमा धेरै उदाहरणहरू चलाइरहेका छौं, र यसले केही सेटअपहरूमा मेमोरी समाप्त हुन सक्छ, विशेष गरी यदि तपाईं यसै नोटबुकमा आफ्नै परीक्षणहरू गरिरहनुभएको छ भने। यदि तपाईंले मोडेल प्रशिक्षण सुरु गर्दा केही अनौठो त्रुटिहरू सामना गर्नुभयो भने, तपाईंले नोटबुकको कर्नेल पुनः सुरु गर्न चाहनुहुन्छ।\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 को अवस्थामा, प्रत्येक पुनरावर्ती इकाई एक साधारण रेखीय नेटवर्क हो, जसले इनपुट भेक्टर र अवस्था भेक्टरलाई लिन्छ, र नयाँ अवस्था भेक्टर उत्पादन गर्दछ। Keras मा, यसलाई `SimpleRNN` तहद्वारा प्रतिनिधित्व गर्न सकिन्छ।\n",
|
|
"\n",
|
|
"यद्यपि हामी एक-हट एन्कोड गरिएको टोकनहरूलाई RNN तहमा सिधै पास गर्न सक्छौं, यो राम्रो विचार होइन किनभने तिनीहरूको उच्च आयामिकताका कारण। त्यसैले, हामी शब्द भेक्टरहरूको आयामिकता घटाउनको लागि एक एम्बेडिङ तह प्रयोग गर्नेछौं, त्यसपछि RNN तह, र अन्तमा `Dense` वर्गीकरणकर्ता।\n",
|
|
"\n",
|
|
"> **Note**: जब आयामिकता यति उच्च छैन, उदाहरणका लागि जब क्यारेक्टर-स्तर टोकनाइजेशन प्रयोग गरिन्छ, एक-हट एन्कोड गरिएको टोकनहरूलाई सिधै RNN सेलमा पास गर्नु उपयुक्त हुन सक्छ।\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": [
|
|
"> **नोट:** यहाँ हामी सरलताको लागि अप्रशिक्षित एम्बेडिङ लेयर प्रयोग गर्छौं, तर राम्रो नतिजाका लागि हामी Word2Vec प्रयोग गरेर प्रशिक्षित एम्बेडिङ लेयर प्रयोग गर्न सक्छौं, जसको वर्णन अघिल्लो इकाईमा गरिएको छ। यो कोडलाई प्रशिक्षित एम्बेडिङसँग काम गर्न अनुकूल बनाउनु तपाईंको लागि राम्रो अभ्यास हुनेछ।\n",
|
|
"\n",
|
|
"अब हामी हाम्रो RNN प्रशिक्षण गर्नेछौं। सामान्यतया RNN प्रशिक्षण गर्न निकै कठिन हुन्छ, किनभने RNN सेलहरूलाई अनुक्रमको लम्बाइसम्म अनरोल गर्दा, ब्याकप्रोपागेसनमा संलग्न तहहरूको संख्या धेरै ठूलो हुन्छ। त्यसैले हामीले सानो सिकाइ दर चयन गर्नुपर्छ, र राम्रो नतिजा उत्पादन गर्न ठूलो डेटासेटमा नेटवर्क प्रशिक्षण गर्नुपर्छ। यसले धेरै समय लिन सक्छ, त्यसैले 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": [
|
|
"## भेरिएबल सिक्वेन्सहरू पुनः हेर्दै\n",
|
|
"\n",
|
|
"`TextVectorization` लेयरले मिनिब्याचमा भेरिएबल लम्बाइ भएका सिक्वेन्सहरूलाई स्वचालित रूपमा प्याड टोकनहरूसँग प्याड गर्ने कुरा याद गर्नुहोस्। ती टोकनहरूले पनि प्रशिक्षणमा भाग लिन्छन्, जसले गर्दा मोडेलको कनभर्जेन्स जटिल हुन सक्छ।\n",
|
|
"\n",
|
|
"प्याडिङको मात्रा कम गर्नका लागि हामीले लिन सक्ने केही उपायहरू छन्। तीमध्ये एक उपाय भनेको डेटासेटलाई सिक्वेन्सको लम्बाइअनुसार पुनः क्रमबद्ध गर्नु र सबै सिक्वेन्सहरूलाई साइजअनुसार समूह बनाउनु हो। यो `tf.data.experimental.bucket_by_sequence_length` फंक्शन प्रयोग गरेर गर्न सकिन्छ (हेर्नुहोस् [डकुमेन्टेसन](https://www.tensorflow.org/api_docs/python/tf/data/experimental/bucket_by_sequence_length))।\n",
|
|
"\n",
|
|
"अर्को उपाय भनेको **मास्किङ** प्रयोग गर्नु हो। Keras मा, केही लेयरहरूले थप इनपुटलाई समर्थन गर्छन्, जसले प्रशिक्षण गर्दा कुन टोकनहरूलाई ध्यान दिनुपर्छ भनेर देखाउँछ। हाम्रो मोडेलमा मास्किङ समावेश गर्न, हामी या त छुट्टै `Masking` लेयर ([डकुमेन्टेसन](https://keras.io/api/layers/core_layers/masking/)) समावेश गर्न सक्छौं, या `Embedding` लेयरको `mask_zero=True` प्यारामिटर निर्दिष्ट गर्न सक्छौं।\n",
|
|
"\n",
|
|
"> **Note**: यो प्रशिक्षणले सम्पूर्ण डेटासेटमा एउटा इपोक पूरा गर्न करिब ५ मिनेट समय लिन्छ। यदि तपाईंलाई धैर्य सकियो भने कुनै पनि समयमा प्रशिक्षण रोक्न सक्नुहुन्छ। तपाईंले प्रशिक्षणका लागि प्रयोग गरिने डाटाको मात्रा सीमित गर्न पनि सक्नुहुन्छ, `ds_train` र `ds_test` डेटासेटहरू पछि `.take(...)` क्लज थपेर।\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": [
|
|
"अब हामीले मास्किङ प्रयोग गरिरहेको छौं, त्यसैले हामी शीर्षकहरू र विवरणहरूको सम्पूर्ण डेटासेटमा मोडेललाई प्रशिक्षण दिन सक्छौं।\n",
|
|
"\n",
|
|
"> **Note**: के तपाईंले ध्यान दिनुभएको छ कि हामीले समाचार शीर्षकहरूमा प्रशिक्षण गरिएको भेक्टराइजर प्रयोग गरिरहेका छौं, न कि लेखको सम्पूर्ण सामग्रीमा? सम्भावित रूपमा, यसले केही टोकनहरूलाई बेवास्ता गर्न सक्छ, त्यसैले भेक्टराइजरलाई पुनः प्रशिक्षण गर्नु राम्रो हुन्छ। तर, यसले सानो मात्र प्रभाव पार्न सक्छ, त्यसैले सरलताका लागि हामी अघिल्लो पूर्व-प्रशिक्षित भेक्टराइजरमै रहनेछौं।\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## LSTM: लामो छोटो-अवधि स्मृति\n",
|
|
"\n",
|
|
"RNNs को मुख्य समस्याहरू मध्ये एक हो **vanishing gradients**। RNNs धेरै लामो हुन सक्छन्, र ब्याकप्रोपोगेसनको क्रममा नेटवर्कको पहिलो तहसम्म ग्रेडियन्टहरू फैलाउन गाह्रो हुन सक्छ। जब यस्तो हुन्छ, नेटवर्कले टाढाका टोकनहरू बीचको सम्बन्ध सिक्न सक्दैन। यो समस्यालाई टार्नको लागि **गेटहरू** प्रयोग गरेर **स्पष्ट अवस्था व्यवस्थापन** प्रस्तुत गर्ने एउटा उपाय हो। गेटहरू प्रस्तुत गर्ने दुई सबैभन्दा सामान्य आर्किटेक्चरहरू हुन् **लामो छोटो-अवधि स्मृति** (LSTM) र **गेटेड रिलेस यूनिट** (GRU)। यहाँ हामी LSTM हरूको बारेमा छलफल गर्नेछौं।\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"LSTM नेटवर्क RNN जस्तै तरिकाले व्यवस्थित हुन्छ, तर दुई अवस्थाहरू छन् जुन तहदेखि तहसम्म पास गरिन्छ: वास्तविक अवस्था $c$, र लुकेको भेक्टर $h$। प्रत्येक युनिटमा, लुकेको भेक्टर $h_{t-1}$ इनपुट $x_t$ सँग संयोजन गरिन्छ, र तिनीहरूले सँगै **गेटहरू** मार्फत अवस्था $c_t$ र आउटपुट $h_{t}$ मा के हुन्छ भन्ने नियन्त्रण गर्छन्। प्रत्येक गेटमा सिग्मोइड सक्रियता हुन्छ (आउटपुट $[0,1]$ को दायरामा), जसलाई अवस्था भेक्टरसँग गुणा गर्दा बिटवाइज मास्कको रूपमा सोच्न सकिन्छ। LSTM हरूसँग निम्न गेटहरू हुन्छन् (माथिको चित्रमा बायाँदेखि दायाँ):\n",
|
|
"* **भूल्ने गेट** जसले निर्णय गर्छ कि भेक्टर $c_{t-1}$ का कुन घटकहरू बिर्सनु पर्छ, र कुन पास गर्न दिनु पर्छ।\n",
|
|
"* **इनपुट गेट** जसले निर्णय गर्छ कि इनपुट भेक्टर र अघिल्लो लुकेको भेक्टरबाट कति जानकारी अवस्था भेक्टरमा समावेश गर्नुपर्छ।\n",
|
|
"* **आउटपुट गेट** जसले नयाँ अवस्था भेक्टर लिन्छ र यसको कुन घटकहरू नयाँ लुकेको भेक्टर $h_t$ उत्पादन गर्न प्रयोग गरिनेछ भनेर निर्णय गर्छ।\n",
|
|
"\n",
|
|
"अवस्था $c$ का घटकहरूलाई झण्डाहरूको रूपमा सोच्न सकिन्छ जसलाई अन र अफ गर्न सकिन्छ। उदाहरणका लागि, जब हामी अनुक्रममा *Alice* नाम भेट्छौं, हामी अनुमान गर्छौं कि यो महिला हो, र अवस्थामा झण्डा उठाउँछौं जसले भन्छ कि वाक्यमा महिला संज्ञा छ। जब हामी थप *and Tom* शब्दहरू भेट्छौं, हामी झण्डा उठाउँछौं जसले भन्छ कि बहुवचन संज्ञा छ। यसरी अवस्थालाई हेरफेर गरेर हामी वाक्यका व्याकरणीय गुणहरू ट्र्याक गर्न सक्छौं।\n",
|
|
"\n",
|
|
"> **Note**: LSTM हरूको आन्तरिक संरचना बुझ्नको लागि यहाँ एक उत्कृष्ट स्रोत छ: [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) क्रिस्टोफर ओलाहद्वारा।\n",
|
|
"\n",
|
|
"यद्यपि LSTM सेलको आन्तरिक संरचना जटिल देखिन सक्छ, Keras ले यो कार्यान्वयनलाई `LSTM` तहभित्र लुकाउँछ, त्यसैले माथिको उदाहरणमा हामीले गर्नुपर्ने एक मात्र कुरा भनेको पुनरावर्ती तहलाई प्रतिस्थापन गर्नु हो:\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": [
|
|
"## द्विदिशात्मक र बहु-स्तरीय RNNs\n",
|
|
"\n",
|
|
"हाम्रो अहिलेसम्मका उदाहरणहरूमा, पुनरावर्ती नेटवर्कहरूले अनुक्रमको सुरुदेखि अन्त्यसम्म काम गर्छन्। यो हामीलाई स्वाभाविक लाग्छ किनभने यो त्यही दिशामा हुन्छ जसरी हामी पढ्छौं वा भाषण सुन्छौं। तर, त्यस्ता परिदृश्यहरूका लागि जसमा इनपुट अनुक्रमको अनियमित पहुँच आवश्यक पर्छ, पुनरावर्ती गणना दुबै दिशामा चलाउनु बढी उपयुक्त हुन्छ। RNNs जसले दुबै दिशामा गणना गर्न अनुमति दिन्छन्, तिनीहरूलाई **द्विदिशात्मक** RNNs भनिन्छ, र तिनीहरूलाई पुनरावर्ती तहलाई विशेष `Bidirectional` तहले आवरण गरेर सिर्जना गर्न सकिन्छ।\n",
|
|
"\n",
|
|
"> **Note**: `Bidirectional` तहले आफ्नो भित्रको तहको दुई प्रतिलिपि बनाउँछ, र तीमध्ये एकको `go_backwards` गुणलाई `True` मा सेट गर्छ, जसले गर्दा यो अनुक्रमको विपरीत दिशामा जान्छ।\n",
|
|
"\n",
|
|
"पुनरावर्ती नेटवर्कहरूले, एकदिशात्मक होस् वा द्विदिशात्मक, अनुक्रमभित्रका ढाँचाहरूलाई समात्छन्, र तिनीहरूलाई अवस्था भेक्टरहरूमा भण्डारण गर्छन् वा तिनीहरूलाई आउटपुटको रूपमा फिर्ता दिन्छन्। कन्भोल्युसनल नेटवर्कहरूको जस्तै, हामी पहिलो तहले निकालेका तल्लो स्तरका ढाँचाहरूबाट उच्च स्तरका ढाँचाहरू समात्न अर्को पुनरावर्ती तह निर्माण गर्न सक्छौं। यसले हामीलाई **बहु-स्तरीय RNN** को अवधारणामा पुर्याउँछ, जसमा दुई वा बढी पुनरावर्ती नेटवर्कहरू हुन्छन्, जहाँ अघिल्लो तहको आउटपुटलाई अर्को तहमा इनपुटको रूपमा पठाइन्छ।\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"*फर्नान्डो लोपेजको [यो उत्कृष्ट पोस्ट](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) बाट लिइएको चित्र।*\n",
|
|
"\n",
|
|
"Keras ले यी नेटवर्कहरू निर्माण गर्न सजिलो बनाउँछ, किनभने तपाईंले मोडेलमा थप पुनरावर्ती तहहरू थप्न मात्र आवश्यक छ। अन्तिम तह बाहेक सबै तहहरूको लागि, हामीले `return_sequences=True` प्यारामिटर निर्दिष्ट गर्नुपर्छ, किनभने हामीले तहलाई पुनरावर्ती गणनाको अन्तिम अवस्था मात्र होइन, सबै मध्यवर्ती अवस्थाहरू फिर्ता दिन आवश्यक छ।\n",
|
|
"\n",
|
|
"अब, हाम्रो वर्गीकरण समस्याको लागि दुई-तह द्विदिशात्मक LSTM बनाऔं।\n",
|
|
"\n",
|
|
"> **Note** यो कोडले फेरि धेरै समय लिन सक्छ, तर यसले अहिलेसम्म देखिएको सबैभन्दा उच्च सटीकता दिन्छ। त्यसैले सायद यो पर्खन र परिणाम हेर्न लायक छ।\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": [
|
|
"## अन्य कार्यहरूको लागि RNNs\n",
|
|
"\n",
|
|
"अहिलेसम्म, हामीले RNNs प्रयोग गरेर पाठको क्रमलाई वर्गीकरण गर्ने कुरामा ध्यान केन्द्रित गरेका छौं। तर तिनीहरूले पाठ सिर्जना र भाषा अनुवाद जस्ता धेरै अन्य कार्यहरू पनि गर्न सक्छन् — हामी ती कार्यहरूलाई अर्को इकाईमा विचार गर्नेछौं।\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-28T09:34:55+00:00",
|
|
"source_file": "lessons/5-NLP/16-RNN/RNNTF.ipynb",
|
|
"language_code": "ne"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |