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",
|
|
"शब्द अर्थ व्यक्त करतात, त्यामुळे कधी कधी आपण एखाद्या मजकूराचा अर्थ फक्त त्यातील स्वतंत्र शब्दांकडे पाहून समजू शकतो, वाक्यातील त्यांच्या क्रमाकडे दुर्लक्ष करून. उदाहरणार्थ, जेव्हा बातम्या वर्गीकृत करायच्या असतात, तेव्हा *weather* आणि *snow* सारखे शब्द *हवामान अंदाज* सूचित करतात, तर *stocks* आणि *dollar* सारखे शब्द *आर्थिक बातम्या* दर्शवतील.\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",
|
|
"> **टीप**: तरीही आम्हाला आमच्या डेटासेटवर `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",
|
|
"बॅग-ऑफ-वर्ड्स पद्धतीची एक मर्यादा म्हणजे काही शब्द बहु-शब्द अभिव्यक्तींचा भाग असतात. उदाहरणार्थ, 'hot dog' या शब्दाचा अर्थ इतर संदर्भांतील 'hot' आणि 'dog' या शब्दांपेक्षा पूर्णपणे वेगळा असतो. जर आपण 'hot' आणि 'dog' या शब्दांना नेहमी समान व्हेक्टर वापरून दर्शवले, तर ते आपल्या मॉडेलसाठी गोंधळ निर्माण करू शकते.\n",
|
|
"\n",
|
|
"यावर उपाय म्हणून, **एन-ग्राम प्रतिनिधित्व** दस्तऐवज वर्गीकरणाच्या पद्धतींमध्ये वापरले जाते, जिथे प्रत्येक शब्द, द्वि-शब्द किंवा त्रि-शब्दाची वारंवारता वर्गीकरण करणारे प्रशिक्षक तयार करण्यासाठी उपयुक्त वैशिष्ट्य असते. उदाहरणार्थ, बायग्राम प्रतिनिधित्वामध्ये, मूळ शब्दांव्यतिरिक्त, आपण सर्व शब्द जोड्या शब्दसंग्रहात समाविष्ट करू.\n",
|
|
"\n",
|
|
"खाली Scikit 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` पॅरामीटर पास करावा लागेल. बायग्राम शब्दसंग्रहाची लांबी **लक्षणीयरीत्या मोठी** असते, आपल्या बाबतीत ती 1.3 दशलक्षांहून अधिक टोकन्स आहे! त्यामुळे बायग्राम टोकन्सना काहीतरी वाजवी मर्यादेने मर्यादित करणे योग्य ठरेल.\n",
|
|
"\n",
|
|
"आपण वरीलप्रमाणेच कोड वापरून वर्गीकरणकर्ता प्रशिक्षित करू शकतो, परंतु हे खूपच मेमरी-अकार्यक्षम ठरेल. पुढील युनिटमध्ये, आपण embeddings वापरून बायग्राम वर्गीकरणकर्ता प्रशिक्षित करू. तोपर्यंत, आपण या नोटबुकमध्ये बायग्राम वर्गीकरणकर्ता प्रशिक्षणाचा प्रयोग करू शकता आणि अधिक अचूकता मिळवता येते का ते पाहू शकता.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## BoW व्हेक्टर आपोआप गणना करणे\n",
|
|
"\n",
|
|
"वरील उदाहरणात, आपण वैयक्तिक शब्दांच्या वन-हॉट एन्कोडिंग्सची बेरीज करून BoW व्हेक्टर हाताने गणना केली. तथापि, TensorFlow च्या नवीनतम आवृत्तीमध्ये, आपण `output_mode='count'` पॅरामीटर व्हेक्टरायझर कन्स्ट्रक्टरला पास करून BoW व्हेक्टर आपोआप गणना करू शकतो. यामुळे आपले मॉडेल परिभाषित करणे आणि प्रशिक्षण देणे खूपच सोपे होते:\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",
|
|
"अधिक औपचारिकपणे, दस्तऐवज $j$ मधील शब्द $i$ चे वजन $w_{ij}$ खालीलप्रमाणे परिभाषित केले जाते:\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-28T09:53:58+00:00",
|
|
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
|
|
"language_code": "mr"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |