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

494 lines
44 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ജനറേറ്റീവ് നെറ്റ്വർക്കുകൾ\n",
"\n",
"റികറന്റ് ന്യൂറൽ നെറ്റ്വർക്കുകൾ (RNNs) மற்றும் അവയുടെ ഗേറ്റഡ് സെൽ വകഭേദങ്ങൾ, ഉദാഹരണത്തിന് ലോങ് ഷോർട്ട് ടേം മെമ്മറി സെലുകൾ (LSTMs) மற்றும் ഗേറ്റഡ് റികറന്റ് യൂണിറ്റുകൾ (GRUs), ഭാഷാ മോഡലിംഗിന് ഒരു സംവിധാനം നൽകുന്നു, അതായത് അവ വാക്കുകളുടെ ക്രമീകരണം പഠിച്ച് ഒരു സീക്വൻസിലെ അടുത്ത വാക്ക് പ്രവചിക്കാൻ കഴിയും. ഇതിലൂടെ RNN-കൾ **ജനറേറ്റീവ് ടാസ്കുകൾ**ക്കായി ഉപയോഗിക്കാം, ഉദാഹരണത്തിന് സാധാരണ ടെക്സ്റ്റ് ജനറേഷൻ, മെഷീൻ ട്രാൻസ്ലേഷൻ,甚至 ഇമേജ് ക്യാപ്ഷനിംഗ്.\n",
"\n",
"മുൻ യൂണിറ്റിൽ ചർച്ച ചെയ്ത RNN ആർക്കിടെക്ചറിൽ, ഓരോ RNN യൂണിറ്റും അടുത്ത ഹിഡൻ സ്റ്റേറ്റ് ഔട്ട്പുട്ടായി ഉൽപ്പാദിപ്പിച്ചിരുന്നു. എന്നാൽ, ഓരോ റികറന്റ് യൂണിറ്റിനും മറ്റൊരു ഔട്ട്പുട്ട് കൂടി ചേർക്കാം, ഇത് ഒരു **സീക്വൻസ്** (മൂല സീക്വൻസിന്റെ നീളത്തിന് തുല്യമായ) ഔട്ട്പുട്ട് നൽകാൻ സഹായിക്കും. കൂടാതെ, ഓരോ ഘട്ടത്തിലും ഇൻപുട്ട് സ്വീകരിക്കാത്ത RNN യൂണിറ്റുകൾ ഉപയോഗിച്ച്, ചില പ്രാരംഭ സ്റ്റേറ്റ് വെക്ടർ എടുത്ത്, തുടർന്ന് ഔട്ട്പുട്ടുകളുടെ ഒരു സീക്വൻസ് ഉൽപ്പാദിപ്പിക്കാം.\n",
"\n",
"ഈ നോട്ട്‌ബുക്കിൽ, നാം ടെക്സ്റ്റ് ജനറേറ്റ് ചെയ്യാൻ സഹായിക്കുന്ന ലളിതമായ ജനറേറ്റീവ് മോഡലുകളെ കേന്ദ്രീകരിക്കും. ലളിതത്വത്തിനായി, നാം **ക്യാരക്ടർ-ലെവൽ നെറ്റ്വർക്ക്** നിർമ്മിക്കാം, ഇത് അക്ഷരമുതൽ അക്ഷരം ടെക്സ്റ്റ് ജനറേറ്റ് ചെയ്യും. പരിശീലനത്തിനിടെ, നാം ഒരു ടെക്സ്റ്റ് കോർപ്പസ് എടുത്ത്, അത് അക്ഷര സീക്വൻസുകളായി വിഭജിക്കണം.\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": [
"## അക്ഷര വാക്ക് നിർമ്മാണം\n",
"\n",
"അക്ഷരനിര അടിസ്ഥാനത്തിലുള്ള ജനറേറ്റീവ് നെറ്റ്‌വർക്ക് നിർമ്മിക്കാൻ, വാക്കുകൾക്ക് പകരം ടെക്സ്റ്റ് വ്യക്തിഗത അക്ഷരങ്ങളായി വിഭജിക്കേണ്ടതുണ്ട്. മുമ്പ് ഉപയോഗിച്ച `TextVectorization` ലെയർ അത് ചെയ്യാൻ കഴിയില്ല, അതിനാൽ ഞങ്ങൾക്ക് രണ്ട് ഓപ്ഷനുകൾ ഉണ്ട്:\n",
"\n",
"* കൈയോടെ ടെക്സ്റ്റ് ലോഡ് ചെയ്ത് ടോക്കനൈസേഷൻ ചെയ്യുക, [ഈ ഔദ്യോഗിക Keras ഉദാഹരണത്തിൽ](https://keras.io/examples/generative/lstm_character_level_text_generation/) കാണുന്നതുപോലെ\n",
"* അക്ഷരനിര ടോക്കനൈസേഷനായി `Tokenizer` ക്ലാസ് ഉപയോഗിക്കുക.\n",
"\n",
"നാം രണ്ടാം ഓപ്ഷൻ തിരഞ്ഞെടുക്കും. `Tokenizer` വാക്കുകളായി ടോക്കനൈസ് ചെയ്യാനും ഉപയോഗിക്കാം, അതിനാൽ അക്ഷരനിര ടോക്കനൈസേഷനിൽ നിന്ന് വാക്ക് നിര ടോക്കനൈസേഷനിലേക്ക് എളുപ്പത്തിൽ മാറാൻ കഴിയും.\n",
"\n",
"അക്ഷരനിര ടോക്കനൈസേഷൻ ചെയ്യാൻ, `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": [
"നാം ഒരു പ്രത്യേക ടോക്കൺ ഉപയോഗിച്ച് **ക്രമത്തിന്റെ അവസാനത്തെ** സൂചിപ്പിക്കാൻ ആഗ്രഹിക്കുന്നു, അതിനെ `<eos>` എന്ന് വിളിക്കും. അത് നമുക്ക് വാക്കുകളുടെ സമാഹാരത്തിൽ കൈമാറി ചേർക്കാം:\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": [
"ഇപ്പോൾ, ടെക്സ്റ്റ് നമ്പറുകളുടെ ക്രമങ്ങളായി എൻകോഡ് ചെയ്യാൻ, നാം ഉപയോഗിക്കാം:\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": [
"## തലക്കെട്ടുകൾ സൃഷ്ടിക്കാൻ ജനറേറ്റീവ് RNN പരിശീലിപ്പിക്കൽ\n",
"\n",
"നാം വാർത്താ തലക്കെട്ടുകൾ സൃഷ്ടിക്കാൻ RNN എങ്ങനെ പരിശീലിപ്പിക്കുമെന്ന് പറയുന്നത് ഇങ്ങനെ ആണ്. ഓരോ ഘട്ടത്തിലും, ഒരു തലക്കെട്ട് എടുത്ത് അത് RNN-ലേക്ക് നൽകും, ഓരോ ഇൻപുട്ട് അക്ഷരത്തിനും നെറ്റ്‌വർക്കിന് അടുത്ത ഔട്ട്പുട്ട് അക്ഷരം സൃഷ്ടിക്കാൻ ആവശ്യപ്പെടും:\n",
"\n",
"!['HELLO' എന്ന വാക്കിന്റെ ഉദാഹരണ RNN സൃഷ്ടി കാണിക്കുന്ന ചിത്രം.](../../../../../translated_images/ml/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"നമ്മുടെ സീക്വൻസിലെ അവസാന അക്ഷരത്തിന്, നെറ്റ്‌വർക്കിന് `<eos>` ടോക്കൺ സൃഷ്ടിക്കാൻ ആവശ്യപ്പെടും.\n",
"\n",
"നാം ഇവിടെ ഉപയോഗിക്കുന്ന ജനറേറ്റീവ് RNN-ന്റെ പ്രധാന വ്യത്യാസം, RNN-ന്റെ ഓരോ ഘട്ടത്തിലും ഔട്ട്പുട്ട് എടുക്കുന്നതാണ്, അവസാന സെല്ലിൽ നിന്നല്ല. ഇത് RNN സെല്ലിന് `return_sequences` പാരാമീറ്റർ നൽകിക്കൊണ്ട് സാധ്യമാക്കാം.\n",
"\n",
"അതിനാൽ, പരിശീലന സമയത്ത്, നെറ്റ്‌വർക്കിന്റെ ഇൻപുട്ട് ഒരു നിശ്ചിത നീളമുള്ള എൻകോഡുചെയ്ത അക്ഷരങ്ങളുടെ സീക്വൻസായിരിക്കും, ഔട്ട്പുട്ട് അതേ നീളമുള്ള, പക്ഷേ ഒരു ഘടകം മാറ്റിയതും `<eos>`-ൽ അവസാനിക്കുന്നതുമായ സീക്വൻസായിരിക്കും. മിനിബാച്ച് പല സീക്വൻസുകളും ഉൾക്കൊള്ളും, അതിനാൽ എല്ലാ സീക്വൻസുകളും സജ്ജമാക്കാൻ **padding** ഉപയോഗിക്കേണ്ടതുണ്ട്.\n",
"\n",
"ഡാറ്റാസെറ്റ് മാറ്റാൻ സഹായിക്കുന്ന ഫംഗ്ഷനുകൾ സൃഷ്ടിക്കാം. മിനിബാച്ച് തലത്തിൽ സീക്വൻസുകൾ പാഡ് ചെയ്യേണ്ടതിനാൽ, ആദ്യം `.batch()` വിളിച്ച് ഡാറ്റാസെറ്റ് ബാച്ച് ചെയ്യുകയും, പിന്നീട് `map` ഉപയോഗിച്ച് മാറ്റം വരുത്തുകയും ചെയ്യും. അതിനാൽ, മാറ്റം വരുത്തുന്ന ഫംഗ്ഷൻ മുഴുവൻ മിനിബാച്ച് ഒരു പാരാമീറ്ററായി സ്വീകരിക്കും:\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": [
"നാം ഇവിടെ ചെയ്യുന്ന ചില പ്രധാന കാര്യങ്ങൾ:\n",
"* ആദ്യം സ്ട്രിംഗ് ടെൻസറിൽ നിന്ന് യഥാർത്ഥ ടെക്സ്റ്റ് എടുക്കുന്നു\n",
"* `text_to_sequences` സ്ട്രിംഗുകളുടെ ലിസ്റ്റ് ഇന്റിജർ ടെൻസറുകളുടെ ലിസ്റ്റായി മാറ്റുന്നു\n",
"* `pad_sequences` ആ ടെൻസറുകളെ അവരുടെ പരമാവധി നീളത്തിലേക്ക് പാഡ് ചെയ്യുന്നു\n",
"* അവസാനം എല്ലാ അക്ഷരങ്ങളും വൺ-ഹോട്ട് എൻകോഡ് ചെയ്യുകയും, ഷിഫ്റ്റിംഗ് ചെയ്യുകയും `<eos>` ചേർക്കുകയും ചെയ്യുന്നു. വൺ-ഹോട്ട് എൻകോഡ് ചെയ്ത അക്ഷരങ്ങൾ എന്തിന് വേണ്ടിയാണെന്ന് നമുക്ക് ഉടൻ കാണാം\n",
"\n",
"എങ്കിലും, ഈ ഫംഗ്ഷൻ **Pythonic** ആണ്, അതായത് ഇത് സ്വയം Tensorflow കംപ്യൂട്ടേഷണൽ ഗ്രാഫിലേക്ക് മാറ്റാൻ കഴിയില്ല. ഈ ഫംഗ്ഷൻ നേരിട്ട് `Dataset.map` ഫംഗ്ഷനിൽ ഉപയോഗിക്കാൻ ശ്രമിച്ചാൽ പിശകുകൾ ഉണ്ടാകും. അതിനാൽ ഈ Pythonic കോൾ `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": [
"> **കുറിപ്പ്**: Pythonic-ഉം Tensorflow ട്രാൻസ്ഫർമേഷൻ ഫങ്ഷനുകളും തമ്മിലുള്ള വ്യത്യാസം കുറച്ച് സങ്കീർണ്ണമായി തോന്നാം, കൂടാതെ dataset-നെ `fit`-ന് മുമ്പ് സാധാരണ Python ഫങ്ഷനുകൾ ഉപയോഗിച്ച് ട്രാൻസ്ഫോം ചെയ്യാത്തതെന്തുകൊണ്ടെന്ന് നിങ്ങൾ ചോദിച്ചേക്കാം. ഇത് തീർച്ചയായും ചെയ്യാവുന്നതാണ്, എന്നാൽ `Dataset.map` ഉപയോഗിക്കുന്നത് വലിയ ഗുണം നൽകുന്നു, കാരണം ഡാറ്റ ട്രാൻസ്ഫർമേഷൻ പൈപ്പ്‌ലൈൻ Tensorflow കംപ്യൂട്ടേഷണൽ ഗ്രാഫ് ഉപയോഗിച്ച് പ്രവർത്തിക്കുന്നു, ഇത് GPU കംപ്യൂട്ടേഷനുകളുടെ പ്രയോജനം എടുക്കുകയും CPU/GPU-വിനിടയിൽ ഡാറ്റ കൈമാറ്റം കുറയ്ക്കുകയും ചെയ്യുന്നു.\n",
"\n",
"ഇപ്പോൾ നാം നമ്മുടെ ജനറേറ്റർ നെറ്റ്‌വർക്ക് നിർമ്മിച്ച് പരിശീലനം ആരംഭിക്കാം. ഇത് മുമ്പത്തെ യൂണിറ്റിൽ ചർച്ച ചെയ്ത ഏതെങ്കിലും റിക്കറന്റ് സെല്ലിൽ അടിസ്ഥാനമാക്കാവുന്നതാണ് (സിംപിൾ, LSTM അല്ലെങ്കിൽ GRU). നമ്മുടെ ഉദാഹരണത്തിൽ LSTM ഉപയോഗിക്കും.\n",
"\n",
"നെറ്റ്‌വർക്ക് കാറക്ടറുകൾ ഇൻപുട്ടായി സ്വീകരിക്കുന്നതിനാൽ, വാക്കുകളുടെ വലുപ്പം വളരെ ചെറുതാണ്, അതിനാൽ embedding ലെയർ ആവശ്യമില്ല, one-hot-encoded ഇൻപുട്ട് നേരിട്ട് LSTM സെല്ലിലേക്ക് പോകാം. ഔട്ട്പുട്ട് ലെയർ LSTM ഔട്ട്പുട്ട് one-hot-encoded ടോക്കൺ നമ്പറുകളായി മാറ്റുന്ന `Dense` ക്ലാസിഫയർ ആയിരിക്കും.\n",
"\n",
"കൂടാതെ, വ്യത്യസ്ത നീളമുള്ള സീക്വൻസുകളുമായി കൈകാര്യം ചെയ്യുന്നതിനാൽ, പാഡുചെയ്ത ഭാഗം അവഗണിക്കുന്ന ഒരു മാസ്ക് സൃഷ്ടിക്കാൻ `Masking` ലെയർ ഉപയോഗിക്കാം. `<eos>` ടോക്കണിന് ശേഷം വരുന്ന എല്ലാം നമ്മൾ വളരെ ശ്രദ്ധിക്കാത്തതിനാൽ ഇത് കർശനമായി ആവശ്യമായില്ല, പക്ഷേ ഈ ലെയർ തരം ഉപയോഗിച്ച് അനുഭവം നേടുന്നതിനായി ഇത് ഉപയോഗിക്കും. `input_shape` `(None, vocab_size)` ആയിരിക്കും, ഇവിടെ `None` വ്യത്യസ്ത നീളമുള്ള സീക്വൻസിനെ സൂചിപ്പിക്കുന്നു, ഔട്ട്പുട്ട് ഷേപ്പ് `(None, vocab_size)` ആണെന്നും `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": [
"## ഔട്ട്പുട്ട് സൃഷ്ടിക്കൽ\n",
"\n",
"ഇപ്പോൾ മോഡൽ പരിശീലിപ്പിച്ചതിനുശേഷം, അതുപയോഗിച്ച് ചില ഔട്ട്പുട്ടുകൾ സൃഷ്ടിക്കാൻ ആഗ്രഹിക്കുന്നു. ആദ്യം, ടോക്കൺ നമ്പറുകളുടെ ശ്രേണിയാൽ പ്രതിനിധീകരിച്ച ടെക്സ്റ്റ് ഡീകോഡ് ചെയ്യാനുള്ള ഒരു മാർഗം വേണം. ഇതിന്, `tokenizer.sequences_to_texts` ഫംഗ്ഷൻ ഉപയോഗിക്കാമായിരുന്നു; എന്നാൽ, ഇത് കറക്റ്റർ-ലെവൽ ടോക്കണൈസേഷനുമായി നല്ല രീതിയിൽ പ്രവർത്തിക്കുന്നില്ല. അതിനാൽ, ടോക്കണൈസറിൽ നിന്നുള്ള ടോക്കൺ ഡിക്ഷണറി (പേര് `word_index`) എടുത്ത്, അതിന്റെ റിവേഴ്സ് മാപ്പ് നിർമ്മിച്ച്, ഞങ്ങൾ സ്വന്തം ഡീകോഡിംഗ് ഫംഗ്ഷൻ എഴുതും:\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": [
"ഇപ്പോൾ, നമുക്ക് ജനറേഷൻ ചെയ്യാം. നാം ചില സ്ട്രിംഗ് `start` ഉപയോഗിച്ച് തുടങ്ങും, അതിനെ ഒരു സീക്വൻസ് `inp` ആയി എൻകോഡ് ചെയ്യും, പിന്നീട് ഓരോ ഘട്ടത്തിലും അടുത്ത അക്ഷരം പ്രവചിക്കാൻ നമ്മുടെ നെറ്റ്‌വർക്ക് വിളിക്കും.\n",
"\n",
"നെറ്റ്‌വർക്കിന്റെ ഔട്ട്പുട്ട് `out` എന്നത് `vocab_size` ഘടകങ്ങളുള്ള ഒരു വെക്ടറാണ്, ഓരോ ടോക്കണിന്റെയും സാധ്യതകൾ പ്രതിനിധീകരിക്കുന്നു, ഏറ്റവും സാധ്യതയുള്ള ടോക്കൺ നമ്പർ കണ്ടെത്താൻ `argmax` ഉപയോഗിക്കാം. പിന്നീട് ആ അക്ഷരം ജനറേറ്റുചെയ്ത ടോക്കൺ ലിസ്റ്റിൽ ചേർക്കുകയും, ജനറേഷൻ തുടരുകയും ചെയ്യും. ഒരു അക്ഷരം ജനറേറ്റ് ചെയ്യാനുള്ള ഈ പ്രക്രിയ `size` തവണ ആവർത്തിച്ച് ആവശ്യമായ അക്ഷരങ്ങളുടെ എണ്ണം സൃഷ്ടിക്കും, കൂടാതെ `eos_token` കണ്ടുപിടിച്ചാൽ നേരത്തെ അവസാനിപ്പിക്കും.\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Today #39;s lead to strike for the strike for the strike for the strike (AFP)'"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def generate(model,size=100,start='Today '):\n",
" inp = tokenizer.texts_to_sequences([start])[0]\n",
" chars = inp\n",
" for i in range(size):\n",
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
" nc = tf.argmax(out)\n",
" if nc==eos_token:\n",
" break\n",
" chars.append(nc.numpy())\n",
" inp = inp+[nc]\n",
" return decode(chars)\n",
" \n",
"generate(model)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## പരിശീലനത്തിനിടെ സാമ്പിളിംഗ് ഔട്ട്പുട്ട്\n",
"\n",
"*ശുദ്ധത* പോലുള്ള ഉപകാരപ്രദമായ മെട്രിക്കുകൾ ഇല്ലാത്തതിനാൽ, നമ്മുടെ മോഡൽ മെച്ചപ്പെടുന്നുണ്ടെന്ന് കാണാനുള്ള ഏക മാർഗം പരിശീലനത്തിനിടെ സൃഷ്ടിച്ച സ്ട്രിംഗ് **സാമ്പിളിംഗ്** ചെയ്യലാണ്. ഇത് ചെയ്യാൻ, നാം **കോൾബാക്കുകൾ** ഉപയോഗിക്കും, അഥവാ `fit` ഫംഗ്ഷനിലേക്ക് പാസ്സ് ചെയ്യാവുന്ന, പരിശീലനത്തിനിടെ കാലക്രമേണ വിളിക്കപ്പെടുന്ന ഫംഗ്ഷനുകൾ.\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": [
"ഈ ഉദാഹരണം ഇതിനകം തന്നെ നല്ലൊരു ടെക്സ്റ്റ് സൃഷ്ടിക്കുന്നു, പക്ഷേ ഇത് പലവിധത്തിൽ മെച്ചപ്പെടുത്താൻ കഴിയും:\n",
"* **കൂടുതൽ ടെക്സ്റ്റ്**. ഞങ്ങൾ നമ്മുടെ ടാസ്കിനായി തലക്കെട്ടുകൾ മാത്രം ഉപയോഗിച്ചിട്ടുണ്ട്, പക്ഷേ നിങ്ങൾ പൂർണ്ണ ടെക്സ്റ്റുമായി പരീക്ഷണം നടത്താൻ ആഗ്രഹിക്കാം. RNN-കൾ ദീർഘമായ സീക്വൻസുകൾ കൈകാര്യം ചെയ്യുന്നതിൽ അത്ര നല്ലതല്ലെന്ന് ഓർക്കുക, അതിനാൽ അവയെ ചെറുതായുള്ള വാക്യങ്ങളായി വിഭജിക്കുക അല്ലെങ്കിൽ നിശ്ചിത നീളമുള്ള സീക്വൻസിൽ (ഉദാ., `num_chars` എന്ന മുൻകൂട്ടി നിശ്ചയിച്ച മൂല്യം, 256 പോലുള്ളത്) പരിശീലനം നടത്തുന്നത് ബുദ്ധിമുട്ടില്ല. മുകളിൽ നൽകിയ ഉദാഹരണം [അധികൃത Keras ട്യൂട്ടോറിയൽ](https://keras.io/examples/generative/lstm_character_level_text_generation/) പ്രചോദനമായി ഉപയോഗിച്ച് ഇത്തരത്തിലുള്ള ആർക്കിടെക്ചറിലേക്ക് മാറ്റാൻ ശ്രമിക്കാം.\n",
"* **മൾട്ടിലെയർ LSTM**. 2 അല്ലെങ്കിൽ 3 ലെയറുകളുടെ LSTM സെല്ലുകൾ പരീക്ഷിക്കുന്നത് ഉചിതമാണ്. മുൻ യൂണിറ്റിൽ പറഞ്ഞതുപോലെ, ഓരോ LSTM ലെയറും ടെക്സ്റ്റിൽ നിന്നുള്ള പ്രത്യേക പാറ്റേണുകൾ എടുക്കുന്നു, കറക്റ്റർ-ലെവൽ ജനറേറ്ററിന്റെ കാര്യത്തിൽ താഴത്തെ LSTM ലെയർ സില്ലബിളുകൾ എടുക്കുന്നതിന് ഉത്തരവാദിയാകും, മുകളിലെ ലെയറുകൾ വാക്കുകളും വാക്കുകളുടെ സംയോജനങ്ങളും എടുക്കുന്നതിന്. ഇത് LSTM കൺസ്ട്രക്ടറിലേക്ക് ലെയറുകളുടെ എണ്ണം പാരാമീറ്ററായി നൽകുന്നതിലൂടെ എളുപ്പത്തിൽ നടപ്പിലാക്കാം.\n",
"* **GRU യൂണിറ്റുകൾ** ഉപയോഗിച്ച് പരീക്ഷണം നടത്താനും ഏത് മെച്ചമാണ് എന്ന് കാണാനും, കൂടാതെ **വിവിധ ഹിഡൻ ലെയർ വലുപ്പങ്ങൾ** പരീക്ഷിക്കാനും നിങ്ങൾ ആഗ്രഹിക്കാം. വളരെ വലിയ ഹിഡൻ ലെയർ ഓവർഫിറ്റിങ്ങിന് കാരണമാകാം (ഉദാ., നെറ്റ്‌വർക്ക് കൃത്യമായ ടെക്സ്റ്റ് പഠിക്കും), ചെറുതായുള്ള വലുപ്പം നല്ല ഫലം നൽകാതിരിക്കാം.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## സോഫ്റ്റ് ടെക്സ്റ്റ് ജനറേഷൻ ಮತ್ತು ടെംപറേച്ചർ\n",
"\n",
"മുൻപ് `generate` എന്ന നിർവചനത്തിൽ, നാം എപ്പോഴും ഏറ്റവും ഉയർന്ന സാധ്യതയുള്ള അക്ഷരത്തെ അടുത്ത അക്ഷരമായി എടുത്തിരുന്നു. ഇതിന്റെ ഫലമായി, ടെക്സ്റ്റ് പലപ്പോഴും ഒരേ അക്ഷരക്രമങ്ങൾ വീണ്ടും വീണ്ടും \"സൈക്ല്\" ചെയ്യുന്നതായി കണ്ടു, ഉദാഹരണത്തിന് താഴെ കാണുന്ന പോലെ:\n",
"```\n",
"today of the second the company and a second the company ...\n",
"```\n",
"\n",
"എങ്കിലും, അടുത്ത അക്ഷരത്തിനുള്ള സാധ്യത വിതരണത്തെ നോക്കിയാൽ, ഏറ്റവും ഉയർന്ന ചില സാധ്യതകളുടെ വ്യത്യാസം വലിയതല്ലായിരിക്കാം, ഉദാഹരണത്തിന് ഒരു അക്ഷരത്തിന് 0.2 സാധ്യതയുണ്ടെങ്കിൽ, മറ്റൊന്ന് 0.19 ആയിരിക്കാം. ഉദാഹരണത്തിന് '*play*' എന്ന ക്രമത്തിൽ അടുത്ത അക്ഷരം സ്പേസ് ആകാമോ, അല്ലെങ്കിൽ **e** (പദമായ *player* ൽപോലെ) ആകാമോ എന്നത് സമാനമായ സാധ്യതയുള്ളതാണ്.\n",
"\n",
"ഇത് നമ്മെ ഈ നിഗമനത്തിലേക്ക് നയിക്കുന്നു: ഏറ്റവും ഉയർന്ന സാധ്യതയുള്ള അക്ഷരം തിരഞ്ഞെടുക്കുന്നത് എപ്പോഴും \"ന്യായമായ\" കാര്യമല്ല, കാരണം രണ്ടാം ഉയർന്ന സാധ്യതയുള്ളത് തിരഞ്ഞെടുക്കുന്നതും അർത്ഥവത്തായ ടെക്സ്റ്റിലേക്ക് നയിക്കാം. നെറ്റ്‌വർക്ക് ഔട്ട്പുട്ട് നൽകുന്ന സാധ്യത വിതരണത്തിൽ നിന്നാണ് അക്ഷരങ്ങൾ **സാമ്പിൾ** ചെയ്യുന്നത് കൂടുതൽ ബുദ്ധിമുട്ടുള്ളതും ഉചിതവുമാണ്.\n",
"\n",
"ഈ സാമ്പിളിംഗ് `np.multinomial` ഫംഗ്ഷൻ ഉപയോഗിച്ച് ചെയ്യാം, ഇത് **മൾട്ടിനോമിയൽ വിതരണ** നടപ്പിലാക്കുന്നു. താഴെ ഈ **സോഫ്റ്റ്** ടെക്സ്റ്റ് ജനറേഷൻ നടപ്പിലാക്കുന്ന ഫംഗ്ഷൻ നിർവചിച്ചിരിക്കുന്നു:\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": [
"നാം **temperature** എന്ന ഒരു പുതിയ പാരാമീറ്റർ പരിചയപ്പെടുത്തി, ഇത് ഏറ്റവും ഉയർന്ന സാധ്യതയോട് എത്രമാത്രം കർശനമായി പാലിക്കണമെന്ന് സൂചിപ്പിക്കാൻ ഉപയോഗിക്കുന്നു. temperature 1.0 ആണെങ്കിൽ, നാം ശരാശരി മൾട്ടിനോമിയൽ സാമ്പ്ലിംഗ് നടത്തുന്നു, temperature അനന്തതയിലേക്ക് പോകുമ്പോൾ - എല്ലാ സാധ്യതകളും സമാനമാകുന്നു, പിന്നെ നാം യാദൃച്ഛികമായി അടുത്ത അക്ഷരം തിരഞ്ഞെടുക്കുന്നു. താഴെ കൊടുത്ത ഉദാഹരണത്തിൽ temperature വളരെ കൂടുമ്പോൾ വാചകം അർത്ഥരഹിതമാകുന്നത് കാണാം, കൂടാതെ അത് 0-ന് അടുത്ത് പോകുമ്പോൾ \"cycled\" കർശനമായി സൃഷ്ടിച്ച വാചകത്തെപ്പോലെ തോന്നുന്നു.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**അസൂയാ**: \nഈ രേഖ AI വിവർത്തന സേവനം [Co-op Translator](https://github.com/Azure/co-op-translator) ഉപയോഗിച്ച് വിവർത്തനം ചെയ്തതാണ്. നാം കൃത്യതയ്ക്ക് ശ്രമിച്ചെങ്കിലും, സ്വയം പ്രവർത്തിക്കുന്ന വിവർത്തനങ്ങളിൽ പിശകുകൾ അല്ലെങ്കിൽ തെറ്റുകൾ ഉണ്ടാകാമെന്ന് ദയവായി ശ്രദ്ധിക്കുക. അതിന്റെ മാതൃഭാഷയിലുള്ള യഥാർത്ഥ രേഖ അധികാരപരമായ ഉറവിടമായി കണക്കാക്കപ്പെടണം. നിർണായക വിവരങ്ങൾക്ക്, പ്രൊഫഷണൽ മനുഷ്യ വിവർത്തനം ശുപാർശ ചെയ്യപ്പെടുന്നു. ഈ വിവർത്തനത്തിന്റെ ഉപയോഗത്തിൽ നിന്നുണ്ടാകുന്ന ഏതെങ്കിലും തെറ്റിദ്ധാരണകൾക്കോ തെറ്റായ വ്യാഖ്യാനങ്ങൾക്കോ ഞങ്ങൾ ഉത്തരവാദികളല്ല.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\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-11-26T02:16:28+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "ml"
}
},
"nbformat": 4,
"nbformat_minor": 4
}