647 lines
39 KiB
Plaintext
647 lines
39 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# टेक्स्ट वर्गीकरण कार्य\n",
|
|
"\n",
|
|
"इस मॉड्यूल में, हम **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)** डेटासेट पर आधारित एक सरल टेक्स्ट वर्गीकरण कार्य से शुरुआत करेंगे: हम समाचार शीर्षकों को चार श्रेणियों में वर्गीकृत करेंगे: वर्ल्ड, स्पोर्ट्स, बिज़नेस और साइ/टेक।\n",
|
|
"\n",
|
|
"## डेटासेट\n",
|
|
"\n",
|
|
"डेटासेट को लोड करने के लिए, हम **[TensorFlow Datasets](https://www.tensorflow.org/datasets)** API का उपयोग करेंगे।\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",
|
|
"\n",
|
|
"# In this tutorial, we will be training a lot of models. In order to use GPU memory cautiously,\n",
|
|
"# we will 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",
|
|
"dataset = tfds.load('ag_news_subset')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"हम अब `dataset['train']` और `dataset['test']` का उपयोग करके डेटासेट के प्रशिक्षण और परीक्षण भागों तक पहुंच सकते हैं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Length of train dataset = 120000\n",
|
|
"Length of test dataset = 7600\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"ds_train = dataset['train']\n",
|
|
"ds_test = dataset['test']\n",
|
|
"\n",
|
|
"print(f\"Length of train dataset = {len(ds_train)}\")\n",
|
|
"print(f\"Length of test dataset = {len(ds_test)}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"चलो हमारे डेटा सेट से पहले 10 नई सुर्खियाँ प्रिंट करें:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"3 (Sci/Tech) -> b'AMD Debuts Dual-Core Opteron Processor' b'AMD #39;s new dual-core Opteron chip is designed mainly for corporate computing applications, including databases, Web services, and financial transactions.'\n",
|
|
"1 (Sports) -> b\"Wood's Suspension Upheld (Reuters)\" b'Reuters - Major League Baseball\\\\Monday announced a decision on the appeal filed by Chicago Cubs\\\\pitcher Kerry Wood regarding a suspension stemming from an\\\\incident earlier this season.'\n",
|
|
"2 (Business) -> b'Bush reform may have blue states seeing red' b'President Bush #39;s quot;revenue-neutral quot; tax reform needs losers to balance its winners, and people claiming the federal deduction for state and local taxes may be in administration planners #39; sights, news reports say.'\n",
|
|
"3 (Sci/Tech) -> b\"'Halt science decline in schools'\" b'Britain will run out of leading scientists unless science education is improved, says Professor Colin Pillinger.'\n",
|
|
"1 (Sports) -> b'Gerrard leaves practice' b'London, England (Sports Network) - England midfielder Steven Gerrard injured his groin late in Thursday #39;s training session, but is hopeful he will be ready for Saturday #39;s World Cup qualifier against Austria.'\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
|
|
"\n",
|
|
"for i,x in zip(range(5),ds_train):\n",
|
|
" print(f\"{x['label']} ({classes[x['label']]}) -> {x['title']} {x['description']}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## टेक्स्ट वेक्टराइजेशन\n",
|
|
"\n",
|
|
"अब हमें टेक्स्ट को **संख्याओं** में बदलना होगा, जिन्हें टेन्सर्स के रूप में प्रस्तुत किया जा सके। अगर हमें शब्द-स्तरीय प्रतिनिधित्व चाहिए, तो हमें दो चीजें करनी होंगी:\n",
|
|
"\n",
|
|
"* एक **टोकनाइज़र** का उपयोग करके टेक्स्ट को **टोकन्स** में विभाजित करें।\n",
|
|
"* उन टोकन्स का एक **शब्दकोश** (वोकैबुलरी) बनाएं।\n",
|
|
"\n",
|
|
"### शब्दकोश का आकार सीमित करना\n",
|
|
"\n",
|
|
"AG News डेटासेट के उदाहरण में, शब्दकोश का आकार काफी बड़ा है, 100k से अधिक शब्द। सामान्य तौर पर, हमें उन शब्दों की आवश्यकता नहीं होती जो टेक्स्ट में बहुत कम बार आते हैं — केवल कुछ वाक्यों में ही वे मौजूद होंगे, और मॉडल उनसे कुछ सीख नहीं पाएगा। इसलिए, शब्दकोश के आकार को छोटा करने के लिए इसे सीमित करना समझदारी है। यह वेक्टराइज़र कंस्ट्रक्टर में एक आर्ग्युमेंट पास करके किया जा सकता है:\n",
|
|
"\n",
|
|
"इन दोनों चरणों को **TextVectorization** लेयर का उपयोग करके संभाला जा सकता है। आइए वेक्टराइज़र ऑब्जेक्ट को इंस्टैंसिएट करें, और फिर `adapt` मेथड को कॉल करें ताकि सभी टेक्स्ट को पार किया जा सके और एक शब्दकोश बनाया जा सके:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"vocab_size = 50000\n",
|
|
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size)\n",
|
|
"vectorizer.adapt(ds_train.take(500).map(lambda x: x['title']+' '+x['description']))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"> **नोट** हम पूरे डेटासेट का केवल एक छोटा हिस्सा उपयोग कर रहे हैं ताकि शब्दावली बनाई जा सके। ऐसा हम निष्पादन समय को तेज करने और आपको इंतजार न कराने के लिए कर रहे हैं। हालांकि, हम यह जोखिम उठा रहे हैं कि पूरे डेटासेट के कुछ शब्द शब्दावली में शामिल नहीं होंगे और प्रशिक्षण के दौरान अनदेखा कर दिए जाएंगे। इसलिए, पूरे शब्दावली आकार का उपयोग करना और `adapt` के दौरान पूरे डेटासेट से गुजरना अंतिम सटीकता को बढ़ा सकता है, लेकिन बहुत अधिक नहीं।\n",
|
|
"\n",
|
|
"अब हम वास्तविक शब्दावली तक पहुंच सकते हैं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"['', '[UNK]', 'the', 'to', 'a', 'in', 'of', 'and', 'on', 'for']\n",
|
|
"Length of vocabulary: 5335\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"vocab = vectorizer.get_vocabulary()\n",
|
|
"vocab_size = len(vocab)\n",
|
|
"print(vocab[:10])\n",
|
|
"print(f\"Length of vocabulary: {vocab_size}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"वेक्टराइज़र का उपयोग करके, हम आसानी से किसी भी पाठ को संख्याओं के एक सेट में एन्कोड कर सकते हैं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<tf.Tensor: shape=(7,), dtype=int64, numpy=array([ 112, 3695, 3, 304, 11, 1041, 1], dtype=int64)>"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"vectorizer('I love to play with my words')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## बैग-ऑफ-वर्ड्स टेक्स्ट प्रतिनिधित्व\n",
|
|
"\n",
|
|
"क्योंकि शब्द अर्थ को दर्शाते हैं, कभी-कभी हम केवल व्यक्तिगत शब्दों को देखकर किसी टेक्स्ट के अर्थ का पता लगा सकते हैं, भले ही वे वाक्य में किस क्रम में हों। उदाहरण के लिए, जब समाचार वर्गीकृत कर रहे हों, तो *मौसम* और *बर्फ* जैसे शब्द *मौसम पूर्वानुमान* का संकेत दे सकते हैं, जबकि *शेयर* और *डॉलर* जैसे शब्द *वित्तीय समाचार* की ओर इशारा करेंगे।\n",
|
|
"\n",
|
|
"**बैग-ऑफ-वर्ड्स** (BoW) वेक्टर प्रतिनिधित्व सबसे सरल और पारंपरिक वेक्टर प्रतिनिधित्व है जिसे समझा जा सकता है। प्रत्येक शब्द को एक वेक्टर इंडेक्स से जोड़ा जाता है, और एक वेक्टर तत्व में दिए गए दस्तावेज़ में प्रत्येक शब्द की घटनाओं की संख्या होती है।\n",
|
|
"\n",
|
|
" \n",
|
|
"\n",
|
|
"> **Note**: आप BoW को टेक्स्ट में व्यक्तिगत शब्दों के लिए सभी वन-हॉट-एनकोडेड वेक्टर का योग भी मान सकते हैं।\n",
|
|
"\n",
|
|
"नीचे Scikit Learn पायथन लाइब्रेरी का उपयोग करके बैग-ऑफ-वर्ड्स प्रतिनिधित्व उत्पन्न करने का एक उदाहरण दिया गया है:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
|
]
|
|
},
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
|
"sc_vectorizer = CountVectorizer()\n",
|
|
"corpus = [\n",
|
|
" 'I like hot dogs.',\n",
|
|
" 'The dog ran fast.',\n",
|
|
" 'Its hot outside.',\n",
|
|
" ]\n",
|
|
"sc_vectorizer.fit_transform(corpus)\n",
|
|
"sc_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"हम ऊपर परिभाषित किए गए Keras वेक्टराइज़र का भी उपयोग कर सकते हैं, प्रत्येक शब्द संख्या को एक वन-हॉट एन्कोडिंग में परिवर्तित करके और उन सभी वेक्टरों को जोड़ सकते हैं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([0., 5., 0., ..., 0., 0., 0.], dtype=float32)"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"def to_bow(text):\n",
|
|
" return tf.reduce_sum(tf.one_hot(vectorizer(text),vocab_size),axis=0)\n",
|
|
"\n",
|
|
"to_bow('My dog likes hot dogs on a hot day.').numpy()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"> **नोट**: आपको यह देखकर आश्चर्य हो सकता है कि परिणाम पिछले उदाहरण से अलग है। इसका कारण यह है कि Keras उदाहरण में वेक्टर की लंबाई शब्दावली के आकार के अनुरूप होती है, जो पूरे AG News डेटासेट से बनाई गई थी, जबकि Scikit Learn उदाहरण में हमने नमूना पाठ से तुरंत शब्दावली बनाई।\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## BoW क्लासिफायर को प्रशिक्षित करना\n",
|
|
"\n",
|
|
"अब जब हमने अपने टेक्स्ट का बैग-ऑफ-वर्ड्स प्रतिनिधित्व बनाना सीख लिया है, तो चलिए एक क्लासिफायर को प्रशिक्षित करते हैं जो इसका उपयोग करता है। सबसे पहले, हमें अपने डेटासेट को बैग-ऑफ-वर्ड्स प्रतिनिधित्व में बदलना होगा। इसे निम्नलिखित तरीके से `map` फ़ंक्शन का उपयोग करके प्राप्त किया जा सकता है:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"batch_size = 128\n",
|
|
"\n",
|
|
"ds_train_bow = ds_train.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)\n",
|
|
"ds_test_bow = ds_test.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"अब चलिए एक साधारण वर्गीकरण न्यूरल नेटवर्क को परिभाषित करते हैं जिसमें एक रैखिक परत होती है। इनपुट आकार `vocab_size` है, और आउटपुट आकार वर्गों की संख्या (4) के अनुरूप है। क्योंकि हम एक वर्गीकरण कार्य को हल कर रहे हैं, अंतिम सक्रियण फ़ंक्शन **softmax** है:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"938/938 [==============================] - 66s 70ms/step - loss: 0.6144 - acc: 0.8427 - val_loss: 0.4416 - val_acc: 0.8697\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<keras.callbacks.History at 0x20c70a947f0>"
|
|
]
|
|
},
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"model = keras.models.Sequential([\n",
|
|
" keras.layers.Dense(4,activation='softmax',input_shape=(vocab_size,))\n",
|
|
"])\n",
|
|
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
|
"model.fit(ds_train_bow,validation_data=ds_test_bow)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"चूंकि हमारे पास 4 क्लासेस हैं, 80% से अधिक की सटीकता एक अच्छा परिणाम है।\n",
|
|
"\n",
|
|
"## एक नेटवर्क के रूप में क्लासिफायर को ट्रेन करना\n",
|
|
"\n",
|
|
"क्योंकि वेक्टराइज़र भी एक Keras लेयर है, हम एक ऐसा नेटवर्क परिभाषित कर सकते हैं जिसमें यह शामिल हो, और इसे एंड-टू-एंड ट्रेन कर सकते हैं। इस तरीके से हमें `map` का उपयोग करके डेटासेट को वेक्टराइज़ करने की आवश्यकता नहीं होगी, हम बस मूल डेटासेट को नेटवर्क के इनपुट में पास कर सकते हैं।\n",
|
|
"\n",
|
|
"> **Note**: फिर भी हमें अपने डेटासेट पर `map` लागू करना होगा ताकि डिक्शनरी (जैसे `title`, `description` और `label`) से फील्ड्स को ट्यूपल्स में बदल सकें। हालांकि, जब डिस्क से डेटा लोड कर रहे हों, तो हम शुरुआत में ही आवश्यक संरचना के साथ एक डेटासेट बना सकते हैं।\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Model: \"model\"\n",
|
|
"_________________________________________________________________\n",
|
|
" Layer (type) Output Shape Param # \n",
|
|
"=================================================================\n",
|
|
" input_1 (InputLayer) [(None, 1)] 0 \n",
|
|
" \n",
|
|
" text_vectorization (TextVec (None, None) 0 \n",
|
|
" torization) \n",
|
|
" \n",
|
|
" tf.one_hot (TFOpLambda) (None, None, 5335) 0 \n",
|
|
" \n",
|
|
" tf.math.reduce_sum (TFOpLam (None, 5335) 0 \n",
|
|
" bda) \n",
|
|
" \n",
|
|
" dense_2 (Dense) (None, 4) 21344 \n",
|
|
" \n",
|
|
"=================================================================\n",
|
|
"Total params: 21,344\n",
|
|
"Trainable params: 21,344\n",
|
|
"Non-trainable params: 0\n",
|
|
"_________________________________________________________________\n",
|
|
"938/938 [==============================] - 73s 77ms/step - loss: 0.6057 - acc: 0.8414 - val_loss: 0.4202 - val_acc: 0.8736\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<keras.callbacks.History at 0x20c721521f0>"
|
|
]
|
|
},
|
|
"execution_count": 13,
|
|
"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",
|
|
"inp = keras.Input(shape=(1,),dtype=tf.string)\n",
|
|
"x = vectorizer(inp)\n",
|
|
"x = tf.reduce_sum(tf.one_hot(x,vocab_size),axis=1)\n",
|
|
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
|
|
"model = keras.models.Model(inp,out)\n",
|
|
"model.summary()\n",
|
|
"\n",
|
|
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
|
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## बाइग्राम, ट्राइग्राम और एन-ग्राम\n",
|
|
"\n",
|
|
"बैग-ऑफ-वर्ड्स दृष्टिकोण की एक सीमा यह है कि कुछ शब्द बहु-शब्द अभिव्यक्तियों का हिस्सा होते हैं। उदाहरण के लिए, 'हॉट डॉग' शब्द का अर्थ 'हॉट' और 'डॉग' शब्दों से बिल्कुल अलग होता है। यदि हम हमेशा 'हॉट' और 'डॉग' शब्दों को एक ही वेक्टर का उपयोग करके दर्शाते हैं, तो यह हमारे मॉडल को भ्रमित कर सकता है।\n",
|
|
"\n",
|
|
"इस समस्या को हल करने के लिए, **एन-ग्राम प्रतिनिधित्व** का उपयोग अक्सर दस्तावेज़ वर्गीकरण की विधियों में किया जाता है, जहां प्रत्येक शब्द, द्वि-शब्द या त्रि-शब्द की आवृत्ति वर्गीकरण मॉडल को प्रशिक्षित करने के लिए एक उपयोगी विशेषता होती है। उदाहरण के लिए, बाइग्राम प्रतिनिधित्व में, हम मूल शब्दों के अलावा सभी शब्द युग्मों को शब्दावली में जोड़ देंगे।\n",
|
|
"\n",
|
|
"नीचे यह दिखाने के लिए एक उदाहरण दिया गया है कि स्कikit Learn का उपयोग करके बाइग्राम बैग-ऑफ-वर्ड्स प्रतिनिधित्व कैसे बनाया जा सकता है:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Vocabulary:\n",
|
|
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
|
" dtype=int64)"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
|
|
"corpus = [\n",
|
|
" 'I like hot dogs.',\n",
|
|
" 'The dog ran fast.',\n",
|
|
" 'Its hot outside.',\n",
|
|
" ]\n",
|
|
"bigram_vectorizer.fit_transform(corpus)\n",
|
|
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
|
|
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"n-gram दृष्टिकोण की मुख्य कमी यह है कि शब्दावली का आकार बहुत तेजी से बढ़ने लगता है। व्यवहार में, हमें n-gram प्रतिनिधित्व को एक आयामीय कमी तकनीक, जैसे *embeddings*, के साथ संयोजित करने की आवश्यकता होती है, जिसे हम अगले यूनिट में चर्चा करेंगे।\n",
|
|
"\n",
|
|
"हमारे **AG News** डेटासेट में n-gram प्रतिनिधित्व का उपयोग करने के लिए, हमें `TextVectorization` कंस्ट्रक्टर में `ngrams` पैरामीटर पास करना होगा। एक bigram शब्दावली की लंबाई **काफी बड़ी** होती है, हमारे मामले में यह 1.3 मिलियन से अधिक टोकन है! इसलिए, यह समझदारी होगी कि bigram टोकन को भी किसी उचित संख्या तक सीमित किया जाए।\n",
|
|
"\n",
|
|
"हम ऊपर दिए गए कोड का उपयोग करके क्लासिफायर को प्रशिक्षित कर सकते हैं, लेकिन यह मेमोरी के लिहाज से बहुत अक्षम होगा। अगले यूनिट में, हम embeddings का उपयोग करके bigram क्लासिफायर को प्रशिक्षित करेंगे। इस बीच, आप इस नोटबुक में bigram क्लासिफायर प्रशिक्षण के साथ प्रयोग कर सकते हैं और देख सकते हैं कि क्या आप उच्च सटीकता प्राप्त कर सकते हैं।\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## BoW वेक्टर स्वचालित रूप से गणना करना\n",
|
|
"\n",
|
|
"ऊपर दिए गए उदाहरण में, हमने व्यक्तिगत शब्दों के वन-हॉट एन्कोडिंग को जोड़कर BoW वेक्टर को हाथ से गणना की थी। हालांकि, TensorFlow के नवीनतम संस्करण में, हम BoW वेक्टर को स्वचालित रूप से गणना कर सकते हैं, बस `output_mode='count` पैरामीटर को वेक्टराइज़र कंस्ट्रक्टर में पास करके। यह हमारे मॉडल को परिभाषित और प्रशिक्षित करना काफी आसान बना देता है:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Training vectorizer\n",
|
|
"938/938 [==============================] - 7s 7ms/step - loss: 0.5929 - acc: 0.8486 - val_loss: 0.4168 - val_acc: 0.8772\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<keras.callbacks.History at 0x20c725217c0>"
|
|
]
|
|
},
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"model = keras.models.Sequential([\n",
|
|
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='count'),\n",
|
|
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
|
"])\n",
|
|
"print(\"Training vectorizer\")\n",
|
|
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
|
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
|
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## टर्म फ्रीक्वेंसी - इनवर्स डॉक्यूमेंट फ्रीक्वेंसी (TF-IDF)\n",
|
|
"\n",
|
|
"BoW प्रतिनिधित्व में, शब्दों की उपस्थिति को एक ही तकनीक का उपयोग करके वेट किया जाता है, चाहे वह शब्द कोई भी हो। हालांकि, यह स्पष्ट है कि *a* और *in* जैसे सामान्य शब्द वर्गीकरण के लिए उतने महत्वपूर्ण नहीं होते जितने कि विशेष शब्द। अधिकांश NLP कार्यों में कुछ शब्द दूसरों की तुलना में अधिक प्रासंगिक होते हैं।\n",
|
|
"\n",
|
|
"**TF-IDF** का मतलब है **टर्म फ्रीक्वेंसी - इनवर्स डॉक्यूमेंट फ्रीक्वेंसी**। यह बैग-ऑफ-वर्ड्स का एक प्रकार है, जिसमें किसी दस्तावेज़ में शब्द की उपस्थिति को दर्शाने वाले बाइनरी 0/1 मान के बजाय, एक फ्लोटिंग-पॉइंट मान का उपयोग किया जाता है, जो कॉर्पस में शब्द की उपस्थिति की आवृत्ति से संबंधित होता है।\n",
|
|
"\n",
|
|
"औपचारिक रूप से, किसी शब्द $i$ का वजन $w_{ij}$ दस्तावेज़ $j$ में इस प्रकार परिभाषित किया गया है:\n",
|
|
"$$\n",
|
|
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
|
|
"$$\n",
|
|
"जहां\n",
|
|
"* $tf_{ij}$ दस्तावेज़ $j$ में $i$ की उपस्थिति की संख्या है, यानी वह BoW मान जिसे हमने पहले देखा था\n",
|
|
"* $N$ संग्रह में दस्तावेज़ों की संख्या है\n",
|
|
"* $df_i$ पूरे संग्रह में शब्द $i$ को शामिल करने वाले दस्तावेज़ों की संख्या है\n",
|
|
"\n",
|
|
"TF-IDF मान $w_{ij}$ किसी दस्तावेज़ में शब्द की उपस्थिति की संख्या के अनुपात में बढ़ता है और कॉर्पस में उन दस्तावेज़ों की संख्या से ऑफसेट होता है जिसमें वह शब्द शामिल है। यह इस तथ्य को समायोजित करने में मदद करता है कि कुछ शब्द दूसरों की तुलना में अधिक बार दिखाई देते हैं। उदाहरण के लिए, यदि कोई शब्द *हर* दस्तावेज़ में दिखाई देता है, तो $df_i=N$, और $w_{ij}=0$, और उन शब्दों को पूरी तरह से नजरअंदाज कर दिया जाएगा।\n",
|
|
"\n",
|
|
"आप आसानी से Scikit Learn का उपयोग करके टेक्स्ट का TF-IDF वेक्टराइज़ेशन बना सकते हैं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
|
|
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
|
|
" 0. , 0. , 0. , 0. , 0. ,\n",
|
|
" 0. ]])"
|
|
]
|
|
},
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
|
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
|
|
"vectorizer.fit_transform(corpus)\n",
|
|
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Keras में, `TextVectorization` लेयर `output_mode='tf-idf'` पैरामीटर पास करके स्वचालित रूप से TF-IDF आवृत्तियों की गणना कर सकती है। आइए ऊपर उपयोग किए गए कोड को दोहराते हैं ताकि देख सकें कि TF-IDF का उपयोग करने से सटीकता बढ़ती है या नहीं:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Training vectorizer\n",
|
|
"938/938 [==============================] - 12s 12ms/step - loss: 0.4197 - acc: 0.8662 - val_loss: 0.3432 - val_acc: 0.8849\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<keras.callbacks.History at 0x20c729dfd30>"
|
|
]
|
|
},
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"model = keras.models.Sequential([\n",
|
|
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='tf-idf'),\n",
|
|
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
|
"])\n",
|
|
"print(\"Training vectorizer\")\n",
|
|
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
|
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\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",
|
|
"हालांकि TF-IDF प्रतिनिधित्व विभिन्न शब्दों को आवृत्ति भार प्रदान करते हैं, वे न तो अर्थ को व्यक्त कर सकते हैं और न ही क्रम को। जैसा कि प्रसिद्ध भाषाविद् जे. आर. फर्थ ने 1935 में कहा था, \"शब्द का पूर्ण अर्थ हमेशा संदर्भात्मक होता है, और संदर्भ से अलग अर्थ का कोई भी अध्ययन गंभीरता से नहीं लिया जा सकता।\" हम इस पाठ्यक्रम में आगे भाषा मॉडलिंग का उपयोग करके पाठ से संदर्भात्मक जानकारी को कैप्चर करना सीखेंगे।\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**अस्वीकरण**: \nयह दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) का उपयोग करके अनुवादित किया गया है। जबकि हम सटीकता सुनिश्चित करने का प्रयास करते हैं, कृपया ध्यान दें कि स्वचालित अनुवाद में त्रुटियां या अशुद्धियां हो सकती हैं। मूल भाषा में उपलब्ध मूल दस्तावेज़ को प्रामाणिक स्रोत माना जाना चाहिए। महत्वपूर्ण जानकारी के लिए, पेशेवर मानव अनुवाद की सिफारिश की जाती है। इस अनुवाद के उपयोग से उत्पन्न किसी भी गलतफहमी या गलत व्याख्या के लिए हम उत्तरदायी नहीं हैं।\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"interpreter": {
|
|
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
|
},
|
|
"kernel_info": {
|
|
"name": "conda-env-py37_tensorflow-py"
|
|
},
|
|
"kernelspec": {
|
|
"display_name": "py37_tensorflow",
|
|
"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"
|
|
},
|
|
"nteract": {
|
|
"version": "nteract-front-end@1.0.0"
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "19b43951d55b377a76209c24c1f017e4",
|
|
"translation_date": "2025-08-31T15:31:44+00:00",
|
|
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
|
|
"language_code": "hi"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |