Merge pull request #488 from microsoft/update-translations

🌐 Update translations via Co-op Translator
This commit is contained in:
Lee Stott 2025-08-28 10:57:49 +01:00 committed by GitHub
commit dab0fadba9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
159 changed files with 150320 additions and 0 deletions

View File

@ -0,0 +1,478 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# प्राणी तज्ज्ञ प्रणाली अंमलात आणणे\n",
"\n",
"[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) मधील एक उदाहरण.\n",
"\n",
"या नमुन्यात, आपण काही शारीरिक वैशिष्ट्यांवर आधारित प्राणी ओळखण्यासाठी एक साधी ज्ञान-आधारित प्रणाली अंमलात आणू. ही प्रणाली खालील AND-OR झाडाद्वारे दर्शविली जाऊ शकते (हे संपूर्ण झाडाचा एक भाग आहे, आपण सहजपणे आणखी काही नियम जोडू शकतो):\n",
"\n",
"![](../../../../translated_images/AND-OR-Tree.5592d2c70187f283703c8e9c0d69d6a786eb370f4ace67f9a7aae5ada3d260b0.mr.png)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मागील अनुमानासह आमची स्वतःची तज्ज्ञ प्रणाली शेल\n",
"\n",
"चला उत्पादन नियमांवर आधारित ज्ञानाचे प्रतिनिधित्व करण्यासाठी एक साधी भाषा परिभाषित करण्याचा प्रयत्न करूया. नियम परिभाषित करण्यासाठी आम्ही Python वर्गांचा कीवर्ड म्हणून वापर करू. मुख्यतः 3 प्रकारचे वर्ग असतील:\n",
"* `Ask` वापरकर्त्याला विचारायच्या प्रश्नाचे प्रतिनिधित्व करते. यात संभाव्य उत्तरांचा संच असतो.\n",
"* `If` नियमाचे प्रतिनिधित्व करते, आणि नियमाच्या सामग्री साठवण्यासाठी फक्त एक सिंटॅक्टिक शुगर आहे.\n",
"* `AND`/`OR` हे वर्ग झाडाच्या AND/OR शाखांचे प्रतिनिधित्व करण्यासाठी आहेत. ते फक्त आतल्या युक्तिवादांची यादी साठवतात. कोड सुलभ करण्यासाठी, सर्व कार्यक्षमता पालक वर्ग `Content` मध्ये परिभाषित केली आहे.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Ask():\n",
" def __init__(self,choices=['y','n']):\n",
" self.choices = choices\n",
" def ask(self):\n",
" if max([len(x) for x in self.choices])>1:\n",
" for i,x in enumerate(self.choices):\n",
" print(\"{0}. {1}\".format(i,x),flush=True)\n",
" x = int(input())\n",
" return self.choices[x]\n",
" else:\n",
" print(\"/\".join(self.choices),flush=True)\n",
" return input()\n",
"\n",
"class Content():\n",
" def __init__(self,x):\n",
" self.x=x\n",
" \n",
"class If(Content):\n",
" pass\n",
"\n",
"class AND(Content):\n",
" pass\n",
"\n",
"class OR(Content):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आमच्या प्रणालीमध्ये, कार्यरत स्मृतीमध्ये **गुणधर्म-मूल्य जोड्या** म्हणून **तथ्यांची** यादी असेल. ज्ञानकोशाला एक मोठा शब्दकोश म्हणून परिभाषित करता येईल, जो क्रिया (कार्यरत स्मृतीमध्ये समाविष्ट करावयाच्या नवीन तथ्ये) अटींशी नकाशित करतो, ज्या AND-OR अभिव्यक्ती म्हणून व्यक्त केल्या जातात. तसेच, काही तथ्ये `विचारली` जाऊ शकतात.\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"rules = {\n",
" 'default': Ask(['y','n']),\n",
" 'color' : Ask(['red-brown','black and white','other']),\n",
" 'pattern' : Ask(['dark stripes','dark spots']),\n",
" 'mammal': If(OR(['hair','gives milk'])),\n",
" 'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),\n",
" 'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),\n",
" 'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),\n",
" 'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),\n",
" 'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),\n",
" 'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),\n",
" 'animal:zebra' : If(['ungulate','pattern:dark stripes']),\n",
" 'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),\n",
" 'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),\n",
" 'animal:albatross' : If(['bird','flies well'])\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"बॅकवर्ड इनफरन्स करण्यासाठी, आपण `Knowledgebase` नावाचा वर्ग परिभाषित करू. हा वर्ग खालील गोष्टींचा समावेश करेल:\n",
"* कार्यरत `memory` - एक डिक्शनरी जी गुणधर्मांना त्यांच्या मूल्यांशी नकाशित करते\n",
"* `rules` - वरीलप्रमाणे परिभाषित केलेल्या स्वरूपातील ज्ञानभांडार नियम\n",
"\n",
"मुख्य दोन पद्धती आहेत:\n",
"* `get` - एखाद्या गुणधर्माचे मूल्य प्राप्त करण्यासाठी, आवश्यक असल्यास इनफरन्स करणे. उदाहरणार्थ, `get('color')` हे रंगाच्या स्लॉटचे मूल्य मिळवेल (जर आवश्यक असेल तर विचारेल आणि नंतरच्या वापरासाठी कार्यरत मेमरीमध्ये मूल्य साठवेल). जर आपण `get('color:blue')` विचारले, तर ते रंग विचारेल आणि नंतर रंगावर आधारित `y`/`n` मूल्य परत करेल.\n",
"* `eval` - प्रत्यक्ष इनफरन्स करते, म्हणजे AND/OR ट्री ट्रॅव्हर्स करते, उप-लक्ष्यांचे मूल्यांकन करते, इत्यादी.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class KnowledgeBase():\n",
" def __init__(self,rules):\n",
" self.rules = rules\n",
" self.memory = {}\n",
" \n",
" def get(self,name):\n",
" if ':' in name:\n",
" k,v = name.split(':')\n",
" vv = self.get(k)\n",
" return 'y' if v==vv else 'n'\n",
" if name in self.memory.keys():\n",
" return self.memory[name]\n",
" for fld in self.rules.keys():\n",
" if fld==name or fld.startswith(name+\":\"):\n",
" # print(\" + proving {}\".format(fld))\n",
" value = 'y' if fld==name else fld.split(':')[1]\n",
" res = self.eval(self.rules[fld],field=name)\n",
" if res!='y' and res!='n' and value=='y':\n",
" self.memory[name] = res\n",
" return res\n",
" if res=='y':\n",
" self.memory[name] = value\n",
" return value\n",
" # field is not found, using default\n",
" res = self.eval(self.rules['default'],field=name)\n",
" self.memory[name]=res\n",
" return res\n",
" \n",
" def eval(self,expr,field=None):\n",
" # print(\" + eval {}\".format(expr))\n",
" if isinstance(expr,Ask):\n",
" print(field)\n",
" return expr.ask()\n",
" elif isinstance(expr,If):\n",
" return self.eval(expr.x)\n",
" elif isinstance(expr,AND) or isinstance(expr,list):\n",
" expr = expr.x if isinstance(expr,AND) else expr\n",
" for x in expr:\n",
" if self.eval(x)=='n':\n",
" return 'n'\n",
" return 'y'\n",
" elif isinstance(expr,OR):\n",
" for x in expr.x:\n",
" if self.eval(x)=='y':\n",
" return 'y'\n",
" return 'n'\n",
" elif isinstance(expr,str):\n",
" return self.get(expr)\n",
" else:\n",
" print(\"Unknown expr: {}\".format(expr))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण आपले प्राणी ज्ञानकोश परिभाषित करूया आणि सल्लामसलत करूया. लक्षात ठेवा की ही प्रक्रिया तुम्हाला प्रश्न विचारेल. तुम्ही `y`/`n` टाइप करून होय-नाही प्रश्नांची उत्तरे देऊ शकता, किंवा लांब बहुपर्यायी उत्तरांसाठी संख्या (0..N) निर्दिष्ट करून उत्तर देऊ शकता.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hair\n",
"y/n\n",
"sharp teeth\n",
"y/n\n",
"claws\n",
"y/n\n",
"forward-looking eyes\n",
"y/n\n",
"color\n",
"0. red-brown\n",
"1. black and white\n",
"2. other\n",
"has hooves\n",
"y/n\n",
"long neck\n",
"y/n\n",
"long legs\n",
"y/n\n",
"pattern\n",
"0. dark stripes\n",
"1. dark spots\n"
]
},
{
"data": {
"text/plain": [
"'giraffe'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"kb = KnowledgeBase(rules)\n",
"kb.get('animal')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PyKnow वापरून फॉरवर्ड इनफरन्स\n",
"\n",
"पुढील उदाहरणात, ज्ञान सादरीकरणासाठीच्या लायब्ररींपैकी एक, [PyKnow](https://github.com/buguroo/pyknow/) वापरून फॉरवर्ड इनफरन्स कसे अंमलात आणायचे ते पाहू. **PyKnow** ही Python मध्ये फॉरवर्ड इनफरन्स सिस्टीम तयार करण्यासाठीची लायब्ररी आहे, जी जुन्या पारंपरिक प्रणाली [CLIPS](http://www.clipsrules.net/index.html) सारखी डिझाइन केली गेली आहे.\n",
"\n",
"आपण स्वतः फॉरवर्ड चेनिंग अंमलात आणू शकलो असतो, आणि त्यात फारसे अडचणीही आल्या नसत्या, पण साध्या अंमलबजावणी सहसा फार कार्यक्षम नसतात. अधिक प्रभावी नियम जुळवण्यासाठी एक विशेष अल्गोरिदम [Rete](https://en.wikipedia.org/wiki/Rete_algorithm) वापरला जातो.\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting git+https://github.com/buguroo/pyknow/\n",
" Cloning https://github.com/buguroo/pyknow/ to /tmp/pip-req-build-3cqeulyl\n",
" Running command git clone --filter=blob:none --quiet https://github.com/buguroo/pyknow/ /tmp/pip-req-build-3cqeulyl\n",
" Resolved https://github.com/buguroo/pyknow/ to commit 48818336f2e9a126f1964f2d8dc22d37ff800fe8\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hCollecting frozendict==1.2\n",
" Using cached frozendict-1.2.tar.gz (2.6 kB)\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hCollecting schema==0.6.7\n",
" Using cached schema-0.6.7-py2.py3-none-any.whl (14 kB)\n",
"Building wheels for collected packages: pyknow, frozendict\n",
" Building wheel for pyknow (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25h Created wheel for pyknow: filename=pyknow-1.7.0-py3-none-any.whl size=34228 sha256=b7de5b09292c4007667c72f69b98d5a1b5f7324ff15f9dd8e077c3d5f7aade42\n",
" Stored in directory: /tmp/pip-ephem-wheel-cache-k7jpave7/wheels/81/1a/d3/f6c15dbe1955598a37755215f2a10449e7418500d7bd4b9508\n",
" Building wheel for frozendict (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25h Created wheel for frozendict: filename=frozendict-1.2-py3-none-any.whl size=3148 sha256=2863d55c240d2409cddf05ccfe600591f8478681549fc97555c47c90dc6bb160\n",
" Stored in directory: /home/rg/.cache/pip/wheels/49/ac/f8/cb8120244e710bdb479c86198b03c7b08c3c2d3d2bf448fd6e\n",
"Successfully built pyknow frozendict\n",
"Installing collected packages: schema, frozendict, pyknow\n",
"Successfully installed frozendict-1.2 pyknow-1.7.0 schema-0.6.7\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install git+https://github.com/buguroo/pyknow/"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from pyknow import *\n",
"#import pyknow"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही आमची प्रणाली `KnowledgeEngine` चे उपवर्ग असलेल्या वर्ग म्हणून परिभाषित करू. प्रत्येक नियम `@Rule` या अॅनोटेशनसह स्वतंत्र फंक्शनद्वारे परिभाषित केला जातो, जो नियम कधी कार्यान्वित होईल हे निर्दिष्ट करतो. नियमाच्या आत, आम्ही `declare` फंक्शनचा वापर करून नवीन तथ्ये जोडू शकतो, आणि ती तथ्ये जोडल्याने पुढील अनुमान इंजिनद्वारे आणखी काही नियम कार्यान्वित केले जातील.\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Animals(KnowledgeEngine):\n",
" @Rule(OR(\n",
" AND(Fact('sharp teeth'),Fact('claws'),Fact('forward looking eyes')),\n",
" Fact('eats meat')))\n",
" def cornivor(self):\n",
" self.declare(Fact('carnivor'))\n",
" \n",
" @Rule(OR(Fact('hair'),Fact('gives milk')))\n",
" def mammal(self):\n",
" self.declare(Fact('mammal'))\n",
"\n",
" @Rule(Fact('mammal'),\n",
" OR(Fact('has hooves'),Fact('chews cud')))\n",
" def hooves(self):\n",
" self.declare('ungulate')\n",
" \n",
" @Rule(OR(Fact('feathers'),AND(Fact('flies'),Fact('lays eggs'))))\n",
" def bird(self):\n",
" self.declare('bird')\n",
" \n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark spots'))\n",
" def monkey(self):\n",
" self.declare(Fact(animal='monkey'))\n",
"\n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'))\n",
" def tiger(self):\n",
" self.declare(Fact(animal='tiger'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact('long neck'),\n",
" Fact('long legs'),\n",
" Fact(pattern='dark spots'))\n",
" def giraffe(self):\n",
" self.declare(Fact(animal='giraffe'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact(pattern='dark stripes'))\n",
" def zebra(self):\n",
" self.declare(Fact(animal='zebra'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('long neck'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def straus(self):\n",
" self.declare(Fact(animal='ostrich'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('swims'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def pinguin(self):\n",
" self.declare(Fact(animal='pinguin'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('flies well'))\n",
" def albatros(self):\n",
" self.declare(Fact(animal='albatross'))\n",
" \n",
" @Rule(Fact(animal=MATCH.a))\n",
" def print_result(self,a):\n",
" print('Animal is {}'.format(a))\n",
" \n",
" def factz(self,l):\n",
" for x in l:\n",
" self.declare(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"एकदा आपण ज्ञानकोश परिभाषित केला की, आपण आपल्या कार्यरत स्मृतीत काही प्रारंभिक तथ्ये भरतो आणि नंतर `run()` पद्धत कॉल करून अनुमान प्रक्रिया करतो. परिणामी, आपण पाहू शकता की नवीन अनुमानित तथ्ये कार्यरत स्मृतीत जोडली जातात, ज्यामध्ये प्राण्याबद्दलचे अंतिम तथ्य समाविष्ट आहे (जर आपण सर्व प्रारंभिक तथ्ये योग्यरित्या सेट केली असतील तर).\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Animal is tiger\n"
]
},
{
"data": {
"text/plain": [
"FactList([(0, InitialFact()),\n",
" (1, Fact(color='red-brown')),\n",
" (2, Fact(pattern='dark stripes')),\n",
" (3, Fact('sharp teeth')),\n",
" (4, Fact('claws')),\n",
" (5, Fact('forward looking eyes')),\n",
" (6, Fact('gives milk')),\n",
" (7, Fact('mammal')),\n",
" (8, Fact('carnivor')),\n",
" (9, Fact(animal='tiger'))])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ex1 = Animals()\n",
"ex1.reset()\n",
"ex1.factz([\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'),\n",
" Fact('sharp teeth'),\n",
" Fact('claws'),\n",
" Fact('forward looking eyes'),\n",
" Fact('gives milk')])\n",
"ex1.run()\n",
"ex1.facts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) चा वापर करून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात घ्या की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील मूळ दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर केल्यामुळे उद्भवणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.11.2"
},
"coopTranslator": {
"original_hash": "ab2bd97b0453415b89a469284609a8ce",
"translation_date": "2025-08-28T08:34:45+00:00",
"source_file": "lessons/2-Symbolic/Animals.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,593 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# कुटुंब संबंधांचे ऑंटोलॉजी\n",
"\n",
"हा उदाहरण [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) चा एक भाग आहे, आणि [या ब्लॉग पोस्ट](https://habr.com/post/270857/) द्वारे प्रेरित आहे.\n",
"\n",
"मला नेहमीच कुटुंबातील लोकांमधील वेगवेगळे संबंध लक्षात ठेवणे कठीण वाटते. या उदाहरणात, आपण कुटुंब संबंध परिभाषित करणारे ऑंटोलॉजी आणि प्रत्यक्ष वंशावळ घेऊ, आणि नंतर आपोआप निष्कर्ष काढून सर्व नातेवाईक शोधण्याचा मार्ग दाखवू.\n",
"\n",
"### वंशावळ मिळवणे\n",
"\n",
"उदाहरण म्हणून, आपण [Romanov Tsar Family](https://en.wikipedia.org/wiki/House_of_Romanov) ची वंशावळ घेऊ. कुटुंब संबंधांचे वर्णन करण्यासाठी सर्वात सामान्य स्वरूप [GEDCOM](https://en.wikipedia.org/wiki/GEDCOM) आहे. आपण Romanov कुटुंबाची वंशावळ GEDCOM स्वरूपात घेऊ:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 HEAD\n",
"1 CHAR UTF8\n",
"1 GEDC\n",
"2 VERS 5.5\n",
"0 @0@ INDI\n",
"1 NAME Mihail Fedorovich /Romanov/\n",
"1 SEX M\n",
"1 BIRT\n",
"2 DATE 1613\n",
"1 DEAT \n",
"2 DATE 1645\n",
"1 FAMS @41@\n",
"0 @1@ INDI\n",
"1 NAME Evdokija Lukjanovna /Streshneva/\n",
"1 SEX F\n"
]
}
],
"source": [
"!head -15 data/tsars.ged"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"GEDCOM फाइल वापरण्यासाठी, आपण `python-gedcom` लायब्ररी वापरू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting python-gedcom\n",
" Downloading python_gedcom-1.0.0-py2.py3-none-any.whl (35 kB)\n",
"Installing collected packages: python-gedcom\n",
"Successfully installed python-gedcom-1.0.0\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install python-gedcom"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ही लायब्ररी फाइल पार्सिंगसंबंधी काही तांत्रिक समस्या दूर करते, परंतु तरीही ती झाडातील सर्व व्यक्ती आणि कुटुंबांपर्यंत खूपच लो-लेव्हल प्रवेश देते. येथे आपण फाइल कशी पार्स करू शकतो आणि सर्व व्यक्तींची यादी कशी दाखवू शकतो ते दिले आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from gedcom.parser import Parser\n",
"from gedcom.element.individual import IndividualElement\n",
"from gedcom.element.family import FamilyElement\n",
"g = Parser()\n",
"g.parse_file('data/tsars.ged')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true,
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"[('@0@', ('Mihail Fedorovich', 'Romanov')),\n",
" ('@1@', ('Evdokija Lukjanovna', 'Streshneva')),\n",
" ('@2@', ('Aleksej Mihajlovich', 'Romanov')),\n",
" ('@3@', ('Marija Ilinichna', 'Miloslavskaja')),\n",
" ('@4@', ('Natalja Kirillovna', 'Naryshkina')),\n",
" ('@5@', ('Marfa Matveevna', 'Apraksina')),\n",
" ('@6@', ('Fedor Alekseevich', 'Romanov')),\n",
" ('@7@', ('Sofja Aleksevna', 'Romanova')),\n",
" ('@8@', ('Ivan V Alekseevich', 'Romanov')),\n",
" ('@9@', ('Praskovja Fedorovna', 'Saltykova')),\n",
" ('@10@', ('Ekaterina Ivanovna', 'Romanova')),\n",
" ('@11@', ('Anna Ivanovna', 'Romanova')),\n",
" ('@12@', ('Fridrih Vilgelm', 'Kurlandskij')),\n",
" ('@13@', ('Karl Leopold', 'Meklenburg-Shverinskij')),\n",
" ('@14@', ('Anna Leopoldovna', 'Meklenburg-Shverinskaja')),\n",
" ('@15@', ('Anton Ulrih', 'Braunshvejg-Volfenbjuttelskij')),\n",
" ('@16@', ('Ivan VI Antonovich', 'Braunshvejg-Volfenbjuttelskij')),\n",
" ('@17@', ('Petr I Alekseevich', 'Romanov')),\n",
" ('@18@', ('Evdokija Fedorovna', 'Lopuhina')),\n",
" ('@19@', ('Ekaterina I Alekseevna', 'Mihajlova')),\n",
" ('@20@', ('Aleksej Petrovich', 'Romanov')),\n",
" ('@21@', ('Sharlotta Kristina', 'Braunshvejg-Volfenbjuttelskaja')),\n",
" ('@22@', ('Petr II Alekseevich', 'Romanov')),\n",
" ('@23@', ('Anna Petrovna', 'Romanova')),\n",
" ('@24@', ('Elizaveta Petrovna', 'Romanova')),\n",
" ('@25@', ('Karl Fridrih', 'Golshtejn-Gottorpskij')),\n",
" ('@26@', ('Petr III Fedorovich', 'Romanov')),\n",
" ('@27@', ('Ekaterina II', 'Alekseevna')),\n",
" ('@28@', ('Pavel I Petrovich', 'Romanov')),\n",
" ('@29@', ('Natalja Alekseevna', 'Gessen-Darmshtadskaja')),\n",
" ('@30@', ('Marija Fedorovna', 'Vjurtembergskaja')),\n",
" ('@31@', ('Aleksandr I Pavlovich', 'Romanov')),\n",
" ('@32@', ('Elizaveta Alekseevna', 'Baden-Durlahskaja')),\n",
" ('@33@', ('Nikolaj I Pavlovich', 'Romanov')),\n",
" ('@34@', ('Aleksandra Fedorovna', 'Prusskaja')),\n",
" ('@35@', ('Aleksandr II Nikolaevich', 'Romanov')),\n",
" ('@36@', ('Marija Aleksandrovna', 'Gessenskaja')),\n",
" ('@37@', ('Aleksandr III Aleksandrovich', 'Romanov')),\n",
" ('@38@', ('Marija Fedorovna', 'Datskaja')),\n",
" ('@39@', ('Nikolaj II Aleksandrovich', 'Romanov')),\n",
" ('@40@', ('Aleksandra Fedorovna', 'Gessenskaja'))]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = g.get_element_dictionary()\n",
"[ (k,v.get_name()) for k,v in d.items() if isinstance(v,IndividualElement)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"कुटुंबांबद्दल माहिती कशी मिळवायची ते येथे आहे. लक्षात घ्या की हे आपल्याला **ओळखपत्रांची** यादी देते, आणि अधिक स्पष्टता हवी असल्यास आपल्याला ती नावे मध्ये रूपांतरित करावी लागतील:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('@41@', ['@0@', '@1@', '@2@']),\n",
" ('@42@', ['@2@', '@3@', '@6@', '@7@', '@8@']),\n",
" ('@43@', ['@8@', '@9@', '@10@', '@11@']),\n",
" ('@44@', ['@13@', '@10@', '@14@']),\n",
" ('@45@', ['@15@', '@14@', '@16@']),\n",
" ('@46@', ['@2@', '@4@', '@17@']),\n",
" ('@47@', ['@17@', '@18@', '@20@']),\n",
" ('@48@', ['@20@', '@21@', '@22@']),\n",
" ('@49@', ['@17@', '@19@', '@23@', '@24@']),\n",
" ('@50@', ['@25@', '@23@', '@26@']),\n",
" ('@51@', ['@26@', '@27@', '@28@']),\n",
" ('@52@', ['@28@', '@30@', '@31@', '@33@']),\n",
" ('@53@', ['@33@', '@34@', '@35@']),\n",
" ('@54@', ['@35@', '@36@', '@37@']),\n",
" ('@55@', ['@37@', '@38@', '@39@'])]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = g.get_element_dictionary()\n",
"[ (k,[x.get_value() for x in v.get_child_elements()]) for k,v in d.items() if isinstance(v,FamilyElement)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### कुटुंब ऑंटोलॉजी मिळवणे\n",
"\n",
"आता, [कुटुंब ऑंटोलॉजी](https://raw.githubusercontent.com/blokhin/genealogical-trees/master/data/header.ttl) वर एक नजर टाकूया, जी सेमँटिक वेब ट्रिपलेट्सच्या संचाच्या स्वरूपात परिभाषित केली आहे. या ऑंटोलॉजीमध्ये `isUncleOf`, `isCousinOf` आणि इतर अनेक नातेसंबंध परिभाषित केले आहेत. हे सर्व नातेसंबंध मूलभूत प्रेडिकेट्स `isMotherOf`, `isFatherOf`, `isBrotherOf` आणि `isSisterOf` च्या आधारे परिभाषित केले आहेत. आपण ऑंटोलॉजीचा वापर करून स्वयंचलित तर्कशक्तीच्या मदतीने इतर सर्व नातेसंबंध शोधून काढणार आहोत.\n",
"\n",
"`isAuntOf` प्रॉपर्टीच्या परिभाषेचे एक उदाहरण येथे दिले आहे, जी `isSisterOf` आणि `isParentOf` च्या संयोजनाने परिभाषित केली आहे (*आजी म्हणजे एखाद्याच्या पालकाची बहीण*).\n",
"\n",
"```\n",
"fhkb:isAuntOf a owl:ObjectProperty ;\n",
" rdfs:domain fhkb:Woman ;\n",
" rdfs:range fhkb:Person ;\n",
" owl:propertyChainAxiom ( fhkb:isSisterOf fhkb:isParentOf ) .\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"@prefix fhkb: <http://www.example.com/genealogy.owl#> .\n",
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n",
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
"@prefix xml: <http://www.w3.org/XML/1998/namespace> .\n",
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
"\n",
"<http://www.example.com/genealogy.owl#> a owl:Ontology .\n",
"\n",
"fhkb:DomainEntity a owl:Class .\n",
"\n",
"fhkb:Man a owl:Class ;\n",
" owl:equivalentClass [ a owl:Class ;\n",
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n",
" owl:onProperty fhkb:hasSex ;\n",
" owl:someValuesFrom fhkb:Male ] ) ] .\n",
"\n",
"fhkb:Woman a owl:Class ;\n",
" owl:equivalentClass [ a owl:Class ;\n",
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n"
]
}
],
"source": [
"!head -20 data/onto.ttl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### अनुमानासाठी ऑंटोलॉजी तयार करणे\n",
"\n",
"सोप्या पद्धतीने, आपण एक ऑंटोलॉजी फाइल तयार करू ज्यामध्ये कौटुंबिक ऑंटोलॉजीमधील मूळ नियम आणि आमच्या GEDCOM फाइलमधील व्यक्तींच्या तथ्यांचा समावेश असेल. आपण GEDCOM फाइलमधून कुटुंबे आणि व्यक्तींबद्दलची माहिती काढू आणि ती त्रिकुटांमध्ये रूपांतरित करू.\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"!cp data/onto.ttl .\n",
"\n",
"gedcom_dict = g.get_element_dictionary()\n",
"individuals, marriages = {}, {}\n",
"\n",
"def term2id(el):\n",
" return \"i\" + el.get_pointer().replace('@', '').lower()\n",
"\n",
"out = open(\"onto.ttl\",\"a\")\n",
"\n",
"for k, v in gedcom_dict.items():\n",
" if isinstance(v,IndividualElement):\n",
" children, siblings = set(), set()\n",
" idx = term2id(v)\n",
"\n",
" title = v.get_name()[0] + \" \" + v.get_name()[1]\n",
" title = title.replace('\"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()\n",
"\n",
" own_families = g.get_families(v, 'FAMS')\n",
" for fam in own_families:\n",
" children |= set(term2id(i) for i in g.get_family_members(fam, \"CHIL\"))\n",
"\n",
" parent_families = g.get_families(v, 'FAMC')\n",
" if len(parent_families):\n",
" for member in g.get_family_members(parent_families[0], \"CHIL\"): # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)\n",
" if member.get_pointer() == v.get_pointer():\n",
" continue\n",
" siblings.add(term2id(member))\n",
"\n",
" if idx in individuals:\n",
" children |= individuals[idx].get('children', set())\n",
" siblings |= individuals[idx].get('siblings', set())\n",
" individuals[idx] = {'sex': v.get_gender().lower(), 'children': children, 'siblings': siblings, 'title': title}\n",
"\n",
" elif isinstance(v,FamilyElement):\n",
" wife, husb, children = None, None, set()\n",
" children = set(term2id(i) for i in g.get_family_members(v, \"CHIL\"))\n",
"\n",
" try:\n",
" wife = g.get_family_members(v, \"WIFE\")[0]\n",
" wife = term2id(wife)\n",
" if wife in individuals: individuals[wife]['children'] |= children\n",
" else: individuals[wife] = {'children': children}\n",
" except IndexError: pass\n",
" try:\n",
" husb = g.get_family_members(v, \"HUSB\")[0]\n",
" husb = term2id(husb)\n",
" if husb in individuals: individuals[husb]['children'] |= children\n",
" else: individuals[husb] = {'children': children}\n",
" except IndexError: pass\n",
"\n",
" if wife and husb: marriages[wife + husb] = (term2id(v), wife, husb)\n",
"\n",
"for idx, val in individuals.items():\n",
" added_terms = ''\n",
" if val['sex'] == 'f':\n",
" parent_predicate, sibl_predicate = \"isMotherOf\", \"isSisterOf\"\n",
" else:\n",
" parent_predicate, sibl_predicate = \"isFatherOf\", \"isBrotherOf\"\n",
" if len(val['children']):\n",
" added_terms += \" ;\\n fhkb:\" + parent_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['children']])\n",
" if len(val['siblings']):\n",
" added_terms += \" ;\\n fhkb:\" + sibl_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['siblings']])\n",
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing%s ;\\n rdfs:label \\\"%s\\\" .\\n\" % (idx, added_terms, val['title']))\n",
"\n",
"for k, v in marriages.items():\n",
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing ;\\n fhkb:hasFemalePartner fhkb:%s ;\\n fhkb:hasMalePartner fhkb:%s .\\n\" % v)\n",
"\n",
"out.write(\"[] a owl:AllDifferent ;\\n owl:distinctMembers (\")\n",
"for idx in individuals.keys():\n",
" out.write(\" fhkb:\" + idx)\n",
"for k, v in marriages.items():\n",
" out.write(\" fhkb:\" + v[0])\n",
"out.write(\" ) .\")\n",
"out.close()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" fhkb:hasFemalePartner fhkb:i34 ;\n",
" fhkb:hasMalePartner fhkb:i33 .\n",
"fhkb:i54 a owl:NamedIndividual, owl:Thing ;\n",
" fhkb:hasFemalePartner fhkb:i36 ;\n",
" fhkb:hasMalePartner fhkb:i35 .\n",
"fhkb:i55 a owl:NamedIndividual, owl:Thing ;\n",
" fhkb:hasFemalePartner fhkb:i38 ;\n",
" fhkb:hasMalePartner fhkb:i37 .\n",
"[] a owl:AllDifferent ;\n",
" owl:distinctMembers ( fhkb:i0 fhkb:i1 fhkb:i2 fhkb:i3 fhkb:i4 fhkb:i5 fhkb:i6 fhkb:i7 fhkb:i8 fhkb:i9 fhkb:i10 fhkb:i11 fhkb:i12 fhkb:i13 fhkb:i14 fhkb:i15 fhkb:i16 fhkb:i17 fhkb:i18 fhkb:i19 fhkb:i20 fhkb:i21 fhkb:i22 fhkb:i23 fhkb:i24 fhkb:i25 fhkb:i26 fhkb:i27 fhkb:i28 fhkb:i29 fhkb:i30 fhkb:i31 fhkb:i32 fhkb:i33 fhkb:i34 fhkb:i35 fhkb:i36 fhkb:i37 fhkb:i38 fhkb:i39 fhkb:i40 fhkb:i41 fhkb:i42 fhkb:i43 fhkb:i44 fhkb:i45 fhkb:i46 fhkb:i47 fhkb:i48 fhkb:i49 fhkb:i50 fhkb:i51 fhkb:i52 fhkb:i53 fhkb:i54 fhkb:i55 ) ."
]
}
],
"source": [
"!tail onto.ttl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### अनुमान करणे\n",
"\n",
"आता आपण या ऑंटोलॉजीचा उपयोग अनुमान आणि क्वेरीसाठी करू इच्छितो. यासाठी आपण [RDFLib](https://github.com/RDFLib) या लायब्ररीचा वापर करू, जी RDF ग्राफ वेगवेगळ्या स्वरूपात वाचणे, त्यावर क्वेरी करणे इत्यादीसाठी उपयुक्त आहे.\n",
"\n",
"तार्किक अनुमानासाठी, आपण [OWL-RL](https://github.com/RDFLib/OWL-RL) लायब्ररीचा वापर करू, जी आपल्याला RDF ग्राफचे **क्लोजर** तयार करण्यास अनुमती देते, म्हणजेच सर्व शक्य संकल्पना आणि नातेसंबंध जे अनुमानित केले जाऊ शकतात ते जोडणे.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: rdflib in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (6.3.2)\n",
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (0.6.1)\n",
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (3.0.9)\n",
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib) (1.16.0)\n",
"Collecting git+https://github.com/RDFLib/OWL-RL.git\n",
" Cloning https://github.com/RDFLib/OWL-RL.git to /tmp/pip-req-build-lbfzwi3m\n",
" Running command git clone --filter=blob:none --quiet https://github.com/RDFLib/OWL-RL.git /tmp/pip-req-build-lbfzwi3m\n",
" Resolved https://github.com/RDFLib/OWL-RL.git to commit a77e1791b88b54aace609bc6000aac14c7add4ff\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hRequirement already satisfied: rdflib>=6.0.2 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from owlrl==6.0.2) (6.3.2)\n",
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (0.6.1)\n",
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (3.0.9)\n",
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib>=6.0.2->owlrl==6.0.2) (1.16.0)\n"
]
}
],
"source": [
"!{sys.executable} -m pip install rdflib\n",
"!{sys.executable} -m pip install git+https://github.com/RDFLib/OWL-RL.git"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला ऑंटोलॉजी फाइल उघडू आणि त्यात किती त्रिकुटे आहेत ते पाहू:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Triplets found:669\n"
]
}
],
"source": [
"import rdflib\n",
"from owlrl import DeductiveClosure, OWLRL_Extension\n",
"\n",
"g = rdflib.Graph()\n",
"g.parse(\"onto.ttl\", format=\"turtle\")\n",
"\n",
"print(\"Triplets found:%d\" % len(g))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Triplets after inference:4246\n"
]
}
],
"source": [
"DeductiveClosure(OWLRL_Extension).expand(g)\n",
"print(\"Triplets after inference:%d\" % len(g))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### नातेवाईकांसाठी क्वेरी करणे\n",
"\n",
"आता आपण ग्राफ क्वेरी करून लोकांमधील वेगवेगळ्या नातेसंबंधांचा शोध घेऊ शकतो. आपण **SPARQL** भाषा `query` पद्धतीसह वापरू शकतो. आपल्या उदाहरणात, आपल्या कुटुंबाच्या वंशवृक्षातील सर्व **काका** पाहूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fedor Alekseevich Romanov is uncle of Ekaterina Ivanovna Romanova\n",
"Aleksandr I Pavlovich Romanov is uncle of Aleksandr II Nikolaevich Romanov\n",
"Fedor Alekseevich Romanov is uncle of Anna Ivanovna Romanova\n"
]
}
],
"source": [
"qres = g.query(\n",
" \"\"\"SELECT DISTINCT ?aname ?bname\n",
" WHERE {\n",
" ?a fhkb:isUncleOf ?b .\n",
" ?a rdfs:label ?aname .\n",
" ?b rdfs:label ?bname .\n",
" }\"\"\")\n",
"\n",
"for row in qres:\n",
" print(\"%s is uncle of %s\" % row)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"वेगवेगळ्या कुटुंबीय संबंधांशी प्रयोग करण्यासाठी मोकळ्या मनाने प्रयत्न करा. उदाहरणार्थ, तुम्ही `isAncestorOf` संबंध पाहू शकता, जो पुनरावृत्तीने दिलेल्या व्यक्तीचे सर्व पूर्वज परिभाषित करतो.\n",
"\n",
"शेवटी, चला साफसफाई करूया!\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"!rm onto.ttl"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात घ्या की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील मूळ दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी, व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
},
"kernelspec": {
"display_name": "Python 3.6",
"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.11.2"
},
"coopTranslator": {
"original_hash": "6537d5597320e27b6052b4377b8ff8bb",
"translation_date": "2025-08-28T08:31:48+00:00",
"source_file": "lessons/2-Symbolic/FamilyOntology.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,548 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## मायक्रोसॉफ्ट कॉन्सेप्ट ग्राफ\n",
"\n",
"[Microsoft Concept Graph](https://concept.research.microsoft.com/) ही इंटरनेटवरून संकलित केलेल्या संकल्पनांची मोठी वर्गवारी आहे, ज्यामध्ये संकल्पनांमधील `is-a` संबंध आहेत.\n",
"\n",
"कॉन्सेप्ट ग्राफ दोन प्रकारांमध्ये उपलब्ध आहे:\n",
" * डाउनलोडसाठी मोठा मजकूर फाइल\n",
" * REST API\n",
"\n",
"आकडेवारी:\n",
" * 5401933 अद्वितीय संकल्पना,\n",
" * 12551613 अद्वितीय उदाहरणे\n",
" * 87603947 `is-a` संबंध\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## वेब सेवा वापरणे\n",
"\n",
"वेब सेवा विविध गटांमध्ये एखाद्या संकल्पनेच्या संबंधिततेची शक्यता मोजण्यासाठी वेगवेगळ्या कॉल्स प्रदान करते. अधिक माहिती [येथे](https://concept.research.microsoft.com/Home/Api) उपलब्ध आहे. \n",
"कॉल करण्यासाठी नमुना URL येथे दिला आहे: `https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance=microsoft&topK=10`\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'company': 0.6105356614382954,\n",
" 'vendor': 0.08858636677518003,\n",
" 'client': 0.048239124001183784,\n",
" 'firm': 0.045476965571668145,\n",
" 'large company': 0.043109401203511886,\n",
" 'organization': 0.043010752688172046,\n",
" 'corporation': 0.035908059583703265,\n",
" 'brand': 0.03383644076156654,\n",
" 'software company': 0.027522935779816515,\n",
" 'technology company': 0.023774292196902438}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import urllib\n",
"import json\n",
"import ssl\n",
"\n",
"def http(x):\n",
" ssl._create_default_https_context = ssl._create_unverified_context\n",
" response = urllib.request.urlopen(x)\n",
" data = response.read()\n",
" return data.decode('utf-8')\n",
"\n",
"def query(x):\n",
" return json.loads(http(\"https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance={}&topK=10\".format(urllib.parse.quote(x))))\n",
"\n",
"query('microsoft')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला बातम्यांच्या शीर्षकांना मुख्य संकल्पनांच्या आधारे वर्गीकृत करण्याचा प्रयत्न करूया. बातम्यांची शीर्षके मिळवण्यासाठी, आपण [NewsApi.org](http://newsapi.org) सेवा वापरणार आहोत. ही सेवा वापरण्यासाठी तुम्हाला स्वतःचा API की मिळवावा लागेल - वेबसाइटवर जा आणि मोफत डेव्हलपर प्लॅनसाठी नोंदणी करा.\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"newsapi_key = '<your API key here>'\n",
"def get_news(country='us'):\n",
" res = json.loads(http(\"https://newsapi.org/v2/top-headlines?country={0}&apiKey={1}\".format(country,newsapi_key)))\n",
" return res['articles']\n",
"\n",
"all_titles = [x['title'] for x in get_news('us')+get_news('gb')]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Covid-19 Live Updates: Vaccines and Boosters News - The New York Times',\n",
" 'Ukrainians Flee Mariupol as Russian Forces Push to Take Port City - The Wall Street Journal',\n",
" 'Bond Yields Jump, Stock Futures Rise After Powell Says Fed Is Ready to Be More Aggressive - The Wall Street Journal',\n",
" 'Putin critic Alexei Navalny found guilty by Russian court - New York Post ',\n",
" \"Supreme Court nominee Ketanji Brown Jackson will face questions at confirmation hearing's second day - CNN\",\n",
" '2 teachers killed at Swedish high school, student arrested - ABC News',\n",
" 'Clues to Covid-19s Next Moves Come From Sewers - The Wall Street Journal',\n",
" 'Republicans to roll dice by grilling Jackson over child-pornography sentencing decisions | TheHill - The Hill',\n",
" 'Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
" \"US stocks whipsawed overnight after Fed Chair Powell's remarks - Fox Business\",\n",
" \"'We've learned absolutely nothing': Tests could again be in short supply if Covid surges - POLITICO\",\n",
" \"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\",\n",
" 'China searches for victims, flight recorders after first plane crash in 12 years - Reuters',\n",
" 'Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters',\n",
" 'Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español',\n",
" 'Powers Remain and Threats Lurk as Womens Sweet 16 Is Set - The New York Times',\n",
" 'Webb Space Telescope Begins Multi-Instrument Alignment - SciTechDaily',\n",
" \"UConn vs UCF - NCAA women's tournament second-round highlights - March Madness\",\n",
" 'Bucking Republican Trend, Indiana Governor Vetoes Transgender Sports Bill - The New York Times',\n",
" \"Maggie Fox dead: Coronation Street and Shameless actress dies after 'sudden accident' - Mirror Online - The Mirror\",\n",
" 'China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent',\n",
" 'Daniel Morgan murder: damning report condemns Met police - The Guardian',\n",
" 'What to expect from Rishi Sunaks Spring Statement - BBC.com',\n",
" 'UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian',\n",
" \"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\",\n",
" 'Brass Eyes outtakes show the brutal TV comedy was the tip of an iceberg - The Guardian',\n",
" \"Vladimir Putin threatens civilians to break Mariupol's spirit - The Times\",\n",
" 'Shell U-turn on Cambo oilfield would threaten green targets, say campaigners - The Guardian',\n",
" 'St Helens dog attack: Girl aged 17 months killed at home - BBC',\n",
" \"PlayStation to buy 'Assassin's Creed' veteran Jade Raymond's Haven Studios - NME\",\n",
" 'Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
" 'Nintendo Switch finally has folders • Eurogamer.net - Eurogamer.net',\n",
" 'FA to “find a solution” as Liverpool fan group blasts “shambolic” Wembley travel - This Is Anfield',\n",
" 'Manchester United transfer news LIVE Erik ten Hag latest and Man Utd manager updates - Manchester Evening News',\n",
" 'Inflation raises cost of UK government borrowing in February; crude oil up again business live - The Guardian',\n",
" 'Alexei Navalny: Kremlin critic found guilty of large-scale fraud and contempt of court by Russian court - Sky News',\n",
" \"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\",\n",
" 'Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian']"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"all_titles"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"सर्वप्रथम, आम्हाला बातम्यांच्या शीर्षकांमधून नामे काढता यावीत असे हवे आहे. आम्ही हे करण्यासाठी `TextBlob` लायब्ररीचा वापर करू, जी अशा प्रकारच्या अनेक सामान्य NLP कार्यांना सुलभ करते.\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: textblob in c:\\winapp\\miniconda3\\lib\\site-packages (0.17.1)\n",
"Requirement already satisfied: nltk>=3.1 in c:\\winapp\\miniconda3\\lib\\site-packages (from textblob) (3.5)\n",
"Requirement already satisfied: joblib in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (1.0.1)\n",
"Requirement already satisfied: regex in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (2021.11.10)\n",
"Requirement already satisfied: tqdm in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (4.61.2)\n",
"Requirement already satisfied: click in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (8.0.3)\n",
"Requirement already satisfied: colorama in c:\\winapp\\miniconda3\\lib\\site-packages (from click->nltk>=3.1->textblob) (0.4.4)\n",
"Finished.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[nltk_data] Downloading package brown to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package brown is already up-to-date!\n",
"[nltk_data] Downloading package punkt to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package punkt is already up-to-date!\n",
"[nltk_data] Downloading package wordnet to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package wordnet is already up-to-date!\n",
"[nltk_data] Downloading package averaged_perceptron_tagger to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package averaged_perceptron_tagger is already up-to-\n",
"[nltk_data] date!\n",
"[nltk_data] Downloading package conll2000 to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package conll2000 is already up-to-date!\n",
"[nltk_data] Downloading package movie_reviews to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package movie_reviews is already up-to-date!\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install textblob\n",
"!{sys.executable} -m textblob.download_corpora\n",
"from textblob import TextBlob"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'covid-19 live updates': 1,\n",
" 'vaccines': 1,\n",
" 'boosters': 1,\n",
" 'york': 4,\n",
" 'ukrainians flee mariupol': 1,\n",
" 'forces push': 1,\n",
" 'port city': 1,\n",
" 'wall street journal': 3,\n",
" 'bond yields': 1,\n",
" 'futures rise': 1,\n",
" 'powell says fed': 1,\n",
" 'ready': 1,\n",
" 'be': 1,\n",
" 'aggressive': 1,\n",
" 'putin': 3,\n",
" 'alexei navalny': 2,\n",
" 'russian': 2,\n",
" 'supreme court nominee': 1,\n",
" 'ketanji brown jackson': 1,\n",
" \"confirmation hearing 's\": 1,\n",
" 'cnn': 1,\n",
" 'swedish': 1,\n",
" 'high school': 1,\n",
" 'abc': 1,\n",
" 'clues': 1,\n",
" 'covid-19': 1,\n",
" ' s': 2,\n",
" 'moves': 1,\n",
" 'sewers': 1,\n",
" 'roll dice': 1,\n",
" 'jackson': 1,\n",
" 'decisions |': 1,\n",
" 'thehill': 1,\n",
" 'clear': 2,\n",
" 'chemical weapons': 2,\n",
" 'ukraine': 3,\n",
" 'claims president': 2,\n",
" 'biden': 2,\n",
" 'nasa': 2,\n",
" 'solar system': 2,\n",
" 'daily mail': 3,\n",
" 'us stocks': 1,\n",
" 'fed chair powell': 1,\n",
" \"'s remarks\": 1,\n",
" 'fox': 1,\n",
" \"'we 've\": 1,\n",
" 'tests': 1,\n",
" 'covid': 1,\n",
" 'politico': 1,\n",
" 'duchess': 1,\n",
" 'cambridge': 1,\n",
" 'swaps khaki jungle gear': 1,\n",
" 'vampire': 1,\n",
" 'wife': 1,\n",
" 'belize': 1,\n",
" 'china': 2,\n",
" 'flight recorders': 1,\n",
" 'plane crash': 1,\n",
" 'reuters': 2,\n",
" 'russian oligarch': 1,\n",
" 'abramovich': 1,\n",
" 'live': 1,\n",
" 'russia': 2,\n",
" 'stops talks': 1,\n",
" 'japan': 1,\n",
" 'español': 1,\n",
" 'powers remain': 1,\n",
" 'threats lurk': 1,\n",
" 'set': 1,\n",
" 'webb': 1,\n",
" 'telescope begins multi-instrument alignment': 1,\n",
" 'scitechdaily': 1,\n",
" 'uconn': 1,\n",
" 'ucf': 1,\n",
" 'ncaa': 1,\n",
" \"women 's tournament second-round highlights\": 1,\n",
" 'march madness': 1,\n",
" 'bucking republican trend': 1,\n",
" 'indiana': 1,\n",
" 'vetoes transgender': 1,\n",
" 'bill': 1,\n",
" 'maggie fox': 1,\n",
" 'coronation': 1,\n",
" 'shameless': 1,\n",
" \"'sudden accident\": 1,\n",
" 'mirror online': 1,\n",
" 'mirror': 2,\n",
" 'plane crash ': 1,\n",
" 'search': 1,\n",
" 'moment flight': 1,\n",
" 'daniel morgan': 1,\n",
" 'report condemns': 1,\n",
" 'met': 1,\n",
" 'guardian': 6,\n",
" 'rishi sunak': 1,\n",
" ' s spring': 1,\n",
" 'statement': 1,\n",
" 'bbc.com': 1,\n",
" 'uk': 3,\n",
" 'ireland': 1,\n",
" 'euro': 1,\n",
" 'vladimir putin': 2,\n",
" \"'s 'lover\": 1,\n",
" 'brass eye': 1,\n",
" ' s outtakes': 1,\n",
" 'brutal tv comedy': 1,\n",
" 'threatens civilians': 1,\n",
" 'mariupol': 1,\n",
" \"'s spirit\": 1,\n",
" 'shell u-turn': 1,\n",
" 'cambo': 1,\n",
" 'green targets': 1,\n",
" 'st helens': 1,\n",
" 'dog attack': 1,\n",
" 'girl': 1,\n",
" 'bbc': 1,\n",
" 'playstation': 1,\n",
" \"'assassin 's\": 1,\n",
" 'creed': 1,\n",
" 'jade raymond': 1,\n",
" 'haven studios': 1,\n",
" 'nme': 1,\n",
" 'nintendo switch': 1,\n",
" 'folders •': 1,\n",
" 'eurogamer.net': 2,\n",
" 'fa': 1,\n",
" 'solution ”': 1,\n",
" 'liverpool': 1,\n",
" 'fan group blasts “ shambolic ”': 1,\n",
" 'wembley': 1,\n",
" 'anfield': 1,\n",
" 'manchester': 1,\n",
" 'live erik': 1,\n",
" 'hag': 1,\n",
" 'utd': 1,\n",
" 'manager updates': 1,\n",
" 'manchester evening': 1,\n",
" 'inflation': 1,\n",
" 'government borrowing': 1,\n",
" 'february': 1,\n",
" 'crude oil': 1,\n",
" ' business': 1,\n",
" 'kremlin': 1,\n",
" 'large-scale fraud': 1,\n",
" 'sky': 1,\n",
" 'natural gas': 1,\n",
" 'gazprom': 1,\n",
" 'retail unit': 1,\n",
" 'insider': 1,\n",
" 'zaghari-ratcliffe': 1,\n",
" 'hunt': 1,\n",
" 'iran': 1,\n",
" 'debt payment': 1}"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w = {}\n",
"for x in all_titles:\n",
" for n in TextBlob(x).noun_phrases:\n",
" if n in w:\n",
" w[n].append(x)\n",
" else:\n",
" w[n]=[x]\n",
"{ x:len(w[x]) for x in w.keys()}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही पाहू शकतो की नामे आपल्याला मोठ्या विषयात्मक गट देत नाहीत. चला संकल्पना ग्राफमधून मिळवलेल्या अधिक सामान्य शब्दांनी नामे बदलूया. यासाठी काही वेळ लागेल, कारण आम्ही प्रत्येक नाम वाक्यांशासाठी REST कॉल करत आहोत.\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"w = {}\n",
"for x in all_titles:\n",
" for noun in TextBlob(x).noun_phrases:\n",
" terms = query(noun.replace(' ','%20'))\n",
" for term in [u for u in terms.keys() if terms[u]>0.1]:\n",
" if term in w:\n",
" w[term].append(x)\n",
" else:\n",
" w[term]=[x]"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'city': 9,\n",
" 'brand': 4,\n",
" 'place': 9,\n",
" 'town': 4,\n",
" 'factor': 4,\n",
" 'film': 4,\n",
" 'nation': 11,\n",
" 'state': 5,\n",
" 'person': 4,\n",
" 'organization': 5,\n",
" 'publication': 10,\n",
" 'market': 5,\n",
" 'economy': 4,\n",
" 'company': 6,\n",
" 'newspaper': 6,\n",
" 'relationship': 6}"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{ x:len(w[x]) for x in w.keys() if len(w[x])>3}"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"ECONOMY:\n",
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
"\n",
"NATION:\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
"UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian\n",
"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
"Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian\n",
"\n",
"PERSON:\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
"Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n"
]
}
],
"source": [
"print('\\nECONOMY:\\n'+'\\n'.join(w['economy']))\n",
"print('\\nNATION:\\n'+'\\n'.join(w['nation']))\n",
"print('\\nPERSON:\\n'+'\\n'.join(w['person']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात घ्या की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील मूळ दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी, व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवणाऱ्या कोणत्याही गैरसमजुतींसाठी किंवा चुकीच्या अर्थ लावण्यास आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.9.5"
},
"coopTranslator": {
"original_hash": "4087f998407d06ceb2947016ba4605d0",
"translation_date": "2025-08-28T08:33:32+00:00",
"source_file": "lessons/2-Symbolic/MSConceptGraph.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,183 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# एमएनिस्ट अंक वर्गीकरण आमच्या स्वतःच्या फ्रेमवर्कसह\n",
"\n",
"[एआय फॉर बिगिनर्स करिक्युलम](https://github.com/microsoft/ai-for-beginners) मधील प्रयोगशाळा असाइनमेंट.\n",
"\n",
"### डेटासेट वाचणे\n",
"\n",
"हा कोड इंटरनेटवरील रिपॉझिटरीमधून डेटासेट डाउनलोड करतो. तुम्ही एआय करिक्युलम रिपोच्या `/data` डिरेक्टरीमधून डेटासेट मॅन्युअली कॉपी देखील करू शकता.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" % Total % Received % Xferd Average Speed Time Time Time Current\n",
" Dload Upload Total Spent Left Speed\n",
"\n",
" 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n",
"100 9.9M 100 9.9M 0 0 9.9M 0 0:00:01 --:--:-- 0:00:01 15.8M\n"
]
}
],
"source": [
"!rm *.pkl\n",
"!wget https://raw.githubusercontent.com/microsoft/AI-For-Beginners/main/data/mnist.pkl.gz\n",
"!gzip -d mnist.pkl.gz"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import pickle\n",
"with open('mnist.pkl','rb') as f:\n",
" MNIST = pickle.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"labels = MNIST['Train']['Labels']\n",
"data = MNIST['Train']['Features']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला पाहूया आपल्याकडे असलेल्या डेटाचा आकार काय आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(42000, 784)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### डेटाचे विभाजन\n",
"\n",
"आम्ही Scikit Learn चा वापर करून डेटाचे प्रशिक्षण आणि चाचणी डेटासेटमध्ये विभाजन करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Train samples: 33600, test samples: 8400\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"features_train, features_test, labels_train, labels_test = train_test_split(data,labels,test_size=0.2)\n",
"\n",
"print(f\"Train samples: {len(features_train)}, test samples: {len(features_test)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### सूचना\n",
"\n",
"1. धडा दिलेला फ्रेमवर्क कोड या नोटबुकमध्ये पेस्ट करा, किंवा (अधिक चांगले) वेगळ्या Python मॉड्यूलमध्ये पेस्ट करा.\n",
"1. एक-स्तरीय परसेप्ट्रॉन परिभाषित करा आणि प्रशिक्षित करा, प्रशिक्षण आणि प्रमाणीकरण अचूकता प्रशिक्षणादरम्यान निरीक्षण करा.\n",
"1. ओव्हरफिटिंग झाले आहे का हे समजून घेण्याचा प्रयत्न करा आणि अचूकता सुधारण्यासाठी स्तराचे पॅरामीटर्स समायोजित करा.\n",
"1. 2- आणि 3-स्तरीय परसेप्ट्रॉनसाठी मागील चरणांची पुनरावृत्ती करा. स्तरांमधील वेगवेगळ्या सक्रियता फंक्शन्ससह प्रयोग करण्याचा प्रयत्न करा.\n",
"1. खालील प्रश्नांची उत्तरे देण्याचा प्रयत्न करा:\n",
" - स्तरांमधील सक्रियता फंक्शन नेटवर्कच्या कार्यक्षमतेवर परिणाम करते का?\n",
" - या कार्यासाठी आपल्याला 2- किंवा 3-स्तरीय नेटवर्कची आवश्यकता आहे का?\n",
" - नेटवर्क प्रशिक्षित करताना तुम्हाला काही समस्या आल्या का? विशेषतः स्तरांची संख्या वाढल्यावर.\n",
" - प्रशिक्षणादरम्यान नेटवर्कचे वजन कसे वागतात? वजनाचा कमाल abs मूल्य vs. epoch प्लॉट करून संबंध समजून घेता येईल.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरे त्रुटी किंवा अचूकतेच्या अभावाने युक्त असू शकतात. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.9.5"
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "6fa055f484eb5d6bdf41166a356d3abf",
"translation_date": "2025-08-28T08:43:39+00:00",
"source_file": "lessons/3-NeuralNetworks/04-OwnFramework/lab/MyFW_MNIST.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,108 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ऑप्टिकल फ्लो वापरून तळहाताच्या हालचालींचा शोध\n",
"\n",
"हा प्रयोग [AI for Beginners Curriculum](http://aka.ms/ai-beginners) चा भाग आहे.\n",
"\n",
"[हा व्हिडिओ](../../../../../../lessons/4-ComputerVision/06-IntroCV/lab/palm-movement.mp4) पहा, ज्यामध्ये एका व्यक्तीचा तळहात स्थिर पार्श्वभूमीवर डावीकडे/उजवीकडे/वर/खाली हलतो.\n",
"\n",
"**तुमचे उद्दिष्ट** ऑप्टिकल फ्लो वापरून ठरवणे आहे की व्हिडिओच्या कोणत्या भागांमध्ये वर/खाली/डावे/उजवे हालचाली आहेत.\n",
"\n",
"लेक्चरमध्ये वर्णन केल्याप्रमाणे व्हिडिओ फ्रेम्स मिळवून सुरुवात करा:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता, व्याख्यानात वर्णन केल्याप्रमाणे घनदाट ऑप्टिकल फ्लो फ्रेम्सची गणना करा, आणि घनदाट ऑप्टिकल फ्लोला ध्रुवीय समन्वयांमध्ये रूपांतरित करा:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"प्रत्येक ऑप्टिकल फ्लो फ्रेमसाठी दिशांचा हिस्टोग्राम तयार करा. हिस्टोग्राम दाखवतो की किती व्हेक्टर्स विशिष्ट बिनमध्ये येतात, आणि तो फ्रेमवरील वेगवेगळ्या दिशांच्या हालचाली वेगळ्या करतो.\n",
"\n",
"> तुम्हाला कदाचित अशा सर्व व्हेक्टर्सना शून्य करायचे असेल ज्यांची मॅग्निट्यूड ठराविक थ्रेशहोल्डच्या खाली आहे. यामुळे व्हिडिओमधील डोळे आणि डोके यांसारख्या छोट्या अतिरिक्त हालचाली दूर होतील.\n",
"\n",
"काही फ्रेम्ससाठी हिस्टोग्राम्स प्लॉट करा.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हिस्टोग्रामकडे पाहताना, हालचालीची दिशा कशी ठरवायची हे समजणे सोपे असावे. तुम्हाला त्या बिन्स निवडाव्या लागतील ज्या वर/खाली/डावीकडे/उजवीकडे दिशांना संबंधित आहेत आणि ज्या विशिष्ट मर्यादेपेक्षा वर आहेत.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अभिनंदन! जर तुम्ही वरील सर्व चरण पूर्ण केले असतील, तर तुम्ही प्रयोगशाळा पूर्ण केली आहे!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) चा वापर करून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात घ्या की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील मूळ दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर केल्यामुळे उद्भवणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "153d9e417e079bf62f8f693002d0deaf",
"translation_date": "2025-08-28T08:09:26+00:00",
"source_file": "lessons/4-ComputerVision/06-IntroCV/lab/MovementDetection.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,577 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# मजकूर वर्गीकरण कार्य\n",
"\n",
"जसे आपण आधी उल्लेख केले आहे, आपण **AG_NEWS** डेटासेटवर आधारित एक साधे मजकूर वर्गीकरण कार्यावर लक्ष केंद्रित करू, ज्यामध्ये बातम्यांच्या मथळ्यांना चार श्रेणींमध्ये वर्गीकृत करायचे आहे: जागतिक, क्रीडा, व्यवसाय आणि विज्ञान/तंत्रज्ञान.\n",
"\n",
"## डेटासेट\n",
"\n",
"हा डेटासेट [`torchtext`](https://github.com/pytorch/text) मॉड्यूलमध्ये अंगभूत आहे, त्यामुळे आपण याला सहजपणे प्रवेश करू शकतो.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import torchtext\n",
"import os\n",
"import collections\n",
"os.makedirs('./data',exist_ok=True)\n",
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"येथे, `train_dataset` आणि `test_dataset` मध्ये अशा संग्रहांचा समावेश आहे जे अनुक्रमे वर्गाचा क्रमांक (लेबल) आणि मजकूराची जोड परत करतात, उदाहरणार्थ:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3,\n",
" \"Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.\")"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(train_dataset)[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"मग, चला आपल्या डेटासेटमधील पहिल्या 10 नवीन हेडलाईन्स प्रिंट करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"**Sci/Tech** -> Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\band of ultra-cynics, are seeing green again.\n",
"**Sci/Tech** -> Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\which has a reputation for making well-timed and occasionally\\controversial plays in the defense industry, has quietly placed\\its bets on another part of the market.\n",
"**Sci/Tech** -> Oil and Economy Cloud Stocks' Outlook (Reuters) Reuters - Soaring crude prices plus worries\\about the economy and the outlook for earnings are expected to\\hang over the stock market next week during the depth of the\\summer doldrums.\n",
"**Sci/Tech** -> Iraq Halts Oil Exports from Main Southern Pipeline (Reuters) Reuters - Authorities have halted oil export\\flows from the main pipeline in southern Iraq after\\intelligence showed a rebel militia could strike\\infrastructure, an oil official said on Saturday.\n",
"**Sci/Tech** -> Oil prices soar to all-time record, posing new menace to US economy (AFP) AFP - Tearaway world oil prices, toppling records and straining wallets, present a new economic menace barely three months before the US presidential elections.\n"
]
}
],
"source": [
"for i,x in zip(range(5),train_dataset):\n",
" print(f\"**{classes[x[0]]}** -> {x[1]}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"डेटासेट्स इटरेटर असल्यामुळे, जर आपल्याला डेटा अनेक वेळा वापरायचा असेल तर आपल्याला तो यादीमध्ये रूपांतरित करणे आवश्यक आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
"train_dataset = list(train_dataset)\n",
"test_dataset = list(test_dataset)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टोकनायझेशन\n",
"\n",
"आता आपल्याला मजकूर **संख्यांमध्ये** रूपांतरित करायचा आहे ज्याचे प्रतिनिधित्व टेन्सर्स म्हणून करता येईल. जर आपल्याला शब्द-स्तरीय प्रतिनिधित्व हवे असेल, तर आपल्याला दोन गोष्टी कराव्या लागतील:\n",
"* **टोकनायझर** वापरून मजकूर **टोकन्स** मध्ये विभाजित करणे\n",
"* त्या टोकन्सचे **शब्दसंग्रह** तयार करणे.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['he', 'said', 'hello']"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
"tokenizer('He said: hello')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" counter.update(tokenizer(line))\n",
"vocab = torchtext.vocab.vocab(counter, min_freq=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"शब्दसंग्रह वापरून, आपण सहजपणे आमच्या टोकन केलेल्या स्ट्रिंगला संख्यांच्या संचामध्ये एन्कोड करू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocab size if 95810\n"
]
},
{
"data": {
"text/plain": [
"[599, 3279, 97, 1220, 329, 225, 7368]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vocab_size = len(vocab)\n",
"print(f\"Vocab size if {vocab_size}\")\n",
"\n",
"stoi = vocab.get_stoi() # dict to convert tokens to indices\n",
"\n",
"def encode(x):\n",
" return [stoi[s] for s in tokenizer(x)]\n",
"\n",
"encode('I love to play with my words')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## शब्दांची पिशवी (Bag of Words) मजकूराचे प्रतिनिधित्व\n",
"\n",
"कारण शब्द अर्थ व्यक्त करतात, कधी कधी आपण फक्त स्वतंत्र शब्दांकडे पाहून, वाक्यातील त्यांच्या क्रमाकडे दुर्लक्ष करून, मजकूराचा अर्थ समजू शकतो. उदाहरणार्थ, जेव्हा बातम्या वर्गीकृत करायच्या असतात, तेव्हा *weather* (हवामान), *snow* (हिमवृष्टी) यांसारखे शब्द *हवामान अंदाज* दर्शवण्याची शक्यता असते, तर *stocks* (शेअर्स), *dollar* (डॉलर) यांसारखे शब्द *आर्थिक बातम्या* याकडे झुकतात.\n",
"\n",
"**शब्दांची पिशवी** (BoW) वेक्टर प्रतिनिधित्व हे पारंपरिक वेक्टर प्रतिनिधित्वांपैकी सर्वात जास्त वापरले जाणारे आहे. प्रत्येक शब्द एका वेक्टर निर्देशांकाशी जोडलेला असतो, आणि वेक्टर घटक दिलेल्या दस्तऐवजात त्या शब्दाच्या उपस्थितीची संख्या दर्शवतो.\n",
"\n",
"![शब्दांची पिशवी वेक्टर प्रतिनिधित्व स्मृतीत कसे सादर केले जाते हे दाखवणारी प्रतिमा.](../../../../../translated_images/bag-of-words-example.606fc1738f1d7ba98a9d693e3bcd706c6e83fa7bf8221e6e90d1a206d82f2ea4.mr.png)\n",
"\n",
"> **टीप**: तुम्ही BoW ला मजकूरातील स्वतंत्र शब्दांसाठी असलेल्या सर्व एक-हॉट-एन्कोडेड वेक्टरच्या बेरीजप्रमाणे देखील विचार करू शकता.\n",
"\n",
"खाली Scikit Learn पायथन लायब्ररी वापरून शब्दांची पिशवी प्रतिनिधित्व कसे तयार करायचे याचे एक उदाहरण दिले आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.feature_extraction.text import CountVectorizer\n",
"vectorizer = CountVectorizer()\n",
"corpus = [\n",
" 'I like hot dogs.',\n",
" 'The dog ran fast.',\n",
" 'Its hot outside.',\n",
" ]\n",
"vectorizer.fit_transform(corpus)\n",
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आमच्या AG_NEWS डेटासेटच्या व्हेक्टर प्रतिनिधीतून बॅग-ऑफ-वर्ड्स व्हेक्टर गणना करण्यासाठी, आम्ही खालील फंक्शन वापरू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([2., 1., 2., ..., 0., 0., 0.])\n"
]
}
],
"source": [
"vocab_size = len(vocab)\n",
"\n",
"def to_bow(text,bow_vocab_size=vocab_size):\n",
" res = torch.zeros(bow_vocab_size,dtype=torch.float32)\n",
" for i in encode(text):\n",
" if i<bow_vocab_size:\n",
" res[i] += 1\n",
" return res\n",
"\n",
"print(to_bow(train_dataset[0][1]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **टीप:** येथे आम्ही जागतिक `vocab_size` व्हेरिएबल वापरत आहोत शब्दसंग्रहाचा डीफॉल्ट आकार निर्दिष्ट करण्यासाठी. कारण अनेकदा शब्दसंग्रहाचा आकार खूप मोठा असतो, आपण सर्वात वारंवार वापरल्या जाणाऱ्या शब्दांपर्यंत शब्दसंग्रहाचा आकार मर्यादित करू शकतो. `vocab_size` मूल्य कमी करण्याचा प्रयत्न करा आणि खालील कोड चालवा, आणि त्याचा अचूकतेवर कसा परिणाम होतो ते पहा. तुम्हाला काही प्रमाणात अचूकतेत घट अपेक्षित असावी, परंतु ती नाट्यमय नसावी, उच्च कार्यक्षमतेच्या बदल्यात.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## BoW वर्गीकरणकर्ता प्रशिक्षण\n",
"\n",
"आता आपण आपल्या मजकुराचे बॅग-ऑफ-वर्ड्स (BoW) प्रतिनिधित्व कसे तयार करायचे ते शिकलो आहोत, चला त्यावर आधारित एक वर्गीकरणकर्ता प्रशिक्षण देऊया. सर्वप्रथम, आपल्याला आपल्या डेटासेटचे प्रशिक्षणासाठी असे रूपांतर करणे आवश्यक आहे की, सर्व स्थिती वेक्टर प्रतिनिधित्व बॅग-ऑफ-वर्ड्स प्रतिनिधित्वामध्ये रूपांतरित होतील. हे `bowify` फंक्शनला `collate_fn` पॅरामीटर म्हणून स्टँडर्ड torch `DataLoader` मध्ये पास करून साध्य केले जाऊ शकते:\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"from torch.utils.data import DataLoader\n",
"import numpy as np \n",
"\n",
"# this collate function gets list of batch_size tuples, and needs to \n",
"# return a pair of label-feature tensors for the whole minibatch\n",
"def bowify(b):\n",
" return (\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([to_bow(t[1]) for t in b])\n",
" )\n",
"\n",
"train_loader = DataLoader(train_dataset, batch_size=16, collate_fn=bowify, shuffle=True)\n",
"test_loader = DataLoader(test_dataset, batch_size=16, collate_fn=bowify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण एक साधा वर्गीकरण करणारा न्यूरल नेटवर्क परिभाषित करूया ज्यामध्ये एकच रेखीय स्तर आहे. इनपुट व्हेक्टरचा आकार `vocab_size` च्या बरोबरीचा आहे, आणि आउटपुटचा आकार वर्गांच्या संख्येशी (4) संबंधित आहे. कारण आपण वर्गीकरण कार्य सोडवत आहोत, अंतिम सक्रियता फंक्शन `LogSoftmax()` आहे.\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"net = torch.nn.Sequential(torch.nn.Linear(vocab_size,4),torch.nn.LogSoftmax(dim=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण मानक PyTorch प्रशिक्षण लूप परिभाषित करू. कारण आपला डेटासेट खूप मोठा आहे, शिक्षणाच्या उद्देशाने आपण फक्त एका epoch साठी प्रशिक्षण देऊ, आणि कधी कधी एका epoch पेक्षा कमी (प्रशिक्षण मर्यादित करण्यासाठी `epoch_size` पॅरामीटर निर्दिष्ट करण्याची परवानगी देते). प्रशिक्षणादरम्यान संचित प्रशिक्षण अचूकता देखील आम्ही नोंदवू; नोंदवण्याची वारंवारता `report_freq` पॅरामीटर वापरून निर्दिष्ट केली जाते.\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"def train_epoch(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.NLLLoss(),epoch_size=None, report_freq=200):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
" net.train()\n",
" total_loss,acc,count,i = 0,0,0,0\n",
" for labels,features in dataloader:\n",
" optimizer.zero_grad()\n",
" out = net(features)\n",
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss+=loss\n",
" _,predicted = torch.max(out,1)\n",
" acc+=(predicted==labels).sum()\n",
" count+=len(labels)\n",
" i+=1\n",
" if i%report_freq==0:\n",
" print(f\"{count}: acc={acc.item()/count}\")\n",
" if epoch_size and count>epoch_size:\n",
" break\n",
" return total_loss.item()/count, acc.item()/count"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.8028125\n",
"6400: acc=0.8371875\n",
"9600: acc=0.8534375\n",
"12800: acc=0.85765625\n"
]
},
{
"data": {
"text/plain": [
"(0.026090790722161722, 0.8620069296375267)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_epoch(net,train_loader,epoch_size=15000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## बायग्राम्स, ट्रायग्राम्स आणि एन-ग्राम्स\n",
"\n",
"बॅग ऑफ वर्ड्स पद्धतीची एक मर्यादा म्हणजे काही शब्द हे बहु-शब्द अभिव्यक्तींचा भाग असतात. उदाहरणार्थ, 'hot dog' या शब्दाचा अर्थ इतर संदर्भांतील 'hot' आणि 'dog' या शब्दांपेक्षा पूर्णपणे वेगळा असतो. जर आपण 'hot' आणि 'dog' या शब्दांचे नेहमी समान व्हेक्टरद्वारे प्रतिनिधित्व केले, तर ते आपल्या मॉडेलसाठी गोंधळ निर्माण करू शकते.\n",
"\n",
"यावर उपाय म्हणून, **एन-ग्राम प्रतिनिधित्व** दस्तऐवज वर्गीकरणाच्या पद्धतींमध्ये वापरले जाते, जिथे प्रत्येक शब्द, द्वि-शब्द किंवा त्रि-शब्दाची वारंवारता वर्गीकरण करणारे मॉडेल प्रशिक्षणासाठी उपयुक्त वैशिष्ट्य ठरते. उदाहरणार्थ, बायग्राम प्रतिनिधित्वामध्ये, मूळ शब्दांव्यतिरिक्त, सर्व शब्दजोड्या शब्दसंग्रहात समाविष्ट केल्या जातात.\n",
"\n",
"खाली दिलेले उदाहरण स्कायकीट लर्न वापरून बायग्राम बॅग ऑफ वर्ड्स प्रतिनिधित्व कसे तयार करायचे हे दर्शवते:\n"
]
},
{
"cell_type": "code",
"execution_count": 26,
"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": 26,
"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 चे प्रतिनिधित्व वापरण्यासाठी, आपल्याला विशेष ngram शब्दसंग्रह तयार करावा लागेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Bigram vocabulary length = 1308842\n"
]
}
],
"source": [
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" l = tokenizer(line)\n",
" counter.update(torchtext.data.utils.ngrams_iterator(l,ngrams=2))\n",
" \n",
"bi_vocab = torchtext.vocab.vocab(counter, min_freq=1)\n",
"\n",
"print(\"Bigram vocabulary length = \",len(bi_vocab))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपण वर दिलेल्या कोडचा वापर करून वर्गीकरणकर्ता प्रशिक्षित करू शकतो, परंतु हे खूप मेमरी-अकार्यक्षम ठरेल. पुढील युनिटमध्ये, आपण एम्बेडिंग्स वापरून बिग्राम वर्गीकरणकर्ता प्रशिक्षित करू.\n",
"\n",
"> **टीप:** तुम्ही फक्त ते ngrams ठेवू शकता जे मजकुरात निर्दिष्ट केलेल्या वेळेपेक्षा जास्त वेळा येतात. यामुळे कमी वारंवार येणारे बिग्राम वगळले जातील आणि परिमाणात्मकता लक्षणीयरीत्या कमी होईल. हे करण्यासाठी, `min_freq` पॅरामीटरला उच्च मूल्यावर सेट करा आणि शब्दसंग्रहाच्या लांबीतील बदल निरीक्षण करा.\n"
]
},
{
"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": 28,
"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": 28,
"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": [
"## निष्कर्ष\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": "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": "7b9040985e748e4e2d4c689892456ad7",
"translation_date": "2025-08-28T09:50:31+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,647 @@
{
"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",
"![बॅग-ऑफ-वर्ड्स वेक्टर प्रतिनिधित्व मेमरीमध्ये कसे सादर केले जाते हे दाखवणारी प्रतिमा.](../../../../../translated_images/bag-of-words-example.606fc1738f1d7ba98a9d693e3bcd706c6e83fa7bf8221e6e90d1a206d82f2ea4.mr.png) \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
}

View File

@ -0,0 +1,720 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिंग्ज\n",
"\n",
"आपल्या मागील उदाहरणात, आम्ही `vocab_size` लांबीच्या उच्च-आयामी बॅग-ऑफ-वर्ड्स व्हेक्टरवर कार्य केले, आणि आम्ही कमी-आयामी स्थानिक प्रतिनिधित्व व्हेक्टरमधून विरळ वन-हॉट प्रतिनिधित्वामध्ये स्पष्टपणे रूपांतरित करत होतो. हे वन-हॉट प्रतिनिधित्व मेमरीसाठी कार्यक्षम नाही, याशिवाय प्रत्येक शब्द स्वतंत्रपणे हाताळला जातो, म्हणजेच वन-हॉट एन्कोड केलेले व्हेक्टर शब्दांमधील कोणतेही अर्थपूर्ण साम्य व्यक्त करत नाहीत.\n",
"\n",
"या युनिटमध्ये, आपण **News AG** डेटासेटचा अभ्यास सुरू ठेवू. सुरुवात करण्यासाठी, डेटा लोड करूया आणि मागील नोटबुकमधील काही संकल्पना घेऊया.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\train.csv: 29.5MB [00:01, 18.8MB/s] \n",
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\test.csv: 1.86MB [00:00, 11.2MB/s] \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Building vocab...\n",
"Vocab size = 95812\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"import numpy as np\n",
"from torchnlp import *\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_size = len(vocab)\n",
"print(\"Vocab size = \",vocab_size)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिंग म्हणजे काय?\n",
"\n",
"**एम्बेडिंग** ही कल्पना म्हणजे शब्दांचे प्रतिनिधित्व कमी-आयामी घन व्हेक्टरद्वारे करणे, जे काही प्रमाणात शब्दाचा अर्थ प्रतिबिंबित करतात. आपण नंतर अर्थपूर्ण शब्द एम्बेडिंग कसे तयार करायचे यावर चर्चा करू, पण सध्या एम्बेडिंगला शब्द व्हेक्टरची आयाम कमी करण्याचा एक मार्ग म्हणून विचार करूया.\n",
"\n",
"तर, एम्बेडिंग लेयर एक शब्द इनपुट म्हणून घेईल आणि निर्दिष्ट `embedding_size` चा आउटपुट व्हेक्टर तयार करेल. एका अर्थाने, हे `Linear` लेयरसारखेच आहे, पण एक-हॉट एन्कोडेड व्हेक्टर घेण्याऐवजी, ते शब्द क्रमांक इनपुट म्हणून घेऊ शकेल.\n",
"\n",
"आपल्या नेटवर्कमध्ये एम्बेडिंग लेयर प्रथम लेयर म्हणून वापरल्याने, आपण बॅग-ऑफ-वर्ड्स मॉडेलवरून **एम्बेडिंग बॅग** मॉडेलकडे स्विच करू शकतो, जिथे आपण प्रथम आपल्या मजकुरातील प्रत्येक शब्द संबंधित एम्बेडिंगमध्ये रूपांतरित करतो आणि नंतर त्या सर्व एम्बेडिंगवर काही एकत्रित फंक्शन गणना करतो, जसे की `sum`, `average` किंवा `max`.\n",
"\n",
"![पाच अनुक्रम शब्दांसाठी एम्बेडिंग वर्गीकरणकर्ता दर्शवणारी प्रतिमा.](../../../../../translated_images/embedding-classifier-example.b77f021a7ee67eeec8e68bfe11636c5b97d6eaa067515a129bfb1d0034b1ac5b.mr.png)\n",
"\n",
"आपले वर्गीकरणकर्ता न्यूरल नेटवर्क एम्बेडिंग लेयरने सुरू होईल, त्यानंतर एकत्रीकरण लेयर आणि त्यावर लीनियर वर्गीकरणकर्ता असेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class EmbedClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, num_class):\n",
" super().__init__()\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" x = self.embedding(x)\n",
" x = torch.mean(x,dim=1)\n",
" return self.fc(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### बदलत्या व्हेरिएबल अनुक्रम आकाराशी सामना करणे\n",
"\n",
"या आर्किटेक्चरमुळे, आमच्या नेटवर्कसाठी मिनीबॅचेस विशिष्ट पद्धतीने तयार करणे आवश्यक होईल. मागील युनिटमध्ये, बॅग-ऑफ-वर्ड्स वापरताना, मिनीबॅचमधील सर्व BoW टेन्सर्सचा आकार `vocab_size` इतकाच होता, आपल्या मजकूर अनुक्रमाच्या वास्तविक लांबीची पर्वा न करता. जेव्हा आपण वर्ड एम्बेडिंगकडे जातो, तेव्हा प्रत्येक मजकूर नमुन्यात वेगवेगळ्या संख्येने शब्द असतील, आणि ते नमुने मिनीबॅचमध्ये एकत्र करताना आपल्याला काही पॅडिंग लागू करावे लागेल.\n",
"\n",
"हे `collate_fn` फंक्शन डेटा स्रोताला प्रदान करून त्याच तंत्राचा वापर करून करता येते:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def padify(b):\n",
" # b is the list of tuples of length batch_size\n",
" # - first element of a tuple = label, \n",
" # - second = feature (text sequence)\n",
" # build vectorized sequence\n",
" v = [encode(x[1]) for x in b]\n",
" # first, compute max length of a sequence in this minibatch\n",
" l = max(map(len,v))\n",
" return ( # tuple of two tensors - labels and features\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### एम्बेडिंग वर्गीकरण प्रशिक्षण\n",
"\n",
"आता आपण योग्य डेटालोडर परिभाषित केला आहे, आपण मागील युनिटमध्ये परिभाषित केलेल्या प्रशिक्षण फंक्शनचा वापर करून मॉडेल प्रशिक्षण देऊ शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6415625\n",
"6400: acc=0.6865625\n",
"9600: acc=0.7103125\n",
"12800: acc=0.726953125\n",
"16000: acc=0.739375\n",
"19200: acc=0.75046875\n",
"22400: acc=0.7572321428571429\n"
]
},
{
"data": {
"text/plain": [
"(0.889799795315499, 0.7623160588611644)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=1, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **टीप**: वेळेच्या बचतीसाठी आम्ही येथे फक्त २५, नोंदींसाठी प्रशिक्षण देत आहोत (एक पूर्ण युगापेक्षा कमी), परंतु तुम्ही प्रशिक्षण सुरू ठेवू शकता, अनेक युगांसाठी प्रशिक्षण देण्यासाठी एक फंक्शन लिहू शकता आणि उच्च अचूकता मिळवण्यासाठी शिक्षण दर पॅरामीटरसह प्रयोग करू शकता. तुम्ही सुमारे ९०% अचूकतेपर्यंत पोहोचू शकता.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EmbeddingBag लेयर आणि बदलत्या लांबीच्या अनुक्रमाचे प्रतिनिधित्व\n",
"\n",
"मागील आर्किटेक्चरमध्ये, सर्व अनुक्रम समान लांबीचे करण्यासाठी त्यांना पॅड करणे आवश्यक होते, जेणेकरून ते मिनीबॅचमध्ये बसतील. बदलत्या लांबीच्या अनुक्रमांचे प्रतिनिधित्व करण्याचा हा सर्वात कार्यक्षम मार्ग नाही - दुसरा दृष्टिकोन म्हणजे **ऑफसेट** व्हेक्टर वापरणे, जो एका मोठ्या व्हेक्टरमध्ये संग्रहित केलेल्या सर्व अनुक्रमांचे ऑफसेट ठेवेल.\n",
"\n",
"![ऑफसेट अनुक्रमाचे प्रतिनिधित्व दर्शवणारी प्रतिमा](../../../../../translated_images/offset-sequence-representation.eb73fcefb29b46eecfbe74466077cfeb7c0f93a4f254850538a2efbc63517479.mr.png)\n",
"\n",
"> **Note**: वरील चित्रात, आम्ही अक्षरांच्या अनुक्रमाचे प्रदर्शन केले आहे, परंतु आमच्या उदाहरणात आम्ही शब्दांच्या अनुक्रमांवर काम करत आहोत. तथापि, ऑफसेट व्हेक्टरसह अनुक्रमांचे प्रतिनिधित्व करण्याचा सामान्य तत्त्व समान राहतो.\n",
"\n",
"ऑफसेट प्रतिनिधित्वासह काम करण्यासाठी, आम्ही [`EmbeddingBag`](https://pytorch.org/docs/stable/generated/torch.nn.EmbeddingBag.html) लेयर वापरतो. हे `Embedding` सारखेच आहे, परंतु ते कंटेंट व्हेक्टर आणि ऑफसेट व्हेक्टर इनपुट म्हणून घेतो, आणि त्यात सरासरीकरण लेयर देखील समाविष्ट आहे, जे `mean`, `sum` किंवा `max` असू शकते.\n",
"\n",
"येथे `EmbeddingBag` वापरणारे सुधारित नेटवर्क आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class EmbedClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, num_class):\n",
" super().__init__()\n",
" self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim)\n",
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
"\n",
" def forward(self, text, off):\n",
" x = self.embedding(text, off)\n",
" return self.fc(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"डेटासेट प्रशिक्षणासाठी तयार करण्यासाठी, आपल्याला ऑफसेट व्हेक्टर तयार करणारी रूपांतरण फंक्शन प्रदान करावी लागेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def offsetify(b):\n",
" # first, compute data tensor from all sequences\n",
" x = [torch.tensor(encode(t[1])) for t in b]\n",
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
" o = [0] + [len(t) for t in x]\n",
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
" return ( \n",
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
" torch.cat(x), # text \n",
" o\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता लक्षात घ्या, की सर्व पूर्वीच्या उदाहरणांपेक्षा वेगळे, आमचे नेटवर्क आता दोन पॅरामीटर्स स्वीकारते: डेटा व्हेक्टर आणि ऑफसेट व्हेक्टर, जे वेगवेगळ्या आकाराचे आहेत. त्याचप्रमाणे, आमचा डेटा लोडर देखील आम्हाला 2 ऐवजी 3 मूल्ये प्रदान करतो: मजकूर आणि ऑफसेट व्हेक्टर दोन्ही वैशिष्ट्ये म्हणून प्रदान केले जातात. त्यामुळे, आम्हाला आमच्या प्रशिक्षण फंक्शनमध्ये थोडासा बदल करणे आवश्यक आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6153125\n",
"6400: acc=0.6615625\n",
"9600: acc=0.6932291666666667\n",
"12800: acc=0.715078125\n",
"16000: acc=0.7270625\n",
"19200: acc=0.7382291666666667\n",
"22400: acc=0.7486160714285715\n"
]
},
{
"data": {
"text/plain": [
"(22.771553103007037, 0.7551983365323096)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
"\n",
"def train_epoch_emb(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.CrossEntropyLoss(),epoch_size=None, report_freq=200):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
" loss_fn = loss_fn.to(device)\n",
" net.train()\n",
" total_loss,acc,count,i = 0,0,0,0\n",
" for labels,text,off in dataloader:\n",
" optimizer.zero_grad()\n",
" labels,text,off = labels.to(device), text.to(device), off.to(device)\n",
" out = net(text, off)\n",
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss+=loss\n",
" _,predicted = torch.max(out,1)\n",
" acc+=(predicted==labels).sum()\n",
" count+=len(labels)\n",
" i+=1\n",
" if i%report_freq==0:\n",
" print(f\"{count}: acc={acc.item()/count}\")\n",
" if epoch_size and count>epoch_size:\n",
" break\n",
" return total_loss.item()/count, acc.item()/count\n",
"\n",
"\n",
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सिमॅंटिक एम्बेडिंग्स: वर्ड2व्हेक\n",
"\n",
"आपल्या मागील उदाहरणात, मॉडेलच्या एम्बेडिंग लेयरने शब्दांना व्हेक्टर स्वरूपात मॅप करणे शिकले, परंतु या स्वरूपात फारसा सिमॅंटिक अर्थ नव्हता. असे व्हेक्टर स्वरूप शिकणे चांगले ठरेल, ज्यामध्ये समान शब्द किंवा समानार्थी शब्द अशा व्हेक्टरना सादर करतील जे काही व्हेक्टर अंतर (उदा. युक्लिडियन अंतर) यांच्या दृष्टीने एकमेकांच्या जवळ असतील.\n",
"\n",
"हे साध्य करण्यासाठी, आपल्याला मोठ्या प्रमाणातील मजकुरावर विशिष्ट पद्धतीने आपले एम्बेडिंग मॉडेल प्री-ट्रेन करावे लागेल. सिमॅंटिक एम्बेडिंग्स ट्रेन करण्याच्या पहिल्या पद्धतींपैकी एक म्हणजे [Word2Vec](https://en.wikipedia.org/wiki/Word2vec). हे दोन मुख्य आर्किटेक्चर्सवर आधारित आहे, जे शब्दांचे वितरित प्रतिनिधित्व तयार करण्यासाठी वापरले जातात:\n",
"\n",
" - **कंटिन्युअस बॅग-ऑफ-वर्ड्स** (CBoW) — या आर्किटेक्चरमध्ये, आपण मॉडेलला आजूबाजूच्या संदर्भातून एखादा शब्द भाकीत करण्यासाठी ट्रेन करतो. दिलेल्या ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ मध्ये, मॉडेलचे उद्दिष्ट $(W_{-2},W_{-1},W_1,W_2)$ वरून $W_0$ भाकीत करणे आहे.\n",
" - **कंटिन्युअस स्किप-ग्राम** हे CBoW च्या उलट आहे. मॉडेल सध्याचा शब्द भाकीत करण्यासाठी संदर्भातील आजूबाजूच्या शब्दांचा वापर करते.\n",
"\n",
"CBoW जलद आहे, तर स्किप-ग्राम थोडा धीमा आहे, परंतु दुर्मिळ शब्दांचे प्रतिनिधित्व करण्याचे काम अधिक चांगल्या प्रकारे करतो.\n",
"\n",
"![CBoW आणि स्किप-ग्राम अल्गोरिदम्स शब्दांना व्हेक्टरमध्ये रूपांतरित करण्यासाठी दाखवणारी प्रतिमा.](../../../../../translated_images/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6f0f5de66427e8a6eda63809356114e28fb1fa5f4a83ebda7.mr.png)\n",
"\n",
"Google News डेटासेटवर प्री-ट्रेन केलेल्या word2vec एम्बेडिंगसह प्रयोग करण्यासाठी, आपण **gensim** लायब्ररीचा वापर करू शकतो. खाली 'neural' या शब्दाशी सर्वाधिक समान शब्द शोधले आहेत:\n",
"\n",
"> **Note:** जेव्हा तुम्ही प्रथमच शब्दांचे व्हेक्टर तयार करता, तेव्हा त्यांना डाउनलोड करण्यात काही वेळ लागू शकतो!\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import gensim.downloader as api\n",
"w2v = api.load('word2vec-google-news-300')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"neuronal -> 0.7804799675941467\n",
"neurons -> 0.7326500415802002\n",
"neural_circuits -> 0.7252851724624634\n",
"neuron -> 0.7174385190010071\n",
"cortical -> 0.6941086649894714\n",
"brain_circuitry -> 0.6923246383666992\n",
"synaptic -> 0.6699118614196777\n",
"neural_circuitry -> 0.6638563275337219\n",
"neurochemical -> 0.6555314064025879\n",
"neuronal_activity -> 0.6531826257705688\n"
]
}
],
"source": [
"for w,p in w2v.most_similar('neural'):\n",
" print(f\"{w} -> {p}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही शब्दातून व्हेक्टर एम्बेडिंग्स देखील गणना करू शकतो, ज्याचा वापर वर्गीकरण मॉडेल प्रशिक्षणासाठी केला जाऊ शकतो (स्पष्टतेसाठी आम्ही फक्त व्हेक्टरचे पहिले 20 घटक दाखवतो):\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
" dtype=float32)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.word_vec('play')[:20]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('queen', 0.7118192911148071)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"दोन्ही CBoW आणि Skip-Grams हे \"भाकीत करणारे\" एम्बेडिंग्स आहेत, कारण ते फक्त स्थानिक संदर्भांवर आधारित असतात. Word2Vec जागतिक संदर्भाचा फायदा घेत नाही.\n",
"\n",
"**FastText** हे Word2Vec वर आधारित आहे, ज्यामध्ये प्रत्येक शब्दासाठी आणि त्या शब्दामध्ये आढळणाऱ्या अक्षर n-grams साठी व्हेक्टर प्रतिनिधित्व शिकवले जाते. या प्रतिनिधित्वांचे मूल्य प्रत्येक प्रशिक्षण टप्प्यावर एका व्हेक्टरमध्ये सरासरी काढले जाते. जरी यामुळे प्री-ट्रेनिंगसाठी अतिरिक्त गणना लागते, तरीही हे शब्द एम्बेडिंग्सना उप-शब्द माहिती एन्कोड करण्यास सक्षम करते.\n",
"\n",
"आणखी एक पद्धत, **GloVe**, सह-अस्तित्व मॅट्रिक्सच्या संकल्पनेचा उपयोग करते आणि सह-अस्तित्व मॅट्रिक्सला अधिक अभिव्यक्त आणि नॉन-लिनियर शब्द व्हेक्टरमध्ये विघटित करण्यासाठी न्यूरल पद्धतींचा वापर करते.\n",
"\n",
"तुम्ही एम्बेडिंग्स बदलून FastText आणि GloVe वापरून उदाहरण खेळू शकता, कारण gensim विविध शब्द एम्बेडिंग मॉडेल्सला समर्थन देते.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PyTorch मध्ये पूर्व-प्रशिक्षित एम्बेडिंग्ज वापरणे\n",
"\n",
"वरील उदाहरण बदलून आपण आपल्या एम्बेडिंग लेयरमधील मॅट्रिक्सला Word2Vec सारख्या अर्थपूर्ण एम्बेडिंग्जने पूर्व-भरू शकतो. आपल्याला हे लक्षात घ्यावे लागेल की पूर्व-प्रशिक्षित एम्बेडिंग आणि आपल्या टेक्स्ट कॉर्पसचे शब्दसंग्रह (vocabularies) बहुधा जुळणार नाहीत, त्यामुळे गहाळ शब्दांसाठी वेट्स (weights) यादृच्छिक (random) मूल्यांनी प्रारंभ करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Embedding size: 300\n",
"Populating matrix, this will take some time...Done, found 41080 words, 54732 words missing\n"
]
}
],
"source": [
"embed_size = len(w2v.get_vector('hello'))\n",
"print(f'Embedding size: {embed_size}')\n",
"\n",
"net = EmbedClassifier(vocab_size,embed_size,len(classes))\n",
"\n",
"print('Populating matrix, this will take some time...',end='')\n",
"found, not_found = 0,0\n",
"for i,w in enumerate(vocab.get_itos()):\n",
" try:\n",
" net.embedding.weight[i].data = torch.tensor(w2v.get_vector(w))\n",
" found+=1\n",
" except:\n",
" net.embedding.weight[i].data = torch.normal(0.0,1.0,(embed_size,))\n",
" not_found+=1\n",
"\n",
"print(f\"Done, found {found} words, {not_found} words missing\")\n",
"net = net.to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6359375\n",
"6400: acc=0.68109375\n",
"9600: acc=0.7067708333333333\n",
"12800: acc=0.723671875\n",
"16000: acc=0.73625\n",
"19200: acc=0.7463541666666667\n",
"22400: acc=0.7560714285714286\n"
]
},
{
"data": {
"text/plain": [
"(214.1013875559821, 0.7626759436980166)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपल्या बाबतीत, आम्हाला अचूकतेत मोठी वाढ दिसत नाही, ज्याचे मुख्य कारण वेगवेगळ्या शब्दसंग्रहांमुळे असावे. \n",
"वेगवेगळ्या शब्दसंग्रहांच्या समस्येवर मात करण्यासाठी, आपण खालील उपायांपैकी एक वापरू शकतो: \n",
"* आपल्या शब्दसंग्रहावर word2vec मॉडेल पुन्हा प्रशिक्षित करा \n",
"* पूर्व-प्रशिक्षित word2vec मॉडेलमधील शब्दसंग्रहासह आपला डेटासेट लोड करा. डेटासेट लोड करताना वापरला जाणारा शब्दसंग्रह निर्दिष्ट केला जाऊ शकतो. \n",
"\n",
"दुसरा दृष्टिकोन सोपा वाटतो, विशेषतः कारण PyTorch `torchtext` फ्रेमवर्कमध्ये एम्बेडिंगसाठी अंगभूत समर्थन आहे. उदाहरणार्थ, आपण खालीलप्रमाणे GloVe-आधारित शब्दसंग्रह तयार करू शकतो: \n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|█████████▉| 399999/400000 [00:15<00:00, 25411.14it/s]\n"
]
}
],
"source": [
"vocab = torchtext.vocab.GloVe(name='6B', dim=50)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"लोड केलेल्या शब्दसंग्रहामध्ये खालील मूलभूत क्रिया आहेत:\n",
"* `vocab.stoi` शब्दकोश आपल्याला शब्द त्याच्या शब्दकोश निर्देशांकामध्ये रूपांतरित करण्याची परवानगी देतो\n",
"* `vocab.itos` याउलट करते - संख्या शब्दामध्ये रूपांतरित करते\n",
"* `vocab.vectors` हा एम्बेडिंग व्हेक्टरचा सरणी आहे, त्यामुळे एखाद्या शब्दाचा `s` एम्बेडिंग मिळवण्यासाठी आपल्याला `vocab.vectors[vocab.stoi[s]]` वापरावे लागेल\n",
"\n",
"येथे एम्बेडिंग्समध्ये फेरफार करण्याचे उदाहरण दिले आहे, जेणेकरून समीकरण **kind-man+woman = queen** सिद्ध करता येईल (हे कार्य करण्यासाठी मला गुणांक थोडासा बदलावा लागला):\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'queen'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get the vector corresponding to kind-man+woman\n",
"qvec = vocab.vectors[vocab.stoi['king']]-vocab.vectors[vocab.stoi['man']]+1.3*vocab.vectors[vocab.stoi['woman']]\n",
"# find the index of the closest embedding vector \n",
"d = torch.sum((vocab.vectors-qvec)**2,dim=1)\n",
"min_idx = torch.argmin(d)\n",
"# find the corresponding word\n",
"vocab.itos[min_idx]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"डेटासेटला GloVe शब्दसंग्रहाचा वापर करून एन्कोड करण्यासाठी, आम्हाला प्रथम त्या एम्बेडिंग्सचा वापर करून वर्गीकरणकर्ता प्रशिक्षित करावा लागेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def offsetify(b):\n",
" # first, compute data tensor from all sequences\n",
" x = [torch.tensor(encode(t[1],voc=vocab)) for t in b] # pass the instance of vocab to encode function!\n",
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
" o = [0] + [len(t) for t in x]\n",
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
" return ( \n",
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
" torch.cat(x), # text \n",
" o\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जसे आपण वर पाहिले, सर्व व्हेक्टर एम्बेडिंग्ज `vocab.vectors` मॅट्रिक्समध्ये संग्रहित केल्या जातात. साध्या कॉपींगचा वापर करून त्या वेट्स एम्बेडिंग लेयरच्या वेट्समध्ये लोड करणे खूप सोपे होते:\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"net = EmbedClassifier(len(vocab),len(vocab.vectors[0]),len(classes))\n",
"net.embedding.weight.data = vocab.vectors\n",
"net = net.to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6271875\n",
"6400: acc=0.68078125\n",
"9600: acc=0.7030208333333333\n",
"12800: acc=0.71984375\n",
"16000: acc=0.7346875\n",
"19200: acc=0.7455729166666667\n",
"22400: acc=0.7529464285714286\n"
]
},
{
"data": {
"text/plain": [
"(35.53972978646833, 0.7575175943698017)"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)\n",
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही अचूकतेमध्ये लक्षणीय वाढ पाहत नाही याचे एक कारण म्हणजे आमच्या डेटासेटमधील काही शब्द प्री-ट्रेन केलेल्या GloVe शब्दसंग्रहात अनुपस्थित आहेत, आणि त्यामुळे त्याकडे मूलत: दुर्लक्ष केले जाते. या गोष्टीवर मात करण्यासाठी, आम्ही आमच्या डेटासेटवर स्वतःचे एम्बेडिंग्स ट्रेन करू शकतो.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## संदर्भात्मक एम्बेडिंग्स\n",
"\n",
"पारंपरिक प्रीट्रेन केलेल्या एम्बेडिंग्स जसे की Word2Vec यांची एक महत्त्वाची मर्यादा म्हणजे शब्द अर्थ अस्पष्टता (word sense disambiguation) ची समस्या. प्रीट्रेन केलेल्या एम्बेडिंग्स काही प्रमाणात शब्दांचा संदर्भातील अर्थ पकडू शकतात, परंतु प्रत्येक संभाव्य अर्थ एका एम्बेडिंगमध्येच समाविष्ट केला जातो. यामुळे डाउनस्ट्रीम मॉडेल्समध्ये समस्या निर्माण होऊ शकतात, कारण अनेक शब्द, जसे की 'play', वेगवेगळ्या संदर्भांमध्ये वेगवेगळे अर्थ दर्शवतात.\n",
"\n",
"उदाहरणार्थ, 'play' या शब्दाचा खालील दोन वाक्यांमध्ये अर्थ पूर्णपणे वेगळा आहे:\n",
"- मी थिएटरमध्ये एक **play** पाहायला गेलो.\n",
"- जॉनला त्याच्या मित्रांसोबत **play** करायचे आहे.\n",
"\n",
"वरील प्रीट्रेन केलेल्या एम्बेडिंग्स 'play' या शब्दाचे दोन्ही अर्थ एकाच एम्बेडिंगमध्ये दर्शवतात. ही मर्यादा दूर करण्यासाठी, आपल्याला **भाषा मॉडेल** आधारित एम्बेडिंग्स तयार करणे आवश्यक आहे, जे मोठ्या प्रमाणातील मजकूरावर प्रशिक्षित केले जाते आणि *जाणते* की शब्द वेगवेगळ्या संदर्भांमध्ये कसे एकत्र ठेवले जाऊ शकतात. संदर्भात्मक एम्बेडिंग्सवर चर्चा करणे या ट्यूटोरियलच्या कक्षेबाहेर आहे, परंतु आपण पुढील युनिटमध्ये भाषा मॉडेल्सबद्दल बोलताना त्याकडे परत येऊ.\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"
},
"kernelspec": {
"display_name": "py37_pytorch",
"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": "f50b026abce5cf36783a560ea72cb9b1",
"translation_date": "2025-08-28T09:46:19+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,693 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिंग्ज\n",
"\n",
"आपल्या मागील उदाहरणात, आम्ही `vocab_size` लांबीच्या उच्च-आयामी बॅग-ऑफ-वर्ड्स व्हेक्टरवर कार्य केले आणि कमी-आयामी स्थानिक प्रतिनिधित्व व्हेक्टर स्पष्टपणे विरळ वन-हॉट प्रतिनिधित्वात रूपांतरित केले. हे वन-हॉट प्रतिनिधित्व मेमरीसाठी कार्यक्षम नाही. याशिवाय, प्रत्येक शब्द स्वतंत्रपणे विचारात घेतला जातो, त्यामुळे वन-हॉट एन्कोड केलेले व्हेक्टर शब्दांमधील अर्थपूर्ण समानता व्यक्त करत नाहीत.\n",
"\n",
"या युनिटमध्ये, आपण **News AG** डेटासेटचा अभ्यास सुरू ठेवू. सुरुवात करण्यासाठी, डेटा लोड करूया आणि मागील युनिटमधील काही संकल्पना परिभाषित करूया.\n"
]
},
{
"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",
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### एम्बेडिंग म्हणजे काय?\n",
"\n",
"**एम्बेडिंग** ही कल्पना म्हणजे शब्दांचे प्रतिनिधित्व कमी-आयामी घन गटांद्वारे करणे, जे त्या शब्दाचा अर्थपूर्ण अर्थ प्रतिबिंबित करतात. आपण नंतर कसे अर्थपूर्ण शब्द एम्बेडिंग तयार करायचे यावर चर्चा करू, पण सध्या एम्बेडिंगला शब्द वेक्टरची आयामसंख्या कमी करण्याचा एक मार्ग म्हणून विचार करूया.\n",
"\n",
"तर, एक एम्बेडिंग लेयर शब्दाला इनपुट म्हणून घेते आणि निर्दिष्ट `embedding_size` च्या आउटपुट वेक्टरमध्ये रूपांतरित करते. एका अर्थाने, हे `Dense` लेयरसारखेच आहे, पण एक-हॉट एन्कोडेड वेक्टर इनपुट म्हणून घेण्याऐवजी, हे शब्द क्रमांक घेऊ शकते.\n",
"\n",
"आपल्या नेटवर्कमध्ये पहिल्या लेयर म्हणून एम्बेडिंग लेयर वापरल्याने, आपण बॅग-ऑफ-वर्ड्स मॉडेलऐवजी **एम्बेडिंग बॅग** मॉडेलकडे स्विच करू शकतो, जिथे आपण प्रथम आपल्या मजकुरातील प्रत्येक शब्द त्याच्या संबंधित एम्बेडिंगमध्ये रूपांतरित करतो, आणि नंतर त्या सर्व एम्बेडिंग्सवर काही एकत्रित फंक्शन (जसे की `sum`, `average` किंवा `max`) गणना करतो.\n",
"\n",
"![पाच अनुक्रम शब्दांसाठी एम्बेडिंग वर्गीकरण दाखवणारी प्रतिमा.](../../../../../translated_images/embedding-classifier-example.b77f021a7ee67eeec8e68bfe11636c5b97d6eaa067515a129bfb1d0034b1ac5b.mr.png)\n",
"\n",
"आपल्या वर्गीकरण न्यूरल नेटवर्कमध्ये खालील लेयर्स असतात:\n",
"\n",
"* `TextVectorization` लेयर, जी स्ट्रिंगला इनपुट म्हणून घेते आणि टोकन क्रमांकांचा टेन्सर तयार करते. आपण काही वाजवी शब्दसंग्रह आकार `vocab_size` निर्दिष्ट करू, आणि कमी-वारंवार वापरलेले शब्द दुर्लक्षित करू. इनपुट आकार 1 असेल, आणि आउटपुट आकार $n$ असेल, कारण आपल्याला $n$ टोकन्स मिळतील, ज्यामध्ये प्रत्येक टोकन 0 ते `vocab_size` मधील क्रमांक असतील.\n",
"* `Embedding` लेयर, जी $n$ क्रमांक घेते आणि प्रत्येक क्रमांकाला दिलेल्या लांबीच्या घन गटात (उदा. आपल्या उदाहरणात 100) कमी करते. त्यामुळे, $n$ आकाराचा इनपुट टेन्सर $n\\times 100$ आकाराच्या टेन्सरमध्ये रूपांतरित होईल.\n",
"* एकत्रीकरण लेयर, जी या टेन्सरचा पहिल्या अक्षावर सरासरी काढते, म्हणजेच ती वेगवेगळ्या शब्दांसाठी असलेल्या सर्व $n$ इनपुट टेन्सर्सची सरासरी काढेल. हे लेयर अंमलात आणण्यासाठी, आपण `Lambda` लेयर वापरू, आणि त्यात सरासरी काढण्याचे फंक्शन पास करू. आउटपुटचा आकार 100 असेल, आणि तो संपूर्ण इनपुट अनुक्रमाचे संख्यात्मक प्रतिनिधित्व असेल.\n",
"* अंतिम `Dense` रेषीय वर्गीकरणकर्ता.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" text_vectorization (TextVec (None, None) 0 \n",
" torization) \n",
" \n",
" embedding (Embedding) (None, None, 100) 3000000 \n",
" \n",
" lambda (Lambda) (None, 100) 0 \n",
" \n",
" dense (Dense) (None, 4) 404 \n",
" \n",
"=================================================================\n",
"Total params: 3,000,404\n",
"Trainable params: 3,000,404\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"vocab_size = 30000\n",
"batch_size = 128\n",
"\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,input_shape=(1,))\n",
"\n",
"model = keras.models.Sequential([\n",
" vectorizer, \n",
" keras.layers.Embedding(vocab_size,100),\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`summary` च्या प्रिंटआउटमध्ये, **output shape** कॉलममध्ये, पहिला टेन्सर डायमेंशन `None` मिनीबॅचच्या आकाराशी संबंधित आहे, आणि दुसरा टोकन सिक्वेन्सच्या लांबीशी संबंधित आहे. मिनीबॅचमधील सर्व टोकन सिक्वेन्सची लांबी वेगवेगळी असते. यावर कसे काम करायचे, याबद्दल आपण पुढील विभागात चर्चा करू.\n",
"\n",
"आता नेटवर्क प्रशिक्षण देऊया:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 20s 20ms/step - loss: 0.7891 - acc: 0.8155 - val_loss: 0.4470 - val_acc: 0.8642\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x22255515100>"
]
},
"execution_count": 4,
"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",
"print(\"Training vectorizer\")\n",
"vectorizer.adapt(ds_train.take(500).map(extract_text))\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',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": {
"nteract": {
"transient": {
"deleting": false
}
}
},
"source": [
"> **टीप** की आम्ही डेटाच्या उपसमुच्च्यावर आधारित व्हेक्टरायझर तयार करत आहोत. प्रक्रिया वेगवान करण्यासाठी हे केले जाते, आणि यामुळे अशी परिस्थिती निर्माण होऊ शकते की आमच्या मजकुरातील सर्व टोकन्स शब्दसंग्रहात उपस्थित नसतील. अशा परिस्थितीत, त्या टोकन्स दुर्लक्षित केले जातील, ज्यामुळे अचूकतेत थोडीशी घट होऊ शकते. तथापि, वास्तविक जीवनात मजकुराचा उपसमुच्चा अनेकदा चांगल्या शब्दसंग्रहाचा अंदाज देतो.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### चल बदलत्या अनुक्रमणिकेच्या आकारांशी व्यवहार करणे\n",
"\n",
"चला समजून घेऊया की मिनीबॅचेसमध्ये प्रशिक्षण कसे होते. वरील उदाहरणात, इनपुट टेन्सरचे परिमाण 1 आहे, आणि आपण 128-लांब मिनीबॅचेस वापरतो, त्यामुळे टेन्सरचा वास्तविक आकार $128 \\times 1$ आहे. मात्र, प्रत्येक वाक्यातील टोकन्सची संख्या वेगळी असते. जर आपण `TextVectorization` स्तर एका इनपुटवर लागू केला, तर परत मिळणाऱ्या टोकन्सची संख्या वेगळी असते, कारण ती मजकूर कसा टोकनाइझ केला जातो यावर अवलंबून असते:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tf.Tensor([ 1 45], shape=(2,), dtype=int64)\n",
"tf.Tensor([ 112 1271 1 3 1747 158], shape=(6,), dtype=int64)\n"
]
}
],
"source": [
"print(vectorizer('Hello, world!'))\n",
"print(vectorizer('I am glad to meet you!'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"तथापि, जेव्हा आपण वेक्टरायझर अनेक अनुक्रमांवर लागू करतो, तेव्हा त्याला आयताकृती आकाराचा टेन्सर तयार करावा लागतो, त्यामुळे तो न वापरलेल्या घटकांना PAD टोकनने (जो आपल्या बाबतीत शून्य आहे) भरतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tf.Tensor: shape=(2, 6), dtype=int64, numpy=\n",
"array([[ 1, 45, 0, 0, 0, 0],\n",
" [ 112, 1271, 1, 3, 1747, 158]], dtype=int64)>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer(['Hello, world!','I am glad to meet you!'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"येथे आपण एम्बेडिंग्स पाहू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[[ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
" [ 2.57456154e-01, 2.79364467e-01, -2.03605562e-01, ...,\n",
" -2.07474351e-01, 8.31158683e-02, -2.03911960e-01],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02]],\n",
"\n",
" [[ 1.89674050e-01, 2.61548996e-01, -3.67433839e-02, ...,\n",
" -2.07366899e-01, -1.05442435e-01, -2.36952081e-01],\n",
" [ 6.16133213e-02, 1.80511594e-01, 9.77298319e-02, ...,\n",
" -5.46628237e-02, -1.07340455e-01, -1.06589928e-01],\n",
" [ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
" [-4.84890305e-02, -8.41715634e-02, 1.51529670e-01, ...,\n",
" 1.28192469e-01, -7.77286515e-02, 1.26041949e-01],\n",
" [-4.17212099e-02, -5.60694858e-02, 4.08860669e-02, ...,\n",
" 8.70475471e-02, 8.92383084e-02, 1.67974353e-01],\n",
" [ 2.85779923e-01, 4.57767487e-01, 4.52292450e-02, ...,\n",
" -1.97419018e-01, -2.04659685e-01, -2.79758364e-01]]],\n",
" dtype=float32)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.layers[1](vectorizer(['Hello, world!','I am glad to meet you!'])).numpy()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सिमॅंटिक एम्बेडिंग्स: Word2Vec\n",
"\n",
"आपल्या मागील उदाहरणात, एम्बेडिंग लेयरने शब्दांना व्हेक्टर प्रतिनिधित्वात मॅप करणे शिकले, परंतु या प्रतिनिधित्वांना सिमॅंटिक अर्थ नव्हता. असे व्हेक्टर प्रतिनिधित्व शिकणे चांगले होईल ज्यामध्ये समान शब्द किंवा समानार्थी शब्द काही व्हेक्टर अंतराच्या दृष्टीने (उदाहरणार्थ, युक्लिडियन अंतर) एकमेकांच्या जवळ असतील.\n",
"\n",
"हे साध्य करण्यासाठी, आपल्याला [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) सारख्या तंत्राचा वापर करून मोठ्या प्रमाणातील मजकूरावर आपला एम्बेडिंग मॉडेल प्रीट्रेन करणे आवश्यक आहे. हे दोन मुख्य आर्किटेक्चरवर आधारित आहे जे शब्दांचे वितरित प्रतिनिधित्व तयार करण्यासाठी वापरले जातात:\n",
"\n",
" - **कंटिन्युअस बॅग-ऑफ-वर्ड्स** (CBoW), ज्यामध्ये आपण मॉडेलला आजूबाजूच्या संदर्भातून शब्दाचा अंदाज लावण्यासाठी प्रशिक्षित करतो. दिलेल्या ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ मध्ये, मॉडेलचे उद्दिष्ट $(W_{-2},W_{-1},W_1,W_2)$ पासून $W_0$ अंदाज लावणे आहे.\n",
" - **कंटिन्युअस स्किप-ग्राम** CBoW च्या उलट आहे. मॉडेल सध्याचा शब्द अंदाज लावण्यासाठी संदर्भ शब्दांच्या विंडोचा वापर करते.\n",
"\n",
"CBoW जलद आहे, आणि स्किप-ग्राम जरी हळू असला तरी, तो दुर्मिळ शब्दांचे प्रतिनिधित्व अधिक चांगल्या प्रकारे करतो.\n",
"\n",
"![CBoW आणि स्किप-ग्राम अल्गोरिदम्स शब्दांना व्हेक्टरमध्ये रूपांतरित करण्यासाठी दाखवणारी प्रतिमा.](../../../../../translated_images/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6f0f5de66427e8a6eda63809356114e28fb1fa5f4a83ebda7.mr.png)\n",
"\n",
"Google News डेटासेटवर प्रीट्रेन केलेल्या Word2Vec एम्बेडिंगसह प्रयोग करण्यासाठी, आपण **gensim** लायब्ररीचा वापर करू शकतो. खाली 'neural' शब्दाशी सर्वाधिक समान असलेले शब्द शोधले आहेत.\n",
"\n",
"> **टीप:** जेव्हा तुम्ही प्रथम शब्द व्हेक्टर तयार करता, तेव्हा त्यांना डाउनलोड करणे थोडा वेळ घेऊ शकते!\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import gensim.downloader as api\n",
"w2v = api.load('word2vec-google-news-300')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"neuronal -> 0.7804799675941467\n",
"neurons -> 0.7326500415802002\n",
"neural_circuits -> 0.7252851724624634\n",
"neuron -> 0.7174385190010071\n",
"cortical -> 0.6941086649894714\n",
"brain_circuitry -> 0.6923246383666992\n",
"synaptic -> 0.6699118614196777\n",
"neural_circuitry -> 0.6638563275337219\n",
"neurochemical -> 0.6555314064025879\n",
"neuronal_activity -> 0.6531826257705688\n"
]
}
],
"source": [
"for w,p in w2v.most_similar('neural'):\n",
" print(f\"{w} -> {p}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही शब्दातून व्हेक्टर एम्बेडिंग देखील काढू शकतो, जे वर्गीकरण मॉडेल प्रशिक्षणासाठी वापरले जाऊ शकते. एम्बेडिंगमध्ये 300 घटक आहेत, परंतु स्पष्टतेसाठी येथे आम्ही फक्त व्हेक्टरचे पहिले 20 घटक दाखवतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
" dtype=float32)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v['play'][:20]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"सामान्य अर्थाच्या एम्बेडिंग्सबद्दलची महान गोष्ट म्हणजे तुम्ही अर्थाच्या आधारावर व्हेक्टर एन्कोडिंगमध्ये फेरफार करू शकता. उदाहरणार्थ, आपण असे विचारू शकतो की *राजा* आणि *स्त्री* या शब्दांच्या जितके जवळजवळ व्हेक्टर प्रतिनिधित्व असेल आणि *पुरुष* या शब्दापासून जितके दूर असेल असा शब्द शोधा:\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('queen', 0.7118192911148071)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"वरील उदाहरणामध्ये काही अंतर्गत GenSym जादूचा वापर केला आहे, परंतु मूळ तर्कशास्त्र खूपच सोपे आहे. एम्बेडिंग्सबद्दल एक मनोरंजक गोष्ट म्हणजे तुम्ही एम्बेडिंग वेक्टरवर सामान्य वेक्टर ऑपरेशन्स करू शकता, आणि ते शब्दांच्या **अर्थांवर** होणाऱ्या ऑपरेशन्सचे प्रतिबिंबित करेल. वरील उदाहरण वेक्टर ऑपरेशन्सच्या दृष्टीने व्यक्त केले जाऊ शकते: आम्ही **KING-MAN+WOMAN** शी संबंधित वेक्टरची गणना करतो (`+` आणि `-` ऑपरेशन्स संबंधित शब्दांच्या वेक्टर प्रतिनिधींवर केले जातात), आणि नंतर त्या वेक्टरच्या जवळचा शब्द शब्दकोशात शोधतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'queen'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get the vector corresponding to kind-man+woman\n",
"qvec = w2v['king']-1.7*w2v['man']+1.7*w2v['woman']\n",
"# find the index of the closest embedding vector \n",
"d = np.sum((w2v.vectors-qvec)**2,axis=1)\n",
"min_idx = np.argmin(d)\n",
"# find the corresponding word\n",
"w2v.index_to_key[min_idx]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **टीप**: आम्हाला *man* आणि *woman* वेक्टरमध्ये छोटे coefficients जोडावे लागले - ते काढून टाकून काय होते ते पाहा.\n",
"\n",
"सर्वात जवळचा वेक्टर शोधण्यासाठी, आम्ही TensorFlow चा वापर करून आमच्या वेक्टर आणि शब्दसंग्रहातील सर्व वेक्टरमधील अंतराचा वेक्टर मोजतो, आणि नंतर `argmin` वापरून किमान शब्दाचा निर्देशांक शोधतो.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जरी Word2Vec शब्दांच्या अर्थपूर्णतेसाठी एक उत्कृष्ट पद्धत वाटत असली तरी, त्याला अनेक मर्यादा आहेत, जसे की खालीलप्रमाणे:\n",
"\n",
"* CBoW आणि skip-gram मॉडेल्स हे **predictive embeddings** आहेत, आणि ते फक्त स्थानिक संदर्भाचा विचार करतात. Word2Vec जागतिक संदर्भाचा फायदा घेत नाही.\n",
"* Word2Vec शब्दांच्या **रूपविज्ञानाचा** विचार करत नाही, म्हणजेच शब्दाचा अर्थ त्याच्या वेगवेगळ्या भागांवर (जसे की मूळ शब्द) अवलंबून असतो.\n",
"\n",
"**FastText** दुसऱ्या मर्यादेवर मात करण्याचा प्रयत्न करते आणि Word2Vec वर आधारित आहे. हे प्रत्येक शब्दासाठी आणि त्या शब्दामध्ये आढळणाऱ्या अक्षर n-grams साठी व्हेक्टर प्रतिनिधित्व शिकते. या प्रतिनिधित्वांच्या मूल्यांना प्रत्येक प्रशिक्षण टप्प्यावर एका व्हेक्टरमध्ये सरासरी केली जाते. जरी यामुळे पूर्व-प्रशिक्षणासाठी अतिरिक्त गणना लागते, तरीही यामुळे शब्दांच्या embeddings मध्ये उप-शब्द माहिती समाविष्ट होऊ शकते.\n",
"\n",
"दुसरी पद्धत, **GloVe**, शब्दांच्या embeddings साठी वेगळा दृष्टिकोन वापरते, जो शब्द-संदर्भ मॅट्रिक्सच्या घटकांवर आधारित आहे. प्रथम, ती एक मोठी मॅट्रिक्स तयार करते जी वेगवेगळ्या संदर्भांमध्ये शब्दांच्या उपस्थितीची संख्या मोजते, आणि नंतर ती या मॅट्रिक्सचे कमी परिमाणांमध्ये प्रतिनिधित्व करण्याचा प्रयत्न करते, ज्यामुळे पुनर्रचना तोटा (reconstruction loss) कमी होतो.\n",
"\n",
"gensim लायब्ररी या शब्दांच्या embeddings ला समर्थन देते, आणि तुम्ही वरील मॉडेल लोडिंग कोड बदलून त्यांच्यासोबत प्रयोग करू शकता.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## केरस मध्ये पूर्वप्रशिक्षित एम्बेडिंग्सचा वापर\n",
"\n",
"आपण वरील उदाहरण बदलून आपल्या एम्बेडिंग लेयरमध्ये Word2Vec सारख्या सिमॅंटिक एम्बेडिंग्ससह मॅट्रिक्स पूर्वप्रस्थापित करू शकतो. पूर्वप्रशिक्षित एम्बेडिंग आणि मजकूर कॉर्पसची शब्दसंग्रह (vocabularies) बहुधा जुळणार नाहीत, त्यामुळे आपल्याला एक निवड करावी लागेल. येथे आपण दोन शक्य पर्यायांचा अभ्यास करतो: टोकनायझर शब्दसंग्रहाचा वापर करणे आणि Word2Vec एम्बेडिंग्समधील शब्दसंग्रहाचा वापर करणे.\n",
"\n",
"### टोकनायझर शब्दसंग्रहाचा वापर\n",
"\n",
"टोकनायझर शब्दसंग्रहाचा वापर करताना, शब्दसंग्रहातील काही शब्दांना Word2Vec एम्बेडिंग्स असतील, तर काही गहाळ असतील. गृहीत धरले की आपला शब्दसंग्रह आकार `vocab_size` आहे, आणि Word2Vec एम्बेडिंग व्हेक्टरची लांबी `embed_size` आहे, तर एम्बेडिंग लेयर `vocab_size`$\\times$`embed_size` आकाराच्या वेट मॅट्रिक्सने दर्शविला जाईल. आपण हा मॅट्रिक्स शब्दसंग्रहामधून जाऊन भरू:\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Embedding size: 300\n",
"Populating matrix, this will take some time...Done, found 4551 words, 784 words missing\n"
]
}
],
"source": [
"embed_size = len(w2v.get_vector('hello'))\n",
"print(f'Embedding size: {embed_size}')\n",
"\n",
"vocab = vectorizer.get_vocabulary()\n",
"W = np.zeros((vocab_size,embed_size))\n",
"print('Populating matrix, this will take some time...',end='')\n",
"found, not_found = 0,0\n",
"for i,w in enumerate(vocab):\n",
" try:\n",
" W[i] = w2v.get_vector(w)\n",
" found+=1\n",
" except:\n",
" # W[i] = np.random.normal(0.0,0.3,size=(embed_size,))\n",
" not_found+=1\n",
"\n",
"print(f\"Done, found {found} words, {not_found} words missing\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ज्या शब्दांसाठी Word2Vec शब्दसंग्रहात शब्द उपलब्ध नाहीत, त्यांना शून्य म्हणून ठेवू शकतो किंवा एक यादृच्छिक वेक्टर तयार करू शकतो.\n",
"\n",
"आता आपण प्रीट्रेंड वजनांसह एक एम्बेडिंग लेयर परिभाषित करू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"emb = keras.layers.Embedding(vocab_size,embed_size,weights=[W],trainable=False)\n",
"model = keras.models.Sequential([\n",
" vectorizer, emb,\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 10s 10ms/step - loss: 1.1075 - acc: 0.7822 - val_loss: 0.9134 - val_acc: 0.8175\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x2220226ef10>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\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": [
"> **टीप**: लक्षात घ्या की `Embedding` तयार करताना आम्ही `trainable=False` सेट केले आहे, याचा अर्थ आम्ही Embedding लेयर पुन्हा प्रशिक्षण देत नाही. यामुळे अचूकता थोडी कमी होऊ शकते, परंतु प्रशिक्षणाचा वेग वाढतो.\n",
"\n",
"### एम्बेडिंग शब्दसंग्रह वापरणे\n",
"\n",
"मागील पद्धतीसह एक समस्या म्हणजे TextVectorization आणि Embedding मध्ये वापरलेले शब्दसंग्रह वेगवेगळे आहेत. या समस्येवर मात करण्यासाठी, आपण खालीलपैकी एक उपाय वापरू शकतो:\n",
"* आमच्या शब्दसंग्रहावर Word2Vec मॉडेल पुन्हा प्रशिक्षण द्या.\n",
"* प्रीट्रेन केलेल्या Word2Vec मॉडेलमधील शब्दसंग्रहासह आमचा डेटासेट लोड करा. डेटासेट लोड करताना वापरलेले शब्दसंग्रह निर्दिष्ट केले जाऊ शकतात.\n",
"\n",
"दुसरी पद्धत सोपी वाटते, म्हणून ती अंमलात आणूया. सर्वप्रथम, आम्ही Word2Vec एम्बेडिंगमधून घेतलेल्या निर्दिष्ट शब्दसंग्रहासह `TextVectorization` लेयर तयार करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"vocab = list(w2v.vocab.keys())\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(input_shape=(1,))\n",
"vectorizer.set_vocabulary(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जेनसिम वर्ड एम्बेडिंग्ज लायब्ररीमध्ये एक सोयीस्कर फंक्शन, `get_keras_embeddings`, आहे, जे तुमच्यासाठी स्वयंचलितपणे संबंधित केरस एम्बेडिंग्ज लेयर तयार करेल.\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"938/938 [==============================] - 20s 14ms/step - loss: 1.3377 - acc: 0.4978 - val_loss: 1.2995 - val_acc: 0.5647\n",
"Epoch 2/5\n",
"938/938 [==============================] - 10s 10ms/step - loss: 1.2587 - acc: 0.5722 - val_loss: 1.2339 - val_acc: 0.5842\n",
"Epoch 3/5\n",
"938/938 [==============================] - 10s 10ms/step - loss: 1.1980 - acc: 0.5884 - val_loss: 1.1826 - val_acc: 0.5954\n",
"Epoch 4/5\n",
"938/938 [==============================] - 12s 13ms/step - loss: 1.1503 - acc: 0.6002 - val_loss: 1.1417 - val_acc: 0.6018\n",
"Epoch 5/5\n",
"938/938 [==============================] - 11s 12ms/step - loss: 1.1120 - acc: 0.6097 - val_loss: 1.1083 - val_acc: 0.6104\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x2220ccb81c0>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" vectorizer, \n",
" w2v.get_keras_embedding(train_embeddings=False),\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128),epochs=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही उच्च अचूकता पाहत नाही याचे एक कारण म्हणजे आमच्या डेटासेटमधील काही शब्द प्रीट्रेन केलेल्या GloVe शब्दसंग्रहात नसल्यामुळे ते मूलत: दुर्लक्षित केले जातात. यावर मात करण्यासाठी, आम्ही आमच्या डेटासेटच्या आधारे स्वतःचे एम्बेडिंग्स प्रशिक्षण देऊ शकतो.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## संदर्भात्मक एम्बेडिंग्स\n",
"\n",
"Word2Vec सारख्या पारंपरिक प्रीट्रेन केलेल्या एम्बेडिंग्सचे एक मुख्य मर्यादित वैशिष्ट्य म्हणजे, जरी त्या एखाद्या शब्दाचा काही अर्थ पकडू शकतात, तरी त्या वेगवेगळ्या अर्थांमध्ये फरक करू शकत नाहीत. यामुळे डाउनस्ट्रीम मॉडेल्समध्ये समस्या निर्माण होऊ शकतात.\n",
"\n",
"उदाहरणार्थ, 'play' या शब्दाचा दोन वेगवेगळ्या वाक्यांमध्ये वेगळा अर्थ आहे:\n",
"- मी थिएटरमध्ये एक **play** पाहायला गेलो.\n",
"- जॉनला त्याच्या मित्रांसोबत **play** करायचे आहे.\n",
"\n",
"आपण ज्या प्रीट्रेन केलेल्या एम्बेडिंग्सबद्दल बोललो, त्या 'play' या शब्दाच्या दोन्ही अर्थांना एकाच एम्बेडिंगमध्ये दर्शवतात. ही मर्यादा दूर करण्यासाठी, आपल्याला **भाषा मॉडेल**वर आधारित एम्बेडिंग्स तयार करणे आवश्यक आहे, जे मोठ्या प्रमाणावर मजकूरावर प्रशिक्षित केले जाते आणि *जाणते* की शब्द वेगवेगळ्या संदर्भांमध्ये कसे एकत्र ठेवले जाऊ शकतात. संदर्भात्मक एम्बेडिंग्सवर चर्चा करणे या ट्यूटोरियलच्या कक्षेबाहेर आहे, परंतु आपण त्यांच्याबद्दल पुढील युनिटमध्ये भाषा मॉडेल्सवर चर्चा करताना परत येऊ.\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": "b859482be7f61d1eadc2c6a2720a37e4",
"translation_date": "2025-08-28T09:41:54+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,574 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "NXTSugt6ieXh"
},
"source": [
"## CBoW मॉडेल प्रशिक्षण\n",
"\n",
"हे नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) चा एक भाग आहे.\n",
"\n",
"या उदाहरणात, आपण CBoW भाषा मॉडेल प्रशिक्षण देऊन आपले स्वतःचे Word2Vec एम्बेडिंग स्पेस तयार करण्याचा विचार करू. आम्ही AG News डेटासेट मजकुराचा स्रोत म्हणून वापरू.\n"
]
},
{
"cell_type": "code",
"source": [
"import torch\n",
"import torchtext\n",
"import os\n",
"import collections\n",
"import builtins\n",
"import random\n",
"import numpy as np"
],
"metadata": {
"id": "q-UiiJUKaxHj"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
],
"metadata": {
"id": "TFbR8CZaTZ1q"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"प्रथम आपण आपला डेटासेट लोड करूया आणि टोकनायझर आणि शब्दसंग्रह परिभाषित करूया. आपण `vocab_size` 5000 वर सेट करू जेणेकरून गणनांवर थोडी मर्यादा येईल.\n"
],
"metadata": {
"id": "HIwC7lI5T-ov"
}
},
{
"cell_type": "code",
"source": [
"def load_dataset(ngrams = 1, min_freq = 1, vocab_size = 5000 , lines_cnt = 500):\n",
" tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
" print(\"Loading dataset...\")\n",
" test_dataset, train_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
" train_dataset = list(train_dataset)\n",
" test_dataset = list(test_dataset)\n",
" classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
" print('Building vocab...')\n",
" counter = collections.Counter()\n",
" for i, (_, line) in enumerate(train_dataset):\n",
" counter.update(torchtext.data.utils.ngrams_iterator(tokenizer(line),ngrams=ngrams))\n",
" if i == lines_cnt:\n",
" break\n",
" vocab = torchtext.vocab.Vocab(collections.Counter(dict(counter.most_common(vocab_size))), min_freq=min_freq)\n",
" return train_dataset, test_dataset, classes, vocab, tokenizer"
],
"metadata": {
"id": "wdZuygtgiuLG"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"train_dataset, test_dataset, _, vocab, tokenizer = load_dataset()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4d1nU1gsivGu",
"outputId": "949fe272-ae0e-49f5-c373-6703458b3a74"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"def encode(x, vocabulary, tokenizer = tokenizer):\n",
" return [vocabulary[s] for s in tokenizer(x)]"
],
"metadata": {
"id": "1XDYNhG8ToFV"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "LIlQk6_PaHVY"
},
"source": [
"## CBoW मॉडेल\n",
"\n",
"CBoW $2N$ शेजारील शब्दांवर आधारित एखादा शब्द अंदाज करण्यासाठी शिकतो. उदाहरणार्थ, जेव्हा $N=1$ असेल, तेव्हा वाक्य *I like to train networks* मधून आपल्याला खालील जोड्या मिळतील: (like,I), (I, like), (to, like), (like,to), (train,to), (to, train), (networks, train), (train,networks). येथे, पहिला शब्द हा शेजारील शब्द आहे जो इनपुट म्हणून वापरला जातो, आणि दुसरा शब्द हा आपण अंदाज करत असलेला शब्द आहे.\n",
"\n",
"पुढील शब्दाचा अंदाज लावण्यासाठी नेटवर्क तयार करण्यासाठी, आपल्याला शेजारील शब्द इनपुट म्हणून द्यावा लागेल, आणि शब्द क्रमांक आउटपुट म्हणून मिळवावा लागेल. CBoW नेटवर्कची रचना खालीलप्रमाणे आहे:\n",
"\n",
"* इनपुट शब्द एम्बेडिंग लेयरमधून पास केला जातो. हाच एम्बेडिंग लेयर आपला Word2Vec एम्बेडिंग असेल, त्यामुळे आपण त्याला `embedder` नावाच्या व्हेरिएबलमध्ये स्वतंत्रपणे परिभाषित करू. या उदाहरणात आपण एम्बेडिंग साइज = 30 वापरणार आहोत, जरी तुम्हाला उच्च डिमेन्शन्ससह प्रयोग करायचा असेल (खऱ्या Word2Vec मध्ये 300 असतो).\n",
"* एम्बेडिंग व्हेक्टर नंतर एका लीनियर लेयरमधून पास केला जाईल जो आउटपुट शब्दाचा अंदाज लावेल. त्यामुळे त्यात `vocab_size` न्यूरॉन्स असतील.\n",
"\n",
"आउटपुटसाठी, जर आपण `CrossEntropyLoss` ला लॉस फंक्शन म्हणून वापरले, तर आपल्याला अपेक्षित परिणाम म्हणून फक्त शब्द क्रमांक द्यावे लागतील, वन-हॉट एन्कोडिंगशिवाय.\n"
]
},
{
"cell_type": "code",
"source": [
"vocab_size = len(vocab)\n",
"\n",
"embedder = torch.nn.Embedding(num_embeddings = vocab_size, embedding_dim = 30)\n",
"model = torch.nn.Sequential(\n",
" embedder,\n",
" torch.nn.Linear(in_features = 30, out_features = vocab_size),\n",
")\n",
"\n",
"print(model)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "akKTcKQKkfl2",
"outputId": "da687e3e-a8ec-4c1a-e456-ab8cd6ac7dad"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Sequential(\n",
" (0): Embedding(5002, 30)\n",
" (1): Linear(in_features=30, out_features=5002, bias=True)\n",
")\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Nud6jgGPaHVa"
},
"source": [
"## प्रशिक्षण डेटा तयार करणे\n",
"\n",
"आता आपण मुख्य फंक्शन प्रोग्राम करूया, जे मजकूरातून CBoW शब्द जोड्या तयार करेल. हे फंक्शन आपल्याला विंडो आकार निर्दिष्ट करण्याची परवानगी देईल आणि इनपुट व आउटपुट शब्दांच्या जोड्यांचा संच परत करेल. लक्षात ठेवा की हे फंक्शन शब्दांवर तसेच वेक्टर/टेंसरवर देखील वापरले जाऊ शकते - ज्यामुळे आपण मजकूर एन्कोड करू शकतो, `to_cbow` फंक्शनला पास करण्यापूर्वी.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "x-dsXygOieXn",
"outputId": "c2218280-e540-40ba-9546-efe48d0d714f"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[['like', 'I'], ['to', 'I'], ['I', 'like'], ['to', 'like'], ['train', 'like'], ['I', 'to'], ['like', 'to'], ['train', 'to'], ['networks', 'to'], ['like', 'train'], ['to', 'train'], ['networks', 'train'], ['to', 'networks'], ['train', 'networks']]\n",
"[[232, 172], [5, 172], [172, 232], [5, 232], [0, 232], [172, 5], [232, 5], [0, 5], [1202, 5], [232, 0], [5, 0], [1202, 0], [5, 1202], [0, 1202]]\n"
]
}
],
"source": [
"def to_cbow(sent,window_size=2):\n",
" res = []\n",
" for i,x in enumerate(sent):\n",
" for j in range(max(0,i-window_size),min(i+window_size+1,len(sent))):\n",
" if i!=j:\n",
" res.append([sent[j],x])\n",
" return res\n",
"\n",
"print(to_cbow(['I','like','to','train','networks']))\n",
"print(to_cbow(encode('I like to train networks', vocab)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XVaaDLjaaHVb"
},
"source": [
"चला प्रशिक्षण डेटासेट तयार करूया. आपण सर्व बातम्या पाहू, `to_cbow` कॉल करून शब्द जोड्यांची यादी मिळवू, आणि त्या जोड्या `X` आणि `Y` मध्ये जोडू. वेळेच्या बचतीसाठी, आपण फक्त पहिल्या 10k बातम्या विचारात घेऊ - तुमच्याकडे जास्त वेळ असल्यास आणि चांगले एम्बेडिंग्ज मिळवायचे असल्यास तुम्ही ही मर्यादा सहज काढून टाकू शकता :)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "54b-Gd9TieXo"
},
"outputs": [],
"source": [
"X = []\n",
"Y = []\n",
"for i, x in zip(range(10000), train_dataset):\n",
" for w1, w2 in to_cbow(encode(x[1], vocab), window_size = 5):\n",
" X.append(w1)\n",
" Y.append(w2)\n",
"\n",
"X = torch.tensor(X)\n",
"Y = torch.tensor(Y)"
]
},
{
"cell_type": "markdown",
"source": [
"आम्ही त्या डेटाला एका डेटासेटमध्ये रूपांतरित करू आणि डाटालोडर तयार करू:\n"
],
"metadata": {
"id": "cwWy0PzXWhN5"
}
},
{
"cell_type": "code",
"source": [
"class SimpleIterableDataset(torch.utils.data.IterableDataset):\n",
" def __init__(self, X, Y):\n",
" super(SimpleIterableDataset).__init__()\n",
" self.data = []\n",
" for i in range(len(X)):\n",
" self.data.append( (Y[i], X[i]) )\n",
" random.shuffle(self.data)\n",
"\n",
" def __iter__(self):\n",
" return iter(self.data)"
],
"metadata": {
"id": "mfoAcGPFZU8p"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "e4NQ_-5waHVc"
},
"source": [
"आम्ही त्या डेटाला एक डेटासेटमध्ये रूपांतरित करू आणि डेटालोडर तयार करू:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "AbLUcojlieXo"
},
"outputs": [],
"source": [
"ds = SimpleIterableDataset(X, Y)\n",
"dl = torch.utils.data.DataLoader(ds, batch_size = 256)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pKQr7sXeaHVc"
},
"source": [
"आता आपण प्रत्यक्ष प्रशिक्षण करूया. आपण `SGD` ऑप्टिमायझर उच्च शिक्षण दरासह वापरू. तुम्ही `Adam` सारख्या इतर ऑप्टिमायझरचा वापर करूनही पाहू शकता. सुरुवातीला आपण 10 युगांसाठी प्रशिक्षण घेऊ - आणि जर तुम्हाला आणखी कमी तोटा हवा असेल तर तुम्ही ही सेल पुन्हा चालवू शकता.\n"
]
},
{
"cell_type": "code",
"source": [
"def train_epoch(net, dataloader, lr = 0.01, optimizer = None, loss_fn = torch.nn.CrossEntropyLoss(), epochs = None, report_freq = 1):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(), lr = lr)\n",
" loss_fn = loss_fn.to(device)\n",
" net.train()\n",
"\n",
" for i in range(epochs):\n",
" total_loss, j = 0, 0, \n",
" for labels, features in dataloader:\n",
" optimizer.zero_grad()\n",
" features, labels = features.to(device), labels.to(device)\n",
" out = net(features)\n",
" loss = loss_fn(out, labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss += loss\n",
" j += 1\n",
" if i % report_freq == 0:\n",
" print(f\"Epoch: {i+1}: loss={total_loss.item()/j}\")\n",
"\n",
" return total_loss.item()/j"
],
"metadata": {
"id": "HeeCYKr_KF1w"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"train_epoch(net = model, dataloader = dl, optimizer = torch.optim.SGD(model.parameters(), lr = 0.1), loss_fn = torch.nn.CrossEntropyLoss(), epochs = 10)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "KVgwGtDHgDlT",
"outputId": "2447833f-f0e3-4566-c33d-addbfe2f451d"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Epoch: 1: loss=5.664632366860172\n",
"Epoch: 2: loss=5.632101973960962\n",
"Epoch: 3: loss=5.610399051405015\n",
"Epoch: 4: loss=5.594621561080262\n",
"Epoch: 5: loss=5.582538017415446\n",
"Epoch: 6: loss=5.572900234519603\n",
"Epoch: 7: loss=5.564951676341915\n",
"Epoch: 8: loss=5.558288112064614\n",
"Epoch: 9: loss=5.552576955031129\n",
"Epoch: 10: loss=5.547634165194347\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"5.547634165194347"
]
},
"metadata": {},
"execution_count": 16
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W8u2qXZmaHVd"
},
"source": [
"## Word2Vec वापरण्याचा प्रयत्न\n",
"\n",
"Word2Vec वापरण्यासाठी, आपल्या शब्दसंग्रहातील सर्व शब्दांसाठी संबंधित व्हेक्टर काढूया:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "r8TatcXjkU_t"
},
"outputs": [],
"source": [
"vectors = torch.stack([embedder(torch.tensor(vocab[s])) for s in vocab.itos], 0)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3OcX21UOaHVd"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "bz6tAeLzieXp",
"outputId": "5b20850e-4342-45e9-f840-cfac2b4d61d8"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"tensor([-0.0915, 2.1224, -0.0281, -0.6819, 1.1219, 0.6458, -1.3704, -1.3314,\n",
" -1.1437, 0.4496, 0.2301, -0.3515, -0.8485, 1.0481, 0.4386, -0.8949,\n",
" 0.5644, 1.0939, -2.5096, 3.2949, -0.2601, -0.8640, 0.1421, -0.0804,\n",
" -0.5083, -1.0560, 0.9753, -0.5949, -1.6046, 0.5774],\n",
" grad_fn=<EmbeddingBackward>)\n"
]
}
],
"source": [
"paris_vec = embedder(torch.tensor(vocab['paris']))\n",
"print(paris_vec)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pHTJlaeYaHVd"
},
"source": [
"वर्ड2व्हेकचा उपयोग समानार्थी शब्द शोधण्यासाठी करणे मनोरंजक आहे. खालील फंक्शन दिलेल्या इनपुटसाठी `n` जवळचे शब्द परत करेल. त्यांना शोधण्यासाठी, आपण $|w_i - v|$ चे नॉर्म मोजतो, जिथे $v$ हा आपल्या इनपुट शब्दाशी संबंधित व्हेक्टर आहे, आणि $w_i$ हा शब्दसंग्रहातील `i`-व्या शब्दाचे एन्कोडिंग आहे. त्यानंतर आम्ही अॅरे सॉर्ट करतो आणि `argsort` चा वापर करून संबंधित निर्देशांक परत करतो, आणि यादीतील पहिले `n` घटक घेतो, जे शब्दसंग्रहातील जवळच्या शब्दांच्या स्थानांचे एन्कोडिंग करतात.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "NlZyi-_olFar",
"outputId": "b5dbb163-88c4-4d5a-eaf2-6751f700e98c"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['microsoft', 'quoted', 'lp', 'rate', 'top']"
]
},
"metadata": {},
"execution_count": 56
}
],
"source": [
"def close_words(x, n = 5):\n",
" vec = embedder(torch.tensor(vocab[x]))\n",
" top5 = np.linalg.norm(vectors.detach().numpy() - vec.detach().numpy(), axis = 1).argsort()[:n]\n",
" return [ vocab.itos[x] for x in top5 ]\n",
"\n",
"close_words('microsoft')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "-dQq7xeAln0U",
"outputId": "66f768c3-c248-4bfd-ce4f-c8ffc6d0dd0d"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['basketball', 'lot', 'sinai', 'states', 'healthdaynews']"
]
},
"metadata": {},
"execution_count": 51
}
],
"source": [
"close_words('basketball')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "fJXqK26b29sa",
"outputId": "78f0baba-ffd0-485a-dd87-0a12bedfd7fa"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['funds', 'travel', 'sydney', 'japan', 'business']"
]
},
"metadata": {},
"execution_count": 77
}
],
"source": [
"close_words('funds')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "My0VeTDd3Ji8"
},
"source": [
"## मुख्य मुद्दा\n",
"\n",
"CBoW सारख्या हुशार तंत्रांचा वापर करून आपण Word2Vec मॉडेल प्रशिक्षित करू शकतो. तुम्ही skip-gram मॉडेल देखील प्रशिक्षित करण्याचा प्रयत्न करू शकता, जे मध्यवर्ती शब्द दिल्यास शेजारील शब्दाचा अंदाज लावण्यासाठी प्रशिक्षित केले जाते, आणि ते किती चांगले कार्य करते ते पाहू शकता.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) चा वापर करून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरे त्रुटी किंवा अचूकतेच्या अभावाने युक्त असू शकतात. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "CBoW-PyTorch.ipynb",
"provenance": []
},
"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"
},
"orig_nbformat": 4,
"gpuClass": "standard",
"coopTranslator": {
"original_hash": "36df28efe3fe40b6fb0a7fa48fe3ea82",
"translation_date": "2025-08-28T09:18:17+00:00",
"source_file": "lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 0
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,477 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# पुनरावर्ती न्यूरल नेटवर्क्स\n",
"\n",
"मागील मॉड्यूलमध्ये, आपण मजकूराच्या समृद्ध अर्थपूर्ण प्रतिनिधींचा वापर केला आणि एम्बेडिंग्सवर एक साधा रेषीय वर्गीकरणकर्ता वापरला. या आर्किटेक्चरचे कार्य म्हणजे वाक्यातील शब्दांचा एकत्रित अर्थ पकडणे, परंतु ते शब्दांच्या **क्रम** विचारात घेत नाही, कारण एम्बेडिंग्सवर केलेल्या एकत्रीकरणामुळे मूळ मजकूरातील ही माहिती गमावली जाते. या मॉडेल्सना शब्दांच्या क्रमाची मांडणी करता येत नसल्यामुळे, ते मजकूर निर्मिती किंवा प्रश्नोत्तरासारख्या अधिक जटिल किंवा संदिग्ध कार्ये सोडवू शकत नाहीत.\n",
"\n",
"मजकूर अनुक्रमाचा अर्थ पकडण्यासाठी, आपल्याला एक वेगळ्या प्रकारचा न्यूरल नेटवर्क आर्किटेक्चर वापरावा लागतो, ज्याला **पुनरावर्ती न्यूरल नेटवर्क** किंवा RNN म्हणतात. RNN मध्ये, आपण आपले वाक्य नेटवर्कमधून एकावेळी एक चिन्ह पाठवतो, आणि नेटवर्क काही **स्थिती** तयार करते, जी आपण पुढील चिन्हासह पुन्हा नेटवर्कमध्ये पाठवतो.\n",
"\n",
"दिलेल्या इनपुट अनुक्रमातील टोकन्स $X_0,\\dots,X_n$, RNN एक अनुक्रम तयार करते ज्यामध्ये न्यूरल नेटवर्क ब्लॉक्स असतात, आणि हे अनुक्रम एंड-टू-एंड बॅक प्रोपोगेशन वापरून प्रशिक्षित केले जाते. प्रत्येक नेटवर्क ब्लॉक $(X_i,S_i)$ या जोडीला इनपुट म्हणून घेतो आणि $S_{i+1}$ तयार करतो. अंतिम स्थिती $S_n$ किंवा आउटपुट $X_n$ रेषीय वर्गीकरणकर्त्यामध्ये जाते जेणेकरून निकाल तयार करता येईल. सर्व नेटवर्क ब्लॉक्स समान वजन सामायिक करतात आणि एकाच बॅक प्रोपोगेशन पासद्वारे एंड-टू-एंड प्रशिक्षित केले जातात.\n",
"\n",
"कारण स्थिती वेक्टर $S_0,\\dots,S_n$ नेटवर्कमधून पास केले जातात, त्यामुळे नेटवर्कला शब्दांमधील अनुक्रमिक संबंध शिकता येतात. उदाहरणार्थ, जेव्हा *not* हा शब्द अनुक्रमात कुठेतरी दिसतो, तेव्हा नेटवर्क स्थिती वेक्टरमधील विशिष्ट घटकांना नकारात्मक करण्यासाठी शिकू शकते, ज्यामुळे नकार तयार होतो.\n",
"\n",
"> कारण चित्रातील सर्व RNN ब्लॉक्सचे वजन सामायिक केले जाते, त्यामुळे तेच चित्र एका ब्लॉकसारखे (उजवीकडे) पुनरावर्ती फीडबॅक लूपसह दर्शवले जाऊ शकते, जे नेटवर्कच्या आउटपुट स्थितीला पुन्हा इनपुटमध्ये पाठवते.\n",
"\n",
"चला पाहूया की पुनरावर्ती न्यूरल नेटवर्क्स आमच्या न्यूज डेटासेटचे वर्गीकरण करण्यात कसे मदत करू शकतात.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"from torchnlp import *\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_size = len(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## साधा RNN वर्गीकरणकर्ता\n",
"\n",
"साध्या RNN च्या बाबतीत, प्रत्येक पुनरावृत्ती युनिट एक साधे रेखीय नेटवर्क असते, जे एकत्रित इनपुट व्हेक्टर आणि स्थिती व्हेक्टर घेतो आणि नवीन स्थिती व्हेक्टर तयार करतो. PyTorch या युनिटचे प्रतिनिधित्व `RNNCell` वर्गाने करतो, आणि अशा सेल्सच्या नेटवर्कला `RNN` स्तर म्हणून.\n",
"\n",
"RNN वर्गीकरणकर्ता परिभाषित करण्यासाठी, आपण प्रथम एम्बेडिंग स्तर लागू करू जे इनपुट शब्दसंग्रहाची परिमाण कमी करेल, आणि त्यावर RNN स्तर ठेवू:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class RNNClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.rnn = torch.nn.RNN(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" x,h = self.rnn(x)\n",
" return self.fc(x.mean(dim=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **टीप:** येथे सोपेपणासाठी आम्ही अनट्रेंड एम्बेडिंग लेयर वापरतो, परंतु अधिक चांगल्या परिणामांसाठी आपण Word2Vec किंवा GloVe एम्बेडिंगसह प्री-ट्रेंड एम्बेडिंग लेयर वापरू शकतो, जसे की मागील युनिटमध्ये वर्णन केले आहे. अधिक चांगल्या समजासाठी, तुम्ही हा कोड प्री-ट्रेंड एम्बेडिंगसह काम करण्यासाठी अनुकूलित करू शकता.\n",
"\n",
"आपल्या बाबतीत, आम्ही पॅडेड डेटा लोडर वापरणार आहोत, त्यामुळे प्रत्येक बॅचमध्ये समान लांबीच्या पॅडेड सिक्वेन्सेसचा समावेश असेल. RNN लेयर एम्बेडिंग टेन्सर्सच्या सिक्वेन्सला घेईल आणि दोन आउटपुट तयार करेल:\n",
"* $x$ म्हणजे प्रत्येक स्टेपवर RNN सेल आउटपुट्सची सिक्वेन्स\n",
"* $h$ म्हणजे सिक्वेन्सच्या शेवटच्या घटकासाठी अंतिम हिडन स्टेट\n",
"\n",
"यानंतर आम्ही पूर्णपणे कनेक्टेड लीनियर क्लासिफायर लागू करतो, ज्यामुळे वर्गांची संख्या मिळते.\n",
"\n",
"> **टीप:** RNN ट्रेन करणे खूप कठीण असते, कारण RNN सेल्स सिक्वेन्स लांबीसाठी अनरोल केल्यानंतर, बॅक प्रोपोगेशनमध्ये सहभागी होणाऱ्या लेयर्सची संख्या खूप मोठी असते. त्यामुळे आपल्याला लहान लर्निंग रेट निवडणे आवश्यक आहे आणि चांगले परिणाम मिळवण्यासाठी मोठ्या डेटासेटवर नेटवर्क ट्रेन करणे आवश्यक आहे. यासाठी खूप वेळ लागू शकतो, त्यामुळे GPU वापरणे अधिक चांगले ठरते.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.3090625\n",
"6400: acc=0.38921875\n",
"9600: acc=0.4590625\n",
"12800: acc=0.511953125\n",
"16000: acc=0.5506875\n",
"19200: acc=0.57921875\n",
"22400: acc=0.6070089285714285\n",
"25600: acc=0.6304296875\n",
"28800: acc=0.6484027777777778\n",
"32000: acc=0.66509375\n",
"35200: acc=0.6790056818181818\n",
"38400: acc=0.6929166666666666\n",
"41600: acc=0.7035817307692308\n",
"44800: acc=0.7137276785714286\n",
"48000: acc=0.72225\n",
"51200: acc=0.73001953125\n",
"54400: acc=0.7372794117647059\n",
"57600: acc=0.7436631944444444\n",
"60800: acc=0.7503947368421052\n",
"64000: acc=0.75634375\n",
"67200: acc=0.7615773809523809\n",
"70400: acc=0.7662642045454545\n",
"73600: acc=0.7708423913043478\n",
"76800: acc=0.7751822916666666\n",
"80000: acc=0.7790625\n",
"83200: acc=0.7825\n",
"86400: acc=0.7858564814814815\n",
"89600: acc=0.7890513392857142\n",
"92800: acc=0.7920474137931034\n",
"96000: acc=0.7952708333333334\n",
"99200: acc=0.7982258064516129\n",
"102400: acc=0.80099609375\n",
"105600: acc=0.8037594696969697\n",
"108800: acc=0.8060569852941176\n"
]
}
],
"source": [
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)\n",
"net = RNNClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=0.001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## लाँग शॉर्ट टर्म मेमरी (LSTM)\n",
"\n",
"पारंपरिक RNNs च्या मुख्य समस्यांपैकी एक म्हणजे **vanishing gradients** समस्या. कारण RNNs एकाच बॅक-प्रोपागेशन पासमध्ये एंड-टू-एंड प्रशिक्षित केले जातात, त्यामुळे नेटवर्कच्या पहिल्या स्तरांपर्यंत त्रुटी पोहोचवणे कठीण होते, आणि त्यामुळे नेटवर्क दूरच्या टोकनमधील संबंध शिकू शकत नाही. ही समस्या टाळण्यासाठी एक मार्ग म्हणजे **explicit state management** वापरणे, ज्यासाठी **gates** वापरल्या जातात. या प्रकारच्या दोन सर्वात प्रसिद्ध आर्किटेक्चर आहेत: **लाँग शॉर्ट टर्म मेमरी** (LSTM) आणि **गेटेड रिले युनिट** (GRU).\n",
"\n",
"![लाँग शॉर्ट टर्म मेमरी सेलचे उदाहरण दाखवणारी प्रतिमा](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)\n",
"\n",
"LSTM नेटवर्क RNN प्रमाणेच आयोजित केले जाते, पण येथे दोन स्टेट्स स्तरांमधून पास होतात: वास्तविक स्टेट $c$, आणि हिडन व्हेक्टर $h$. प्रत्येक युनिटवर, हिडन व्हेक्टर $h_i$ इनपुट $x_i$ सोबत जोडला जातो, आणि ते **gates** च्या माध्यमातून स्टेट $c$ वर काय होते ते नियंत्रित करतात. प्रत्येक गेट हे सिग्मॉइड अॅक्टिवेशन असलेल्या न्यूरल नेटवर्कसारखे असते (आउटपुट श्रेणी $[0,1]$ मध्ये), जे स्टेट व्हेक्टरसोबत गुणाकार केल्यावर बिटवाइज मास्कसारखे विचार करता येते. खालील गेट्स असतात (वरच्या चित्रात डावीकडून उजवीकडे):\n",
"* **forget gate** हिडन व्हेक्टर घेतो आणि ठरवतो की स्टेट $c$ च्या कोणत्या घटकांना विसरायचे आहे आणि कोणते पास करायचे आहेत.\n",
"* **input gate** इनपुट आणि हिडन व्हेक्टरमधून काही माहिती घेतो आणि ती स्टेटमध्ये समाविष्ट करतो.\n",
"* **output gate** स्टेटला $\\tanh$ अॅक्टिवेशनसह काही रेषीय स्तराद्वारे रूपांतरित करतो, नंतर हिडन व्हेक्टर $h_i$ वापरून त्याचे काही घटक निवडतो आणि नवीन स्टेट $c_{i+1}$ तयार करतो.\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 सेलची अंतर्गत रचना जटिल दिसत असली तरी, PyTorch ही अंमलबजावणी `LSTMCell` वर्गामध्ये लपवते, आणि संपूर्ण LSTM स्तराचे प्रतिनिधित्व करण्यासाठी `LSTM` ऑब्जेक्ट प्रदान करते. त्यामुळे, LSTM वर्गीकरणकर्ता अंमलबजावणी वर पाहिलेल्या साध्या RNN प्रमाणेच असेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class LSTMClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" x,(h,c) = self.rnn(x)\n",
" return self.fc(h[-1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.259375\n",
"6400: acc=0.25859375\n",
"9600: acc=0.26177083333333334\n",
"12800: acc=0.2784375\n",
"16000: acc=0.313\n",
"19200: acc=0.3528645833333333\n",
"22400: acc=0.3965625\n",
"25600: acc=0.4385546875\n",
"28800: acc=0.4752777777777778\n",
"32000: acc=0.505375\n",
"35200: acc=0.5326704545454546\n",
"38400: acc=0.5557552083333334\n",
"41600: acc=0.5760817307692307\n",
"44800: acc=0.5954910714285714\n",
"48000: acc=0.6118333333333333\n",
"51200: acc=0.62681640625\n",
"54400: acc=0.6404779411764706\n",
"57600: acc=0.6520138888888889\n",
"60800: acc=0.662828947368421\n",
"64000: acc=0.673546875\n",
"67200: acc=0.6831547619047619\n",
"70400: acc=0.6917897727272727\n",
"73600: acc=0.6997146739130434\n",
"76800: acc=0.707109375\n",
"80000: acc=0.714075\n",
"83200: acc=0.7209134615384616\n",
"86400: acc=0.727037037037037\n",
"89600: acc=0.7326674107142858\n",
"92800: acc=0.7379633620689655\n",
"96000: acc=0.7433645833333333\n",
"99200: acc=0.7479032258064516\n",
"102400: acc=0.752119140625\n",
"105600: acc=0.7562405303030303\n",
"108800: acc=0.76015625\n",
"112000: acc=0.7641339285714286\n",
"115200: acc=0.7677777777777778\n",
"118400: acc=0.7711233108108108\n"
]
},
{
"data": {
"text/plain": [
"(0.03487814127604167, 0.7728)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = LSTMClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=0.001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## पॅक केलेल्या अनुक्रम\n",
"\n",
"आपल्या उदाहरणात, आम्हाला मिनीबॅचमधील सर्व अनुक्रम शून्य वेक्टरसह पॅड करावे लागले. यामुळे काही प्रमाणात मेमरी वाया जाते, परंतु RNN मध्ये अधिक महत्त्वाचे म्हणजे पॅड केलेल्या इनपुट आयटमसाठी अतिरिक्त RNN सेल्स तयार होतात, जे प्रशिक्षणात भाग घेतात, परंतु कोणतीही महत्त्वाची इनपुट माहिती वाहून नेत नाहीत. फक्त वास्तविक अनुक्रमाच्या आकारावर RNN प्रशिक्षण देणे अधिक चांगले होईल.\n",
"\n",
"हे करण्यासाठी, PyTorch मध्ये पॅड केलेल्या अनुक्रम संचयासाठी एक विशेष स्वरूप सादर केले जाते. समजा आपल्याकडे इनपुट पॅड केलेला मिनीबॅच आहे जो असे दिसतो:\n",
"```\n",
"[[1,2,3,4,5],\n",
" [6,7,8,0,0],\n",
" [9,0,0,0,0]]\n",
"```\n",
"येथे 0 पॅड केलेल्या मूल्यांचे प्रतिनिधित्व करतो, आणि इनपुट अनुक्रमांची वास्तविक लांबी व्हेक्टर `[5,3,1]` आहे.\n",
"\n",
"पॅड केलेल्या अनुक्रमासह RNN प्रभावीपणे प्रशिक्षण देण्यासाठी, आम्हाला RNN सेल्सच्या पहिल्या गटाचे मोठ्या मिनीबॅचसह (`[1,6,9]`) प्रशिक्षण सुरू करायचे आहे, परंतु नंतर तिसऱ्या अनुक्रमाची प्रक्रिया समाप्त करायची आहे आणि छोट्या मिनीबॅचसह (`[2,7]`, `[3,8]`) प्रशिक्षण सुरू ठेवायचे आहे, आणि असेच पुढे. त्यामुळे, पॅक केलेला अनुक्रम एका व्हेक्टरमध्ये दर्शविला जातो - आपल्या बाबतीत `[1,6,9,2,7,3,8,4,5]`, आणि लांबी व्हेक्टर (`[5,3,1]`), ज्यामुळे आपण मूळ पॅड केलेला मिनीबॅच सहजपणे पुन्हा तयार करू शकतो.\n",
"\n",
"पॅक केलेला अनुक्रम तयार करण्यासाठी, आपण `torch.nn.utils.rnn.pack_padded_sequence` फंक्शन वापरू शकतो. सर्व पुनरावृत्ती करणाऱ्या स्तरांमध्ये, RNN, LSTM आणि GRU यांचा समावेश आहे, पॅक केलेले अनुक्रम इनपुट म्हणून स्वीकारले जातात आणि पॅक केलेले आउटपुट तयार करतात, जे `torch.nn.utils.rnn.pad_packed_sequence` वापरून डिकोड केले जाऊ शकते.\n",
"\n",
"पॅक केलेला अनुक्रम तयार करण्यासाठी, आपल्याला नेटवर्कला लांबी व्हेक्टर पास करावा लागतो, आणि त्यामुळे मिनीबॅच तयार करण्यासाठी वेगळ्या फंक्शनची आवश्यकता आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def pad_length(b):\n",
" # build vectorized sequence\n",
" v = [encode(x[1]) for x in b]\n",
" # compute max length of a sequence in this minibatch and length sequence itself\n",
" len_seq = list(map(len,v))\n",
" l = max(len_seq)\n",
" return ( # tuple of three tensors - labels, padded features, length sequence\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v]),\n",
" torch.tensor(len_seq)\n",
" )\n",
"\n",
"train_loader_len = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=pad_length, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"खरं नेटवर्क वरील `LSTMClassifier` सारखंच असेल, पण `forward` पासमध्ये पॅड केलेला मिनीबॅच आणि सिक्वेन्स लांबींचा व्हेक्टर मिळेल. एम्बेडिंगची गणना केल्यानंतर, आम्ही पॅक केलेला सिक्वेन्स तयार करतो, तो LSTM लेयरला पास करतो, आणि मग परिणाम पुन्हा अनपॅक करतो.\n",
"\n",
"> **Note**: आम्ही प्रत्यक्षात अनपॅक केलेला परिणाम `x` वापरत नाही, कारण पुढील गणनांमध्ये आम्ही हिडन लेयरमधून मिळालेला आउटपुट वापरतो. त्यामुळे, आम्ही या कोडमधून अनपॅकिंग पूर्णपणे काढून टाकू शकतो. आम्ही ते इथे ठेवण्याचं कारण म्हणजे तुम्हाला हा कोड सहजपणे बदलता यावा, जर तुम्हाला नेटवर्क आउटपुट पुढील गणनांमध्ये वापरायचा असेल.\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class LSTMPackClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x, lengths):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" pad_x = torch.nn.utils.rnn.pack_padded_sequence(x,lengths,batch_first=True,enforce_sorted=False)\n",
" pad_x,(h,c) = self.rnn(pad_x)\n",
" x, _ = torch.nn.utils.rnn.pad_packed_sequence(pad_x,batch_first=True)\n",
" return self.fc(h[-1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.285625\n",
"6400: acc=0.33359375\n",
"9600: acc=0.3876041666666667\n",
"12800: acc=0.44078125\n",
"16000: acc=0.4825\n",
"19200: acc=0.5235416666666667\n",
"22400: acc=0.5559821428571429\n",
"25600: acc=0.58609375\n",
"28800: acc=0.6116666666666667\n",
"32000: acc=0.63340625\n",
"35200: acc=0.6525284090909091\n",
"38400: acc=0.668515625\n",
"41600: acc=0.6822596153846154\n",
"44800: acc=0.6948214285714286\n",
"48000: acc=0.7052708333333333\n",
"51200: acc=0.71521484375\n",
"54400: acc=0.7239889705882353\n",
"57600: acc=0.7315277777777778\n",
"60800: acc=0.7388486842105263\n",
"64000: acc=0.74571875\n",
"67200: acc=0.7518303571428572\n",
"70400: acc=0.7576988636363636\n",
"73600: acc=0.7628940217391305\n",
"76800: acc=0.7681510416666667\n",
"80000: acc=0.7728125\n",
"83200: acc=0.7772235576923077\n",
"86400: acc=0.7815393518518519\n",
"89600: acc=0.7857700892857142\n",
"92800: acc=0.7895043103448276\n",
"96000: acc=0.7930520833333333\n",
"99200: acc=0.7959072580645161\n",
"102400: acc=0.798994140625\n",
"105600: acc=0.802064393939394\n",
"108800: acc=0.8051378676470589\n",
"112000: acc=0.8077857142857143\n",
"115200: acc=0.8104600694444445\n",
"118400: acc=0.8128293918918919\n"
]
},
{
"data": {
"text/plain": [
"(0.029785829671223958, 0.8138166666666666)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = LSTMPackClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch_emb(net,train_loader_len, lr=0.001,use_pack_sequence=True)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## द्विदिशात्मक आणि बहुपरत RNNs\n",
"\n",
"आपल्या उदाहरणांमध्ये, सर्व पुनरावृत्ती नेटवर्क्स एका दिशेने कार्य करत होती, म्हणजे अनुक्रमाच्या सुरुवातीपासून शेवटापर्यंत. हे नैसर्गिक वाटते, कारण हे आपण वाचतो किंवा भाषण ऐकतो त्या पद्धतीसारखे आहे. परंतु, अनेक व्यावहारिक परिस्थितींमध्ये आपल्याला इनपुट अनुक्रमावर यादृच्छिक प्रवेश असतो, त्यामुळे पुनरावृत्ती गणना दोन्ही दिशांनी चालवणे उपयुक्त ठरू शकते. अशा नेटवर्क्सला **द्विदिशात्मक** RNNs म्हणतात, आणि RNN/LSTM/GRU कन्स्ट्रक्टरला `bidirectional=True` पॅरामीटर पास करून ती तयार करता येतात.\n",
"\n",
"द्विदिशात्मक नेटवर्क हाताळताना, आपल्याला दोन हिडन स्टेट व्हेक्टरची आवश्यकता असते, प्रत्येक दिशेसाठी एक. PyTorch हे व्हेक्टर एका मोठ्या आकाराच्या व्हेक्टरमध्ये एन्कोड करते, जे खूप सोयीचे आहे, कारण सामान्यतः आपण परिणामी हिडन स्टेट पूर्णपणे कनेक्टेड लीनियर लेयरला पास करतो, आणि लेयर तयार करताना फक्त या आकारवाढीचा विचार करावा लागतो.\n",
"\n",
"पुनरावृत्ती नेटवर्क, एकदिशात्मक किंवा द्विदिशात्मक, अनुक्रमातील विशिष्ट नमुने कॅप्चर करते आणि त्यांना स्टेट व्हेक्टरमध्ये साठवते किंवा आउटपुटमध्ये पास करते. जसे कॉनव्होल्यूशनल नेटवर्क्समध्ये होते, तसेच आपण पहिल्या लेयरने काढलेल्या कमी-स्तरीय नमुन्यांवर आधारित उच्च-स्तरीय नमुने कॅप्चर करण्यासाठी पहिल्या लेयरच्या वर आणखी एक पुनरावृत्ती लेयर तयार करू शकतो. यामुळे **बहुपरत RNN** ची संकल्पना तयार होते, ज्यामध्ये दोन किंवा अधिक पुनरावृत्ती नेटवर्क्स असतात, जिथे मागील लेयरचा आउटपुट पुढील लेयरला इनपुट म्हणून दिला जातो.\n",
"\n",
"![मल्टीलेयर लाँग-शॉर्ट-टर्म-मेमरी RNN दर्शवणारी प्रतिमा](../../../../../translated_images/multi-layer-lstm.dd975e29bb2a59fe58b429db833932d734c81f211cad2783797a9608984acb8c.mr.jpg)\n",
"\n",
"*फर्नांडो लोपेझ यांच्या [या अप्रतिम पोस्टमधून](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) घेतलेली प्रतिमा*\n",
"\n",
"PyTorch अशा नेटवर्क्स तयार करणे सोपे बनवते, कारण आपल्याला फक्त RNN/LSTM/GRU कन्स्ट्रक्टरला `num_layers` पॅरामीटर पास करायचा असतो, ज्यामुळे पुनरावृत्तीच्या अनेक स्तर आपोआप तयार होतात. याचा अर्थ हिडन/स्टेट व्हेक्टरचा आकार प्रमाणानुसार वाढेल, आणि पुनरावृत्ती लेयरच्या आउटपुट हाताळताना याचा विचार करावा लागेल.\n"
]
},
{
"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": {
"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": "522ee52ae3d5ae933e283286254e9a55",
"translation_date": "2025-08-28T09:37:56+00:00",
"source_file": "lessons/5-NLP/16-RNN/RNNPyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,460 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# पुनरावृत्ती तंत्रिका नेटवर्क\n",
"\n",
"मागील विभागात, आपण मजकूराच्या समृद्ध अर्थपूर्ण प्रतिनिधित्वांबद्दल चर्चा केली. आपण वापरत असलेली आर्किटेक्चर वाक्यातील शब्दांचा एकत्रित अर्थ पकडते, परंतु ती शब्दांच्या **क्रम** विचारात घेत नाही, कारण एम्बेडिंगनंतर होणारी एकत्रीकरण प्रक्रिया मूळ मजकूरातील ही माहिती काढून टाकते. या मॉडेल्सना शब्द क्रमवारीचे प्रतिनिधित्व करता येत नसल्यामुळे, ते मजकूर निर्मिती किंवा प्रश्नोत्तर यांसारख्या अधिक जटिल किंवा संदिग्ध कार्ये सोडवू शकत नाहीत.\n",
"\n",
"मजकूर अनुक्रमाचा अर्थ पकडण्यासाठी, आपण **पुनरावृत्ती तंत्रिका नेटवर्क** किंवा RNN नावाची तंत्रिका नेटवर्क आर्किटेक्चर वापरणार आहोत. RNN वापरताना, आपण आपले वाक्य नेटवर्कमधून एकावेळी एक टोकन पास करतो, आणि नेटवर्क काही **स्थिती** तयार करते, जी आपण पुढील टोकनसह पुन्हा नेटवर्कमध्ये पास करतो.\n",
"\n",
"![पुनरावृत्ती तंत्रिका नेटवर्क निर्मितीचे उदाहरण दर्शवणारी प्रतिमा.](../../../../../translated_images/rnn.27f5c29c53d727b546ad3961637a267f0fe9ec5ab01f2a26a853c92fcefbb574.mr.png)\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**: संपूर्ण डेटासेटवर एक epoch पूर्ण करण्यासाठी हे प्रशिक्षण सुमारे 5 मिनिटे लागतील. जर तुमचा संयम संपला असेल तर तुम्ही कोणत्याही वेळी प्रशिक्षण थांबवू शकता. तुम्ही प्रशिक्षणासाठी वापरल्या जाणाऱ्या डेटाची मात्रा मर्यादित करू शकता, `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",
"> **टीप**: तुम्ही लक्षात घेतले आहे का की आपण बातम्यांच्या शीर्षकांवर प्रशिक्षित केलेला व्हेक्टरायझर वापरत आहोत, आणि लेखाच्या संपूर्ण मजकुरावर नाही? संभाव्यतः, यामुळे काही टोकन्स दुर्लक्षित होऊ शकतात, त्यामुळे व्हेक्टरायझर पुन्हा प्रशिक्षण देणे चांगले आहे. मात्र, याचा परिणाम फारच कमी होऊ शकतो, त्यामुळे साधेपणासाठी आपण पूर्व-प्रशिक्षित व्हेक्टरायझरच वापरणार आहोत.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LSTM: लाँग शॉर्ट-टर्म मेमरी\n",
"\n",
"RNNs च्या मुख्य समस्यांपैकी एक म्हणजे **vanishing gradients**. RNNs खूप लांब असू शकतात आणि बॅकप्रोपोगेशन दरम्यान नेटवर्कच्या पहिल्या लेयरपर्यंत ग्रेडियंट्स पोहोचवणे कठीण होऊ शकते. जेव्हा असे होते, तेव्हा नेटवर्क दूरच्या टोकनमधील संबंध शिकू शकत नाही. ही समस्या टाळण्यासाठी **explicit state management** वापरणे एक उपाय आहे, ज्यामध्ये **gates** चा वापर केला जातो. **लाँग शॉर्ट-टर्म मेमरी** (LSTM) आणि **gated relay unit** (GRU) या दोन सर्वात सामान्य आर्किटेक्चर आहेत ज्यामध्ये gates असतात. येथे आपण LSTMs बद्दल चर्चा करू.\n",
"\n",
"![लाँग शॉर्ट-टर्म मेमरी सेलचे उदाहरण दाखवणारी प्रतिमा](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)\n",
"\n",
"LSTM नेटवर्क RNN प्रमाणेच आयोजित केले जाते, परंतु दोन states लेयरपासून लेयरपर्यंत पास होतात: actual state $c$, आणि hidden vector $h$. प्रत्येक युनिटवर, hidden vector $h_{t-1}$ input $x_t$ सोबत एकत्रित केला जातो, आणि एकत्रितपणे ते state $c_t$ आणि output $h_{t}$ वर **gates** च्या माध्यमातून नियंत्रण ठेवतात. प्रत्येक gate ला sigmoid activation असते (output $[0,1]$ च्या रेंजमध्ये), ज्याला state vector सोबत गुणाकार केल्यावर bitwise mask म्हणून विचार करता येतो. LSTMs मध्ये खालील gates असतात (वर दिलेल्या चित्रात डावीकडून उजवीकडे):\n",
"* **forget gate** जो ठरवतो की vector $c_{t-1}$ च्या कोणत्या घटकांना विसरायचे आहे आणि कोणते पास करायचे आहेत.\n",
"* **input gate** जो ठरवतो की input vector आणि previous hidden vector मधील किती माहिती state vector मध्ये समाविष्ट करायची आहे.\n",
"* **output gate** जो नवीन state vector घेतो आणि त्याच्या कोणत्या घटकांचा उपयोग नवीन hidden vector $h_t$ तयार करण्यासाठी करायचा आहे हे ठरवतो.\n",
"\n",
"State $c$ चे घटक flags म्हणून विचार करता येऊ शकतात जे ऑन आणि ऑफ केले जाऊ शकतात. उदाहरणार्थ, जेव्हा आपण sequence मध्ये *Alice* हे नाव पाहतो, तेव्हा आपण अंदाज लावतो की ते एका स्त्रीला संदर्भित करते, आणि state मध्ये एक flag उचलतो जो सांगतो की वाक्यात एक स्त्रीलिंगी नाम आहे. जेव्हा आपण पुढे *and Tom* शब्द पाहतो, तेव्हा आपण एक flag उचलतो जो सांगतो की वाक्यात एक बहुवचन नाम आहे. अशा प्रकारे state manipulate करून आपण वाक्याच्या व्याकरणात्मक गुणधर्मांचा मागोवा ठेवू शकतो.\n",
"\n",
"> **Note**: LSTMs च्या अंतर्गत रचना समजून घेण्यासाठी येथे एक उत्कृष्ट स्रोत आहे: [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) क्रिस्टोफर ओलाह यांनी लिहिलेले.\n",
"\n",
"LSTM सेलची अंतर्गत रचना जरी क्लिष्ट दिसत असली तरी Keras ही अंमलबजावणी `LSTM` लेयरमध्ये लपवते, त्यामुळे वर दिलेल्या उदाहरणात आपल्याला फक्त recurrent लेयर बदलणे आवश्यक आहे:\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",
"![मल्टीलेयर लाँग-शॉर्ट-टर्म-मेमरी RNN दर्शवणारी प्रतिमा](../../../../../translated_images/multi-layer-lstm.dd975e29bb2a59fe58b429db833932d734c81f211cad2783797a9608984acb8c.mr.jpg)\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:33:46+00:00",
"source_file": "lessons/5-NLP/16-RNN/RNNTF.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,414 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# जनरेटिव नेटवर्क्स\n",
"\n",
"पुनरावृत्तीशील न्यूरल नेटवर्क्स (RNNs) आणि त्यांचे गेटेड सेल प्रकार जसे की लाँग शॉर्ट टर्म मेमरी सेल्स (LSTMs) आणि गेटेड पुनरावृत्तीशील युनिट्स (GRUs) यांनी भाषा मॉडेलिंगसाठी एक यंत्रणा प्रदान केली आहे, म्हणजेच ते शब्दांची क्रमवारी शिकू शकतात आणि अनुक्रमातील पुढील शब्दासाठी अंदाज देऊ शकतात. यामुळे आपल्याला RNNs **जनरेटिव कार्यांसाठी** वापरण्याची परवानगी मिळते, जसे की सामान्य मजकूर निर्मिती, मशीन अनुवाद, आणि अगदी प्रतिमेचे वर्णन तयार करणे.\n",
"\n",
"आम्ही मागील युनिटमध्ये चर्चा केलेल्या RNN आर्किटेक्चरमध्ये, प्रत्येक RNN युनिटने पुढील लपवलेले स्थिती आउटपुट म्हणून तयार केले. तथापि, आपण प्रत्येक पुनरावृत्तीशील युनिटला आणखी एक आउटपुट जोडू शकतो, ज्यामुळे आपल्याला **अनुक्रम** आउटपुट करता येईल (जो मूळ अनुक्रमाच्या लांबीइतकाच असेल). याशिवाय, आपण असे RNN युनिट्स वापरू शकतो जे प्रत्येक टप्प्यावर इनपुट स्वीकारत नाहीत, आणि फक्त काही प्रारंभिक स्थिती वेक्टर घेतात, आणि नंतर आउटपुट्सचा अनुक्रम तयार करतात.\n",
"\n",
"या नोटबुकमध्ये, आपण मजकूर तयार करण्यात मदत करणाऱ्या साध्या जनरेटिव मॉडेल्सवर लक्ष केंद्रित करू. सोपेपणासाठी, चला **कॅरेक्टर-लेव्हल नेटवर्क** तयार करू, जे अक्षरानुसार मजकूर तयार करते. प्रशिक्षणादरम्यान, आपल्याला काही मजकूर संग्रह घ्यावा लागेल आणि त्याला अक्षरांच्या अनुक्रमांमध्ये विभागावे लागेल.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"import numpy as np\n",
"from torchnlp import *\n",
"train_dataset,test_dataset,classes,vocab = load_dataset()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## अक्षर शब्दसंग्रह तयार करणे\n",
"\n",
"अक्षर-स्तरीय जनरेटिव्ह नेटवर्क तयार करण्यासाठी, आपल्याला मजकूर शब्दांऐवजी स्वतंत्र अक्षरांमध्ये विभागावा लागेल. हे वेगळ्या टोकनायझरची व्याख्या करून केले जाऊ शकते:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocabulary size = 82\n",
"Encoding of 'a' is 1\n",
"Character with code 13 is c\n"
]
}
],
"source": [
"def char_tokenizer(words):\n",
" return list(words) #[word for word in words]\n",
"\n",
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" counter.update(char_tokenizer(line))\n",
"vocab = torchtext.vocab.vocab(counter)\n",
"\n",
"vocab_size = len(vocab)\n",
"print(f\"Vocabulary size = {vocab_size}\")\n",
"print(f\"Encoding of 'a' is {vocab.get_stoi()['a']}\")\n",
"print(f\"Character with code 13 is {vocab.get_itos()[13]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला पाहूया की आपण आपल्या डेटासेटमधील मजकूर कसा एन्कोड करू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([ 0, 1, 2, 2, 3, 4, 5, 6, 3, 7, 8, 1, 9, 10, 3, 11, 2, 1,\n",
" 12, 3, 7, 1, 13, 14, 3, 15, 16, 5, 17, 3, 5, 18, 8, 3, 7, 2,\n",
" 1, 13, 14, 3, 19, 20, 8, 21, 5, 8, 9, 10, 22, 3, 20, 8, 21, 5,\n",
" 8, 9, 10, 3, 23, 3, 4, 18, 17, 9, 5, 23, 10, 8, 2, 2, 8, 9,\n",
" 10, 24, 3, 0, 1, 2, 2, 3, 4, 5, 9, 8, 8, 5, 25, 10, 3, 26,\n",
" 12, 27, 16, 26, 2, 27, 16, 28, 29, 30, 1, 16, 26, 3, 17, 31, 3, 21,\n",
" 2, 5, 9, 1, 23, 13, 32, 16, 27, 13, 10, 24, 3, 1, 9, 8, 3, 10,\n",
" 8, 8, 27, 16, 28, 3, 28, 9, 8, 8, 16, 3, 1, 28, 1, 27, 16, 6])"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def enc(x):\n",
" return torch.LongTensor(encode(x,voc=vocab,tokenizer=char_tokenizer))\n",
"\n",
"enc(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## जनरेटिव RNN प्रशिक्षण\n",
"\n",
"RNNला मजकूर तयार करण्यासाठी प्रशिक्षण देण्याची पद्धत पुढीलप्रमाणे आहे. प्रत्येक चरणावर, आम्ही `nchars` लांबीचा अक्षरांचा क्रम घेऊ आणि नेटवर्कला प्रत्येक इनपुट अक्षरासाठी पुढील आउटपुट अक्षर तयार करण्यास सांगू:\n",
"\n",
"!['HELLO' शब्द तयार करणाऱ्या RNNचे उदाहरण दाखवणारी प्रतिमा.](../../../../../translated_images/rnn-generate.56c54afb52f9781d63a7c16ea9c1b86cb70e6e1eae6a742b56b7b37468576b17.mr.png)\n",
"\n",
"खऱ्या परिस्थितीनुसार, आपल्याला काही विशेष अक्षरे समाविष्ट करायची असू शकतात, जसे की *end-of-sequence* `<eos>`. आपल्या बाबतीत, आम्हाला फक्त अखंड मजकूर तयार करण्यासाठी नेटवर्कला प्रशिक्षण द्यायचे आहे, त्यामुळे आम्ही प्रत्येक क्रमाची लांबी `nchars` टोकन इतकी निश्चित करू. परिणामी, प्रत्येक प्रशिक्षण उदाहरणामध्ये `nchars` इनपुट्स आणि `nchars` आउटपुट्स (जे इनपुट क्रम एका चिन्हाने डावीकडे सरकवलेले असतील) असतील. मिनीबॅचमध्ये अशा अनेक क्रमांचा समावेश असेल.\n",
"\n",
"मिनीबॅच तयार करण्याची पद्धत अशी असेल की प्रत्येक `l` लांबीच्या बातमी मजकुरातून सर्व संभाव्य इनपुट-आउटपुट संयोजन तयार केले जातील (अशा `l-nchars` संयोजन असतील). हे एक मिनीबॅच तयार करतील, आणि प्रत्येक प्रशिक्षण चरणावर मिनीबॅचचा आकार वेगळा असेल.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(tensor([[ 0, 1, 2, ..., 28, 29, 30],\n",
" [ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" ...,\n",
" [20, 8, 21, ..., 1, 28, 1],\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16]]),\n",
" tensor([[ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" [ 2, 3, 4, ..., 1, 16, 26],\n",
" ...,\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16],\n",
" [ 5, 8, 9, ..., 27, 16, 6]]))"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nchars = 100\n",
"\n",
"def get_batch(s,nchars=nchars):\n",
" ins = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" outs = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" for i in range(len(s)-nchars):\n",
" ins[i] = enc(s[i:i+nchars])\n",
" outs[i] = enc(s[i+1:i+nchars+1])\n",
" return ins,outs\n",
"\n",
"get_batch(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण जनरेटर नेटवर्कची व्याख्या करूया. हे कोणत्याही पुनरावृत्ती सेलवर आधारित असू शकते, जे आपण मागील युनिटमध्ये चर्चा केली होती (साधे, LSTM किंवा GRU). आपल्या उदाहरणात आपण LSTM वापरणार आहोत.\n",
"\n",
"कारण नेटवर्क अक्षरे इनपुट म्हणून घेतं, आणि शब्दसंग्रहाचा आकार खूप लहान आहे, त्यामुळे आपल्याला एम्बेडिंग लेयरची गरज नाही, वन-हॉट-एनकोडेड इनपुट थेट LSTM सेलला जाऊ शकतो. मात्र, कारण आपण अक्षरांचे क्रमांक इनपुट म्हणून देतो, त्यामुळे LSTM ला पास करण्यापूर्वी त्यांना वन-हॉट-एनकोड करणे आवश्यक आहे. हे `forward` पास दरम्यान `one_hot` फंक्शन कॉल करून केले जाते. आउटपुट एनकोडर एक रेषीय लेयर असेल, जो लपलेल्या स्थितीला वन-हॉट-एनकोडेड आउटपुटमध्ये रूपांतरित करेल.\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class LSTMGenerator(torch.nn.Module):\n",
" def __init__(self, vocab_size, hidden_dim):\n",
" super().__init__()\n",
" self.rnn = torch.nn.LSTM(vocab_size,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, vocab_size)\n",
"\n",
" def forward(self, x, s=None):\n",
" x = torch.nn.functional.one_hot(x,vocab_size).to(torch.float32)\n",
" x,s = self.rnn(x,s)\n",
" return self.fc(x),s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"प्रशिक्षणादरम्यान, आम्हाला तयार केलेला मजकूर नमुना स्वरूपात मिळवायचा आहे. यासाठी, आपण `generate` नावाची एक फंक्शन परिभाषित करू, जी सुरुवातीच्या स्ट्रिंग `start` पासून सुरू होऊन, लांबी `size` असलेला आउटपुट स्ट्रिंग तयार करेल.\n",
"\n",
"हे कार्य पुढीलप्रमाणे चालते. प्रथम, आपण संपूर्ण `start` स्ट्रिंग नेटवर्कमधून पास करू, आणि आउटपुट स्थिती `s` आणि पुढील अंदाजित अक्षर `out` प्राप्त करू. कारण `out` हे एक-हॉट एन्कोडेड असते, त्यामुळे आम्ही `argmax` वापरून शब्दसंग्रहातील अक्षर `nc` चा अनुक्रमांक मिळवतो, आणि `itos` वापरून प्रत्यक्ष अक्षर शोधतो व ते `chars` नावाच्या अक्षरांच्या यादीत जोडतो. आवश्यक अक्षरांची संख्या तयार करण्यासाठी, हे एक अक्षर तयार करण्याचे कार्य `size` वेळा पुनरावृत्त केले जाते.\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def generate(net,size=100,start='today '):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" nc = torch.argmax(out[0][-1])\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता प्रशिक्षण सुरू करूया! प्रशिक्षण लूप आपल्या मागील उदाहरणांप्रमाणेच आहे, परंतु अचूकतेऐवजी आम्ही प्रत्येक 1000 epochs नंतर नमुना तयार केलेला मजकूर प्रिंट करतो.\n",
"\n",
"गमावलेला डेटा कसा मोजायचा याकडे विशेष लक्ष देणे आवश्यक आहे. आपल्याला एक-हॉट-एनकोडेड आउटपुट `out` आणि अपेक्षित मजकूर `text_out` दिला जातो, जो कॅरेक्टर इंडेक्सची यादी आहे, त्यावर आधारित गमावलेला डेटा मोजावा लागतो. सुदैवाने, `cross_entropy` फंक्शनला पहिला आर्ग्युमेंट म्हणून अननॉर्मलाइज्ड नेटवर्क आउटपुट आणि दुसरा आर्ग्युमेंट म्हणून वर्ग क्रमांक अपेक्षित असतो, जे आपल्याकडे आहे. हे मिनीबॅच आकारावर स्वयंचलित सरासरी देखील करते.\n",
"\n",
"आम्ही `samples_to_train` नमुन्यांद्वारे प्रशिक्षण मर्यादित करतो, जेणेकरून जास्त वेळ लागणार नाही. आम्ही तुम्हाला प्रयोग करण्यासाठी प्रोत्साहित करतो आणि दीर्घ प्रशिक्षणाचा प्रयत्न करा, कदाचित अनेक epochs साठी (अशा परिस्थितीत तुम्हाला या कोडभोवती आणखी एक लूप तयार करावा लागेल).\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Current loss = 4.398899078369141\n",
"today sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr s\n",
"Current loss = 2.161320447921753\n",
"today and to the tor to to the tor to to the tor to to the tor to to the tor to to the tor to to the tor t\n",
"Current loss = 1.6722588539123535\n",
"today and the court to the could to the could to the could to the could to the could to the could to the c\n",
"Current loss = 2.423795223236084\n",
"today and a second to the conternation of the conternation of the conternation of the conternation of the \n",
"Current loss = 1.702607274055481\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.692358136177063\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.9722288846969604\n",
"today and the control the control the control the control the control the control the control the control \n",
"Current loss = 1.8705692291259766\n",
"today and the second to the second to the second to the second to the second to the second to the second t\n",
"Current loss = 1.7626899480819702\n",
"today and a security and a security and a security and a security and a security and a security and a secu\n",
"Current loss = 1.5574463605880737\n",
"today and the company and the company and the company and the company and the company and the company and \n",
"Current loss = 1.5620026588439941\n",
"today and the be that the be the be that the be the be that the be the be that the be the be that the be t\n"
]
}
],
"source": [
"net = LSTMGenerator(vocab_size,64).to(device)\n",
"\n",
"samples_to_train = 10000\n",
"optimizer = torch.optim.Adam(net.parameters(),0.01)\n",
"loss_fn = torch.nn.CrossEntropyLoss()\n",
"net.train()\n",
"for i,x in enumerate(train_dataset):\n",
" # x[0] is class label, x[1] is text\n",
" if len(x[1])-nchars<10:\n",
" continue\n",
" samples_to_train-=1\n",
" if not samples_to_train: break\n",
" text_in, text_out = get_batch(x[1])\n",
" optimizer.zero_grad()\n",
" out,s = net(text_in)\n",
" loss = torch.nn.functional.cross_entropy(out.view(-1,vocab_size),text_out.flatten()) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" if i%1000==0:\n",
" print(f\"Current loss = {loss.item()}\")\n",
" print(generate(net))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हे उदाहरण आधीच चांगला मजकूर तयार करते, परंतु यामध्ये काही पद्धतींनी आणखी सुधारणा करता येऊ शकते:\n",
"\n",
"* **बेहतर मिनीबॅच जनरेशन**. प्रशिक्षणासाठी डेटा तयार करताना, आम्ही एका नमुन्यातून एक मिनीबॅच तयार केला. हे आदर्श नाही, कारण मिनीबॅचेस वेगवेगळ्या आकाराचे असतात, आणि काही वेळा ते तयारही होऊ शकत नाहीत, कारण मजकूर `nchars` पेक्षा लहान असतो. तसेच, लहान मिनीबॅचेस GPU पुरेशा प्रमाणात लोड करत नाहीत. सर्व नमुन्यांमधून एक मोठा मजकूर तुकडा घेणे, नंतर सर्व इनपुट-आउटपुट जोड तयार करणे, त्यांना शफल करणे, आणि समान आकाराचे मिनीबॅचेस तयार करणे अधिक शहाणपणाचे ठरेल.\n",
"\n",
"* **मल्टीलायर LSTM**. LSTM सेल्सच्या 2 किंवा 3 स्तरांचा प्रयत्न करणे उपयुक्त ठरू शकते. जसे आपण मागील युनिटमध्ये नमूद केले, LSTM चा प्रत्येक स्तर मजकूरातून विशिष्ट पॅटर्न काढतो, आणि कॅरेक्टर-लेव्हल जनरेटरच्या बाबतीत आपण अपेक्षा करू शकतो की LSTM चा खालचा स्तर अक्षरसमूह (syllables) काढण्यास जबाबदार असेल, तर उच्च स्तर शब्द आणि शब्दसमूह काढतील. हे LSTM कन्स्ट्रक्टरला नंबर-ऑफ-लेयर्स पॅरामीटर पास करून सोप्या पद्धतीने अंमलात आणता येते.\n",
"\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",
"हे नमुना निवडणे `multinomial` फंक्शन वापरून करता येते, जे तथाकथित **multinomial distribution** लागू करते. खाली दिलेली फंक्शन ही **मऊ** मजकूर निर्मिती लागू करते:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Temperature = 0.3\n",
"Today and a company and complete an all the land the restrational the as a security and has provers the pay to and a report and the computer in the stand has filities and working the law the stations for a company and with the company and the final the first company and refight of the state and and workin\n",
"\n",
"--- Temperature = 0.8\n",
"Today he oniis its first to Aus bomblaties the marmation a to manan boogot that pirate assaid a relaid their that goverfin the the Cappets Ecrotional Assonia Cition targets it annight the w scyments Blamity #39;s TVeer Diercheg Reserals fran envyuil that of ster said access what succers of Dour-provelith\n",
"\n",
"--- Temperature = 1.0\n",
"Today holy they a 11 will meda a toket subsuaties, engins for Chanos, they's has stainger past to opening orital his thempting new Nattona was al innerforder advan-than #36;s night year his religuled talitatian what the but with Wednesday to Justment will wemen of Mark CCC Camp as Timed Nae wome a leaders\n",
"\n",
"--- Temperature = 1.3\n",
"Today gpone 2.5 fech atcusion poor cocles toparsdorM.cht Line Pamage put 43 his calt lowed to the book, that has authh-the silia rruch ailing to'ory andhes beutirsimi- Aefffive heading offil an auf eacklets is charged evis, Gunymy oy) Mony has it after-sloythyor loveId out filme, the Natabl -Najuntaxiggs \n",
"\n",
"--- Temperature = 1.8\n",
"Today plary, P.slan chly\\401 mardregationly #39;t 8.1Mide) closes ,filtcon alfly playin roven!\\grea.-QFBEP: Iss onfarchQ/itilia CCf Zivesigntwasta orce.-Peul-aw.uicrin of fuglinfsut aftaningwo, MIEX awayew Aice Woiduar Corvagiugge oppo esig ThusBratourid canthly-RyI.co lagitems\\eexciaishes.conBabntusmor I\n",
"\n"
]
}
],
"source": [
"def generate_soft(net,size=100,start='today ',temperature=1.0):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" #nc = torch.argmax(out[0][-1])\n",
" out_dist = out[0][-1].div(temperature).exp()\n",
" nc = torch.multinomial(out_dist,1)[0]\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)\n",
" \n",
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
" print(f\"--- Temperature = {i}\\n{generate_soft(net,size=300,start='Today ',temperature=i)}\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही **temperature** नावाचा आणखी एक पॅरामीटर सादर केला आहे, जो आपण उच्चतम संभाव्यतेला किती कठोरपणे अनुसरावे हे दर्शवण्यासाठी वापरला जातो. जर temperature 1.0 असेल, तर आम्ही योग्य मल्टिनॉमियल सॅम्पलिंग करतो, आणि जेव्हा temperature अनंताकडे जाते - तेव्हा सर्व संभाव्यता समान होतात, आणि आम्ही पुढील अक्षर यादृच्छिकपणे निवडतो. खालील उदाहरणात आपण पाहू शकतो की जेव्हा आपण temperature खूप जास्त वाढवतो तेव्हा मजकूर अर्थहीन होतो, आणि जेव्हा तो 0 च्या जवळ जातो तेव्हा तो \"सायकल्ड\" कठोर-निर्मित मजकूरासारखा दिसतो.\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": "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": "7673cd150d96c74c6d6011460094efb4",
"translation_date": "2025-08-28T09:15:24+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,492 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# जनरेटिव नेटवर्क्स\n",
"\n",
"रीकरंट न्यूरल नेटवर्क्स (RNNs) आणि त्यांचे गेटेड सेल प्रकार जसे की लाँग शॉर्ट टर्म मेमरी सेल्स (LSTMs) आणि गेटेड रीकरंट युनिट्स (GRUs) यांनी भाषा मॉडेलिंगसाठी एक यंत्रणा प्रदान केली आहे, म्हणजेच ते शब्दांची क्रमवारी शिकू शकतात आणि अनुक्रमातील पुढील शब्दासाठी अंदाज देऊ शकतात. यामुळे RNNs चा वापर **जनरेटिव टास्क्स** साठी करता येतो, जसे की सामान्य मजकूर निर्मिती, मशीन अनुवाद, आणि अगदी प्रतिमेचे कॅप्शनिंग.\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": []
},
{
"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/rnn-generate.56c54afb52f9781d63a7c16ea9c1b86cb70e6e1eae6a742b56b7b37468576b17.mr.png)\n",
"\n",
"आमच्या अनुक्रमाच्या शेवटच्या अक्षरासाठी, आम्ही नेटवर्कला `<eos>` टोकन तयार करण्यास सांगू.\n",
"\n",
"आपण येथे वापरत असलेल्या जनरेटिव्ह RNN आणि इतर RNN यामधील मुख्य फरक असा आहे की आपण RNN च्या प्रत्येक टप्प्याचा आउटपुट घेऊ, केवळ अंतिम सेलचा नाही. हे RNN सेलसाठी `return_sequences` पॅरामीटर निर्दिष्ट करून साध्य केले जाऊ शकते.\n",
"\n",
"म्हणून, प्रशिक्षणादरम्यान, नेटवर्कसाठी इनपुट काही लांबीच्या एन्कोड केलेल्या अक्षरांचा अनुक्रम असेल, आणि आउटपुट देखील त्याच लांबीचा अनुक्रम असेल, परंतु एका घटकाने शिफ्ट केलेला आणि `<eos>` ने समाप्त केलेला असेल. मिनीबॅचमध्ये अशा अनेक अनुक्रमांचा समावेश असेल, आणि सर्व अनुक्रम एकसंध करण्यासाठी आपल्याला **padding** वापरण्याची गरज असेल.\n",
"\n",
"चला, डेटासेटसाठी रूपांतर करणाऱ्या फंक्शन्स तयार करूया. कारण आपल्याला मिनीबॅच स्तरावर अनुक्रम padding करायचे आहे, आपण प्रथम `.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",
"* सर्वप्रथम, आम्ही string tensor मधून वास्तविक मजकूर काढतो\n",
"* `text_to_sequences` मजकूरांच्या यादीला पूर्णांक tensor च्या यादीत रूपांतरित करते\n",
"* `pad_sequences` त्या tensor ना त्यांच्या जास्तीत जास्त लांबीपर्यंत padding करते\n",
"* शेवटी, आम्ही सर्व अक्षरांचे one-hot encode करतो, तसेच shifting आणि `<eos>` जोडणेही करतो. आम्हाला लवकरच कळेल की one-hot-encoded अक्षरे का आवश्यक आहेत\n",
"\n",
"तथापि, ही फंक्शन **Pythonic** आहे, म्हणजेच ती Tensorflow computational graph मध्ये स्वयंचलितपणे रूपांतरित होऊ शकत नाही. जर आपण ही फंक्शन थेट `Dataset.map` फंक्शनमध्ये वापरण्याचा प्रयत्न केला, तर आपल्याला त्रुटी येतील. या Pythonic कॉलला `py_function` wrapper चा वापर करून enclosed करणे आवश्यक आहे:\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 ट्रान्सफॉर्मेशन फंक्शन्समधील फरक ओळखणे थोडेसे गुंतागुंतीचे वाटू शकते, आणि तुम्हाला प्रश्न पडू शकतो की, डेटासेटला `fit` मध्ये पास करण्यापूर्वी आपण ते स्टँडर्ड Python फंक्शन्स वापरून ट्रान्सफॉर्म का करत नाही. हे नक्कीच शक्य आहे, परंतु `Dataset.map` वापरण्याचा एक मोठा फायदा आहे, कारण डेटा ट्रान्सफॉर्मेशन पाईपलाइन Tensorflow च्या कम्प्युटेशनल ग्राफचा वापर करून कार्यान्वित होते, ज्यामुळे GPU च्या गणनात्मक क्षमतेचा फायदा घेतला जातो आणि CPU/GPU दरम्यान डेटा पास करण्याची गरज कमी होते.\n",
"\n",
"आता आपण आपले जनरेटर नेटवर्क तयार करू शकतो आणि प्रशिक्षण सुरू करू शकतो. हे कोणत्याही पुनरावृत्ती सेलवर आधारित असू शकते, जे आपण मागील युनिटमध्ये (साधे, LSTM किंवा GRU) चर्चा केले होते. आपल्या उदाहरणात आपण LSTM वापरणार आहोत.\n",
"\n",
"कारण नेटवर्क अक्षरे इनपुट म्हणून घेतो, आणि शब्दसंग्रहाचा आकार खूप लहान आहे, त्यामुळे आपल्याला एम्बेडिंग लेयरची गरज नाही; वन-हॉट-एनकोडेड इनपुट थेट LSTM सेलमध्ये जाऊ शकतो. आउटपुट लेयर `Dense` वर्गीकरणकर्ता असेल, जो LSTM आउटपुटला वन-हॉट-एनकोडेड टोकन क्रमांकांमध्ये रूपांतरित करेल.\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",
"* **अधिक मजकूर**. आपण आपल्या कार्यासाठी फक्त शीर्षके वापरली आहेत, पण तुम्ही पूर्ण मजकूरावर प्रयोग करू शकता. लक्षात ठेवा की RNNs लांब अनुक्रम हाताळण्यात फारसे चांगले नसतात, त्यामुळे त्यांना लहान वाक्यांमध्ये विभागणे किंवा पूर्वनिर्धारित `num_chars` (उदा. 256) मूल्याच्या निश्चित अनुक्रम लांबीवर नेहमी प्रशिक्षण देणे योग्य ठरते. तुम्ही वरील उदाहरण अशा प्रकारच्या आर्किटेक्चरमध्ये बदलण्याचा प्रयत्न करू शकता, [अधिकृत Keras ट्यूटोरियल](https://keras.io/examples/generative/lstm_character_level_text_generation/) याचा प्रेरणादायक म्हणून वापर करून.\n",
"* **मल्टीलेयर LSTM**. LSTM सेल्सच्या 2 किंवा 3 स्तरांचा प्रयत्न करणे योग्य ठरते. जसे आपण मागील युनिटमध्ये उल्लेख केले होते, 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 च्या जवळ जातो तेव्हा तो \"सायकल केलेला\" कठोर-निर्मित मजकूरासारखा दिसतो.\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": "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-08-28T09:11:56+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,353 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# लक्षवेधी यंत्रणा आणि ट्रान्सफॉर्मर्स\n",
"\n",
"पुनरावृत्ती नेटवर्क्सचा एक मोठा तोटा म्हणजे एका अनुक्रमातील सर्व शब्दांचा परिणामावर समान प्रभाव असतो. यामुळे नामनिर्देशन ओळख (Named Entity Recognition) आणि यंत्राद्वारे भाषांतर (Machine Translation) यांसारख्या अनुक्रम-ते-अनुक्रम कार्यांसाठी मानक LSTM एन्कोडर-डिकोडर मॉडेल्सची कार्यक्षमता कमी होते. प्रत्यक्षात, इनपुट अनुक्रमातील विशिष्ट शब्दांचा अनुक्रमिक आउटपुटवर इतरांपेक्षा अधिक प्रभाव असतो.\n",
"\n",
"यंत्राद्वारे भाषांतरासारख्या अनुक्रम-ते-अनुक्रम मॉडेलचा विचार करा. हे दोन पुनरावृत्ती नेटवर्क्सद्वारे अंमलात आणले जाते, जिथे एक नेटवर्क (**एन्कोडर**) इनपुट अनुक्रमाला लपलेल्या स्थितीत (hidden state) रूपांतरित करते, आणि दुसरे नेटवर्क (**डिकोडर**) त्या लपलेल्या स्थितीला भाषांतरित परिणामात बदलते. या दृष्टिकोनातील समस्या अशी आहे की नेटवर्कची अंतिम स्थिती वाक्याच्या सुरुवातीचा भाग लक्षात ठेवण्यात अडचण निर्माण करते, ज्यामुळे लांब वाक्यांवर मॉडेलची गुणवत्ता कमी होते.\n",
"\n",
"**लक्षवेधी यंत्रणा (Attention Mechanisms)** RNN च्या प्रत्येक आउटपुट अंदाजावर प्रत्येक इनपुट वेक्टरच्या संदर्भात्मक प्रभावाचे वजन करण्याचा एक मार्ग प्रदान करतात. हे अंमलात आणण्याचा मार्ग म्हणजे इनपुट RNN च्या मध्यवर्ती स्थिती आणि आउटपुट RNN यांच्यात शॉर्टकट तयार करणे. अशा प्रकारे, आउटपुट चिन्ह $y_t$ तयार करताना, आपण सर्व इनपुट लपलेल्या स्थिती $h_i$ विचारात घेऊ, वेगवेगळ्या वजन गुणांक $\\alpha_{t,i}$ सह.\n",
"\n",
"![एन्कोडर/डिकोडर मॉडेल आणि अ‍ॅडिटिव्ह लक्षवेधी स्तर दर्शविणारी प्रतिमा](../../../../../translated_images/encoder-decoder-attention.7a726296894fb567aa2898c94b17b3289087f6705c11907df8301df9e5eeb3de.mr.png)\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) मधील अ‍ॅडिटिव्ह लक्षवेधी यंत्रणेसह एन्कोडर-डिकोडर मॉडेल, [या ब्लॉग पोस्टमधून](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) उद्धृत]*\n",
"\n",
"लक्षवेधी मॅट्रिक्स $\\{\\alpha_{i,j}\\}$ हे दर्शवेल की आउटपुट अनुक्रमातील विशिष्ट शब्द तयार करण्यात कोणत्या इनपुट शब्दांचा किती प्रभाव आहे. खाली अशा मॅट्रिक्सचे उदाहरण दिले आहे:\n",
"\n",
"![RNNsearch-50 ने सापडलेले नमुना संरेखन दर्शविणारी प्रतिमा, Bahdanau - arviz.org कडून घेतलेली](../../../../../translated_images/bahdanau-fig3.09ba2d37f202a6af11de6c82d2d197830ba5f4528d9ea430eb65fd3a75065973.mr.png)\n",
"\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) (आकृती 3) मधून घेतलेली आकृती]*\n",
"\n",
"लक्षवेधी यंत्रणा नैसर्गिक भाषा प्रक्रिया (Natural Language Processing) मध्ये सध्याच्या किंवा जवळपासच्या अत्याधुनिक तंत्रज्ञानासाठी मोठ्या प्रमाणावर जबाबदार आहेत. मात्र, लक्षवेधी यंत्रणा जोडल्याने मॉडेलच्या पॅरामीटर्सची संख्या मोठ्या प्रमाणात वाढते, ज्यामुळे RNNs सह स्केलिंग समस्या निर्माण होतात. RNNs स्केल करण्याचे एक महत्त्वाचे बंधन म्हणजे मॉडेल्सच्या पुनरावृत्ती स्वरूपामुळे प्रशिक्षण बॅचिंग आणि समांतरित करणे कठीण होते. RNN मध्ये अनुक्रमातील प्रत्येक घटक क्रमाने प्रक्रिया करणे आवश्यक असते, ज्यामुळे ते सहजपणे समांतरित करता येत नाही.\n",
"\n",
"लक्षवेधी यंत्रणांचा अवलंब आणि या बंधनामुळे आज आपण ओळखत असलेल्या अत्याधुनिक ट्रान्सफॉर्मर मॉडेल्सची निर्मिती झाली, जसे की BERT आणि OpenGPT3.\n",
"\n",
"## ट्रान्सफॉर्मर मॉडेल्स\n",
"\n",
"प्रत्येक मागील अंदाजाचा संदर्भ पुढील मूल्यांकन चरणात पाठविण्याऐवजी, **ट्रान्सफॉर्मर मॉडेल्स** **स्थिती कोडिंग्स (positional encodings)** आणि लक्षवेधी यंत्रणा वापरून दिलेल्या मजकूराच्या खिडकीत (window) इनपुटचा संदर्भ कॅप्चर करतात. खालील प्रतिमा दर्शवते की स्थिती कोडिंग्ससह लक्षवेधी यंत्रणा दिलेल्या खिडकीत संदर्भ कसा कॅप्चर करू शकते.\n",
"\n",
"![ट्रान्सफॉर्मर मॉडेल्समध्ये मूल्यांकन कसे केले जाते हे दर्शविणारा अ‍ॅनिमेटेड GIF.](../../../../../lessons/5-NLP/18-Transformers/images/transformer-animated-explanation.gif)\n",
"\n",
"प्रत्येक इनपुट स्थिती स्वतंत्रपणे प्रत्येक आउटपुट स्थितीशी मॅप केल्यामुळे, ट्रान्सफॉर्मर्स RNNs पेक्षा चांगले समांतरित होऊ शकतात, ज्यामुळे खूप मोठी आणि अधिक अभिव्यक्तीक्षम भाषा मॉडेल्स सक्षम होतात. प्रत्येक लक्षवेधी हेड वेगवेगळ्या शब्दांमधील संबंध शिकण्यासाठी वापरला जाऊ शकतो, ज्यामुळे नैसर्गिक भाषा प्रक्रिया कार्ये सुधारतात.\n",
"\n",
"**BERT** (Bidirectional Encoder Representations from Transformers) हे 12 स्तरांसाठी *BERT-base* आणि 24 स्तरांसाठी *BERT-large* असलेले खूप मोठे बहुस्तरीय ट्रान्सफॉर्मर नेटवर्क आहे. हे मॉडेल मोठ्या प्रमाणावर मजकूर डेटावर (विकिपीडिया + पुस्तके) असंरचित प्रशिक्षण (unsupervised training) वापरून आधी प्रशिक्षणित केले जाते (वाक्यातील लपवलेले शब्द ओळखणे). पूर्व-प्रशिक्षणादरम्यान मॉडेल महत्त्वपूर्ण भाषिक समज आत्मसात करते, ज्याचा नंतर इतर डेटासेट्ससह सूक्ष्म-ट्यूनिंगद्वारे उपयोग केला जाऊ शकतो. या प्रक्रियेला **स्थानांतरण शिक्षण (transfer learning)** म्हणतात.\n",
"\n",
"![http://jalammar.github.io/illustrated-bert/ येथून घेतलेली प्रतिमा](../../../../../translated_images/jalammarBERT-language-modeling-masked-lm.34f113ea5fec4362e39ee4381aab7cad06b5465a0b5f053a0f2aa05fbe14e746.mr.png)\n",
"\n",
"BERT, DistilBERT, BigBird, OpenGPT3 आणि इतर अनेक ट्रान्सफॉर्मर आर्किटेक्चर्सच्या विविध आवृत्त्या आहेत, ज्या सूक्ष्म-ट्यूनिंगसाठी वापरता येतात. [HuggingFace पॅकेज](https://github.com/huggingface/) PyTorch सह या आर्किटेक्चर्सपैकी अनेकांचे प्रशिक्षण घेण्यासाठी रिपॉझिटरी प्रदान करते.\n",
"\n",
"## मजकूर वर्गीकरणासाठी BERT चा वापर\n",
"\n",
"आता आपण पूर्व-प्रशिक्षित BERT मॉडेलचा वापर करून आपले पारंपरिक कार्य कसे सोडवू शकतो ते पाहू: अनुक्रम वर्गीकरण. आपण आपल्या मूळ AG News डेटासेटचे वर्गीकरण करू.\n",
"\n",
"सुरुवातीला, HuggingFace लायब्ररी आणि आपला डेटासेट लोड करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"from torchnlp import *\n",
"import transformers\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_len = len(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"कारण आपण पूर्व-प्रशिक्षित BERT मॉडेल वापरणार आहोत, त्यामुळे आपल्याला विशिष्ट टोकनायझर वापरावा लागेल. प्रथम, आपण पूर्व-प्रशिक्षित BERT मॉडेलशी संबंधित टोकनायझर लोड करू.\n",
"\n",
"HuggingFace लायब्ररीमध्ये पूर्व-प्रशिक्षित मॉडेल्सचा संग्रह आहे, ज्याचा आपण फक्त त्यांच्या नावांचा `from_pretrained` फंक्शन्समध्ये युक्तिवाद म्हणून उल्लेख करून वापर करू शकता. मॉडेलसाठी आवश्यक असलेली सर्व बायनरी फाइल्स आपोआप डाउनलोड केल्या जातील.\n",
"\n",
"तथापि, काही वेळा आपल्याला स्वतःचे मॉडेल्स लोड करावे लागतील, अशा परिस्थितीत आपण त्या डिरेक्टरीचा उल्लेख करू शकता ज्यामध्ये सर्व संबंधित फाइल्स असतील, जसे की टोकनायझरसाठीचे पॅरामीटर्स, मॉडेल पॅरामीटर्ससह `config.json` फाइल, बायनरी वेट्स इत्यादी.\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# To load the model from Internet repository using model name. \n",
"# Use this if you are running from your own copy of the notebooks\n",
"bert_model = 'bert-base-uncased' \n",
"\n",
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
"# prepared all required files for you.\n",
"bert_model = './bert'\n",
"\n",
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
"\n",
"MAX_SEQ_LEN = 128\n",
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`tokenizer` ऑब्जेक्टमध्ये `encode` फंक्शन असते जी थेट मजकूर एन्कोड करण्यासाठी वापरली जाऊ शकते:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[101, 1052, 22123, 2953, 2818, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer.encode('PyTorch is a great framework for NLP')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"मग, प्रशिक्षणादरम्यान डेटा ऍक्सेस करण्यासाठी आपण ज्या इटरेटर्सचा वापर करू ते तयार करूया. कारण BERT त्याच्या स्वतःच्या एन्कोडिंग फंक्शनचा वापर करतो, त्यामुळे आपल्याला यापूर्वी परिभाषित केलेल्या `padify` सारखी एक पॅडिंग फंक्शन परिभाषित करावी लागेल:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def pad_bert(b):\n",
" # b is the list of tuples of length batch_size\n",
" # - first element of a tuple = label, \n",
" # - second = feature (text sequence)\n",
" # build vectorized sequence\n",
" v = [tokenizer.encode(x[1]) for x in b]\n",
" # compute max length of a sequence in this minibatch\n",
" l = max(map(len,v))\n",
" return ( # tuple of two tensors - labels and features\n",
" torch.LongTensor([t[0] for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, collate_fn=pad_bert, shuffle=True)\n",
"test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=8, collate_fn=pad_bert)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आमच्या बाबतीत, आम्ही `bert-base-uncased` नावाचा पूर्व-प्रशिक्षित BERT मॉडेल वापरणार आहोत. चला `BertForSequenceClassfication` पॅकेज वापरून मॉडेल लोड करूया. यामुळे आपले मॉडेल वर्गीकरणासाठी आवश्यक असलेली आर्किटेक्चर, अंतिम वर्गीकरणकर्ता समावेशासह, आधीच तयार आहे याची खात्री होते. तुम्हाला एक चेतावणी संदेश दिसेल ज्यामध्ये म्हटले जाईल की अंतिम वर्गीकरणकर्त्याचे वजन प्रारंभिक केलेले नाही, आणि मॉडेलला पूर्व-प्रशिक्षणाची आवश्यकता असेल - ते पूर्णपणे ठीक आहे, कारण आपण नेमके तेच करणार आहोत!\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Some weights of the model checkpoint at ./bert were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']\n",
"- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
"- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
"Some weights of BertForSequenceClassification were not initialized from the model checkpoint at ./bert and are newly initialized: ['classifier.weight', 'classifier.bias']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
]
}
],
"source": [
"model = transformers.BertForSequenceClassification.from_pretrained(bert_model,num_labels=4).to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण प्रशिक्षण सुरू करण्यासाठी तयार आहोत! कारण BERT आधीच प्री-ट्रेन केलेला आहे, त्यामुळे सुरुवातीला लहान learning rate वापरणे महत्त्वाचे आहे, जेणेकरून सुरुवातीचे weights खराब होऊ नयेत.\n",
"\n",
"संपूर्ण मेहनत `BertForSequenceClassification` मॉडेलद्वारे केली जाते. जेव्हा आपण प्रशिक्षण डेटावर मॉडेल कॉल करतो, तेव्हा ते इनपुट minibatch साठी loss आणि नेटवर्क output दोन्ही परत करते. आम्ही loss चा वापर parameter optimization साठी करतो (`loss.backward()` बॅकवर्ड पास करते), आणि `out` चा वापर प्रशिक्षण accuracy मोजण्यासाठी करतो, ज्यामध्ये मिळालेल्या labels `labs` (जे `argmax` वापरून गणना केले जातात) अपेक्षित `labels` शी तुलना केली जाते.\n",
"\n",
"प्रक्रियेवर नियंत्रण ठेवण्यासाठी, आम्ही loss आणि accuracy अनेक iterations वर जमा करतो आणि प्रत्येक `report_freq` प्रशिक्षण चक्रांनंतर त्यांना प्रिंट करतो.\n",
"\n",
"हे प्रशिक्षण कदाचित बराच वेळ घेईल, त्यामुळे आम्ही iterations ची संख्या मर्यादित ठेवतो.\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loss = 1.1254194641113282, Accuracy = 0.585\n",
"Loss = 0.6194715118408203, Accuracy = 0.83\n",
"Loss = 0.46665248870849607, Accuracy = 0.8475\n",
"Loss = 0.4309701919555664, Accuracy = 0.8575\n",
"Loss = 0.35427074432373046, Accuracy = 0.8825\n",
"Loss = 0.3306886291503906, Accuracy = 0.8975\n",
"Loss = 0.30340143203735354, Accuracy = 0.8975\n",
"Loss = 0.26139299392700194, Accuracy = 0.915\n",
"Loss = 0.26708646774291994, Accuracy = 0.9225\n",
"Loss = 0.3667240524291992, Accuracy = 0.8675\n"
]
}
],
"source": [
"optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)\n",
"\n",
"report_freq = 50\n",
"iterations = 500 # make this larger to train for longer time!\n",
"\n",
"model.train()\n",
"\n",
"i,c = 0,0\n",
"acc_loss = 0\n",
"acc_acc = 0\n",
"\n",
"for labels,texts in train_loader:\n",
" labels = labels.to(device)-1 # get labels in the range 0-3 \n",
" texts = texts.to(device)\n",
" loss, out = model(texts, labels=labels)[:2]\n",
" labs = out.argmax(dim=1)\n",
" acc = torch.mean((labs==labels).type(torch.float32))\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" acc_loss += loss\n",
" acc_acc += acc\n",
" i+=1\n",
" c+=1\n",
" if i%report_freq==0:\n",
" print(f\"Loss = {acc_loss.item()/c}, Accuracy = {acc_acc.item()/c}\")\n",
" c = 0\n",
" acc_loss = 0\n",
" acc_acc = 0\n",
" iterations-=1\n",
" if not iterations:\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपण पाहू शकता (विशेषतः जर तुम्ही पुनरावृत्तीची संख्या वाढवली आणि थोडा वेळ थांबलात), की BERT वर्गीकरण आपल्याला खूप चांगली अचूकता देते! याचे कारण असे की BERT आधीच भाषेची रचना चांगल्या प्रकारे समजून घेतो, आणि आपल्याला फक्त अंतिम वर्गीकरणकर्ता सुधारित करायचा असतो. मात्र, BERT हा मोठा मॉडेल असल्यामुळे, संपूर्ण प्रशिक्षण प्रक्रिया खूप वेळखाऊ असते आणि ती करण्यासाठी प्रचंड संगणकीय शक्तीची आवश्यकता असते! (GPU, आणि शक्यतो एकापेक्षा जास्त).\n",
"\n",
"> **टीप:** आपल्या उदाहरणात, आपण सर्वात लहान पूर्व-प्रशिक्षित BERT मॉडेल्सपैकी एकाचा वापर केला आहे. मोठ्या मॉडेल्स उपलब्ध आहेत, जे कदाचित अधिक चांगले परिणाम देतील.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मॉडेलच्या कार्यक्षमतेचे मूल्यमापन\n",
"\n",
"आता आपण चाचणी डेटासेटवर आपल्या मॉडेलच्या कार्यक्षमतेचे मूल्यमापन करू शकतो. मूल्यांकन लूप प्रशिक्षण लूपसारखाच असतो, परंतु `model.eval()` कॉल करून मॉडेलला मूल्यांकन मोडमध्ये स्विच करणे विसरू नये.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Final accuracy: 0.9047029702970297\n"
]
}
],
"source": [
"model.eval()\n",
"iterations = 100\n",
"acc = 0\n",
"i = 0\n",
"for labels,texts in test_loader:\n",
" labels = labels.to(device)-1 \n",
" texts = texts.to(device)\n",
" _, out = model(texts, labels=labels)[:2]\n",
" labs = out.argmax(dim=1)\n",
" acc += torch.mean((labs==labels).type(torch.float32))\n",
" i+=1\n",
" if i>iterations: break\n",
" \n",
"print(f\"Final accuracy: {acc.item()/i}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य मुद्दा\n",
"\n",
"या युनिटमध्ये, आपण पाहिले की **transformers** लायब्ररीमधून पूर्व-प्रशिक्षित भाषा मॉडेल घेणे आणि ते आपल्या टेक्स्ट वर्गीकरण कार्यासाठी अनुकूल करणे किती सोपे आहे. त्याचप्रमाणे, BERT मॉडेल्सचा वापर घटक शोधणे, प्रश्नोत्तर, आणि इतर NLP कार्यांसाठी केला जाऊ शकतो.\n",
"\n",
"Transformer मॉडेल्स NLP मधील अत्याधुनिक तंत्रज्ञानाचे प्रतिनिधित्व करतात, आणि बहुतेक प्रकरणांमध्ये, कस्टम NLP सोल्यूशन्स अंमलात आणताना प्रयोग सुरू करण्यासाठी ही पहिली निवड असावी. तथापि, जर तुम्हाला प्रगत न्यूरल मॉडेल्स तयार करायचे असतील, तर या मॉड्यूलमध्ये चर्चिलेल्या पुनरावृत्ती न्यूरल नेटवर्क्सच्या मूलभूत तत्त्वांचे समजून घेणे अत्यंत महत्त्वाचे आहे.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py37_pytorch",
"language": "python",
"name": "conda-env-py37_pytorch-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.7"
},
"coopTranslator": {
"original_hash": "753865967678a92dbce7d7efbd36d980",
"translation_date": "2025-08-28T09:22:53+00:00",
"source_file": "lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,819 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# अटेन्शन मेकॅनिझम्स आणि ट्रान्सफॉर्मर्स\n",
"\n",
"रीकरंट नेटवर्क्सचा एक मोठा तोटा म्हणजे एका अनुक्रमातील सर्व शब्दांचा परिणामावर समान प्रभाव असतो. यामुळे नेम्ड एंटिटी रिकग्निशन आणि मशीन ट्रान्सलेशनसारख्या अनुक्रम-ते-अनुक्रम कार्यांसाठी स्टँडर्ड LSTM एन्कोडर-डिकोडर मॉडेल्समध्ये कमी कार्यक्षमता दिसून येते. प्रत्यक्षात, इनपुट अनुक्रमातील विशिष्ट शब्दांचा अनुक्रमिक आउटपुटवर इतरांपेक्षा अधिक प्रभाव असतो.\n",
"\n",
"मशीन ट्रान्सलेशनसारख्या अनुक्रम-ते-अनुक्रम मॉडेलचा विचार करा. हे दोन रीकरंट नेटवर्क्सद्वारे अंमलात आणले जाते, जिथे एक नेटवर्क (**एन्कोडर**) इनपुट अनुक्रमाला हिडन स्टेटमध्ये रूपांतरित करते, आणि दुसरे नेटवर्क (**डिकोडर**) त्या हिडन स्टेटला ट्रान्सलेटेड आउटपुटमध्ये बदलते. या पद्धतीचा एक मोठा तोटा म्हणजे नेटवर्कचा अंतिम स्टेट वाक्याच्या सुरुवातीचा भाग लक्षात ठेवण्यात अडचण निर्माण करतो, ज्यामुळे लांब वाक्यांवर मॉडेलची गुणवत्ता कमी होते.\n",
"\n",
"**अटेन्शन मेकॅनिझम्स** RNN च्या प्रत्येक आउटपुट प्रेडिक्शनवर प्रत्येक इनपुट व्हेक्टरच्या संदर्भात्मक प्रभावाचे वजन करण्याचा एक मार्ग प्रदान करतात. हे अंमलात आणण्याचा मार्ग म्हणजे इनपुट RNN च्या इंटरमिजिएट स्टेट्स आणि आउटपुट RNN दरम्यान शॉर्टकट तयार करणे. अशा प्रकारे, जेव्हा आउटपुट चिन्ह $y_t$ तयार करतो, तेव्हा आपण सर्व इनपुट हिडन स्टेट्स $h_i$ विचारात घेऊ, वेगवेगळ्या वजन गुणांक $\\alpha_{t,i}$ सह.\n",
"\n",
"![एन्कोडर/डिकोडर मॉडेल अ‍ॅडिटिव्ह अटेन्शन लेयरसह दर्शविणारी प्रतिमा](../../../../../translated_images/encoder-decoder-attention.7a726296894fb567aa2898c94b17b3289087f6705c11907df8301df9e5eeb3de.mr.png)\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) मधील अ‍ॅडिटिव्ह अटेन्शन मेकॅनिझमसह एन्कोडर-डिकोडर मॉडेल, [या ब्लॉग पोस्टमधून](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) घेतलेले*\n",
"\n",
"अटेन्शन मॅट्रिक्स $\\{\\alpha_{i,j}\\}$ हे दर्शवते की आउटपुट अनुक्रमातील विशिष्ट शब्द तयार करण्यात कोणत्या इनपुट शब्दांचा किती प्रभाव आहे. खाली अशा मॅट्रिक्सचे उदाहरण दिले आहे:\n",
"\n",
"![RNNsearch-50 ने सापडलेले नमुना अलाइनमेंट दर्शविणारी प्रतिमा, Bahdanau - arviz.org कडून घेतलेली](../../../../../translated_images/bahdanau-fig3.09ba2d37f202a6af11de6c82d2d197830ba5f4528d9ea430eb65fd3a75065973.mr.png)\n",
"\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) (Fig.3) मधून घेतलेली आकृती]*\n",
"\n",
"अटेन्शन मेकॅनिझम्स नैसर्गिक भाषा प्रक्रिया (NLP) मध्ये सध्याच्या किंवा जवळपासच्या अत्याधुनिक स्थितीसाठी जबाबदार आहेत. मात्र, अटेन्शन जोडल्याने मॉडेल पॅरामीटर्सची संख्या मोठ्या प्रमाणात वाढते, ज्यामुळे RNNs सह स्केलिंग समस्या निर्माण होतात. RNNs च्या स्केलिंगसाठी एक महत्त्वाची अडचण म्हणजे मॉडेल्सच्या रीकरंट स्वरूपामुळे प्रशिक्षण बॅच करणे आणि पॅरललाइज करणे कठीण होते. RNN मध्ये अनुक्रमातील प्रत्येक घटकाला अनुक्रमिक क्रमाने प्रक्रिया करावी लागते, ज्यामुळे ते सहजपणे पॅरललाइज करता येत नाही.\n",
"\n",
"अटेन्शन मेकॅनिझम्सचा अवलंब आणि या अडचणीमुळे आज आपण वापरत असलेल्या अत्याधुनिक ट्रान्सफॉर्मर मॉडेल्सचा जन्म झाला, जसे की BERT आणि OpenGPT3.\n",
"\n",
"## ट्रान्सफॉर्मर मॉडेल्स\n",
"\n",
"प्रत्येक मागील प्रेडिक्शनचा संदर्भ पुढील मूल्यांकन चरणात पाठविण्याऐवजी, **ट्रान्सफॉर्मर मॉडेल्स** **पोजिशनल एन्कोडिंग्स** आणि **अटेन्शन** वापरून दिलेल्या मजकूराच्या विंडोमध्ये इनपुटचा संदर्भ कॅप्चर करतात. खालील प्रतिमा दर्शवते की पोजिशनल एन्कोडिंग्ससह अटेन्शन दिलेल्या विंडोमध्ये संदर्भ कसा कॅप्चर करू शकतो.\n",
"\n",
"![ट्रान्सफॉर्मर मॉडेल्समध्ये मूल्यांकन कसे केले जाते हे दर्शविणारा अ‍ॅनिमेटेड GIF](../../../../../lessons/5-NLP/18-Transformers/images/transformer-animated-explanation.gif)\n",
"\n",
"प्रत्येक इनपुट पोझिशन स्वतंत्रपणे प्रत्येक आउटपुट पोझिशनशी मॅप केल्यामुळे, ट्रान्सफॉर्मर्स RNNs पेक्षा चांगले पॅरललाइज करू शकतात, ज्यामुळे खूप मोठी आणि अधिक अभिव्यक्तीक्षम भाषा मॉडेल्स सक्षम होतात. प्रत्येक अटेन्शन हेड वेगवेगळ्या शब्दांमधील संबंध शिकण्यासाठी वापरला जाऊ शकतो, ज्यामुळे नैसर्गिक भाषा प्रक्रिया कार्ये सुधारतात.\n",
"\n",
"## साधे ट्रान्सफॉर्मर मॉडेल तयार करणे\n",
"\n",
"Keras मध्ये अंगभूत ट्रान्सफॉर्मर लेयर नाही, परंतु आपण स्वतः तयार करू शकतो. यापूर्वीप्रमाणे, आपण AG News डेटासेटच्या मजकूर वर्गीकरणावर लक्ष केंद्रित करू, परंतु हे नमूद करणे महत्त्वाचे आहे की ट्रान्सफॉर्मर मॉडेल्स अधिक कठीण NLP कार्यांमध्ये सर्वोत्तम परिणाम दाखवतात.\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()\n",
"\n",
"def extract_text(x):\n",
" return x['title']+' '+x['description']\n",
"\n",
"def tupelize(x):\n",
" return (extract_text(x),x['label'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"केरस मधील नवीन स्तरांना `Layer` वर्गाचे उपवर्ग बनवावे लागेल आणि `call` पद्धत लागू करावी लागेल. चला **Positional Embedding** स्तरासह सुरुवात करूया. आम्ही [अधिकृत केरस दस्तऐवजातील काही कोड](https://keras.io/examples/nlp/text_classification_with_transformer/) वापरणार आहोत. आम्ही गृहित धरतो की आम्ही सर्व इनपुट अनुक्रम `maxlen` लांबीपर्यंत पॅड करतो.\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class TokenAndPositionEmbedding(keras.layers.Layer):\n",
" def __init__(self, maxlen, vocab_size, embed_dim):\n",
" super(TokenAndPositionEmbedding, self).__init__()\n",
" self.token_emb = keras.layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)\n",
" self.pos_emb = keras.layers.Embedding(input_dim=maxlen, output_dim=embed_dim)\n",
" self.maxlen = maxlen\n",
"\n",
" def call(self, x):\n",
" maxlen = self.maxlen\n",
" positions = tf.range(start=0, limit=maxlen, delta=1)\n",
" positions = self.pos_emb(positions)\n",
" x = self.token_emb(x)\n",
" return x+positions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"या स्तरामध्ये दोन `Embedding` स्तरांचा समावेश आहे: टोकनसाठी एम्बेडिंग (जसा आपण यापूर्वी चर्चा केली आहे) आणि टोकनच्या स्थानांसाठी. टोकनची स्थानं 0 ते `maxlen` पर्यंत नैसर्गिक संख्यांच्या अनुक्रमाप्रमाणे `tf.range` वापरून तयार केली जातात आणि नंतर एम्बेडिंग स्तरामधून पाठवली जातात. परिणामी दोन एम्बेडिंग व्हेक्टर एकत्र केले जातात, ज्यामुळे `maxlen`$\\times$`embed_dim` आकाराच्या इनपुटचे स्थानिक-एम्बेडेड प्रतिनिधित्व तयार होते.\n",
"\n",
"आता, आपण ट्रान्सफॉर्मर ब्लॉक लागू करूया. हा ब्लॉक यापूर्वी परिभाषित केलेल्या एम्बेडिंग स्तराच्या आउटपुटला घेईल:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"class TransformerBlock(keras.layers.Layer):\n",
" def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):\n",
" super(TransformerBlock, self).__init__()\n",
" self.att = keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim, name='attn')\n",
" self.ffn = keras.Sequential(\n",
" [keras.layers.Dense(ff_dim, activation=\"relu\"), keras.layers.Dense(embed_dim),]\n",
" )\n",
" self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
" self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
" self.dropout1 = keras.layers.Dropout(rate)\n",
" self.dropout2 = keras.layers.Dropout(rate)\n",
"\n",
" def call(self, inputs, training):\n",
" attn_output = self.att(inputs, inputs)\n",
" attn_output = self.dropout1(attn_output, training=training)\n",
" out1 = self.layernorm1(inputs + attn_output)\n",
" ffn_output = self.ffn(out1)\n",
" ffn_output = self.dropout2(ffn_output, training=training)\n",
" return self.layernorm2(out1 + ffn_output)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता, आपण पूर्ण ट्रान्सफॉर्मर मॉडेल परिभाषित करण्यासाठी तयार आहोत:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"text_vectorization (TextVect (None, 256) 0 \n",
"_________________________________________________________________\n",
"token_and_position_embedding (None, 256, 32) 648192 \n",
"_________________________________________________________________\n",
"transformer_block (Transform (None, 256, 32) 10656 \n",
"_________________________________________________________________\n",
"global_average_pooling1d (Gl (None, 32) 0 \n",
"_________________________________________________________________\n",
"dropout_2 (Dropout) (None, 32) 0 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 20) 660 \n",
"_________________________________________________________________\n",
"dropout_3 (Dropout) (None, 20) 0 \n",
"_________________________________________________________________\n",
"dense_3 (Dense) (None, 4) 84 \n",
"=================================================================\n",
"Total params: 659,592\n",
"Trainable params: 659,592\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"embed_dim = 32 # Embedding size for each token\n",
"num_heads = 2 # Number of attention heads\n",
"ff_dim = 32 # Hidden layer size in feed forward network inside transformer\n",
"maxlen = 256\n",
"vocab_size = 20000\n",
"\n",
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_sequence_length=maxlen, input_shape=(1,)),\n",
" TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim),\n",
" TransformerBlock(embed_dim, num_heads, ff_dim),\n",
" keras.layers.GlobalAveragePooling1D(),\n",
" keras.layers.Dropout(0.1),\n",
" keras.layers.Dense(20, activation=\"relu\"),\n",
" keras.layers.Dropout(0.1),\n",
" keras.layers.Dense(4, activation=\"softmax\")\n",
"])\n",
"\n",
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training tokenizer\n",
"938/938 [==============================] - 45s 39ms/step - loss: 0.4978 - acc: 0.8068 - val_loss: 0.2808 - val_acc: 0.9124\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9c2427a0d0>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"print('Training tokenizer')\n",
"model.layers[0].adapt(ds_train.map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## BERT Transformer Models\n",
"\n",
"**BERT** (Bidirectional Encoder Representations from Transformers) हा एक मोठा मल्टी लेयर ट्रान्सफॉर्मर नेटवर्क आहे ज्यामध्ये *BERT-base* साठी 12 स्तर आणि *BERT-large* साठी 24 स्तर आहेत. हा मॉडेल प्रथम मोठ्या प्रमाणावर मजकूर डेटावर (WikiPedia + पुस्तके) असुपरवाइज्ड ट्रेनिंगचा वापर करून (वाक्यातील मास्क केलेल्या शब्दांची भविष्यवाणी करणे) प्री-ट्रेन केला जातो. प्री-ट्रेनिंग दरम्यान मॉडेल महत्त्वपूर्ण भाषिक समज आत्मसात करते, ज्याचा नंतर इतर डेटासेटसह फाइन ट्यूनिंगद्वारे उपयोग केला जाऊ शकतो. या प्रक्रियेला **ट्रान्सफर लर्निंग** म्हणतात.\n",
"\n",
"![picture from http://jalammar.github.io/illustrated-bert/](../../../../../translated_images/jalammarBERT-language-modeling-masked-lm.34f113ea5fec4362e39ee4381aab7cad06b5465a0b5f053a0f2aa05fbe14e746.mr.png)\n",
"\n",
"BERT, DistilBERT, BigBird, OpenGPT3 आणि इतर अनेक ट्रान्सफॉर्मर आर्किटेक्चरचे प्रकार आहेत, जे फाइन ट्यून केले जाऊ शकतात.\n",
"\n",
"चला पाहूया की प्री-ट्रेन केलेल्या BERT मॉडेलचा उपयोग पारंपरिक सिक्वेन्स वर्गीकरण समस्येचे निराकरण करण्यासाठी कसा करता येईल. आपण [अधिकृत दस्तऐवज](https://www.tensorflow.org/text/tutorials/classify_text_with_bert) मधून कल्पना आणि काही कोड उधार घेऊ.\n",
"\n",
"प्री-ट्रेन केलेले मॉडेल लोड करण्यासाठी, आपण **Tensorflow hub** वापरणार आहोत. प्रथम, BERT-विशिष्ट व्हेक्टरायझर लोड करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"ename": "ModuleNotFoundError",
"evalue": "No module named 'tensorflow_text'",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_41180/4216669875.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_text\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_hub\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mvectorizer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mKerasLayer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'tensorflow_text'"
]
}
],
"source": [
"import tensorflow_text \n",
"import tensorflow_hub as hub\n",
"vectorizer = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'input_type_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
" dtype=int32)>,\n",
" 'input_word_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[ 101, 1045, 2293, 19081, 102, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0]], dtype=int32)>,\n",
" 'input_mask': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
" dtype=int32)>}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer(['I love transformers'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"मूळ नेटवर्क प्रशिक्षणासाठी वापरलेला तोच व्हेक्टरायझर वापरणे महत्त्वाचे आहे. तसेच, BERT व्हेक्टरायझर तीन घटक परत करतो:\n",
"* `input_word_ids`, जो इनपुट वाक्यांसाठी टोकन क्रमांकांची मालिका असतो\n",
"* `input_mask`, जो दर्शवतो की मालिकेचा कोणता भाग वास्तविक इनपुट आहे आणि कोणता भाग पॅडिंग आहे. हे `Masking` स्तराद्वारे तयार केलेल्या मास्कसारखेच असते\n",
"* `input_type_ids` भाषा मॉडेलिंग कार्यांसाठी वापरले जाते आणि एका मालिकेत दोन इनपुट वाक्ये निर्दिष्ट करण्याची परवानगी देते.\n",
"\n",
"यानंतर, आपण BERT वैशिष्ट्य एक्स्ट्रॅक्टर तयार करू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"bert = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-128_A-2/1')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pooled_output -> (1, 128)\n",
"encoder_outputs -> 4\n",
"sequence_output -> (1, 128, 128)\n",
"default -> (1, 128)\n"
]
}
],
"source": [
"z = bert(vectorizer(['I love transformers']))\n",
"for i,x in z.items():\n",
" print(f\"{i} -> { len(x) if isinstance(x, list) else x.shape }\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"तर, BERT लेयर काही उपयुक्त परिणाम परत करते:\n",
"* `pooled_output` हा अनुक्रमातील सर्व टोकनचा सरासरी काढण्याचा परिणाम आहे. तुम्ही याला संपूर्ण नेटवर्कचे एक बुद्धिमान सिमॅंटिक एम्बेडिंग म्हणून पाहू शकता. हे आपल्या आधीच्या मॉडेलमधील `GlobalAveragePooling1D` लेयरच्या आउटपुटसारखेच आहे.\n",
"* `sequence_output` हा शेवटच्या ट्रान्सफॉर्मर लेयरचा आउटपुट आहे (आपल्या वरील मॉडेलमधील `TransformerBlock` च्या आउटपुटशी संबंधित आहे).\n",
"* `encoder_outputs` हे सर्व ट्रान्सफॉर्मर लेयर्सचे आउटपुट आहेत. आपण 4-लेयर BERT मॉडेल लोड केले आहे (जसे तुम्ही नावावरून अंदाज लावू शकता, ज्यामध्ये `4_H` समाविष्ट आहे), त्यामुळे यामध्ये 4 टेन्सर्स आहेत. यातील शेवटचा `sequence_output` सारखाच आहे.\n",
"\n",
"आता आपण एंड-टू-एंड वर्गीकरण मॉडेल परिभाषित करू. आपण *फंक्शनल मॉडेल डिफिनिशन* वापरणार आहोत, जिथे आपण मॉडेल इनपुट परिभाषित करू, आणि नंतर त्याच्या आउटपुटची गणना करण्यासाठी एक मालिका अभिव्यक्ती प्रदान करू. आपण BERT मॉडेलचे वेट्स ट्रेन करण्यायोग्य ठेवणार नाही, आणि फक्त अंतिम वर्गीकरणकर्ता ट्रेन करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"__________________________________________________________________________________________________\n",
"Layer (type) Output Shape Param # Connected to \n",
"==================================================================================================\n",
"input_1 (InputLayer) [(None,)] 0 \n",
"__________________________________________________________________________________________________\n",
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
"__________________________________________________________________________________________________\n",
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
" keras_layer[0][1] \n",
" keras_layer[0][2] \n",
"__________________________________________________________________________________________________\n",
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
"__________________________________________________________________________________________________\n",
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
"==================================================================================================\n",
"Total params: 4,782,981\n",
"Trainable params: 516\n",
"Non-trainable params: 4,782,465\n",
"__________________________________________________________________________________________________\n"
]
}
],
"source": [
"inp = keras.Input(shape=(),dtype=tf.string)\n",
"x = vectorizer(inp)\n",
"x = bert(x)\n",
"x = keras.layers.Dropout(0.1)(x['pooled_output'])\n",
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
"model = keras.models.Model(inp,out)\n",
"bert.trainable = False\n",
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 528s 559ms/step - loss: 0.8056 - acc: 0.6983 - val_loss: 0.5953 - val_acc: 0.7888\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9bb1e36d00>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जरी ट्रेन करण्यायोग्य पॅरामिटर्स कमी असले तरी, प्रक्रिया खूपच धीमी आहे, कारण BERT फीचर एक्स्ट्रॅक्टर संगणकीयदृष्ट्या जड आहे. असे दिसते की आम्ही योग्य अचूकता साध्य करण्यात अयशस्वी ठरलो, कदाचित प्रशिक्षणाच्या अभावामुळे किंवा मॉडेल पॅरामिटर्सच्या अभावामुळे.\n",
"\n",
"आता BERT चे वेट्स अनफ्रीज करून त्याला देखील ट्रेन करण्याचा प्रयत्न करूया. यासाठी खूपच कमी लर्निंग रेट आवश्यक आहे, तसेच **वॉर्मअप** आणि **AdamW** ऑप्टिमायझर वापरून अधिक काळजीपूर्वक प्रशिक्षण धोरण आवश्यक आहे. ऑप्टिमायझर तयार करण्यासाठी आम्ही `tf-models-official` पॅकेज वापरणार आहोत:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"__________________________________________________________________________________________________\n",
"Layer (type) Output Shape Param # Connected to \n",
"==================================================================================================\n",
"input_1 (InputLayer) [(None,)] 0 \n",
"__________________________________________________________________________________________________\n",
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
"__________________________________________________________________________________________________\n",
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
" keras_layer[0][1] \n",
" keras_layer[0][2] \n",
"__________________________________________________________________________________________________\n",
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
"__________________________________________________________________________________________________\n",
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
"==================================================================================================\n",
"Total params: 4,782,981\n",
"Trainable params: 4,782,980\n",
"Non-trainable params: 1\n",
"__________________________________________________________________________________________________\n",
"938/938 [==============================] - 629s 664ms/step - loss: 0.6344 - acc: 0.7658 - val_loss: 0.4876 - val_acc: 0.8247\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9bb0bd0070>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from official.nlp import optimization \n",
"bert.trainable=True\n",
"model.summary()\n",
"epochs = 3\n",
"opt = optimization.create_optimizer(\n",
" init_lr=3e-5,\n",
" num_train_steps=epochs*len(ds_train),\n",
" num_warmup_steps=0.1*epochs*len(ds_train),\n",
" optimizer_type='adamw')\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer=opt)\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जसे तुम्ही पाहू शकता, प्रशिक्षण प्रक्रिया खूपच हळूहळू चालते - पण तुम्हाला कदाचित काही epochs (5-10) साठी मॉडेल प्रशिक्षण देऊन पाहावेसे वाटेल आणि आपण यापूर्वी वापरलेल्या पद्धतींच्या तुलनेत सर्वोत्तम परिणाम मिळवू शकता का ते तपासावे.\n",
"\n",
"## Huggingface Transformers लायब्ररी\n",
"\n",
"Transformer मॉडेल्स वापरण्याचा आणखी एक खूप सामान्य (आणि थोडासा सोपा) मार्ग म्हणजे [HuggingFace पॅकेज](https://github.com/huggingface/), जे विविध NLP कार्यांसाठी सोपी बिल्डिंग ब्लॉक्स प्रदान करते. हे Tensorflow आणि PyTorch या आणखी एका लोकप्रिय न्यूरल नेटवर्क फ्रेमवर्कसाठी उपलब्ध आहे.\n",
"\n",
"> **टीप**: जर तुम्हाला Transformers लायब्ररी कशी कार्य करते हे पाहण्यात रस नसेल - तर तुम्ही या नोटबुकच्या शेवटी जाऊ शकता, कारण तुम्हाला वर केलेल्या गोष्टींपेक्षा काही वेगळे दिसणार नाही. आम्ही वेगळी लायब्ररी आणि तुलनेने मोठ्या मॉडेलचा वापर करून BERT मॉडेल प्रशिक्षणाची तीच पावले पुन्हा घेणार आहोत. त्यामुळे, प्रक्रियेमध्ये काहीसे दीर्घ प्रशिक्षण समाविष्ट आहे, त्यामुळे तुम्हाला फक्त कोड पाहणे अधिक सोयीचे वाटेल.\n",
"\n",
"चला पाहूया की आपली समस्या [Huggingface Transformers](http://huggingface.co) वापरून कशी सोडवता येईल.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"सर्वप्रथम, आपल्याला वापरण्यासाठी कोणता मॉडेल निवडायचा आहे ते ठरवावे लागेल. काही अंगभूत मॉडेल्स व्यतिरिक्त, Huggingface मध्ये [ऑनलाइन मॉडेल रिपॉझिटरी](https://huggingface.co/models) आहे, जिथे तुम्हाला समुदायाने तयार केलेली बरीच प्री-ट्रेन मॉडेल्स सापडतील. या सर्व मॉडेल्स केवळ मॉडेलचे नाव दिल्याने लोड आणि वापरता येतात. मॉडेलसाठी आवश्यक असलेली सर्व बायनरी फाइल्स आपोआप डाउनलोड केल्या जातील.\n",
"\n",
"काही वेळा तुम्हाला स्वतःचे मॉडेल्स लोड करायची गरज भासेल, अशा वेळी तुम्ही त्या डिरेक्टरीचा पत्ता देऊ शकता ज्यामध्ये संबंधित सर्व फाइल्स असतील, जसे की टोकनायझरसाठीचे पॅरामिटर्स, मॉडेल पॅरामिटर्ससह `config.json` फाइल, बायनरी वेट्स इत्यादी.\n",
"\n",
"मॉडेलच्या नावावरून, आपण मॉडेल आणि टोकनायझर दोन्ही तयार करू शकतो. चला टोकनायझरपासून सुरुवात करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import transformers\n",
"\n",
"# To load the model from Internet repository using model name. \n",
"# Use this if you are running from your own copy of the notebooks\n",
"bert_model = 'bert-base-uncased' \n",
"\n",
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
"# prepared all required files for you.\n",
"#bert_model = './bert'\n",
"\n",
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
"\n",
"MAX_SEQ_LEN = 128\n",
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`tokenizer` ऑब्जेक्टमध्ये `encode` फंक्शन असते जी थेट मजकूर एन्कोड करण्यासाठी वापरली जाऊ शकते:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[101, 23435, 12314, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer.encode('Tensorflow is a great framework for NLP')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही टोकनायझरचा वापर करून अनुक्रम एका अशा प्रकारे एन्कोड करू शकतो जो मॉडेलला पास करण्यासाठी योग्य असेल, उदा. `token_ids`, `input_mask` फील्ड्स समाविष्ट करून. तसेच, आम्ही `return_tensors='tf'` युक्तिवाद प्रदान करून Tensorflow टेन्सर्स हवे आहेत हे निर्दिष्ट करू शकतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'input_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[ 101, 7592, 1010, 2045, 102]], dtype=int32)>, 'token_type_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[0, 0, 0, 0, 0]], dtype=int32)>, 'attention_mask': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[1, 1, 1, 1, 1]], dtype=int32)>}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer(['Hello, there'],return_tensors='tf')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपल्या बाबतीत, आपण `bert-base-uncased` नावाचा पूर्व-प्रशिक्षित BERT मॉडेल वापरणार आहोत. *Uncased* म्हणजे मॉडेल केस-संवेदनशील नाही.\n",
"\n",
"मॉडेल प्रशिक्षणाच्या वेळी, आपल्याला टोकनाइझ केलेली अनुक्रमे इनपुट म्हणून प्रदान करावी लागते, आणि म्हणूनच आपण डेटा प्रक्रिया पाइपलाइन डिझाइन करू. कारण `tokenizer.encode` ही एक Python फंक्शन आहे, आपण मागील युनिटमध्ये जसे केले होते त्याच पद्धतीचा वापर करून `py_function` वापरून ती कॉल करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"def process(x):\n",
" return tokenizer.encode(x.numpy().decode('utf-8'),return_tensors='tf',padding='max_length',max_length=MAX_SEQ_LEN,truncation=True)[0]\n",
"\n",
"def process_fn(x):\n",
" s = x['title']+' '+x['description']\n",
" e = tf.py_function(process,inp=[s],Tout=(tf.int32))\n",
" e.set_shape(MAX_SEQ_LEN)\n",
" return e,x['label']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण `BertForSequenceClassification` पॅकेज वापरून वास्तविक मॉडेल लोड करू शकतो. यामुळे आपले मॉडेल वर्गीकरणासाठी आवश्यक असलेली आर्किटेक्चर आधीच तयार असते, ज्यामध्ये अंतिम वर्गीकरणकर्ता समाविष्ट आहे. तुम्हाला एक चेतावणी संदेश दिसेल ज्यामध्ये म्हटले जाईल की अंतिम वर्गीकरणकर्त्याचे वेट्स प्रारंभिक केलेले नाहीत आणि मॉडेलला पूर्व-प्रशिक्षणाची आवश्यकता असेल - ते पूर्णपणे ठीक आहे, कारण आपण नेमके तेच करणार आहोत!\n"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"model = transformers.TFBertForSequenceClassification.from_pretrained(bert_model,num_labels=4,output_attentions=False)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"tf_bert_for_sequence_classification_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"bert (TFBertMainLayer) multiple 109482240 \n",
"_________________________________________________________________\n",
"dropout_75 (Dropout) multiple 0 \n",
"_________________________________________________________________\n",
"classifier (Dense) multiple 3076 \n",
"=================================================================\n",
"Total params: 109,485,316\n",
"Trainable params: 109,485,316\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`summary()` वरून तुम्ही पाहू शकता की, मॉडेलमध्ये जवळजवळ 110 दशलक्ष पॅरामिटर्स आहेत! गृहित धरले तर, जर आपल्याला तुलनेने लहान डेटासेटवर साधे वर्गीकरण कार्य करायचे असेल, तर आपल्याला BERT बेस लेयर प्रशिक्षण द्यायची गरज नाही:\n"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"tf_bert_for_sequence_classification_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"bert (TFBertMainLayer) multiple 109482240 \n",
"_________________________________________________________________\n",
"dropout_75 (Dropout) multiple 0 \n",
"_________________________________________________________________\n",
"classifier (Dense) multiple 3076 \n",
"=================================================================\n",
"Total params: 109,485,316\n",
"Trainable params: 3,076\n",
"Non-trainable params: 109,482,240\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.layers[0].trainable = False\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण प्रशिक्षण सुरू करण्यासाठी तयार आहोत!\n",
"\n",
"> **टीप**: पूर्ण-स्केल BERT मॉडेलचे प्रशिक्षण घेणे खूप वेळखाऊ असू शकते! त्यामुळे आपण फक्त पहिल्या 32 बॅचेससाठी प्रशिक्षण घेणार आहोत. हे फक्त मॉडेल प्रशिक्षण कसे सेट केले जाते हे दाखवण्यासाठी आहे. जर तुम्हाला पूर्ण-स्केल प्रशिक्षण करून पाहायचे असेल - तर `steps_per_epoch` आणि `validation_steps` पॅरामीटर्स काढा, आणि थोडा वेळ थांबण्याची तयारी करा!\n"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32/32 [==============================] - 142s 4s/step - loss: 1.3896 - acc: 0.2500 - val_loss: 1.3863 - val_acc: 0.2480\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f1d40a4b6a0>"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile('adam','sparse_categorical_crossentropy',['acc'])\n",
"tf.get_logger().setLevel('ERROR')\n",
"model.fit(ds_train.map(process_fn).batch(32),validation_data=ds_test.map(process_fn).batch(32),steps_per_epoch=32,validation_steps=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जर तुम्ही पुनरावृत्तींची संख्या वाढवली आणि पुरेसा वेळ दिला, तसेच अनेक epochs साठी प्रशिक्षण दिले, तर तुम्ही अपेक्षा करू शकता की BERT वर्गीकरण आपल्याला सर्वोत्तम अचूकता देईल! कारण BERT आधीच भाषेची रचना चांगल्या प्रकारे समजून घेतो, आणि आपल्याला फक्त अंतिम वर्गीकरणकर्ता fine-tune करायचा आहे. मात्र, BERT हा मोठा मॉडेल असल्यामुळे संपूर्ण प्रशिक्षण प्रक्रिया खूप वेळ घेते आणि त्यासाठी प्रचंड संगणकीय शक्तीची आवश्यकता असते! (GPU, आणि शक्यतो एकापेक्षा जास्त).\n",
"\n",
"> **Note:** आमच्या उदाहरणात, आम्ही सर्वात लहान pre-trained BERT मॉडेलपैकी एक वापरत आहोत. मोठे मॉडेल्स उपलब्ध आहेत जे अधिक चांगले परिणाम देण्याची शक्यता आहे.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य मुद्दा\n",
"\n",
"या युनिटमध्ये, आपण **transformers** आधारित अत्याधुनिक मॉडेल आर्किटेक्चर पाहिले. आपण त्यांचा उपयोग आपल्या टेक्स्ट वर्गीकरण कार्यासाठी केला, परंतु त्याचप्रमाणे BERT मॉडेल्सचा उपयोग घटक शोधणे, प्रश्नोत्तर, आणि इतर NLP कार्यांसाठी केला जाऊ शकतो.\n",
"\n",
"Transformer मॉडेल्स NLP मध्ये सध्याच्या अत्याधुनिक तंत्रज्ञानाचे प्रतिनिधित्व करतात, आणि बहुतेक प्रकरणांमध्ये, कस्टम NLP सोल्यूशन्स अंमलात आणताना प्रयोग करण्यासाठी ही पहिली निवड असावी. तथापि, प्रगत न्यूरल मॉडेल्स तयार करायचे असल्यास, या मॉड्यूलमध्ये चर्चिलेल्या पुनरावृत्ती न्यूरल नेटवर्क्सच्या मूलभूत तत्त्वांचे समजून घेणे अत्यंत महत्त्वाचे आहे.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"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"
},
"kernelspec": {
"display_name": "py38_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"
},
"coopTranslator": {
"original_hash": "ab59c532409774988ab875f2260e8e53",
"translation_date": "2025-08-28T09:26:33+00:00",
"source_file": "lessons/5-NLP/18-Transformers/TransformersTF.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,490 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# नामित घटक ओळख (NER)\n",
"\n",
"हा नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) मधून घेतलेला आहे.\n",
"\n",
"या उदाहरणात, आपण [Annotated Corpus for Named Entity Recognition](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus) या Kaggle वरील डेटासेटचा वापर करून NER मॉडेल कसे प्रशिक्षण द्यायचे ते शिकणार आहोत. पुढे जाण्यापूर्वी, कृपया [ner_dataset.csv](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus?resource=download&select=ner_dataset.csv) फाइल सध्याच्या डिरेक्टरीमध्ये डाउनलोड करा.\n"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from tensorflow import keras\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## डेटासेट तयार करणे\n",
"\n",
"आम्ही डेटासेट वाचून ते एका डेटा फ्रेममध्ये आणण्यापासून सुरुवात करू. तुम्हाला Pandas वापरण्याबद्दल अधिक जाणून घ्यायचे असल्यास, आमच्या [Data Science for Beginners](http://aka.ms/datascience-beginners) मधील [डेटा प्रक्रिया शिकवणी](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python) ला भेट द्या.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Sentence #</th>\n",
" <th>Word</th>\n",
" <th>POS</th>\n",
" <th>Tag</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Sentence: 1</td>\n",
" <td>Thousands</td>\n",
" <td>NNS</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>NaN</td>\n",
" <td>of</td>\n",
" <td>IN</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>demonstrators</td>\n",
" <td>NNS</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>NaN</td>\n",
" <td>have</td>\n",
" <td>VBP</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>NaN</td>\n",
" <td>marched</td>\n",
" <td>VBN</td>\n",
" <td>O</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Sentence # Word POS Tag\n",
"0 Sentence: 1 Thousands NNS O\n",
"1 NaN of IN O\n",
"2 NaN demonstrators NNS O\n",
"3 NaN have VBP O\n",
"4 NaN marched VBN O"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv('ner_dataset.csv',encoding='unicode-escape')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['O', 'B-geo', 'B-gpe', 'B-per', 'I-geo', 'B-org', 'I-org', 'B-tim',\n",
" 'B-art', 'I-art', 'I-per', 'I-gpe', 'I-tim', 'B-nat', 'B-eve',\n",
" 'I-eve', 'I-nat'], dtype=object)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tags = df.Tag.unique()\n",
"tags"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'O'"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"id2tag = dict(enumerate(tags))\n",
"tag2id = { v : k for k,v in id2tag.items() }\n",
"\n",
"id2tag[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपल्याला शब्दसंग्रहासह तेच करणे आवश्यक आहे. सोप्या पद्धतीसाठी, आपण शब्दांची वारंवारता विचारात न घेता शब्दसंग्रह तयार करू; प्रत्यक्ष जीवनात, आपण Keras व्हेक्टरायझर वापरू शकता आणि शब्दांची संख्या मर्यादित करू शकता.\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"vocab = set(df['Word'].apply(lambda x: x.lower()))\n",
"id2word = { i+1 : v for i,v in enumerate(vocab) }\n",
"id2word[0] = '<UNK>'\n",
"vocab.add('<UNK>')\n",
"word2id = { v : k for k,v in id2word.items() }"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्हाला प्रशिक्षणासाठी वाक्यांचा डेटासेट तयार करायचा आहे. चला मूळ डेटासेटमधून फेरफटका मारू आणि सर्व स्वतंत्र वाक्ये `X` (शब्दांच्या यादी) आणि `Y` (टोकनची यादी) मध्ये विभाजित करू:\n"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"X,Y = [],[]\n",
"s,t = [],[]\n",
"for i,row in df[['Sentence #','Word','Tag']].iterrows():\n",
" if pd.isna(row['Sentence #']):\n",
" s.append(row['Word'])\n",
" t.append(row['Tag'])\n",
" else:\n",
" if len(s)>0:\n",
" X.append(s)\n",
" Y.append(t)\n",
" s,t = [row['Word']],[row['Tag']]\n",
"X.append(s)\n",
"Y.append(t)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"([10386,\n",
" 23515,\n",
" 4134,\n",
" 29620,\n",
" 7954,\n",
" 13583,\n",
" 21193,\n",
" 12222,\n",
" 27322,\n",
" 18258,\n",
" 5815,\n",
" 15880,\n",
" 5355,\n",
" 25242,\n",
" 31327,\n",
" 18258,\n",
" 27067,\n",
" 23515,\n",
" 26444,\n",
" 14412,\n",
" 358,\n",
" 26551,\n",
" 5011,\n",
" 30558],\n",
" [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0])"
]
},
"execution_count": 93,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def vectorize(seq):\n",
" return [word2id[x.lower()] for x in seq]\n",
"\n",
"def tagify(seq):\n",
" return [tag2id[x] for x in seq]\n",
"\n",
"Xv = list(map(vectorize,X))\n",
"Yv = list(map(tagify,Y))\n",
"\n",
"Xv[0], Yv[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"साधेपणासाठी, आपण सर्व वाक्ये कमाल लांबीपर्यंत 0 टोकनसह भरून काढू. वास्तविक जीवनात, आपण अधिक हुशार रणनीती वापरू शकतो आणि फक्त एका मिनीबॅचमध्ये अनुक्रम भरून काढू.\n"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
"X_data = keras.preprocessing.sequence.pad_sequences(Xv,padding='post')\n",
"Y_data = keras.preprocessing.sequence.pad_sequences(Yv,padding='post')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टोकन वर्गीकरण नेटवर्क परिभाषित करणे\n",
"\n",
"टोकन वर्गीकरणासाठी आपण दोन-स्तरीय द्विदिशात्मक LSTM नेटवर्क वापरणार आहोत. शेवटच्या LSTM स्तराच्या प्रत्येक आउटपुटवर घन वर्गीकरणकर्ता लागू करण्यासाठी, आपण `TimeDistributed` संरचना वापरणार आहोत, जी LSTM च्या प्रत्येक टप्प्यावर समान घन स्तराची पुनरावृत्ती करते:\n"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_3\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" embedding_4 (Embedding) (None, 104, 300) 9545400 \n",
" \n",
" bidirectional_6 (Bidirectio (None, 104, 200) 320800 \n",
" nal) \n",
" \n",
" bidirectional_7 (Bidirectio (None, 104, 200) 240800 \n",
" nal) \n",
" \n",
" time_distributed_3 (TimeDis (None, 104, 17) 3417 \n",
" tributed) \n",
" \n",
"=================================================================\n",
"Total params: 10,110,417\n",
"Trainable params: 10,110,417\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"maxlen = X_data.shape[1]\n",
"vocab_size = len(vocab)\n",
"num_tags = len(tags)\n",
"model = keras.models.Sequential([\n",
" keras.layers.Embedding(vocab_size, 300, input_length=maxlen),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
" keras.layers.TimeDistributed(keras.layers.Dense(num_tags, activation='softmax'))\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"येथे आपण आपल्या डेटासेटसाठी `maxlen` स्पष्टपणे निर्दिष्ट करत आहोत - जर आपल्याला नेटवर्कला बदलत्या लांबीच्या अनुक्रमांचे व्यवस्थापन करण्यास सक्षम करायचे असेल, तर नेटवर्क परिभाषित करताना आपल्याला थोडे अधिक हुशार असणे आवश्यक आहे.\n",
"\n",
"आता आपण मॉडेल प्रशिक्षण देऊया. गतीसाठी, आपण फक्त एकच epoch साठी प्रशिक्षण देणार आहोत, परंतु आपण अधिक वेळासाठी प्रशिक्षण देण्याचा प्रयत्न करू शकता. तसेच, आपण डेटासेटचा काही भाग प्रशिक्षण डेटासेट म्हणून वेगळा ठेवू शकता, जेणेकरून सत्यापन अचूकता निरीक्षण करता येईल.\n"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1499/1499 [==============================] - 740s 488ms/step - loss: 0.0667 - acc: 0.9841\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x16f0bb2a310>"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.fit(X_data,Y_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## निकालाची चाचणी करणे\n",
"\n",
"आता पाहूया की आपला एंटिटी ओळखण्याचा मॉडेल एका नमुना वाक्यावर कसा कार्य करतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {},
"outputs": [],
"source": [
"sent = 'John Smith went to Paris to attend a conference in cancer development institute'\n",
"words = sent.lower().split()\n",
"v = keras.preprocessing.sequence.pad_sequences([[word2id[x] for x in words]],padding='post',maxlen=maxlen)\n",
"res = model(v)[0]"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"john -> B-per\n",
"smith -> I-per\n",
"went -> O\n",
"to -> O\n",
"paris -> B-geo\n",
"to -> O\n",
"attend -> O\n",
"a -> O\n",
"conference -> O\n",
"in -> O\n",
"cancer -> B-org\n",
"development -> I-org\n",
"institute -> I-org\n"
]
}
],
"source": [
"r = np.argmax(res.numpy(),axis=1)\n",
"for i,w in zip(r,words):\n",
" print(f\"{w} -> {id2tag[i]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य मुद्दा\n",
"\n",
"साधा LSTM मॉडेल देखील NER मध्ये समाधानकारक परिणाम दाखवतो. मात्र, अधिक चांगले परिणाम मिळवण्यासाठी, तुम्ही BERT सारखे मोठे पूर्व-प्रशिक्षित भाषा मॉडेल्स वापरण्याचा विचार करू शकता. Huggingface Transformers लायब्ररीचा वापर करून NER साठी BERT प्रशिक्षण कसे द्यावे, याचे वर्णन [येथे](https://huggingface.co/course/chapter7/2?fw=pt) केले आहे.\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": "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"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "254d25052dcca4ef84f59a05f2935bdc",
"translation_date": "2025-08-28T09:31:32+00:00",
"source_file": "lessons/5-NLP/19-NER/NER-TF.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,325 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## OpenAI GPT सोबत प्रयोग करणे\n",
"\n",
"हा नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) चा एक भाग आहे.\n",
"\n",
"या नोटबुकमध्ये, आपण Hugging Face च्या `transformers` लायब्ररीचा वापर करून OpenAI-GPT मॉडेलसोबत कसे प्रयोग करू शकतो हे पाहणार आहोत.\n",
"\n",
"तर मग वेळ न दवडता, टेक्स्ट जनरेटिंग पाईपलाइन तयार करूया आणि जनरेट करायला सुरुवात करूया!\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n",
"Downloading model.safetensors: 100%|██████████| 479M/479M [04:28<00:00, 1.78MB/s] \n",
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\huggingface_hub\\file_download.py:133: UserWarning: `huggingface_hub` cache-system uses symlinks by default to efficiently store duplicated files but your machine does not support them in C:\\Users\\bethanycheum\\.cache\\huggingface\\hub. Caching files will still work but in a degraded version that might require more space on your disk. This warning can be disabled by setting the `HF_HUB_DISABLE_SYMLINKS_WARNING` environment variable. For more details, see https://huggingface.co/docs/huggingface_hub/how-to-cache#limitations.\n",
"To support symlinks on Windows, you either need to activate Developer Mode or to run Python as an administrator. In order to see activate developer mode, see this article: https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development\n",
" warnings.warn(message)\n",
"Some weights of OpenAIGPTLMHeadModel were not initialized from the model checkpoint at openai-gpt and are newly initialized: ['position_ids']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
"Downloading (…)neration_config.json: 100%|██████████| 74.0/74.0 [00:00<00:00, 48.8kB/s]\n",
"Downloading (…)olve/main/vocab.json: 100%|██████████| 816k/816k [00:00<00:00, 1.76MB/s]\n",
"Downloading (…)olve/main/merges.txt: 100%|██████████| 458k/458k [00:00<00:00, 1.11MB/s]\n",
"Downloading (…)/main/tokenizer.json: 100%|██████████| 1.27M/1.27M [00:00<00:00, 2.12MB/s]\n",
"Xformers is not installed correctly. If you want to use memory_efficient_attention to accelerate training use the following command to install Xformers\n",
"pip install xformers.\n"
]
},
{
"data": {
"text/plain": [
"[{'generated_text': \"Hello! I am a neural network, and I want to say that i apologize for not coming to you yourself, for not helping you, and that i was too busy getting dressed and studying for a midterm. you know, the kind where the teachers are like that and they come in pairs with their boyfriends, but not with theirs. it's true, that i have had a girlfriend, and i'm only going on wednesdays and thursdays because i was too busy with college, but maybe\"},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that we have been blessed with a wonderful gift ; no one of us has died at all. and our spirits are strong, very strong. in one very lucky moment of luck for you, all has been given direction and destiny, and for us there are no more mysteries. the earth has been chosen for you, and that earth is now ours, and you must be forever in our hearts. \" \\n the words, as one,'},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that if you would just turn and face the general, you would have a nice day. \" \\n \" sure thing, \" said one of the soldiers, and started to run. the rest of the soldiers followed, shouting. the general turned to general zulu, raising his arm. the general said something in his native language, and the general immediately started to run. zulu started to move toward the wall, with the'},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that i am not a doctor but an anthropologist to you, a specialist, a specialist in the field of astrobiological biology, and that i am very much involved in this investigation. i am not sure, i am not certain, but i can confirm your conclusions and therefore i will go to the top. i have a colleague who has just returned from this expedition and his findings confirm that you are a specialist. that is, he'},\n",
" {'generated_text': \"Hello! I am a neural network, and I want to say that everyone here is in agreement that no matter how many times i say to myself,'he was never a man of action on the battlefield,'or'he 'll never take a chance at killing any civilians,'or'he 'll never let his men go undefended against enemy forces of this caliber,'or'that's just what i need in a day like today. \\n you see, there are only three groups that\"}]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from transformers import pipeline\n",
"\n",
"model_name = 'openai-gpt' \n",
"\n",
"generator = pipeline('text-generation', model=model_name)\n",
"\n",
"generator(\"Hello! I am a neural network, and I want to say that\", max_length=100, num_return_sequences=5)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## प्रॉम्प्ट इंजिनिअरिंग\n",
"\n",
"काही समस्यांमध्ये, योग्य प्रॉम्प्ट तयार करून तुम्ही थेट openai-gpt जनरेशनचा वापर करू शकता. खालील उदाहरणे पाहा:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'Synonyms of a word cat: the same cat i used to stare at, and you in'},\n",
" {'generated_text': 'Synonyms of a word cat: cat of the woods, cat of the hills, cat of'},\n",
" {'generated_text': 'Synonyms of a word cat: you! \\n \" it\\'s a girl. \" i said'},\n",
" {'generated_text': \"Synonyms of a word cat: big cat. but how come, we didn't hear it\"},\n",
" {'generated_text': 'Synonyms of a word cat: \" mea - o - c \" which makes them sound'}]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"Synonyms of a word cat:\", max_length=20, num_return_sequences=5)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive this is so horrible - > positive that your brother is gay - >'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i will bring this on you -, < positive am i, i'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i have self - esteem i must take it - : \\n - -'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative this is - : \\n if it were true that the devil would have'},\n",
" {'generated_text': \"I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive i have you - > positive it's a bad thing, > positive\"}]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this ->\", max_length=40, num_return_sequences=5)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'Translate English to French: cat => chat, dog => chien, student => new and unusual. there were no more words to be'},\n",
" {'generated_text': 'Translate English to French: cat => chat, dog => chien, student => student \\n his eyes were huge in his lean face as'},\n",
" {'generated_text': \"Translate English to French: cat => chat, dog => chien, student => the teacher's words, their words, their words.\"}]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"Translate English to French: cat => chat, dog => chien, student => \", top_k=50, max_length=30, num_return_sequences=3)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'People who liked the movie The Matrix also liked it, and there was the movie of the first man after us. \\n i wanted to laugh at how stupid these stupid actors were. no, they were'},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and the film was the result. and that's when the man in the story was brought into reality, after a few decades. \\n a\"},\n",
" {'generated_text': 'People who liked the movie The Matrix also liked the movie the matrix, because there was a very old movie movie called the matrix, where there was a great super hero, and the super hero came out'},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie that didn't have a chance to pay cash, if they could afford it. most often they got a good deal and a lot of money,\"},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and i didn't seem to have the same problem. \\n i 'd met the other half of my family. i spent most of my time\"}]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"People who liked the movie The Matrix also liked \", max_length=40, num_return_sequences=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टेक्स्ट नमुना रणनीती\n",
"\n",
"आत्तापर्यंत आपण साधी **लोभाची** नमुना रणनीती वापरत होतो, जिथे पुढील शब्द उच्चतम संभाव्यतेच्या आधारावर निवडला जात होता. हे कसे कार्य करते:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my friend, a young man, sprawled across the bed in his bed. \\n \" hi, i\\'m mike eptirard. \" \\n there was silence on the other side of the door. i listened for any trace of life but there was nothing. my heart began to pound, i was starting to sweat, i took out my wallet'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my mother on the bed, hugging her legs to her chest and sobbing. i saw my dad and mother from the corner of my eye. \\n elfin face was covered in tears as i entered the room. my dad and mother also wept ; just as they did every other time i came to work. but this time, they had different faces'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw the room had changed because it was dark. it still smelled like a hospital. a new light shined through from a vent in the ceiling. i found myself in a bathroom and a small room with a sink and a wall of glass. the bathroom billion years ago. not so different from all of the rest of the apartment. \\n now...'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a large woman with dark hair and pale skin. she was asleep, but i noticed a faint movement of her face. i could sense she was awake. i got up and walked over to her. \\n \" hello miss. i am inspector michael o\\'dell ; we are investigating the case against you. i wanted to ask if you were the'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw i had an empty table and three empty chairs. that was all i needed. i had left a note on a table in the center of the room and had a pen in hand. \" \\n \" i think what you were doing was something he was doing to her. \" \\n \" yeah, \" i nodded with a grin. \" i'}]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,num_return_sequences=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**बीम सर्च** जनरेटरला मजकूर निर्मितीच्या अनेक दिशांचा (*बीम्स*) शोध घेण्याची आणि उच्च एकूण स्कोअर असलेल्या पर्यायांची निवड करण्याची परवानगी देते. तुम्ही `num_beams` पॅरामीटर प्रदान करून बीम सर्च करू शकता. तुम्ही `no_repeat_ngram_size` निर्दिष्ट करून दिलेल्या आकाराच्या n-grams पुनरावृत्तीबद्दल मॉडेलला दंड देखील लागू करू शकता:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting in a chair with his head in his hands. he didn\\'t look up as i approached. \\n \" excuse me, sir, \" i said. \" can i help you? \" \\n the man looked up at me. his eyes were red - rimmed and his face was pale, as if he hadn\\'t slept in days'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a desk in the middle of the room. he had his back to me, so i couldn\\'t see what he was doing. \" \\n \" what did he look like? \" i asked as i sat down on the bed next to her. \\n she took a deep breath and looked at me with tears in her eyes'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the bed, reading a book. she looked up at me and smiled. \\n \" hi, \" she said. \" can i help you? \" \\n i sat down next to her and looked around the room. the walls were white, and there was a large window in the middle of the wall that looked out on'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a table in the middle of the room. he looked up as i walked in, and when he saw me, he got up and walked over to me. \\n \" can i help you? \" he asked as he put his hand on the small of my back and led me to a chair at the other end of'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the edge of her bed, reading a book. she looked up at me and smiled. \\n \" hello, \" she said. \" can i help you? \" \\n i didn\\'t know what to say, so i just sat down in the chair next to the bed and looked at her. her hair was dark brown'}]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,num_return_sequences=5,num_beams=10,no_repeat_ngram_size=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**नमुना** पुढील शब्द अनिश्चितपणे निवडतो, मॉडेलने परत केलेल्या संभाव्यता वितरणाचा वापर करून. तुम्ही `do_sample=True` पॅरामीटर वापरून नमुना चालू करू शकता. तुम्ही `temperature` देखील निर्दिष्ट करू शकता, ज्यामुळे मॉडेल अधिक किंवा कमी निर्धारक होईल.\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw her. she was on the bed, but she looked very different. \\n \" honey, what\\'s the matter? \" i asked. \\n she sat up. \" i can\\'t believe it\\'s real. i\\'ve been dreaming about you for the last two days. \" \\n \" i can\\'t believe it either. i guess that\\'s how'}]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,do_sample=True,temperature=0.8)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही नमुना घेण्यामध्ये अतिरिक्त पॅरामीटर्स देखील प्रदान करू शकतो:\n",
"* `top_k` नमुना घेताना विचारात घेण्यासारख्या शब्द पर्यायांची संख्या निर्दिष्ट करते. यामुळे आपल्या मजकुरात विचित्र (कमी-प्रमाणिकता असलेले) शब्द येण्याची शक्यता कमी होते.\n",
"* `top_p` यासारखेच आहे, परंतु आम्ही सर्वात संभाव्य शब्दांचा लहान उपसंच निवडतो, ज्यांची एकूण संभाव्यता p पेक्षा जास्त असते.\n",
"\n",
"हे पॅरामीटर्स जोडून प्रयोग करण्यासाठी मोकळ्या मनाने पुढे जा.\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## आपल्या मॉडेल्सचे फाइन-ट्यूनिंग\n",
"\n",
"आपण आपल्या स्वतःच्या डेटासेटवर [आपले मॉडेल फाइन-ट्यून](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/fine-tuning?pivots=programming-language-studio?WT.mc_id=academic-77998-bethanycheum) करू शकता. यामुळे आपल्याला मजकुराचा शैली समायोजित करण्याची परवानगी मिळेल, मुख्य भाषा मॉडेल कायम ठेवत.\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": "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.10.11"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "d4ff89615d38924a55594f16d6d20678",
"translation_date": "2025-08-28T09:30:12+00:00",
"source_file": "lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,49 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## असाइनमेंट: डायोफंटाइन समीकरणे\n",
"\n",
"> हे असाइनमेंट [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) चा भाग आहे आणि [या पोस्ट](https://habr.com/post/128704/) वरून प्रेरित आहे.\n",
"\n",
"तुमचे उद्दिष्ट म्हणजे **डायोफंटाइन समीकरण** सोडवणे - एक असे समीकरण ज्यामध्ये पूर्णांक मुळे आणि पूर्णांक गुणांक असतात. उदाहरणार्थ, खालील समीकरण विचार करा:\n",
"\n",
"$$a+2b+3c+4d=30$$\n",
"\n",
"तुम्हाला असे पूर्णांक मुळे $a$,$b$,$c$,$d\\in\\mathbb{N}$ शोधायचे आहेत जे हे समीकरण पूर्ण करतात.\n",
"\n",
"सूचना:\n",
"1. मुळे [0;30] या श्रेणीत असू शकतात असे गृहीत धरा.\n",
"1. जीन म्हणून, मूळ मूल्यांच्या यादीचा विचार करा.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरे त्रुटी किंवा अचूकतेच्या अभावाने युक्त असू शकतात. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "a967e1fa1e11ab2b6467b19349a4a9aa",
"translation_date": "2025-08-28T07:26:32+00:00",
"source_file": "lessons/6-Other/21-GeneticAlgorithms/Diophantine.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,501 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# कार्टपोल संतुलनासाठी RL प्रशिक्षण\n",
"\n",
"हे नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) चा भाग आहे. हे [अधिकृत PyTorch ट्यूटोरियल](https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html) आणि [Cartpole PyTorch अंमलबजावणी](https://github.com/yc930401/Actor-Critic-pytorch) यापासून प्रेरित आहे.\n",
"\n",
"या उदाहरणात, आपण RL वापरून एक मॉडेल प्रशिक्षित करू जे एका गाड्यावर असलेल्या खांबाला संतुलित ठेवेल, जो आडव्या पट्टीवर डावीकडे आणि उजवीकडे हलू शकतो. आम्ही [OpenAI Gym](https://www.gymlibrary.ml/) पर्यावरणाचा वापर करून खांबाचे अनुकरण करू.\n",
"\n",
"> **Note**: तुम्ही या धड्याचा कोड स्थानिक पातळीवर (उदा. Visual Studio Code मधून) चालवू शकता, अशा परिस्थितीत अनुकरण एका नवीन विंडोमध्ये उघडेल. ऑनलाइन कोड चालवताना, तुम्हाला कोडमध्ये काही बदल करावे लागतील, जसे [येथे](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7) वर्णन केले आहे.\n",
"\n",
"आपण सुरुवात जिम स्थापित असल्याची खात्री करून करू:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"!{sys.executable} -m pip install gym"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता CartPole वातावरण तयार करूया आणि त्यावर कसे कार्य करायचे ते पाहूया. एका वातावरणामध्ये खालील गुणधर्म असतात:\n",
"\n",
"* **Action space** म्हणजे प्रत्येक सिम्युलेशनच्या टप्प्यावर आपण करू शकणाऱ्या संभाव्य क्रियांची श्रेणी \n",
"* **Observation space** म्हणजे आपण करू शकणाऱ्या निरीक्षणांची श्रेणी \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import gym\n",
"\n",
"env = gym.make(\"CartPole-v1\")\n",
"\n",
"print(f\"Action space: {env.action_space}\")\n",
"print(f\"Observation space: {env.observation_space}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला पाहूया की सिम्युलेशन कसे कार्य करते. खालील लूप सिम्युलेशन चालवतो, जोपर्यंत `env.step` टर्मिनेशन फ्लॅग `done` परत करत नाही. आम्ही `env.action_space.sample()` वापरून कृती निवडू, ज्याचा अर्थ असा आहे की प्रयोग फार लवकर अपयशी होण्याची शक्यता आहे (CartPole वातावरण संपते जेव्हा CartPole चा वेग, त्याचे स्थान किंवा कोन विशिष्ट मर्यादांच्या बाहेर जातो).\n",
"\n",
"> सिम्युलेशन नवीन विंडोमध्ये उघडेल. तुम्ही कोड अनेक वेळा चालवू शकता आणि त्याचे वर्तन कसे आहे ते पाहू शकता.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"env.reset()\n",
"\n",
"done = False\n",
"total_reward = 0\n",
"while not done:\n",
" env.render()\n",
" obs, rew, done, info = env.step(env.action_space.sample())\n",
" total_reward += rew\n",
" print(f\"{obs} -> {rew}\")\n",
"print(f\"Total reward: {total_reward}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपण पाहू शकता की निरीक्षणांमध्ये 4 संख्या असतात. त्या आहेत:\n",
"- गाडीची स्थिती\n",
"- गाडीचा वेग\n",
"- खांबाचा कोन\n",
"- खांबाच्या फिरण्याचा दर\n",
"\n",
"`rew` हा प्रत्येक टप्प्यावर आपल्याला मिळणारा बक्षीस आहे. CartPole वातावरणात, प्रत्येक सिम्युलेशन टप्प्यासाठी तुम्हाला 1 गुण दिला जातो, आणि उद्दिष्ट म्हणजे एकूण बक्षीस जास्तीत जास्त करणे, म्हणजे CartPole पडल्याशिवाय तोल सांभाळण्याचा कालावधी वाढवणे.\n",
"\n",
"रिइनफोर्समेंट लर्निंग दरम्यान, आपले उद्दिष्ट म्हणजे एक **पॉलिसी** $\\pi$ तयार करणे, जी प्रत्येक स्थिती $s$ साठी आपल्याला कोणती क्रिया $a$ घ्यायची ते सांगेल, म्हणजेच मूलतः $a = \\pi(s)$.\n",
"\n",
"जर तुम्हाला संभाव्यताधारित उपाय हवा असेल, तर तुम्ही पॉलिसीला प्रत्येक क्रियेसाठी संभाव्यता परत करणारी प्रणाली म्हणून विचार करू शकता, म्हणजे $\\pi(a|s)$ याचा अर्थ असा होईल की स्थिती $s$ वर आपण क्रिया $a$ घ्यावी याची संभाव्यता.\n",
"\n",
"## पॉलिसी ग्रेडियंट पद्धत\n",
"\n",
"सर्वात सोप्या RL अल्गोरिदममध्ये, ज्याला **पॉलिसी ग्रेडियंट** म्हणतात, आपण पुढील क्रिया भाकीत करण्यासाठी एक न्यूरल नेटवर्क प्रशिक्षित करू.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import torch\n",
"\n",
"num_inputs = 4\n",
"num_actions = 2\n",
"\n",
"model = torch.nn.Sequential(\n",
" torch.nn.Linear(num_inputs, 128, bias=False, dtype=torch.float32),\n",
" torch.nn.ReLU(),\n",
" torch.nn.Linear(128, num_actions, bias = False, dtype=torch.float32),\n",
" torch.nn.Softmax(dim=1)\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्ही अनेक प्रयोग चालवून आणि प्रत्येक प्रयोगानंतर आमच्या नेटवर्कचे अद्यतन करून नेटवर्क प्रशिक्षण देऊ. चला एक फंक्शन परिभाषित करूया जे प्रयोग चालवेल आणि परिणाम परत करेल (तथाकथित **ट्रेस**) - सर्व स्थिती, क्रिया (आणि त्यांचे शिफारस केलेले संभाव्यता), आणि बक्षिसे:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def run_episode(max_steps_per_episode = 10000,render=False): \n",
" states, actions, probs, rewards = [],[],[],[]\n",
" state = env.reset()\n",
" for _ in range(max_steps_per_episode):\n",
" if render:\n",
" env.render()\n",
" action_probs = model(torch.from_numpy(np.expand_dims(state,0)))[0]\n",
" action = np.random.choice(num_actions, p=np.squeeze(action_probs.detach().numpy()))\n",
" nstate, reward, done, info = env.step(action)\n",
" if done:\n",
" break\n",
" states.append(state)\n",
" actions.append(action)\n",
" probs.append(action_probs.detach().numpy())\n",
" rewards.append(reward)\n",
" state = nstate\n",
" return np.vstack(states), np.vstack(actions), np.vstack(probs), np.vstack(rewards)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आपण प्रशिक्षित न केलेल्या नेटवर्कसह एक एपिसोड चालवू शकता आणि लक्षात घेऊ शकता की एकूण बक्षीस (एपिसोडची लांबी म्हणून ओळखले जाते) खूप कमी आहे:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s, a, p, r = run_episode()\n",
"print(f\"Total reward: {np.sum(r)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"धोरण ग्रेडियंट अल्गोरिदमच्या क्लिष्ट पैलूंमध्ये **सवलतीच्या बक्षिसांचा** वापर करणे आहे. कल्पना अशी आहे की आपण खेळाच्या प्रत्येक टप्प्यावर एकूण बक्षिसांचा वेक्टर गणना करतो, आणि या प्रक्रियेदरम्यान काही गुणांक $gamma$ वापरून सुरुवातीची बक्षिसे सवलत देतो. आम्ही परिणामी वेक्टर सामान्यीकृत देखील करतो, कारण आम्ही ते आमच्या प्रशिक्षणावर परिणाम करण्यासाठी वजन म्हणून वापरणार आहोत:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eps = 0.0001\n",
"\n",
"def discounted_rewards(rewards,gamma=0.99,normalize=True):\n",
" ret = []\n",
" s = 0\n",
" for r in rewards[::-1]:\n",
" s = r + gamma * s\n",
" ret.insert(0, s)\n",
" if normalize:\n",
" ret = (ret-np.mean(ret))/(np.std(ret)+eps)\n",
" return ret"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता प्रत्यक्ष प्रशिक्षण सुरू करूया! आपण 300 एपिसोड चालवणार आहोत, आणि प्रत्येक एपिसोडमध्ये खालील गोष्टी करूया:\n",
"\n",
"1. प्रयोग चालवा आणि ट्रेस गोळा करा\n",
"1. घेतलेल्या कृती आणि अंदाजित संभाव्यता यांच्यातील फरक (`gradients`) मोजा. फरक जितका कमी असेल, तितके आम्हाला खात्री आहे की योग्य कृती घेतली आहे.\n",
"1. सवलतीच्या बक्षिसे मोजा आणि सवलतीच्या बक्षिसांद्वारे `gradients` गुणाकार करा - यामुळे उच्च बक्षिस असलेल्या टप्प्यांचा अंतिम निकालावर अधिक प्रभाव पडेल, तुलनेने कमी बक्षिस असलेल्या टप्प्यांपेक्षा.\n",
"1. आमच्या न्यूरल नेटवर्कसाठी अपेक्षित लक्ष्य कृती काही प्रमाणात चालवताना अंदाजित संभाव्यतेमधून घेतल्या जातील, आणि काही प्रमाणात गणितीय `gradients` मधून. आम्ही `alpha` पॅरामीटर वापरून ठरवू की `gradients` आणि बक्षिसे किती प्रमाणात विचारात घेतली जातील - याला reinforcement algorithm चा *learning rate* म्हणतात.\n",
"1. शेवटी, आम्ही आमच्या नेटवर्कला states आणि अपेक्षित कृतींवर प्रशिक्षण देतो, आणि प्रक्रिया पुन्हा सुरू करतो.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n",
"\n",
"def train_on_batch(x, y):\n",
" x = torch.from_numpy(x)\n",
" y = torch.from_numpy(y)\n",
" optimizer.zero_grad()\n",
" predictions = model(x)\n",
" loss = -torch.mean(torch.log(predictions) * y)\n",
" loss.backward()\n",
" optimizer.step()\n",
" return loss"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"alpha = 1e-4\n",
"\n",
"history = []\n",
"for epoch in range(300):\n",
" states, actions, probs, rewards = run_episode()\n",
" one_hot_actions = np.eye(2)[actions.T][0]\n",
" gradients = one_hot_actions-probs\n",
" dr = discounted_rewards(rewards)\n",
" gradients *= dr\n",
" target = alpha*np.vstack([gradients])+probs\n",
" train_on_batch(states,target)\n",
" history.append(np.sum(rewards))\n",
" if epoch%100==0:\n",
" print(f\"{epoch} -> {np.sum(rewards)}\")\n",
"\n",
"plt.plot(history)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता परिणाम पाहण्यासाठी रेंडरिंगसह एपिसोड चालवूया:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"_ = run_episode(render=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आशा आहे की आता तुम्हाला दिसत असेल की खांब चांगल्या प्रकारे संतुलित राहू शकतो!\n",
"\n",
"## अभिनेता-समालोचक मॉडेल\n",
"\n",
"अभिनेता-समालोचक मॉडेल हे पॉलिसी ग्रेडियंट्सचे पुढील विकसित रूप आहे, ज्यामध्ये आम्ही धोरण आणि अंदाजित बक्षिसे शिकण्यासाठी एक न्यूरल नेटवर्क तयार करतो. या नेटवर्कला दोन आउटपुट्स असतील (किंवा तुम्ही याला दोन स्वतंत्र नेटवर्क्स म्हणून पाहू शकता):\n",
"* **अभिनेता (Actor)** पॉलिसी ग्रेडियंट मॉडेलप्रमाणेच, स्थितीची संभाव्यता वितरण देऊन कोणती कृती करायची याची शिफारस करतो.\n",
"* **समालोचक (Critic)** त्या कृतींमधून मिळणाऱ्या बक्षिसांचा अंदाज लावतो. दिलेल्या स्थितीत भविष्यातील एकूण अंदाजित बक्षिसे परत करतो.\n",
"\n",
"चला असे मॉडेल परिभाषित करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from itertools import count\n",
"import torch.nn.functional as F"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
"env = gym.make(\"CartPole-v1\")\n",
"\n",
"state_size = env.observation_space.shape[0]\n",
"action_size = env.action_space.n\n",
"lr = 0.0001\n",
"\n",
"class Actor(torch.nn.Module):\n",
" def __init__(self, state_size, action_size):\n",
" super(Actor, self).__init__()\n",
" self.state_size = state_size\n",
" self.action_size = action_size\n",
" self.linear1 = torch.nn.Linear(self.state_size, 128)\n",
" self.linear2 = torch.nn.Linear(128, 256)\n",
" self.linear3 = torch.nn.Linear(256, self.action_size)\n",
"\n",
" def forward(self, state):\n",
" output = F.relu(self.linear1(state))\n",
" output = F.relu(self.linear2(output))\n",
" output = self.linear3(output)\n",
" distribution = torch.distributions.Categorical(F.softmax(output, dim=-1))\n",
" return distribution\n",
"\n",
"\n",
"class Critic(torch.nn.Module):\n",
" def __init__(self, state_size, action_size):\n",
" super(Critic, self).__init__()\n",
" self.state_size = state_size\n",
" self.action_size = action_size\n",
" self.linear1 = torch.nn.Linear(self.state_size, 128)\n",
" self.linear2 = torch.nn.Linear(128, 256)\n",
" self.linear3 = torch.nn.Linear(256, 1)\n",
"\n",
" def forward(self, state):\n",
" output = F.relu(self.linear1(state))\n",
" output = F.relu(self.linear2(output))\n",
" value = self.linear3(output)\n",
" return value"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आम्हाला आमच्या `discounted_rewards` आणि `run_episode` फंक्शन्समध्ये थोडा बदल करावा लागेल:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def discounted_rewards(next_value, rewards, masks, gamma=0.99):\n",
" R = next_value\n",
" returns = []\n",
" for step in reversed(range(len(rewards))):\n",
" R = rewards[step] + gamma * R * masks[step]\n",
" returns.insert(0, R)\n",
" return returns\n",
"\n",
"def run_episode(actor, critic, n_iters):\n",
" optimizerA = torch.optim.Adam(actor.parameters())\n",
" optimizerC = torch.optim.Adam(critic.parameters())\n",
" for iter in range(n_iters):\n",
" state = env.reset()\n",
" log_probs = []\n",
" values = []\n",
" rewards = []\n",
" masks = []\n",
" entropy = 0\n",
" env.reset()\n",
"\n",
" for i in count():\n",
" env.render()\n",
" state = torch.FloatTensor(state).to(device)\n",
" dist, value = actor(state), critic(state)\n",
"\n",
" action = dist.sample()\n",
" next_state, reward, done, _ = env.step(action.cpu().numpy())\n",
"\n",
" log_prob = dist.log_prob(action).unsqueeze(0)\n",
" entropy += dist.entropy().mean()\n",
"\n",
" log_probs.append(log_prob)\n",
" values.append(value)\n",
" rewards.append(torch.tensor([reward], dtype=torch.float, device=device))\n",
" masks.append(torch.tensor([1-done], dtype=torch.float, device=device))\n",
"\n",
" state = next_state\n",
"\n",
" if done:\n",
" print('Iteration: {}, Score: {}'.format(iter, i))\n",
" break\n",
"\n",
"\n",
" next_state = torch.FloatTensor(next_state).to(device)\n",
" next_value = critic(next_state)\n",
" returns = discounted_rewards(next_value, rewards, masks)\n",
"\n",
" log_probs = torch.cat(log_probs)\n",
" returns = torch.cat(returns).detach()\n",
" values = torch.cat(values)\n",
"\n",
" advantage = returns - values\n",
"\n",
" actor_loss = -(log_probs * advantage.detach()).mean()\n",
" critic_loss = advantage.pow(2).mean()\n",
"\n",
" optimizerA.zero_grad()\n",
" optimizerC.zero_grad()\n",
" actor_loss.backward()\n",
" critic_loss.backward()\n",
" optimizerA.step()\n",
" optimizerC.step()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"आता आपण मुख्य प्रशिक्षण लूप चालवू. योग्य तोटा फंक्शन्स मोजून आणि नेटवर्क पॅरामीटर्स अद्यतनित करून आपण मॅन्युअल नेटवर्क प्रशिक्षण प्रक्रिया वापरू:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"actor = Actor(state_size, action_size).to(device)\n",
"critic = Critic(state_size, action_size).to(device)\n",
"run_episode(actor, critic, n_iters=100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"env.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य मुद्दा\n",
"\n",
"या डेमोमध्ये आपण दोन RL अल्गोरिदम पाहिले: साधा पॉलिसी ग्रेडियंट आणि अधिक प्रगत अ‍ॅक्टर-क्रिटिक. तुम्ही पाहू शकता की हे अल्गोरिदम स्टेट, अ‍ॅक्शन आणि रिवॉर्ड यांसारख्या अमूर्त संकल्पनांवर कार्य करतात - त्यामुळे ते खूप वेगवेगळ्या वातावरणांमध्ये लागू केले जाऊ शकतात.\n",
"\n",
"रिइनफोर्समेंट लर्निंग आपल्याला केवळ अंतिम रिवॉर्ड पाहून समस्या सोडवण्यासाठी सर्वोत्तम रणनीती शिकण्याची परवानगी देते. लेबल केलेल्या डेटासेटची गरज नसल्यामुळे, आपल्याला आपल्या मॉडेल्सचा ऑप्टिमायझेशन करण्यासाठी सिम्युलेशन्स अनेक वेळा पुन्हा पुन्हा चालवता येतात. तथापि, RL मध्ये अजूनही अनेक आव्हाने आहेत, जी तुम्हाला शिकता येतील जर तुम्ही या AI च्या रंजक क्षेत्रावर अधिक लक्ष केंद्रित करण्याचा निर्णय घेतला.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून निर्माण होणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.4 64-bit",
"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.10.4"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
}
},
"coopTranslator": {
"original_hash": "04f8d9978cd11281d81dd037cbf6ce20",
"translation_date": "2025-08-28T07:32:18+00:00",
"source_file": "lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,109 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# # माउंटन कारला पळून जाण्यासाठी प्रशिक्षण देणे\n",
"\n",
"[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) मधील प्रयोगशाळा असाइनमेंट.\n",
"\n",
"तुमचे उद्दिष्ट आहे RL एजंटला OpenAI Environment मध्ये [माउंटन कार](https://www.gymlibrary.ml/environments/classic_control/mountain_car/) नियंत्रित करण्यासाठी प्रशिक्षण देणे.\n",
"\n",
"चला वातावरण तयार करून सुरुवात करूया:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import gym\n",
"env = gym.make('MountainCar-v0')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"चला पाहूया की यादृच्छिक प्रयोग कसा दिसतो:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"state = env.reset()\n",
"while True:\n",
" env.render()\n",
" action = env.action_space.sample()\n",
" state, reward, done, info = env.step(action)\n",
" if done:\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"## Lost of code here"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"env.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nहा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपया लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी, व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.\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": "f062b3b18449593ef8e0fcc029868781",
"translation_date": "2025-08-28T07:37:01+00:00",
"source_file": "lessons/6-Other/22-DeepRL/lab/MountainCar.ipynb",
"language_code": "mr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,478 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# जनावर विशेषज्ञ प्रणाली कार्यान्वयन\n",
"\n",
"[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) बाट लिएको एक उदाहरण।\n",
"\n",
"यस नमूनामा, हामी केही भौतिक विशेषताहरूको आधारमा जनावर पहिचान गर्नको लागि एक साधारण ज्ञान-आधारित प्रणाली कार्यान्वयन गर्नेछौं। प्रणालीलाई निम्न AND-OR रूखद्वारा प्रतिनिधित्व गर्न सकिन्छ (यो सम्पूर्ण रूखको एक भाग हो, हामी सजिलै थप नियमहरू थप्न सक्छौं):\n",
"\n",
"![](../../../../translated_images/AND-OR-Tree.5592d2c70187f283703c8e9c0d69d6a786eb370f4ace67f9a7aae5ada3d260b0.ne.png)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## हाम्रो आफ्नै विशेषज्ञ प्रणाली शेल ब्याकवर्ड इन्फरेन्सको साथ\n",
"\n",
"उत्पादन नियमहरूमा आधारित ज्ञान प्रतिनिधित्वको लागि एउटा साधारण भाषा परिभाषित गर्ने प्रयास गरौं। हामी नियमहरू परिभाषित गर्न Python कक्षाहरूलाई कुञ्जीशब्दको रूपमा प्रयोग गर्नेछौं। मुख्यतया ३ प्रकारका कक्षाहरू हुनेछन्:\n",
"* `Ask` एउटा प्रश्नलाई प्रतिनिधित्व गर्छ जुन प्रयोगकर्तालाई सोध्न आवश्यक छ। यसमा सम्भावित उत्तरहरूको सेट समावेश हुन्छ।\n",
"* `If` एउटा नियमलाई प्रतिनिधित्व गर्छ, र यो नियमको सामग्री भण्डारण गर्नको लागि मात्र एक प्रकारको सिंट्याक्टिक सुगर हो।\n",
"* `AND`/`OR` कक्षाहरू रूखको AND/OR शाखाहरूलाई प्रतिनिधित्व गर्नका लागि हुन्। यीले भित्रका तर्कहरूको सूची मात्र भण्डारण गर्छन्। कोडलाई सरल बनाउन, सबै कार्यक्षमता अभिभावक कक्षा `Content` मा परिभाषित गरिएको छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Ask():\n",
" def __init__(self,choices=['y','n']):\n",
" self.choices = choices\n",
" def ask(self):\n",
" if max([len(x) for x in self.choices])>1:\n",
" for i,x in enumerate(self.choices):\n",
" print(\"{0}. {1}\".format(i,x),flush=True)\n",
" x = int(input())\n",
" return self.choices[x]\n",
" else:\n",
" print(\"/\".join(self.choices),flush=True)\n",
" return input()\n",
"\n",
"class Content():\n",
" def __init__(self,x):\n",
" self.x=x\n",
" \n",
"class If(Content):\n",
" pass\n",
"\n",
"class AND(Content):\n",
" pass\n",
"\n",
"class OR(Content):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो प्रणालीमा, कार्य स्मृतिमा **तथ्यहरू** को सूची **गुण-मान जोडीहरू** को रूपमा समावेश हुनेछ। ज्ञान आधारलाई एउटा ठूलो शब्दकोशको रूपमा परिभाषित गर्न सकिन्छ जसले क्रियाहरू (नयाँ तथ्यहरू जुन कार्य स्मृतिमा समावेश गर्नुपर्छ) लाई सर्तहरूसँग नक्सा गर्दछ, जुन AND-OR अभिव्यक्तिहरूको रूपमा व्यक्त गरिन्छ। साथै, केही तथ्यहरूलाई `सोध्न` सकिन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"rules = {\n",
" 'default': Ask(['y','n']),\n",
" 'color' : Ask(['red-brown','black and white','other']),\n",
" 'pattern' : Ask(['dark stripes','dark spots']),\n",
" 'mammal': If(OR(['hair','gives milk'])),\n",
" 'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),\n",
" 'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),\n",
" 'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),\n",
" 'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),\n",
" 'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),\n",
" 'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),\n",
" 'animal:zebra' : If(['ungulate','pattern:dark stripes']),\n",
" 'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),\n",
" 'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),\n",
" 'animal:albatross' : If(['bird','flies well'])\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"पछाडि तर्फको अनुमान गर्नको लागि, हामी `Knowledgebase` नामक कक्षा परिभाषित गर्नेछौं। यसले समावेश गर्नेछ:\n",
"* कार्यरत `memory` - एउटा शब्दकोश जसले विशेषताहरूलाई मानहरूसँग नक्सा बनाउँछ\n",
"* Knowledgebase `rules` - माथि परिभाषित गरिएको ढाँचामा\n",
"\n",
"दुई मुख्य विधिहरू छन्:\n",
"* `get` - कुनै विशेषताको मान प्राप्त गर्न प्रयोग गरिन्छ, आवश्यक परे अनुमान गर्दै। उदाहरणका लागि, `get('color')` ले रंग स्लटको मान प्राप्त गर्नेछ (आवश्यक परे सोध्नेछ, र पछि प्रयोगको लागि कार्यरत मेमोरीमा मान भण्डारण गर्नेछ)। यदि हामी `get('color:blue')` सोध्छौं भने, यो रंगको लागि सोध्नेछ, र त्यसपछि रंगको आधारमा `y`/`n` मान फर्काउनेछ।\n",
"* `eval` - वास्तविक अनुमान प्रदर्शन गर्ने विधि हो, अर्थात् AND/OR ट्रीको यात्रा गर्ने, उप-लक्ष्यहरूको मूल्यांकन गर्ने, आदि।\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class KnowledgeBase():\n",
" def __init__(self,rules):\n",
" self.rules = rules\n",
" self.memory = {}\n",
" \n",
" def get(self,name):\n",
" if ':' in name:\n",
" k,v = name.split(':')\n",
" vv = self.get(k)\n",
" return 'y' if v==vv else 'n'\n",
" if name in self.memory.keys():\n",
" return self.memory[name]\n",
" for fld in self.rules.keys():\n",
" if fld==name or fld.startswith(name+\":\"):\n",
" # print(\" + proving {}\".format(fld))\n",
" value = 'y' if fld==name else fld.split(':')[1]\n",
" res = self.eval(self.rules[fld],field=name)\n",
" if res!='y' and res!='n' and value=='y':\n",
" self.memory[name] = res\n",
" return res\n",
" if res=='y':\n",
" self.memory[name] = value\n",
" return value\n",
" # field is not found, using default\n",
" res = self.eval(self.rules['default'],field=name)\n",
" self.memory[name]=res\n",
" return res\n",
" \n",
" def eval(self,expr,field=None):\n",
" # print(\" + eval {}\".format(expr))\n",
" if isinstance(expr,Ask):\n",
" print(field)\n",
" return expr.ask()\n",
" elif isinstance(expr,If):\n",
" return self.eval(expr.x)\n",
" elif isinstance(expr,AND) or isinstance(expr,list):\n",
" expr = expr.x if isinstance(expr,AND) else expr\n",
" for x in expr:\n",
" if self.eval(x)=='n':\n",
" return 'n'\n",
" return 'y'\n",
" elif isinstance(expr,OR):\n",
" for x in expr.x:\n",
" if self.eval(x)=='y':\n",
" return 'y'\n",
" return 'n'\n",
" elif isinstance(expr,str):\n",
" return self.get(expr)\n",
" else:\n",
" print(\"Unknown expr: {}\".format(expr))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी हाम्रो जनावर ज्ञानको आधार परिभाषित गरौं र परामर्श सञ्चालन गरौं। ध्यान दिनुहोस् कि यो कलले तपाईंलाई प्रश्नहरू सोध्नेछ। तपाईं `y`/`n` टाइप गरेर हो-होइन प्रश्नहरूको उत्तर दिन सक्नुहुन्छ, वा लामो बहुविकल्पीय उत्तरहरू भएका प्रश्नहरूको लागि संख्या (0..N) निर्दिष्ट गरेर उत्तर दिन सक्नुहुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hair\n",
"y/n\n",
"sharp teeth\n",
"y/n\n",
"claws\n",
"y/n\n",
"forward-looking eyes\n",
"y/n\n",
"color\n",
"0. red-brown\n",
"1. black and white\n",
"2. other\n",
"has hooves\n",
"y/n\n",
"long neck\n",
"y/n\n",
"long legs\n",
"y/n\n",
"pattern\n",
"0. dark stripes\n",
"1. dark spots\n"
]
},
{
"data": {
"text/plain": [
"'giraffe'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"kb = KnowledgeBase(rules)\n",
"kb.get('animal')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PyKnow प्रयोग गरेर फर्वार्ड इन्फरेन्स\n",
"\n",
"अर्को उदाहरणमा, हामी ज्ञान प्रतिनिधित्वका लागि उपलब्ध पुस्तकालयहरूमध्ये एक, [PyKnow](https://github.com/buguroo/pyknow/) प्रयोग गरेर फर्वार्ड इन्फरेन्स कार्यान्वयन गर्ने प्रयास गर्नेछौं। **PyKnow** एउटा पुस्तकालय हो जसले Python मा फर्वार्ड इन्फरेन्स प्रणालीहरू बनाउनका लागि प्रयोग गरिन्छ, जुन पुरानो क्लासिकल प्रणाली [CLIPS](http://www.clipsrules.net/index.html) जस्तै डिजाइन गरिएको छ।\n",
"\n",
"हामीले फर्वार्ड चेइनिङ आफैं पनि धेरै समस्याबिना कार्यान्वयन गर्न सक्थ्यौं, तर साधारण कार्यान्वयनहरू प्रायः धेरै प्रभावकारी हुँदैनन्। नियम मिलानलाई अझ प्रभावकारी बनाउनका लागि एउटा विशेष एल्गोरिदम [Rete](https://en.wikipedia.org/wiki/Rete_algorithm) प्रयोग गरिन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting git+https://github.com/buguroo/pyknow/\n",
" Cloning https://github.com/buguroo/pyknow/ to /tmp/pip-req-build-3cqeulyl\n",
" Running command git clone --filter=blob:none --quiet https://github.com/buguroo/pyknow/ /tmp/pip-req-build-3cqeulyl\n",
" Resolved https://github.com/buguroo/pyknow/ to commit 48818336f2e9a126f1964f2d8dc22d37ff800fe8\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hCollecting frozendict==1.2\n",
" Using cached frozendict-1.2.tar.gz (2.6 kB)\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hCollecting schema==0.6.7\n",
" Using cached schema-0.6.7-py2.py3-none-any.whl (14 kB)\n",
"Building wheels for collected packages: pyknow, frozendict\n",
" Building wheel for pyknow (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25h Created wheel for pyknow: filename=pyknow-1.7.0-py3-none-any.whl size=34228 sha256=b7de5b09292c4007667c72f69b98d5a1b5f7324ff15f9dd8e077c3d5f7aade42\n",
" Stored in directory: /tmp/pip-ephem-wheel-cache-k7jpave7/wheels/81/1a/d3/f6c15dbe1955598a37755215f2a10449e7418500d7bd4b9508\n",
" Building wheel for frozendict (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25h Created wheel for frozendict: filename=frozendict-1.2-py3-none-any.whl size=3148 sha256=2863d55c240d2409cddf05ccfe600591f8478681549fc97555c47c90dc6bb160\n",
" Stored in directory: /home/rg/.cache/pip/wheels/49/ac/f8/cb8120244e710bdb479c86198b03c7b08c3c2d3d2bf448fd6e\n",
"Successfully built pyknow frozendict\n",
"Installing collected packages: schema, frozendict, pyknow\n",
"Successfully installed frozendict-1.2 pyknow-1.7.0 schema-0.6.7\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install git+https://github.com/buguroo/pyknow/"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from pyknow import *\n",
"#import pyknow"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी हाम्रो प्रणालीलाई `KnowledgeEngine` को उपवर्गको रूपमा कक्षा रूपमा परिभाषित गर्नेछौं। प्रत्येक नियम `@Rule` एनोटेशनसहितको छुट्टै कार्यद्वारा परिभाषित गरिन्छ, जसले नियम कहिले कार्यान्वयन हुनुपर्छ भनेर निर्दिष्ट गर्दछ। नियमभित्र, हामी `declare` कार्य प्रयोग गरेर नयाँ तथ्यहरू थप्न सक्छौं, र ती तथ्यहरू थप्दा अगाडि निष्कर्ष इन्जिनद्वारा केही थप नियमहरू बोलाइनेछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Animals(KnowledgeEngine):\n",
" @Rule(OR(\n",
" AND(Fact('sharp teeth'),Fact('claws'),Fact('forward looking eyes')),\n",
" Fact('eats meat')))\n",
" def cornivor(self):\n",
" self.declare(Fact('carnivor'))\n",
" \n",
" @Rule(OR(Fact('hair'),Fact('gives milk')))\n",
" def mammal(self):\n",
" self.declare(Fact('mammal'))\n",
"\n",
" @Rule(Fact('mammal'),\n",
" OR(Fact('has hooves'),Fact('chews cud')))\n",
" def hooves(self):\n",
" self.declare('ungulate')\n",
" \n",
" @Rule(OR(Fact('feathers'),AND(Fact('flies'),Fact('lays eggs'))))\n",
" def bird(self):\n",
" self.declare('bird')\n",
" \n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark spots'))\n",
" def monkey(self):\n",
" self.declare(Fact(animal='monkey'))\n",
"\n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'))\n",
" def tiger(self):\n",
" self.declare(Fact(animal='tiger'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact('long neck'),\n",
" Fact('long legs'),\n",
" Fact(pattern='dark spots'))\n",
" def giraffe(self):\n",
" self.declare(Fact(animal='giraffe'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact(pattern='dark stripes'))\n",
" def zebra(self):\n",
" self.declare(Fact(animal='zebra'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('long neck'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def straus(self):\n",
" self.declare(Fact(animal='ostrich'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('swims'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def pinguin(self):\n",
" self.declare(Fact(animal='pinguin'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('flies well'))\n",
" def albatros(self):\n",
" self.declare(Fact(animal='albatross'))\n",
" \n",
" @Rule(Fact(animal=MATCH.a))\n",
" def print_result(self,a):\n",
" print('Animal is {}'.format(a))\n",
" \n",
" def factz(self,l):\n",
" for x in l:\n",
" self.declare(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"एक पटक हामीले ज्ञान आधार परिभाषित गरेपछि, हामी हाम्रो कार्यरत स्मृतिलाई केही प्रारम्भिक तथ्यहरूद्वारा भरिन्छौं, र त्यसपछि `run()` विधिलाई कल गरेर निष्कर्ष निकाल्ने कार्य गर्दछौं। परिणामस्वरूप, तपाईंले देख्न सक्नुहुन्छ कि नयाँ निष्कर्ष निकालिएका तथ्यहरू कार्यरत स्मृतिमा थपिएका छन्, जसमा जनावरको अन्तिम तथ्य पनि समावेश छ (यदि हामीले सबै प्रारम्भिक तथ्यहरू सही रूपमा सेटअप गरेका छौं भने)।\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Animal is tiger\n"
]
},
{
"data": {
"text/plain": [
"FactList([(0, InitialFact()),\n",
" (1, Fact(color='red-brown')),\n",
" (2, Fact(pattern='dark stripes')),\n",
" (3, Fact('sharp teeth')),\n",
" (4, Fact('claws')),\n",
" (5, Fact('forward looking eyes')),\n",
" (6, Fact('gives milk')),\n",
" (7, Fact('mammal')),\n",
" (8, Fact('carnivor')),\n",
" (9, Fact(animal='tiger'))])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ex1 = Animals()\n",
"ex1.reset()\n",
"ex1.factz([\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'),\n",
" Fact('sharp teeth'),\n",
" Fact('claws'),\n",
" Fact('forward looking eyes'),\n",
" Fact('gives milk')])\n",
"ex1.run()\n",
"ex1.facts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छन्। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्त्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं। \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.11.2"
},
"coopTranslator": {
"original_hash": "ab2bd97b0453415b89a469284609a8ce",
"translation_date": "2025-08-28T08:35:22+00:00",
"source_file": "lessons/2-Symbolic/Animals.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,593 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# परिवार सम्बन्धहरूको ओन्टोलोजी\n",
"\n",
"यो उदाहरण [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) को एक भाग हो, र यो [यो ब्लग पोस्ट](https://habr.com/post/270857/) बाट प्रेरित छ।\n",
"\n",
"मलाई सधैं परिवारभित्रका मानिसहरू बीचका विभिन्न सम्बन्धहरू सम्झन गाह्रो लाग्छ। यस उदाहरणमा, हामी एउटा ओन्टोलोजी लिनेछौं जसले परिवार सम्बन्धहरू परिभाषित गर्छ, र वास्तविक वंशावली वृक्ष लिनेछौं, र त्यसपछि सबै नातेदारहरू पत्ता लगाउन स्वचालित निष्कर्ष कसरी निकाल्न सकिन्छ भनेर देखाउनेछौं।\n",
"\n",
"### वंशावली वृक्ष प्राप्त गर्दै\n",
"\n",
"उदाहरणको रूपमा, हामी [Romanov Tsar Family](https://en.wikipedia.org/wiki/House_of_Romanov) को वंशावली वृक्ष लिनेछौं। परिवार सम्बन्धहरू वर्णन गर्नका लागि सबैभन्दा सामान्य ढाँचा [GEDCOM](https://en.wikipedia.org/wiki/GEDCOM) हो। हामी Romanov परिवारको वंशावली वृक्ष GEDCOM ढाँचामा लिनेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 HEAD\n",
"1 CHAR UTF8\n",
"1 GEDC\n",
"2 VERS 5.5\n",
"0 @0@ INDI\n",
"1 NAME Mihail Fedorovich /Romanov/\n",
"1 SEX M\n",
"1 BIRT\n",
"2 DATE 1613\n",
"1 DEAT \n",
"2 DATE 1645\n",
"1 FAMS @41@\n",
"0 @1@ INDI\n",
"1 NAME Evdokija Lukjanovna /Streshneva/\n",
"1 SEX F\n"
]
}
],
"source": [
"!head -15 data/tsars.ged"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"GEDCOM फाइल प्रयोग गर्न, हामी `python-gedcom` लाइब्रेरी प्रयोग गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting python-gedcom\n",
" Downloading python_gedcom-1.0.0-py2.py3-none-any.whl (35 kB)\n",
"Installing collected packages: python-gedcom\n",
"Successfully installed python-gedcom-1.0.0\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install python-gedcom"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यो पुस्तकालयले फाइल पार्सिङसँग सम्बन्धित केही प्राविधिक समस्याहरू हटाउँछ, तर यसले अझै पनि रुखमा रहेका सबै व्यक्तिहरू र परिवारहरूमा कम-स्तरको पहुँच दिन्छ। यहाँ फाइललाई कसरी पार्स गर्ने र सबै व्यक्तिहरूको सूची देखाउने भन्ने छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from gedcom.parser import Parser\n",
"from gedcom.element.individual import IndividualElement\n",
"from gedcom.element.family import FamilyElement\n",
"g = Parser()\n",
"g.parse_file('data/tsars.ged')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true,
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"[('@0@', ('Mihail Fedorovich', 'Romanov')),\n",
" ('@1@', ('Evdokija Lukjanovna', 'Streshneva')),\n",
" ('@2@', ('Aleksej Mihajlovich', 'Romanov')),\n",
" ('@3@', ('Marija Ilinichna', 'Miloslavskaja')),\n",
" ('@4@', ('Natalja Kirillovna', 'Naryshkina')),\n",
" ('@5@', ('Marfa Matveevna', 'Apraksina')),\n",
" ('@6@', ('Fedor Alekseevich', 'Romanov')),\n",
" ('@7@', ('Sofja Aleksevna', 'Romanova')),\n",
" ('@8@', ('Ivan V Alekseevich', 'Romanov')),\n",
" ('@9@', ('Praskovja Fedorovna', 'Saltykova')),\n",
" ('@10@', ('Ekaterina Ivanovna', 'Romanova')),\n",
" ('@11@', ('Anna Ivanovna', 'Romanova')),\n",
" ('@12@', ('Fridrih Vilgelm', 'Kurlandskij')),\n",
" ('@13@', ('Karl Leopold', 'Meklenburg-Shverinskij')),\n",
" ('@14@', ('Anna Leopoldovna', 'Meklenburg-Shverinskaja')),\n",
" ('@15@', ('Anton Ulrih', 'Braunshvejg-Volfenbjuttelskij')),\n",
" ('@16@', ('Ivan VI Antonovich', 'Braunshvejg-Volfenbjuttelskij')),\n",
" ('@17@', ('Petr I Alekseevich', 'Romanov')),\n",
" ('@18@', ('Evdokija Fedorovna', 'Lopuhina')),\n",
" ('@19@', ('Ekaterina I Alekseevna', 'Mihajlova')),\n",
" ('@20@', ('Aleksej Petrovich', 'Romanov')),\n",
" ('@21@', ('Sharlotta Kristina', 'Braunshvejg-Volfenbjuttelskaja')),\n",
" ('@22@', ('Petr II Alekseevich', 'Romanov')),\n",
" ('@23@', ('Anna Petrovna', 'Romanova')),\n",
" ('@24@', ('Elizaveta Petrovna', 'Romanova')),\n",
" ('@25@', ('Karl Fridrih', 'Golshtejn-Gottorpskij')),\n",
" ('@26@', ('Petr III Fedorovich', 'Romanov')),\n",
" ('@27@', ('Ekaterina II', 'Alekseevna')),\n",
" ('@28@', ('Pavel I Petrovich', 'Romanov')),\n",
" ('@29@', ('Natalja Alekseevna', 'Gessen-Darmshtadskaja')),\n",
" ('@30@', ('Marija Fedorovna', 'Vjurtembergskaja')),\n",
" ('@31@', ('Aleksandr I Pavlovich', 'Romanov')),\n",
" ('@32@', ('Elizaveta Alekseevna', 'Baden-Durlahskaja')),\n",
" ('@33@', ('Nikolaj I Pavlovich', 'Romanov')),\n",
" ('@34@', ('Aleksandra Fedorovna', 'Prusskaja')),\n",
" ('@35@', ('Aleksandr II Nikolaevich', 'Romanov')),\n",
" ('@36@', ('Marija Aleksandrovna', 'Gessenskaja')),\n",
" ('@37@', ('Aleksandr III Aleksandrovich', 'Romanov')),\n",
" ('@38@', ('Marija Fedorovna', 'Datskaja')),\n",
" ('@39@', ('Nikolaj II Aleksandrovich', 'Romanov')),\n",
" ('@40@', ('Aleksandra Fedorovna', 'Gessenskaja'))]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = g.get_element_dictionary()\n",
"[ (k,v.get_name()) for k,v in d.items() if isinstance(v,IndividualElement)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यहाँ कसरी हामी परिवारहरूको बारेमा जानकारी प्राप्त गर्न सक्छौं। ध्यान दिनुहोस् कि यसले हामीलाई **पहिचानकर्ता**हरूको सूची दिन्छ, र यदि हामीलाई थप स्पष्टता चाहिन्छ भने तिनीहरूलाई नाममा रूपान्तरण गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('@41@', ['@0@', '@1@', '@2@']),\n",
" ('@42@', ['@2@', '@3@', '@6@', '@7@', '@8@']),\n",
" ('@43@', ['@8@', '@9@', '@10@', '@11@']),\n",
" ('@44@', ['@13@', '@10@', '@14@']),\n",
" ('@45@', ['@15@', '@14@', '@16@']),\n",
" ('@46@', ['@2@', '@4@', '@17@']),\n",
" ('@47@', ['@17@', '@18@', '@20@']),\n",
" ('@48@', ['@20@', '@21@', '@22@']),\n",
" ('@49@', ['@17@', '@19@', '@23@', '@24@']),\n",
" ('@50@', ['@25@', '@23@', '@26@']),\n",
" ('@51@', ['@26@', '@27@', '@28@']),\n",
" ('@52@', ['@28@', '@30@', '@31@', '@33@']),\n",
" ('@53@', ['@33@', '@34@', '@35@']),\n",
" ('@54@', ['@35@', '@36@', '@37@']),\n",
" ('@55@', ['@37@', '@38@', '@39@'])]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = g.get_element_dictionary()\n",
"[ (k,[x.get_value() for x in v.get_child_elements()]) for k,v in d.items() if isinstance(v,FamilyElement)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### परिवार ओन्टोलोजी प्राप्त गर्दै\n",
"\n",
"अब, [परिवार ओन्टोलोजी](https://raw.githubusercontent.com/blokhin/genealogical-trees/master/data/header.ttl) लाई हेरौं, जुन सेम्यान्टिक वेब ट्रिप्लेटहरूको सेटको रूपमा परिभाषित गरिएको छ। यो ओन्टोलोजीले `isUncleOf`, `isCousinOf` जस्ता सम्बन्धहरू र अन्य धेरै सम्बन्धहरू परिभाषित गर्दछ। यी सबै सम्बन्धहरू आधारभूत प्रेडिकेटहरू `isMotherOf`, `isFatherOf`, `isBrotherOf` र `isSisterOf` को सन्दर्भमा परिभाषित गरिएका छन्। हामी ओन्टोलोजी प्रयोग गरेर स्वचालित तर्कको माध्यमबाट अन्य सबै सम्बन्धहरू निस्कर्ष निकाल्नेछौं।\n",
"\n",
"यहाँ `isAuntOf` प्रोपर्टीको एउटा नमूना परिभाषा छ, जुन `isSisterOf` र `isParentOf` को संयोजनको रूपमा परिभाषित गरिएको छ (*आमा वा बुवाको बहिनीलाई काकी भनिन्छ*)। \n",
"\n",
"```\n",
"fhkb:isAuntOf a owl:ObjectProperty ;\n",
" rdfs:domain fhkb:Woman ;\n",
" rdfs:range fhkb:Person ;\n",
" owl:propertyChainAxiom ( fhkb:isSisterOf fhkb:isParentOf ) .\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"@prefix fhkb: <http://www.example.com/genealogy.owl#> .\n",
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n",
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
"@prefix xml: <http://www.w3.org/XML/1998/namespace> .\n",
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
"\n",
"<http://www.example.com/genealogy.owl#> a owl:Ontology .\n",
"\n",
"fhkb:DomainEntity a owl:Class .\n",
"\n",
"fhkb:Man a owl:Class ;\n",
" owl:equivalentClass [ a owl:Class ;\n",
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n",
" owl:onProperty fhkb:hasSex ;\n",
" owl:someValuesFrom fhkb:Male ] ) ] .\n",
"\n",
"fhkb:Woman a owl:Class ;\n",
" owl:equivalentClass [ a owl:Class ;\n",
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n"
]
}
],
"source": [
"!head -20 data/onto.ttl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### अनुमानका लागि ओन्टोलोजी निर्माण\n",
"\n",
"सजिलोका लागि, हामी एउटा ओन्टोलोजी फाइल बनाउनेछौं जसमा परिवार ओन्टोलोजीका मूल नियमहरू र हाम्रो GEDCOM फाइलबाट व्यक्तिहरूका तथ्यहरू समावेश हुनेछन्। हामी GEDCOM फाइललाई अध्ययन गर्नेछौं, परिवारहरू र व्यक्तिहरूको जानकारी निकाल्नेछौं, र तिनलाई त्रिपलेटहरूमा रूपान्तरण गर्नेछौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"!cp data/onto.ttl .\n",
"\n",
"gedcom_dict = g.get_element_dictionary()\n",
"individuals, marriages = {}, {}\n",
"\n",
"def term2id(el):\n",
" return \"i\" + el.get_pointer().replace('@', '').lower()\n",
"\n",
"out = open(\"onto.ttl\",\"a\")\n",
"\n",
"for k, v in gedcom_dict.items():\n",
" if isinstance(v,IndividualElement):\n",
" children, siblings = set(), set()\n",
" idx = term2id(v)\n",
"\n",
" title = v.get_name()[0] + \" \" + v.get_name()[1]\n",
" title = title.replace('\"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()\n",
"\n",
" own_families = g.get_families(v, 'FAMS')\n",
" for fam in own_families:\n",
" children |= set(term2id(i) for i in g.get_family_members(fam, \"CHIL\"))\n",
"\n",
" parent_families = g.get_families(v, 'FAMC')\n",
" if len(parent_families):\n",
" for member in g.get_family_members(parent_families[0], \"CHIL\"): # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)\n",
" if member.get_pointer() == v.get_pointer():\n",
" continue\n",
" siblings.add(term2id(member))\n",
"\n",
" if idx in individuals:\n",
" children |= individuals[idx].get('children', set())\n",
" siblings |= individuals[idx].get('siblings', set())\n",
" individuals[idx] = {'sex': v.get_gender().lower(), 'children': children, 'siblings': siblings, 'title': title}\n",
"\n",
" elif isinstance(v,FamilyElement):\n",
" wife, husb, children = None, None, set()\n",
" children = set(term2id(i) for i in g.get_family_members(v, \"CHIL\"))\n",
"\n",
" try:\n",
" wife = g.get_family_members(v, \"WIFE\")[0]\n",
" wife = term2id(wife)\n",
" if wife in individuals: individuals[wife]['children'] |= children\n",
" else: individuals[wife] = {'children': children}\n",
" except IndexError: pass\n",
" try:\n",
" husb = g.get_family_members(v, \"HUSB\")[0]\n",
" husb = term2id(husb)\n",
" if husb in individuals: individuals[husb]['children'] |= children\n",
" else: individuals[husb] = {'children': children}\n",
" except IndexError: pass\n",
"\n",
" if wife and husb: marriages[wife + husb] = (term2id(v), wife, husb)\n",
"\n",
"for idx, val in individuals.items():\n",
" added_terms = ''\n",
" if val['sex'] == 'f':\n",
" parent_predicate, sibl_predicate = \"isMotherOf\", \"isSisterOf\"\n",
" else:\n",
" parent_predicate, sibl_predicate = \"isFatherOf\", \"isBrotherOf\"\n",
" if len(val['children']):\n",
" added_terms += \" ;\\n fhkb:\" + parent_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['children']])\n",
" if len(val['siblings']):\n",
" added_terms += \" ;\\n fhkb:\" + sibl_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['siblings']])\n",
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing%s ;\\n rdfs:label \\\"%s\\\" .\\n\" % (idx, added_terms, val['title']))\n",
"\n",
"for k, v in marriages.items():\n",
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing ;\\n fhkb:hasFemalePartner fhkb:%s ;\\n fhkb:hasMalePartner fhkb:%s .\\n\" % v)\n",
"\n",
"out.write(\"[] a owl:AllDifferent ;\\n owl:distinctMembers (\")\n",
"for idx in individuals.keys():\n",
" out.write(\" fhkb:\" + idx)\n",
"for k, v in marriages.items():\n",
" out.write(\" fhkb:\" + v[0])\n",
"out.write(\" ) .\")\n",
"out.close()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" fhkb:hasFemalePartner fhkb:i34 ;\n",
" fhkb:hasMalePartner fhkb:i33 .\n",
"fhkb:i54 a owl:NamedIndividual, owl:Thing ;\n",
" fhkb:hasFemalePartner fhkb:i36 ;\n",
" fhkb:hasMalePartner fhkb:i35 .\n",
"fhkb:i55 a owl:NamedIndividual, owl:Thing ;\n",
" fhkb:hasFemalePartner fhkb:i38 ;\n",
" fhkb:hasMalePartner fhkb:i37 .\n",
"[] a owl:AllDifferent ;\n",
" owl:distinctMembers ( fhkb:i0 fhkb:i1 fhkb:i2 fhkb:i3 fhkb:i4 fhkb:i5 fhkb:i6 fhkb:i7 fhkb:i8 fhkb:i9 fhkb:i10 fhkb:i11 fhkb:i12 fhkb:i13 fhkb:i14 fhkb:i15 fhkb:i16 fhkb:i17 fhkb:i18 fhkb:i19 fhkb:i20 fhkb:i21 fhkb:i22 fhkb:i23 fhkb:i24 fhkb:i25 fhkb:i26 fhkb:i27 fhkb:i28 fhkb:i29 fhkb:i30 fhkb:i31 fhkb:i32 fhkb:i33 fhkb:i34 fhkb:i35 fhkb:i36 fhkb:i37 fhkb:i38 fhkb:i39 fhkb:i40 fhkb:i41 fhkb:i42 fhkb:i43 fhkb:i44 fhkb:i45 fhkb:i46 fhkb:i47 fhkb:i48 fhkb:i49 fhkb:i50 fhkb:i51 fhkb:i52 fhkb:i53 fhkb:i54 fhkb:i55 ) ."
]
}
],
"source": [
"!tail onto.ttl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### अनुमान लगाउने कार्य \n",
"\n",
"अब हामी यो ओन्टोलोजीलाई अनुमान लगाउन र प्रश्न सोध्न प्रयोग गर्न चाहन्छौं। हामी [RDFLib](https://github.com/RDFLib) प्रयोग गर्नेछौं, जुन RDF ग्राफलाई विभिन्न ढाँचामा पढ्न, प्रश्न सोध्न आदि गर्नका लागि पुस्तकालय हो। \n",
"\n",
"तार्किक अनुमानका लागि, हामी [OWL-RL](https://github.com/RDFLib/OWL-RL) पुस्तकालय प्रयोग गर्नेछौं, जसले हामीलाई RDF ग्राफको **Closure** निर्माण गर्न अनुमति दिन्छ, अर्थात् अनुमान गर्न सकिने सबै सम्भावित अवधारणाहरू र सम्बन्धहरू थप्न।\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: rdflib in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (6.3.2)\n",
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (0.6.1)\n",
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (3.0.9)\n",
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib) (1.16.0)\n",
"Collecting git+https://github.com/RDFLib/OWL-RL.git\n",
" Cloning https://github.com/RDFLib/OWL-RL.git to /tmp/pip-req-build-lbfzwi3m\n",
" Running command git clone --filter=blob:none --quiet https://github.com/RDFLib/OWL-RL.git /tmp/pip-req-build-lbfzwi3m\n",
" Resolved https://github.com/RDFLib/OWL-RL.git to commit a77e1791b88b54aace609bc6000aac14c7add4ff\n",
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
"\u001b[?25hRequirement already satisfied: rdflib>=6.0.2 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from owlrl==6.0.2) (6.3.2)\n",
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (0.6.1)\n",
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (3.0.9)\n",
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib>=6.0.2->owlrl==6.0.2) (1.16.0)\n"
]
}
],
"source": [
"!{sys.executable} -m pip install rdflib\n",
"!{sys.executable} -m pip install git+https://github.com/RDFLib/OWL-RL.git"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ओन्टोलोजी फाइल खोलौं र यसमा कति ट्रिप्लेट्स छन् हेर्नुहोस्:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Triplets found:669\n"
]
}
],
"source": [
"import rdflib\n",
"from owlrl import DeductiveClosure, OWLRL_Extension\n",
"\n",
"g = rdflib.Graph()\n",
"g.parse(\"onto.ttl\", format=\"turtle\")\n",
"\n",
"print(\"Triplets found:%d\" % len(g))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Triplets after inference:4246\n"
]
}
],
"source": [
"DeductiveClosure(OWLRL_Extension).expand(g)\n",
"print(\"Triplets after inference:%d\" % len(g))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### नातेदारहरूको लागि सोधपुछ गर्नु \n",
"\n",
"अब हामी ग्राफलाई सोधपुछ गरेर मानिसहरू बीचका विभिन्न सम्बन्धहरू हेर्न सक्छौं। हामी **SPARQL** भाषा र `query` विधि प्रयोग गर्न सक्छौं। हाम्रो अवस्थामा, हाम्रो परिवारको रुखमा सबै **काकाहरू** हेर्न प्रयास गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fedor Alekseevich Romanov is uncle of Ekaterina Ivanovna Romanova\n",
"Aleksandr I Pavlovich Romanov is uncle of Aleksandr II Nikolaevich Romanov\n",
"Fedor Alekseevich Romanov is uncle of Anna Ivanovna Romanova\n"
]
}
],
"source": [
"qres = g.query(\n",
" \"\"\"SELECT DISTINCT ?aname ?bname\n",
" WHERE {\n",
" ?a fhkb:isUncleOf ?b .\n",
" ?a rdfs:label ?aname .\n",
" ?b rdfs:label ?bname .\n",
" }\"\"\")\n",
"\n",
"for row in qres:\n",
" print(\"%s is uncle of %s\" % row)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"विभिन्न अन्य पारिवारिक सम्बन्धहरूसँग प्रयोग गरेर हेर्नुहोस्। उदाहरणका लागि, तपाईं `isAncestorOf` सम्बन्धलाई हेर्न सक्नुहुन्छ, जसले कुनै व्यक्तिका सबै पुर्खाहरूलाई पुनरावृत्त रूपमा परिभाषित गर्दछ।\n",
"\n",
"अन्तमा, सफा गरौं!\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"!rm onto.ttl"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटि वा अशुद्धता हुन सक्छ। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुने छैनौं। \n"
]
}
],
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
},
"kernelspec": {
"display_name": "Python 3.6",
"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.11.2"
},
"coopTranslator": {
"original_hash": "6537d5597320e27b6052b4377b8ff8bb",
"translation_date": "2025-08-28T08:32:22+00:00",
"source_file": "lessons/2-Symbolic/FamilyOntology.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,548 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## माइक्रोसफ्ट कन्सेप्ट ग्राफ\n",
"\n",
"[Microsoft Concept Graph](https://concept.research.microsoft.com/) इन्टरनेटबाट संकलित शब्दहरूको ठूलो वर्गीकरण हो, जसमा अवधारणाहरू बीचको `is-a` सम्बन्धहरू समावेश छन्।\n",
"\n",
"कन्सेप्ट ग्राफ दुई प्रकारमा उपलब्ध छ:\n",
" * डाउनलोडको लागि ठूलो पाठ फाइल\n",
" * REST API\n",
"\n",
"तथ्यांक:\n",
" * 5401933 अद्वितीय अवधारणाहरू,\n",
" * 12551613 अद्वितीय उदाहरणहरू\n",
" * 87603947 `is-a` सम्बन्धहरू\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## वेब सेवा प्रयोग गर्दै\n",
"\n",
"वेब सेवाले विभिन्न समूहहरूमा कुनै अवधारणा पर्ने सम्भावना अनुमान गर्नका लागि विभिन्न कलहरू प्रदान गर्दछ। थप जानकारी [यहाँ](https://concept.research.microsoft.com/Home/Api) उपलब्ध छ। \n",
"कल गर्नको लागि यो नमूना URL हो: `https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance=microsoft&topK=10`\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'company': 0.6105356614382954,\n",
" 'vendor': 0.08858636677518003,\n",
" 'client': 0.048239124001183784,\n",
" 'firm': 0.045476965571668145,\n",
" 'large company': 0.043109401203511886,\n",
" 'organization': 0.043010752688172046,\n",
" 'corporation': 0.035908059583703265,\n",
" 'brand': 0.03383644076156654,\n",
" 'software company': 0.027522935779816515,\n",
" 'technology company': 0.023774292196902438}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import urllib\n",
"import json\n",
"import ssl\n",
"\n",
"def http(x):\n",
" ssl._create_default_https_context = ssl._create_unverified_context\n",
" response = urllib.request.urlopen(x)\n",
" data = response.read()\n",
" return data.decode('utf-8')\n",
"\n",
"def query(x):\n",
" return json.loads(http(\"https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance={}&topK=10\".format(urllib.parse.quote(x))))\n",
"\n",
"query('microsoft')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी समाचार शीर्षकहरूलाई अभिभावक अवधारणाहरू प्रयोग गरेर वर्गीकृत गर्ने प्रयास गरौं। समाचार शीर्षकहरू प्राप्त गर्नका लागि, हामी [NewsApi.org](http://newsapi.org) सेवा प्रयोग गर्नेछौं। यो सेवा प्रयोग गर्नका लागि तपाईंले आफ्नो API कुञ्जी प्राप्त गर्न आवश्यक छ - वेबसाइटमा जानुहोस् र निःशुल्क विकासकर्ता योजना दर्ता गर्नुहोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"newsapi_key = '<your API key here>'\n",
"def get_news(country='us'):\n",
" res = json.loads(http(\"https://newsapi.org/v2/top-headlines?country={0}&apiKey={1}\".format(country,newsapi_key)))\n",
" return res['articles']\n",
"\n",
"all_titles = [x['title'] for x in get_news('us')+get_news('gb')]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Covid-19 Live Updates: Vaccines and Boosters News - The New York Times',\n",
" 'Ukrainians Flee Mariupol as Russian Forces Push to Take Port City - The Wall Street Journal',\n",
" 'Bond Yields Jump, Stock Futures Rise After Powell Says Fed Is Ready to Be More Aggressive - The Wall Street Journal',\n",
" 'Putin critic Alexei Navalny found guilty by Russian court - New York Post ',\n",
" \"Supreme Court nominee Ketanji Brown Jackson will face questions at confirmation hearing's second day - CNN\",\n",
" '2 teachers killed at Swedish high school, student arrested - ABC News',\n",
" 'Clues to Covid-19s Next Moves Come From Sewers - The Wall Street Journal',\n",
" 'Republicans to roll dice by grilling Jackson over child-pornography sentencing decisions | TheHill - The Hill',\n",
" 'Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
" \"US stocks whipsawed overnight after Fed Chair Powell's remarks - Fox Business\",\n",
" \"'We've learned absolutely nothing': Tests could again be in short supply if Covid surges - POLITICO\",\n",
" \"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\",\n",
" 'China searches for victims, flight recorders after first plane crash in 12 years - Reuters',\n",
" 'Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters',\n",
" 'Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español',\n",
" 'Powers Remain and Threats Lurk as Womens Sweet 16 Is Set - The New York Times',\n",
" 'Webb Space Telescope Begins Multi-Instrument Alignment - SciTechDaily',\n",
" \"UConn vs UCF - NCAA women's tournament second-round highlights - March Madness\",\n",
" 'Bucking Republican Trend, Indiana Governor Vetoes Transgender Sports Bill - The New York Times',\n",
" \"Maggie Fox dead: Coronation Street and Shameless actress dies after 'sudden accident' - Mirror Online - The Mirror\",\n",
" 'China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent',\n",
" 'Daniel Morgan murder: damning report condemns Met police - The Guardian',\n",
" 'What to expect from Rishi Sunaks Spring Statement - BBC.com',\n",
" 'UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian',\n",
" \"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\",\n",
" 'Brass Eyes outtakes show the brutal TV comedy was the tip of an iceberg - The Guardian',\n",
" \"Vladimir Putin threatens civilians to break Mariupol's spirit - The Times\",\n",
" 'Shell U-turn on Cambo oilfield would threaten green targets, say campaigners - The Guardian',\n",
" 'St Helens dog attack: Girl aged 17 months killed at home - BBC',\n",
" \"PlayStation to buy 'Assassin's Creed' veteran Jade Raymond's Haven Studios - NME\",\n",
" 'Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
" 'Nintendo Switch finally has folders • Eurogamer.net - Eurogamer.net',\n",
" 'FA to “find a solution” as Liverpool fan group blasts “shambolic” Wembley travel - This Is Anfield',\n",
" 'Manchester United transfer news LIVE Erik ten Hag latest and Man Utd manager updates - Manchester Evening News',\n",
" 'Inflation raises cost of UK government borrowing in February; crude oil up again business live - The Guardian',\n",
" 'Alexei Navalny: Kremlin critic found guilty of large-scale fraud and contempt of court by Russian court - Sky News',\n",
" \"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\",\n",
" 'Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian']"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"all_titles"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"सबैभन्दा पहिले, हामी समाचार शीर्षकहरूबाट संज्ञा निकाल्न सक्षम हुन चाहन्छौं। हामी यसका लागि `TextBlob` पुस्तकालय प्रयोग गर्नेछौं, जसले यस प्रकारका धेरै सामान्य NLP कार्यहरूलाई सरल बनाउँछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: textblob in c:\\winapp\\miniconda3\\lib\\site-packages (0.17.1)\n",
"Requirement already satisfied: nltk>=3.1 in c:\\winapp\\miniconda3\\lib\\site-packages (from textblob) (3.5)\n",
"Requirement already satisfied: joblib in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (1.0.1)\n",
"Requirement already satisfied: regex in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (2021.11.10)\n",
"Requirement already satisfied: tqdm in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (4.61.2)\n",
"Requirement already satisfied: click in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (8.0.3)\n",
"Requirement already satisfied: colorama in c:\\winapp\\miniconda3\\lib\\site-packages (from click->nltk>=3.1->textblob) (0.4.4)\n",
"Finished.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[nltk_data] Downloading package brown to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package brown is already up-to-date!\n",
"[nltk_data] Downloading package punkt to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package punkt is already up-to-date!\n",
"[nltk_data] Downloading package wordnet to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package wordnet is already up-to-date!\n",
"[nltk_data] Downloading package averaged_perceptron_tagger to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package averaged_perceptron_tagger is already up-to-\n",
"[nltk_data] date!\n",
"[nltk_data] Downloading package conll2000 to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package conll2000 is already up-to-date!\n",
"[nltk_data] Downloading package movie_reviews to\n",
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package movie_reviews is already up-to-date!\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install textblob\n",
"!{sys.executable} -m textblob.download_corpora\n",
"from textblob import TextBlob"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'covid-19 live updates': 1,\n",
" 'vaccines': 1,\n",
" 'boosters': 1,\n",
" 'york': 4,\n",
" 'ukrainians flee mariupol': 1,\n",
" 'forces push': 1,\n",
" 'port city': 1,\n",
" 'wall street journal': 3,\n",
" 'bond yields': 1,\n",
" 'futures rise': 1,\n",
" 'powell says fed': 1,\n",
" 'ready': 1,\n",
" 'be': 1,\n",
" 'aggressive': 1,\n",
" 'putin': 3,\n",
" 'alexei navalny': 2,\n",
" 'russian': 2,\n",
" 'supreme court nominee': 1,\n",
" 'ketanji brown jackson': 1,\n",
" \"confirmation hearing 's\": 1,\n",
" 'cnn': 1,\n",
" 'swedish': 1,\n",
" 'high school': 1,\n",
" 'abc': 1,\n",
" 'clues': 1,\n",
" 'covid-19': 1,\n",
" ' s': 2,\n",
" 'moves': 1,\n",
" 'sewers': 1,\n",
" 'roll dice': 1,\n",
" 'jackson': 1,\n",
" 'decisions |': 1,\n",
" 'thehill': 1,\n",
" 'clear': 2,\n",
" 'chemical weapons': 2,\n",
" 'ukraine': 3,\n",
" 'claims president': 2,\n",
" 'biden': 2,\n",
" 'nasa': 2,\n",
" 'solar system': 2,\n",
" 'daily mail': 3,\n",
" 'us stocks': 1,\n",
" 'fed chair powell': 1,\n",
" \"'s remarks\": 1,\n",
" 'fox': 1,\n",
" \"'we 've\": 1,\n",
" 'tests': 1,\n",
" 'covid': 1,\n",
" 'politico': 1,\n",
" 'duchess': 1,\n",
" 'cambridge': 1,\n",
" 'swaps khaki jungle gear': 1,\n",
" 'vampire': 1,\n",
" 'wife': 1,\n",
" 'belize': 1,\n",
" 'china': 2,\n",
" 'flight recorders': 1,\n",
" 'plane crash': 1,\n",
" 'reuters': 2,\n",
" 'russian oligarch': 1,\n",
" 'abramovich': 1,\n",
" 'live': 1,\n",
" 'russia': 2,\n",
" 'stops talks': 1,\n",
" 'japan': 1,\n",
" 'español': 1,\n",
" 'powers remain': 1,\n",
" 'threats lurk': 1,\n",
" 'set': 1,\n",
" 'webb': 1,\n",
" 'telescope begins multi-instrument alignment': 1,\n",
" 'scitechdaily': 1,\n",
" 'uconn': 1,\n",
" 'ucf': 1,\n",
" 'ncaa': 1,\n",
" \"women 's tournament second-round highlights\": 1,\n",
" 'march madness': 1,\n",
" 'bucking republican trend': 1,\n",
" 'indiana': 1,\n",
" 'vetoes transgender': 1,\n",
" 'bill': 1,\n",
" 'maggie fox': 1,\n",
" 'coronation': 1,\n",
" 'shameless': 1,\n",
" \"'sudden accident\": 1,\n",
" 'mirror online': 1,\n",
" 'mirror': 2,\n",
" 'plane crash ': 1,\n",
" 'search': 1,\n",
" 'moment flight': 1,\n",
" 'daniel morgan': 1,\n",
" 'report condemns': 1,\n",
" 'met': 1,\n",
" 'guardian': 6,\n",
" 'rishi sunak': 1,\n",
" ' s spring': 1,\n",
" 'statement': 1,\n",
" 'bbc.com': 1,\n",
" 'uk': 3,\n",
" 'ireland': 1,\n",
" 'euro': 1,\n",
" 'vladimir putin': 2,\n",
" \"'s 'lover\": 1,\n",
" 'brass eye': 1,\n",
" ' s outtakes': 1,\n",
" 'brutal tv comedy': 1,\n",
" 'threatens civilians': 1,\n",
" 'mariupol': 1,\n",
" \"'s spirit\": 1,\n",
" 'shell u-turn': 1,\n",
" 'cambo': 1,\n",
" 'green targets': 1,\n",
" 'st helens': 1,\n",
" 'dog attack': 1,\n",
" 'girl': 1,\n",
" 'bbc': 1,\n",
" 'playstation': 1,\n",
" \"'assassin 's\": 1,\n",
" 'creed': 1,\n",
" 'jade raymond': 1,\n",
" 'haven studios': 1,\n",
" 'nme': 1,\n",
" 'nintendo switch': 1,\n",
" 'folders •': 1,\n",
" 'eurogamer.net': 2,\n",
" 'fa': 1,\n",
" 'solution ”': 1,\n",
" 'liverpool': 1,\n",
" 'fan group blasts “ shambolic ”': 1,\n",
" 'wembley': 1,\n",
" 'anfield': 1,\n",
" 'manchester': 1,\n",
" 'live erik': 1,\n",
" 'hag': 1,\n",
" 'utd': 1,\n",
" 'manager updates': 1,\n",
" 'manchester evening': 1,\n",
" 'inflation': 1,\n",
" 'government borrowing': 1,\n",
" 'february': 1,\n",
" 'crude oil': 1,\n",
" ' business': 1,\n",
" 'kremlin': 1,\n",
" 'large-scale fraud': 1,\n",
" 'sky': 1,\n",
" 'natural gas': 1,\n",
" 'gazprom': 1,\n",
" 'retail unit': 1,\n",
" 'insider': 1,\n",
" 'zaghari-ratcliffe': 1,\n",
" 'hunt': 1,\n",
" 'iran': 1,\n",
" 'debt payment': 1}"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w = {}\n",
"for x in all_titles:\n",
" for n in TextBlob(x).noun_phrases:\n",
" if n in w:\n",
" w[n].append(x)\n",
" else:\n",
" w[n]=[x]\n",
"{ x:len(w[x]) for x in w.keys()}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी देख्न सक्छौं कि संज्ञाहरूले हामीलाई ठूला थिमेटिक समूहहरू दिँदैनन्। आउनुहोस्, संज्ञाहरूलाई अवधारणा ग्राफबाट प्राप्त सामान्य शब्दहरूद्वारा प्रतिस्थापन गरौं। यसले केही समय लिनेछ, किनभने हामी प्रत्येक संज्ञा वाक्यांशको लागि REST कल गर्दैछौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"w = {}\n",
"for x in all_titles:\n",
" for noun in TextBlob(x).noun_phrases:\n",
" terms = query(noun.replace(' ','%20'))\n",
" for term in [u for u in terms.keys() if terms[u]>0.1]:\n",
" if term in w:\n",
" w[term].append(x)\n",
" else:\n",
" w[term]=[x]"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'city': 9,\n",
" 'brand': 4,\n",
" 'place': 9,\n",
" 'town': 4,\n",
" 'factor': 4,\n",
" 'film': 4,\n",
" 'nation': 11,\n",
" 'state': 5,\n",
" 'person': 4,\n",
" 'organization': 5,\n",
" 'publication': 10,\n",
" 'market': 5,\n",
" 'economy': 4,\n",
" 'company': 6,\n",
" 'newspaper': 6,\n",
" 'relationship': 6}"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{ x:len(w[x]) for x in w.keys() if len(w[x])>3}"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"ECONOMY:\n",
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
"\n",
"NATION:\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
"China plane crash live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
"UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian\n",
"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
"Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian\n",
"\n",
"PERSON:\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
"Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters\n",
"Clear sign Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n"
]
}
],
"source": [
"print('\\nECONOMY:\\n'+'\\n'.join(w['economy']))\n",
"print('\\nNATION:\\n'+'\\n'.join(w['nation']))\n",
"print('\\nPERSON:\\n'+'\\n'.join(w['person']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव शुद्धताको प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छन्। मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं।\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.9.5"
},
"coopTranslator": {
"original_hash": "4087f998407d06ceb2947016ba4605d0",
"translation_date": "2025-08-28T08:33:49+00:00",
"source_file": "lessons/2-Symbolic/MSConceptGraph.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,183 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# हाम्रो आफ्नै फ्रेमवर्क प्रयोग गरेर MNIST अंक वर्गीकरण\n",
"\n",
"[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) बाट ल्याब असाइनमेन्ट।\n",
"\n",
"### डेटासेट पढ्ने\n",
"\n",
"यो कोडले इन्टरनेटमा रहेको रिपोजिटरीबाट डेटासेट डाउनलोड गर्छ। तपाईंले AI Curriculum रिपोको `/data` डाइरेक्टरीबाट डेटासेटलाई म्यानुअली पनि कपी गर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" % Total % Received % Xferd Average Speed Time Time Time Current\n",
" Dload Upload Total Spent Left Speed\n",
"\n",
" 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n",
"100 9.9M 100 9.9M 0 0 9.9M 0 0:00:01 --:--:-- 0:00:01 15.8M\n"
]
}
],
"source": [
"!rm *.pkl\n",
"!wget https://raw.githubusercontent.com/microsoft/AI-For-Beginners/main/data/mnist.pkl.gz\n",
"!gzip -d mnist.pkl.gz"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import pickle\n",
"with open('mnist.pkl','rb') as f:\n",
" MNIST = pickle.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"labels = MNIST['Train']['Labels']\n",
"data = MNIST['Train']['Features']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हेरौं, हाम्रोसँग रहेको डाटाको आकार कस्तो छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(42000, 784)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### डेटा विभाजन\n",
"\n",
"हामी Scikit Learn प्रयोग गरेर डेटा प्रशिक्षण र परीक्षण डेटासेटमा विभाजन गर्नेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Train samples: 33600, test samples: 8400\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"features_train, features_test, labels_train, labels_test = train_test_split(data,labels,test_size=0.2)\n",
"\n",
"print(f\"Train samples: {len(features_train)}, test samples: {len(features_test)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### निर्देशनहरू\n",
"\n",
"1. पाठबाट फ्रेमवर्क कोड लिनुहोस् र यसलाई यो नोटबुकमा टाँस्नुहोस्, वा (अझ राम्रो) छुट्टै Python मोड्युलमा टाँस्नुहोस्।\n",
"1. एक-स्तरीय परसेप्ट्रोन परिभाषित गर्नुहोस् र प्रशिक्षण गर्नुहोस्, प्रशिक्षण र मान्यताको शुद्धता प्रशिक्षणको क्रममा अवलोकन गर्नुहोस्।\n",
"1. बुझ्ने प्रयास गर्नुहोस् कि ओभरफिटिंग भयो कि भएन, र लेयरका प्यारामिटरहरू समायोजन गरेर शुद्धता सुधार गर्नुहोस्।\n",
"1. 2-स्तरीय र 3-स्तरीय परसेप्ट्रोनहरूको लागि अघिल्लो चरणहरू दोहोर्याउनुहोस्। लेयरहरू बीच विभिन्न सक्रियता कार्यहरू प्रयोग गरेर प्रयोग गर्ने प्रयास गर्नुहोस्।\n",
"1. निम्न प्रश्नहरूको उत्तर दिने प्रयास गर्नुहोस्:\n",
" - के इन्टर-लेयर सक्रियता कार्यले नेटवर्कको प्रदर्शनलाई असर गर्छ?\n",
" - के यो कार्यको लागि 2-स्तरीय वा 3-स्तरीय नेटवर्क आवश्यक छ?\n",
" - नेटवर्क प्रशिक्षण गर्दा कुनै समस्या अनुभव गर्नुभयो? विशेष गरी जब लेयरहरूको संख्या बढ्यो।\n",
" - प्रशिक्षणको क्रममा नेटवर्कका वजनहरू कसरी व्यवहार गर्छन्? वजनहरूको अधिकतम परिमाणात्मक मान बनाम इपोकको सम्बन्ध बुझ्नको लागि यसलाई प्लट गर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव शुद्धता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छन्। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं।\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"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.9.5"
},
"orig_nbformat": 2,
"coopTranslator": {
"original_hash": "6fa055f484eb5d6bdf41166a356d3abf",
"translation_date": "2025-08-28T08:43:55+00:00",
"source_file": "lessons/3-NeuralNetworks/04-OwnFramework/lab/MyFW_MNIST.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,108 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## अप्टिकल फ्लो प्रयोग गरेर हातको चाल पत्ता लगाउने\n",
"\n",
"यो प्रयोगशाला [AI for Beginners Curriculum](http://aka.ms/ai-beginners) को हिस्सा हो।\n",
"\n",
"[यो भिडियो](../../../../../../lessons/4-ComputerVision/06-IntroCV/lab/palm-movement.mp4) हेर्नुहोस्, जसमा एक व्यक्तिको हात स्थिर पृष्ठभूमिमा बायाँ/दायाँ/माथि/तल सर्छ। \n",
"\n",
"**तपाईंको लक्ष्य** अप्टिकल फ्लो प्रयोग गरेर भिडियोका कुन भागमा माथि/तल/बायाँ/दायाँ चाल भएको छ भनेर पत्ता लगाउनु हुनेछ।\n",
"\n",
"भिडियो फ्रेमहरू प्राप्त गर्न, व्याख्यानमा वर्णन गरिएझैं सुरु गर्नुहोस्:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब, व्याख्यानमा वर्णन गरिएझैं घना अप्टिकल फ्लो फ्रेमहरू गणना गर्नुहोस्, र घना अप्टिकल फ्लोलाई ध्रुवीय निर्देशाङ्कमा रूपान्तरण गर्नुहोस्:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"प्रत्येक अप्टिकल फ्लो फ्रेमको लागि दिशाहरूको हिस्टोग्राम बनाउनुहोस्। हिस्टोग्रामले देखाउँछ कि कति भेक्टरहरू निश्चित बिनमा पर्छन्, र यसले फ्रेममा विभिन्न दिशाहरूको आन्दोलनलाई अलग गर्नुपर्छ।\n",
"\n",
"> तपाईंले ती सबै भेक्टरहरूलाई पनि शून्य बनाउन चाहन सक्नुहुन्छ जसको परिमाण निश्चित थ्रेसहोल्डभन्दा कम छ। यसले भिडियोमा साना अतिरिक्त आन्दोलनहरू, जस्तै आँखा र टाउकोको हलचल, हटाउन मद्दत गर्दछ।\n",
"\n",
"केही फ्रेमहरूको लागि हिस्टोग्रामहरू प्लट गर्नुहोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हिस्टोग्रामहरू हेर्दा, गति दिशाको निर्धारण कसरी गर्ने भन्ने कुरा धेरै सरल हुनुपर्छ। तपाईंले ती बिनहरू चयन गर्न आवश्यक छ जुन माथि/तल/बायाँ/दायाँ दिशाहरूलाई प्रतिनिधित्व गर्छन्, र जुन निश्चित थ्रेसहोल्डभन्दा माथि छन्।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"बधाई छ! यदि तपाईंले माथिका सबै चरणहरू पूरा गर्नुभएको छ भने, तपाईंले प्रयोगशाला पूरा गर्नुभएको छ!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छन्। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्त्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं।\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "153d9e417e079bf62f8f693002d0deaf",
"translation_date": "2025-08-28T08:09:45+00:00",
"source_file": "lessons/4-ComputerVision/06-IntroCV/lab/MovementDetection.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,577 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# पाठ वर्गीकरण कार्य\n",
"\n",
"जसरी हामीले उल्लेख गरेका छौं, हामी **AG_NEWS** डेटासेटमा आधारित साधारण पाठ वर्गीकरण कार्यमा केन्द्रित हुनेछौं, जसले समाचार शीर्षकहरूलाई चार श्रेणीहरूमा वर्गीकृत गर्नुपर्छ: विश्व, खेलकुद, व्यापार, र विज्ञान/प्रविधि।\n",
"\n",
"## डेटासेट\n",
"\n",
"यो डेटासेट [`torchtext`](https://github.com/pytorch/text) मोड्युलमा समावेश गरिएको छ, त्यसैले हामी यसलाई सजिलै पहुँच गर्न सक्छौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import torchtext\n",
"import os\n",
"import collections\n",
"os.makedirs('./data',exist_ok=True)\n",
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यहाँ, `train_dataset` र `test_dataset` ले क्रमशः वर्गको संख्या (लेबल) र पाठको जोडीहरू फर्काउने संग्रहहरू समावेश गर्दछ, उदाहरणका लागि:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3,\n",
" \"Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.\")"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(train_dataset)[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"त्यसैले, हाम्रो डाटासेटबाट पहिलो १० नयाँ शीर्षकहरू प्रिन्ट गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"**Sci/Tech** -> Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\band of ultra-cynics, are seeing green again.\n",
"**Sci/Tech** -> Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\which has a reputation for making well-timed and occasionally\\controversial plays in the defense industry, has quietly placed\\its bets on another part of the market.\n",
"**Sci/Tech** -> Oil and Economy Cloud Stocks' Outlook (Reuters) Reuters - Soaring crude prices plus worries\\about the economy and the outlook for earnings are expected to\\hang over the stock market next week during the depth of the\\summer doldrums.\n",
"**Sci/Tech** -> Iraq Halts Oil Exports from Main Southern Pipeline (Reuters) Reuters - Authorities have halted oil export\\flows from the main pipeline in southern Iraq after\\intelligence showed a rebel militia could strike\\infrastructure, an oil official said on Saturday.\n",
"**Sci/Tech** -> Oil prices soar to all-time record, posing new menace to US economy (AFP) AFP - Tearaway world oil prices, toppling records and straining wallets, present a new economic menace barely three months before the US presidential elections.\n"
]
}
],
"source": [
"for i,x in zip(range(5),train_dataset):\n",
" print(f\"**{classes[x[0]]}** -> {x[1]}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"किनभने डेटासेटहरू इटरेटरहरू हुन्, यदि हामीले डाटा धेरै पटक प्रयोग गर्न चाहन्छौं भने हामीले यसलाई सूचीमा रूपान्तरण गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
"train_dataset = list(train_dataset)\n",
"test_dataset = list(test_dataset)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टोकनाइजेशन\n",
"\n",
"अब हामीले पाठलाई **संख्या** मा रूपान्तरण गर्न आवश्यक छ जसलाई टेन्सरको रूपमा प्रस्तुत गर्न सकिन्छ। यदि हामी शब्द-स्तरको प्रतिनिधित्व चाहन्छौं भने, हामीले दुई कुरा गर्नुपर्छ:\n",
"* पाठलाई **टोकन** मा विभाजन गर्न **टोकनाइजर** प्रयोग गर्नुहोस्\n",
"* ती टोकनहरूको **शब्दकोश** निर्माण गर्नुहोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['he', 'said', 'hello']"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
"tokenizer('He said: hello')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" counter.update(tokenizer(line))\n",
"vocab = torchtext.vocab.vocab(counter, min_freq=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"शब्दावली प्रयोग गरेर, हामी सजिलैसँग टोकन गरिएको स्ट्रिङलाई संख्याको सेटमा एन्कोड गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocab size if 95810\n"
]
},
{
"data": {
"text/plain": [
"[599, 3279, 97, 1220, 329, 225, 7368]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vocab_size = len(vocab)\n",
"print(f\"Vocab size if {vocab_size}\")\n",
"\n",
"stoi = vocab.get_stoi() # dict to convert tokens to indices\n",
"\n",
"def encode(x):\n",
" return [stoi[s] for s in tokenizer(x)]\n",
"\n",
"encode('I love to play with my words')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## शब्दहरूको झोला (Bag of Words) पाठ प्रतिनिधित्व\n",
"\n",
"किनभने शब्दहरूले अर्थ व्यक्त गर्छन्, कहिलेकाहीँ हामी वाक्यको क्रमको पर्वाह नगरी, व्यक्तिगत शब्दहरू हेरेरै पाठको अर्थ पत्ता लगाउन सक्छौं। उदाहरणका लागि, समाचार वर्गीकरण गर्दा, *मौसम*, *हिउँ* जस्ता शब्दहरूले *मौसम पूर्वानुमान* जनाउन सक्छन्, जबकि *स्टक*, *डलर* जस्ता शब्दहरूले *आर्थिक समाचार* तर्फ सङ्केत गर्न सक्छन्।\n",
"\n",
"**शब्दहरूको झोला** (BoW) भेक्टर प्रतिनिधित्व परम्परागत भेक्टर प्रतिनिधित्वमा सबैभन्दा धेरै प्रयोग गरिने विधि हो। प्रत्येक शब्दलाई भेक्टरको सूचकसँग जोडिन्छ, र भेक्टरको तत्त्वले कुनै विशेष दस्तावेजमा शब्दको उपस्थितिको सङ्ख्या समावेश गर्दछ।\n",
"\n",
"![शब्दहरूको झोला भेक्टर प्रतिनिधित्व मेमोरीमा कसरी देखिन्छ भन्ने देखाउने छवि।](../../../../../translated_images/bag-of-words-example.606fc1738f1d7ba98a9d693e3bcd706c6e83fa7bf8221e6e90d1a206d82f2ea4.ne.png)\n",
"\n",
"> **Note**: तपाईं BoW लाई पाठका व्यक्तिगत शब्दहरूको लागि सबै एक-तर्फ-कोड गरिएको भेक्टरहरूको योगको रूपमा पनि सोच्न सक्नुहुन्छ।\n",
"\n",
"तल Scikit Learn पायथन पुस्तकालय प्रयोग गरेर शब्दहरूको झोला प्रतिनिधित्व कसरी निर्माण गर्ने उदाहरण दिइएको छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.feature_extraction.text import CountVectorizer\n",
"vectorizer = CountVectorizer()\n",
"corpus = [\n",
" 'I like hot dogs.',\n",
" 'The dog ran fast.',\n",
" 'Its hot outside.',\n",
" ]\n",
"vectorizer.fit_transform(corpus)\n",
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"AG_NEWS डेटासेटको भेक्टर प्रतिनिधित्वबाट bag-of-words भेक्टर गणना गर्न, हामी निम्न फङ्सन प्रयोग गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([2., 1., 2., ..., 0., 0., 0.])\n"
]
}
],
"source": [
"vocab_size = len(vocab)\n",
"\n",
"def to_bow(text,bow_vocab_size=vocab_size):\n",
" res = torch.zeros(bow_vocab_size,dtype=torch.float32)\n",
" for i in encode(text):\n",
" if i<bow_vocab_size:\n",
" res[i] += 1\n",
" return res\n",
"\n",
"print(to_bow(train_dataset[0][1]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **नोट:** यहाँ हामीले डिफल्ट शब्दकोशको आकार निर्दिष्ट गर्न ग्लोबल `vocab_size` भेरिएबल प्रयोग गरेका छौं। किनभने प्रायः शब्दकोशको आकार धेरै ठूलो हुन्छ, हामी शब्दकोशको आकारलाई सबैभन्दा बारम्बार प्रयोग हुने शब्दहरूमा सीमित गर्न सक्छौं। `vocab_size` को मान घटाएर तलको कोड चलाउने प्रयास गर्नुहोस्, र यसले शुद्धतामा कसरी प्रभाव पार्छ हेर्नुहोस्। तपाईंले केही शुद्धता घट्ने अपेक्षा गर्नुपर्छ, तर प्रदर्शन सुधारको सट्टामा नाटकीय रूपमा होइन।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## BoW वर्गीकरणकर्ता प्रशिक्षण\n",
"\n",
"अब हामीले हाम्रो पाठको Bag-of-Words प्रतिनिधित्व कसरी निर्माण गर्ने भनेर सिकिसकेपछि, यसमा आधारित भएर एक वर्गीकरणकर्ता प्रशिक्षण गरौं। पहिलो चरणमा, हामीले हाम्रो डेटासेटलाई यस्तो तरिकाले प्रशिक्षणका लागि रूपान्तरण गर्नुपर्छ, जसले गर्दा सबै स्थानगत भेक्टर प्रतिनिधित्वहरूलाई Bag-of-Words प्रतिनिधित्वमा परिवर्तन गरिन्छ। यो `bowify` फंक्शनलाई मानक torch `DataLoader` मा `collate_fn` प्यारामिटरको रूपमा पास गरेर हासिल गर्न सकिन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"from torch.utils.data import DataLoader\n",
"import numpy as np \n",
"\n",
"# this collate function gets list of batch_size tuples, and needs to \n",
"# return a pair of label-feature tensors for the whole minibatch\n",
"def bowify(b):\n",
" return (\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([to_bow(t[1]) for t in b])\n",
" )\n",
"\n",
"train_loader = DataLoader(train_dataset, batch_size=16, collate_fn=bowify, shuffle=True)\n",
"test_loader = DataLoader(test_dataset, batch_size=16, collate_fn=bowify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी एउटा साधारण वर्गीकरण न्युरल नेटवर्क परिभाषित गरौं जसमा एउटा मात्र रेखीय तह हुन्छ। इनपुट भेक्टरको आकार `vocab_size` बराबर हुन्छ, र आउटपुट आकार कक्षाहरूको संख्या (4) सँग मेल खान्छ। किनभने हामी वर्गीकरण कार्य समाधान गर्दैछौं, अन्तिम सक्रियता प्रकार्य `LogSoftmax()` हो।\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"net = torch.nn.Sequential(torch.nn.Linear(vocab_size,4),torch.nn.LogSoftmax(dim=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी मानक PyTorch प्रशिक्षण लूप परिभाषित गर्नेछौं। किनभने हाम्रो डेटासेट धेरै ठूलो छ, हाम्रो शिक्षण उद्देश्यको लागि हामी केवल एक इपोकको लागि प्रशिक्षण गर्नेछौं, र कहिलेकाहीँ इपोकभन्दा पनि कम (प्रशिक्षण सीमित गर्न `epoch_size` प्यारामिटर निर्दिष्ट गर्न सकिन्छ)। हामीले प्रशिक्षणको क्रममा संचित प्रशिक्षण शुद्धता पनि रिपोर्ट गर्नेछौं; रिपोर्ट गर्ने आवृत्ति `report_freq` प्यारामिटर प्रयोग गरेर निर्दिष्ट गरिन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"def train_epoch(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.NLLLoss(),epoch_size=None, report_freq=200):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
" net.train()\n",
" total_loss,acc,count,i = 0,0,0,0\n",
" for labels,features in dataloader:\n",
" optimizer.zero_grad()\n",
" out = net(features)\n",
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss+=loss\n",
" _,predicted = torch.max(out,1)\n",
" acc+=(predicted==labels).sum()\n",
" count+=len(labels)\n",
" i+=1\n",
" if i%report_freq==0:\n",
" print(f\"{count}: acc={acc.item()/count}\")\n",
" if epoch_size and count>epoch_size:\n",
" break\n",
" return total_loss.item()/count, acc.item()/count"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.8028125\n",
"6400: acc=0.8371875\n",
"9600: acc=0.8534375\n",
"12800: acc=0.85765625\n"
]
},
{
"data": {
"text/plain": [
"(0.026090790722161722, 0.8620069296375267)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_epoch(net,train_loader,epoch_size=15000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## BiGrams, TriGrams र N-Grams\n",
"\n",
"Bag of words विधिको एउटा सीमितता भनेको केही शब्दहरू बहु-शब्द अभिव्यक्तिहरूको हिस्सा हुन्छन्। उदाहरणका लागि, 'hot dog' शब्दको अर्थ 'hot' र 'dog' शब्दहरूको अन्य सन्दर्भमा भन्दा पूर्ण रूपमा फरक हुन्छ। यदि हामी 'hot' र 'dog' शब्दहरूलाई सधैं एउटै भेक्टरद्वारा प्रतिनिधित्व गर्छौं भने, यसले हाम्रो मोडेललाई भ्रमित गर्न सक्छ।\n",
"\n",
"यस समस्यालाई समाधान गर्न, **N-gram प्रतिनिधित्वहरू** प्रायः कागजात वर्गीकरणका विधिहरूमा प्रयोग गरिन्छ, जहाँ प्रत्येक शब्द, दुई-शब्द (bi-word) वा तीन-शब्द (tri-word) को आवृत्ति classifiers प्रशिक्षण गर्नका लागि उपयोगी विशेषता हुन्छ। उदाहरणका लागि, bigram प्रतिनिधित्वमा, हामी मूल शब्दहरूको अतिरिक्त सबै शब्द जोडीहरूलाई पनि शब्दकोशमा थप्नेछौं।\n",
"\n",
"तल Scikit Learn प्रयोग गरेर bigram bag of word प्रतिनिधित्व कसरी निर्माण गर्ने भन्ने उदाहरण छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 26,
"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": 26,
"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 प्रतिनिधित्व प्रयोग गर्न, हामीले विशेष ngram शब्दकोश निर्माण गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Bigram vocabulary length = 1308842\n"
]
}
],
"source": [
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" l = tokenizer(line)\n",
" counter.update(torchtext.data.utils.ngrams_iterator(l,ngrams=2))\n",
" \n",
"bi_vocab = torchtext.vocab.vocab(counter, min_freq=1)\n",
"\n",
"print(\"Bigram vocabulary length = \",len(bi_vocab))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी माथिको जस्तै कोड प्रयोग गरेर classifier प्रशिक्षण गर्न सक्थ्यौं, तर यो धेरै मेमोरी-अक्षम हुने थियो। अर्को इकाईमा, हामी embeddings प्रयोग गरेर bigram classifier प्रशिक्षण गर्नेछौं।\n",
"\n",
"> **Note:** तपाईंले केवल ती ngrams छोड्न सक्नुहुन्छ जुन पाठमा निर्दिष्ट गरिएको संख्याभन्दा बढी पटक देखा पर्छ। यसले सुनिश्चित गर्नेछ कि कम बारम्बार देखा पर्ने bigrams हटाइनेछ, र dimensionality उल्लेखनीय रूपमा घट्नेछ। यसका लागि, `min_freq` parameter लाई उच्च मानमा सेट गर्नुहोस्, र vocabulary को लम्बाइ परिवर्तनलाई अवलोकन गर्नुहोस्।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टर्म फ्रिक्वेन्सी इनभर्स डकुमेन्ट फ्रिक्वेन्सी TF-IDF\n",
"\n",
"BoW प्रतिनिधित्वमा, शब्दको उपस्थितिलाई समान तौल दिइन्छ, चाहे शब्द कस्तो भए पनि। तर, यो स्पष्ट छ कि बारम्बार प्रयोग हुने शब्दहरू, जस्तै *a*, *in*, आदि वर्गीकरणका लागि विशेष शब्दहरूको तुलनामा धेरै कम महत्त्वपूर्ण हुन्छन्। वास्तवमा, अधिकांश NLP कार्यहरूमा केही शब्दहरू अरूभन्दा बढी सान्दर्भिक हुन्छन्।\n",
"\n",
"**TF-IDF** को अर्थ **टर्म फ्रिक्वेन्सी–इनभर्स डकुमेन्ट फ्रिक्वेन्सी** हो। यो बाग अफ वर्ड्सको एक भिन्नता हो, जहाँ कुनै शब्दको उपस्थितिलाई संकेत गर्ने 0/1 बाइनरी मानको सट्टा, फ्लोटिङ-पोइन्ट मान प्रयोग गरिन्छ, जुन शब्दको कर्पसमा उपस्थितिको फ्रिक्वेन्सीसँग सम्बन्धित हुन्छ।\n",
"\n",
"औपचारिक रूपमा, शब्द $i$ को डकुमेन्ट $j$ मा तौल $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": 28,
"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": 28,
"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": [
"## निष्कर्ष\n",
"\n",
"यद्यपि TF-IDF प्रतिनिधित्वहरूले विभिन्न शब्दहरूलाई आवृत्तिको तौल प्रदान गर्छन्, तिनीहरूले अर्थ वा क्रमलाई प्रतिनिधित्व गर्न असमर्थ छन्। प्रसिद्ध भाषाविद् जे. आर. फर्थले १९३५ मा भनेका थिए, \"शब्दको पूर्ण अर्थ सधैं सन्दर्भमा आधारित हुन्छ, र सन्दर्भबाहेकको अर्थको कुनै पनि अध्ययनलाई गम्भीरतापूर्वक लिन सकिँदैन।\"। हामी यस पाठ्यक्रममा पछि पाठबाट भाषागत मोडेलिङ प्रयोग गरी कसरी पाठबाट सन्दर्भगत जानकारी कब्जा गर्ने भन्ने कुरा सिक्नेछौं।\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": "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": "7b9040985e748e4e2d4c689892456ad7",
"translation_date": "2025-08-28T09:51:29+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,647 @@
{
"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": [
"हाम्रो डाटासेटबाट पहिलो १० नयाँ शीर्षकहरू प्रिन्ट गरौं:\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 डेटासेटको उदाहरणमा, शब्दकोशको आकार धेरै ठूलो छ, १k भन्दा बढी शब्दहरू। सामान्यतया, हामीलाई पाठमा कम उपस्थित हुने शब्दहरूको आवश्यकता हुँदैन — केवल केही वाक्यहरूमा मात्र ती शब्दहरू हुनेछन्, र मोडेलले तीबाट सिक्ने छैन। त्यसैले, शब्दकोशको आकारलाई सानो संख्यामा सीमित गर्नु उपयुक्त हुन्छ, जसका लागि भेक्टराइजर कन्स्ट्रक्टरमा एउटा आर्गुमेन्ट पास गर्न सकिन्छ:\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": [
"## शब्दहरूको झोला (Bag-of-words) पाठ प्रतिनिधित्व\n",
"\n",
"किनभने शब्दहरूले अर्थ व्यक्त गर्छन्, कहिलेकाहीं हामी वाक्यको क्रमको पर्वाह नगरी व्यक्तिगत शब्दहरू हेरेर पाठको अर्थ पत्ता लगाउन सक्छौं। उदाहरणका लागि, समाचार वर्गीकरण गर्दा, *मौसम* र *हिउँ* जस्ता शब्दहरूले *मौसम पूर्वानुमान* संकेत गर्न सक्छन्, जबकि *स्टक* र *डलर* जस्ता शब्दहरूले *आर्थिक समाचार* तर्फ गणना गर्न सक्छन्।\n",
"\n",
"**शब्दहरूको झोला** (BoW) भेक्टर प्रतिनिधित्व परम्परागत भेक्टर प्रतिनिधित्वहरू मध्ये सबैभन्दा सरल र बुझ्न सजिलो हो। प्रत्येक शब्दलाई भेक्टरको सूचकसँग जोडिन्छ, र भेक्टरको तत्वले कुनै पनि दस्तावेजमा प्रत्येक शब्दको उपस्थितिको संख्या समावेश गर्दछ।\n",
"\n",
"![शब्दहरूको झोला भेक्टर प्रतिनिधित्व मेमोरीमा कसरी प्रतिनिधित्व गरिन्छ भन्ने देखाउने चित्र।](../../../../../translated_images/bag-of-words-example.606fc1738f1d7ba98a9d693e3bcd706c6e83fa7bf8221e6e90d1a206d82f2ea4.ne.png)\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 vectorizer पनि प्रयोग गर्न सक्छौं, प्रत्येक शब्द संख्या एक-हट एन्कोडिङमा परिवर्तन गरेर ती सबै भेक्टरहरूलाई जोड्न:\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": [
"> **Note**: तपाईंलाई अचम्म लाग्न सक्छ कि नतिजा अघिल्लो उदाहरणभन्दा फरक छ। यसको कारण के हो भने 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": [
"चूँकि हामीसँग ४ वटा वर्गहरू छन्, ८०% भन्दा माथिको शुद्धता राम्रो नतिजा हो।\n",
"\n",
"## एक नेटवर्कको रूपमा वर्गीकरणकर्ता प्रशिक्षण गर्ने\n",
"\n",
"किनभने भेक्टराइजर पनि Keras लेयर हो, हामी यसलाई समावेश गर्ने नेटवर्क परिभाषित गर्न सक्छौं र यसलाई अन्त-देखि-अन्तसम्म प्रशिक्षण गर्न सक्छौं। यसरी हामीले `map` प्रयोग गरेर डेटासेटलाई भेक्टराइज गर्न आवश्यक पर्दैन, हामी नेटवर्कको इनपुटमा मूल डेटासेट मात्र पास गर्न सक्छौं।\n",
"\n",
"> **Note**: हामीले अझै पनि हाम्रो डेटासेटमा `title`, `description` र `label` जस्ता डिक्सनरीबाट फिल्डहरूलाई टपल्समा रूपान्तरण गर्न `map` लागू गर्नुपर्नेछ। तर, जब डिस्कबाट डेटा लोड गर्दैछौं, हामी सुरुमा आवश्यक संरचनासहितको डेटासेट निर्माण गर्न सक्छौं।\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",
"तल स्काइ-किट लर्न प्रयोग गरेर बाइग्राम ब्याग-अफ-वर्ड्स प्रतिनिधित्व कसरी निर्माण गर्ने भन्ने उदाहरण छ:\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` प्यारामिटर पास गर्नुपर्छ। बिग्राम शब्दकोशको लम्बाइ **धेरै ठूलो** हुन्छ, हाम्रो केसमा यो १.३ मिलियनभन्दा बढी टोकनहरू हुन्छ! त्यसैले, बिग्राम टोकनहरूलाई पनि कुनै उपयुक्त सीमामा सीमित गर्नु उचित हुन्छ।\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** को अर्थ **टर्म फ्रिक्वेन्सी - इनभर्स डकुमेन्ट फ्रिक्वेन्सी** हो। यो bag-of-words को एक भिन्नता हो, जहाँ कुनै शब्दको उपस्थितिलाई संकेत गर्ने 0/1 बाइनरी मानको सट्टा, फ्लोटिङ-प्वाइन्ट मान प्रयोग गरिन्छ, जुन शब्दको कर्पसमा उपस्थितिको फ्रिक्वेन्सीसँग सम्बन्धित हुन्छ।\n",
"\n",
"औपचारिक रूपमा, शब्द $i$ को डकुमेन्ट $j$ मा तौल $w_{ij}$ यसरी परिभाषित गरिन्छ:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"जहाँ\n",
"* $tf_{ij}$ भनेको $i$ को $j$ मा उपस्थितिको संख्या हो, अर्थात् हामीले पहिले देखेको 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 प्रतिनिधित्वहरूले विभिन्न शब्दहरूलाई आवृत्ति तौल प्रदान गर्छन्, तिनीहरूले अर्थ वा क्रमलाई प्रतिनिधित्व गर्न सक्दैनन्। प्रसिद्ध भाषाविद् जे. आर. फर्थले १९३५ मा भनेका थिए, \"शब्दको पूर्ण अर्थ सधैं सन्दर्भात्मक हुन्छ, र सन्दर्भबाहेकको अर्थको कुनै पनि अध्ययनलाई गम्भीरतापूर्वक लिन सकिँदैन।\" हामी पाठबाट सन्दर्भात्मक जानकारी कसरी समात्ने भन्ने कुरा यस पाठ्यक्रममा पछि भाषा मोडलिङ प्रयोग गरेर सिक्नेछौं।\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:55:06+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,720 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिङहरू\n",
"\n",
"हाम्रो अघिल्लो उदाहरणमा, हामीले `vocab_size` लम्बाइ भएका उच्च-आयामीय बाग-ऑफ-वर्ड्स भेक्टरहरूमा काम गरेका थियौं, र हामीले कम-आयामीय स्थानगत प्रतिनिधित्व भेक्टरहरूलाई स्पष्ट रूपमा sparse one-hot प्रतिनिधित्वमा रूपान्तरण गरिरहेका थियौं। यो one-hot प्रतिनिधित्व मेमोरी-कुशल छैन, साथै, प्रत्येक शब्दलाई एक-अर्काबाट स्वतन्त्र रूपमा व्यवहार गरिन्छ, अर्थात् one-hot एन्कोड गरिएको भेक्टरहरूले शब्दहरू बीचको कुनै पनि अर्थपूर्ण समानता व्यक्त गर्दैनन्।\n",
"\n",
"यस इकाईमा, हामी **News AG** डेटासेटको अन्वेषण जारी राख्नेछौं। सुरु गर्नका लागि, डेटा लोड गरौं र अघिल्लो नोटबुकबाट केही परिभाषाहरू प्राप्त गरौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\train.csv: 29.5MB [00:01, 18.8MB/s] \n",
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\test.csv: 1.86MB [00:00, 11.2MB/s] \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Building vocab...\n",
"Vocab size = 95812\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"import numpy as np\n",
"from torchnlp import *\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_size = len(vocab)\n",
"print(\"Vocab size = \",vocab_size)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिङ भनेको के हो?\n",
"\n",
"**एम्बेडिङ** को विचार भनेको शब्दहरूलाई कम-आयामीय घना भेक्टरहरूद्वारा प्रतिनिधित्व गर्नु हो, जसले कुनै प्रकारले शब्दको अर्थलाई झल्काउँछ। हामी पछि कसरी अर्थपूर्ण शब्द एम्बेडिङहरू निर्माण गर्ने भन्ने छलफल गर्नेछौं, तर अहिलेका लागि एम्बेडिङलाई शब्द भेक्टरको आयाम घटाउने तरिकाको रूपमा सोचौं। \n",
"\n",
"त्यसैले, एम्बेडिङ लेयरले शब्दलाई इनपुटको रूपमा लिन्छ, र निर्दिष्ट गरिएको `embedding_size` को आउटपुट भेक्टर उत्पादन गर्छ। यो अर्थमा, यो `Linear` लेयरसँग धेरै मिल्दोजुल्दो छ, तर यो एक-हट इन्कोड गरिएको भेक्टर लिने सट्टा, शब्दको नम्बरलाई इनपुटको रूपमा लिन सक्षम हुनेछ।\n",
"\n",
"हाम्रो नेटवर्कमा पहिलो लेयरको रूपमा एम्बेडिङ लेयर प्रयोग गरेर, हामी ब्याग-अफ-वर्ड्स मोडेलबाट **एम्बेडिङ ब्याग** मोडेलमा स्विच गर्न सक्छौं, जहाँ हामी पहिलो पटक हाम्रो पाठका प्रत्येक शब्दलाई सम्बन्धित एम्बेडिङमा रूपान्तरण गर्छौं, र त्यसपछि ती सबै एम्बेडिङहरूमा `sum`, `average` वा `max` जस्ता कुनै एग्रिगेट फङ्सन गणना गर्छौं। \n",
"\n",
"![पाँच अनुक्रम शब्दहरूको लागि एम्बेडिङ क्लासिफायर देखाउने छवि।](../../../../../translated_images/embedding-classifier-example.b77f021a7ee67eeec8e68bfe11636c5b97d6eaa067515a129bfb1d0034b1ac5b.ne.png)\n",
"\n",
"हाम्रो क्लासिफायर न्यूरल नेटवर्क एम्बेडिङ लेयरबाट सुरु हुनेछ, त्यसपछि एग्रिगेसन लेयर, र यसको माथि लीनियर क्लासिफायर हुनेछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class EmbedClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, num_class):\n",
" super().__init__()\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" x = self.embedding(x)\n",
" x = torch.mean(x,dim=1)\n",
" return self.fc(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### भिन्न-भिन्न आकारका भेरिएबल अनुक्रमसँग काम गर्ने\n",
"\n",
"यो आर्किटेक्चरको परिणामस्वरूप, हाम्रो नेटवर्कका लागि मिनिब्याचहरू विशेष तरिकाले तयार गर्नुपर्ने हुन्छ। अघिल्लो युनिटमा, जब bag-of-words प्रयोग गरिँदै थियो, सबै BoW टेन्सरहरूको आकार मिनिब्याचमा `vocab_size` बराबर हुन्थ्यो, चाहे हाम्रो पाठ अनुक्रमको वास्तविक लम्बाइ जेसुकै किन नहोस्। जब हामी word embeddings तर्फ सर्छौं, प्रत्येक पाठ नमूनामा शब्दहरूको संख्या फरक-फरक हुन सक्छ, र ती नमूनाहरूलाई मिनिब्याचमा संयोजन गर्दा हामीले केही padding लागू गर्नुपर्ने हुन्छ।\n",
"\n",
"यो काम datasource मा `collate_fn` function प्रदान गरेर गर्न सकिन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def padify(b):\n",
" # b is the list of tuples of length batch_size\n",
" # - first element of a tuple = label, \n",
" # - second = feature (text sequence)\n",
" # build vectorized sequence\n",
" v = [encode(x[1]) for x in b]\n",
" # first, compute max length of a sequence in this minibatch\n",
" l = max(map(len,v))\n",
" return ( # tuple of two tensors - labels and features\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### एम्बेडिङ वर्गीकरणकर्ता प्रशिक्षण गर्दै\n",
"\n",
"अब हामीले उपयुक्त डाटालोडर परिभाषित गरिसकेपछि, हामीले अघिल्लो इकाईमा परिभाषित गरेको प्रशिक्षण कार्य प्रयोग गरेर मोडेल प्रशिक्षण गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6415625\n",
"6400: acc=0.6865625\n",
"9600: acc=0.7103125\n",
"12800: acc=0.726953125\n",
"16000: acc=0.739375\n",
"19200: acc=0.75046875\n",
"22400: acc=0.7572321428571429\n"
]
},
{
"data": {
"text/plain": [
"(0.889799795315499, 0.7623160588611644)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=1, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **नोट**: हामी यहाँ समय बचतको लागि मात्र २५ हजार रेकर्डहरू (एक पूर्ण युगभन्दा कम) को लागि प्रशिक्षण गर्दैछौं, तर तपाईं प्रशिक्षण जारी राख्न सक्नुहुन्छ, धेरै युगहरूको लागि प्रशिक्षण गर्नको लागि एक कार्य लेख्न सक्नुहुन्छ, र उच्च शुद्धता प्राप्त गर्नको लागि सिक्ने दर प्यारामिटरसँग प्रयोग गर्न सक्नुहुन्छ। तपाईं लगभग ९०% शुद्धतामा जान सक्षम हुनुहुनेछ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EmbeddingBag लेयर र भिन्न-लम्बाइ अनुक्रमको प्रतिनिधित्व\n",
"\n",
"अघिल्लो आर्किटेक्चरमा, हामीले सबै अनुक्रमहरूलाई एउटै लम्बाइमा ल्याउनका लागि padding गर्नुपर्ने हुन्थ्यो ताकि तिनीहरूलाई मिनिब्याचमा फिट गर्न सकियोस्। यो भिन्न-लम्बाइ अनुक्रमहरूको प्रतिनिधित्व गर्ने सबैभन्दा प्रभावकारी तरिका होइन - अर्को तरिका भनेको **offset** भेक्टर प्रयोग गर्नु हो, जसले एउटै ठूलो भेक्टरमा भण्डारण गरिएका सबै अनुक्रमहरूको offsets राख्छ।\n",
"\n",
"![Offset अनुक्रम प्रतिनिधित्व देखाउने चित्र](../../../../../translated_images/offset-sequence-representation.eb73fcefb29b46eecfbe74466077cfeb7c0f93a4f254850538a2efbc63517479.ne.png)\n",
"\n",
"> **Note**: माथिको चित्रमा, हामीले क्यारेक्टरहरूको अनुक्रम देखाएका छौं, तर हाम्रो उदाहरणमा हामी शब्दहरूको अनुक्रमसँग काम गरिरहेका छौं। यद्यपि, offset भेक्टर प्रयोग गरेर अनुक्रमहरूको प्रतिनिधित्व गर्ने सामान्य सिद्धान्त उस्तै रहन्छ।\n",
"\n",
"Offset प्रतिनिधित्वसँग काम गर्नका लागि, हामी [`EmbeddingBag`](https://pytorch.org/docs/stable/generated/torch.nn.EmbeddingBag.html) लेयर प्रयोग गर्छौं। यो `Embedding` जस्तै छ, तर यसले सामग्री भेक्टर र offset भेक्टरलाई इनपुटको रूपमा लिन्छ, र यसमा औसत गर्ने लेयर पनि समावेश छ, जुन `mean`, `sum` वा `max` हुन सक्छ।\n",
"\n",
"यहाँ `EmbeddingBag` प्रयोग गर्ने परिमार्जित नेटवर्क छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class EmbedClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, num_class):\n",
" super().__init__()\n",
" self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim)\n",
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
"\n",
" def forward(self, text, off):\n",
" x = self.embedding(text, off)\n",
" return self.fc(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"डेटासेट प्रशिक्षणको लागि तयार गर्न, हामीले अफसेट भेक्टर तयार गर्ने रूपान्तरण कार्य प्रदान गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def offsetify(b):\n",
" # first, compute data tensor from all sequences\n",
" x = [torch.tensor(encode(t[1])) for t in b]\n",
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
" o = [0] + [len(t) for t in x]\n",
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
" return ( \n",
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
" torch.cat(x), # text \n",
" o\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ध्यान दिनुहोस्, कि सबै अघिल्लो उदाहरणहरू भन्दा फरक, हाम्रो नेटवर्कले अब दुई प्यारामिटरहरू स्वीकार गर्दछ: डेटा भेक्टर र अफसेट भेक्टर, जसको आकार फरक छ। त्यस्तै गरी, हाम्रो डेटा लोडरले पनि हामीलाई २ को सट्टा ३ मानहरू प्रदान गर्दछ: पाठ र अफसेट भेक्टरहरू दुवैलाई सुविधाहरूको रूपमा प्रदान गरिन्छ। त्यसैले, हामीले हाम्रो प्रशिक्षण कार्यलाई त्यसको हेरचाह गर्न अलिकति समायोजन गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6153125\n",
"6400: acc=0.6615625\n",
"9600: acc=0.6932291666666667\n",
"12800: acc=0.715078125\n",
"16000: acc=0.7270625\n",
"19200: acc=0.7382291666666667\n",
"22400: acc=0.7486160714285715\n"
]
},
{
"data": {
"text/plain": [
"(22.771553103007037, 0.7551983365323096)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
"\n",
"def train_epoch_emb(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.CrossEntropyLoss(),epoch_size=None, report_freq=200):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
" loss_fn = loss_fn.to(device)\n",
" net.train()\n",
" total_loss,acc,count,i = 0,0,0,0\n",
" for labels,text,off in dataloader:\n",
" optimizer.zero_grad()\n",
" labels,text,off = labels.to(device), text.to(device), off.to(device)\n",
" out = net(text, off)\n",
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss+=loss\n",
" _,predicted = torch.max(out,1)\n",
" acc+=(predicted==labels).sum()\n",
" count+=len(labels)\n",
" i+=1\n",
" if i%report_freq==0:\n",
" print(f\"{count}: acc={acc.item()/count}\")\n",
" if epoch_size and count>epoch_size:\n",
" break\n",
" return total_loss.item()/count, acc.item()/count\n",
"\n",
"\n",
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सेम्यान्टिक एम्बेडिङ: वर्ड२भेक\n",
"\n",
"हाम्रो अघिल्लो उदाहरणमा, मोडेलको एम्बेडिङ तहले शब्दहरूलाई भेक्टर प्रतिनिधित्वमा म्याप गर्न सिक्यो, तर यो प्रतिनिधित्वमा धेरै सेम्यान्टिक अर्थ थिएन। यस्तो भेक्टर प्रतिनिधित्व सिक्न राम्रो हुने थियो, जहाँ समान शब्दहरू वा पर्यायवाची शब्दहरू केही भेक्टर दूरी (जस्तै, युक्लिडियन दूरी) को हिसाबले एक-अर्कासँग नजिक हुनेछन्।\n",
"\n",
"यसका लागि, हामीले हाम्रो एम्बेडिङ मोडेललाई विशेष तरिकाले ठूलो पाठ संग्रहमा प्रि-ट्रेन गर्न आवश्यक छ। सेम्यान्टिक एम्बेडिङहरू ट्रेन गर्ने पहिलो तरिकाहरू मध्ये एकलाई [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) भनिन्छ। यो शब्दहरूको वितरित प्रतिनिधित्व उत्पादन गर्न प्रयोग गरिने दुई मुख्य आर्किटेक्चरहरूमा आधारित छ:\n",
"\n",
" - **कन्टिन्युअस ब्याग-अफ-वर्ड्स** (CBoW) — यस आर्किटेक्चरमा, हामी मोडेललाई वरपरको सन्दर्भबाट शब्दको भविष्यवाणी गर्न ट्रेन गर्छौं। दिइएको ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ मा, मोडेलको लक्ष्य $(W_{-2},W_{-1},W_1,W_2)$ बाट $W_0$ को भविष्यवाणी गर्नु हो।\n",
" - **कन्टिन्युअस स्किप-ग्राम** CBoW को विपरीत हो। मोडेलले सन्दर्भ शब्दहरूको वरपरको विन्डो प्रयोग गरेर वर्तमान शब्दको भविष्यवाणी गर्छ।\n",
"\n",
"CBoW छिटो हुन्छ, जबकि स्किप-ग्राम ढिलो हुन्छ, तर दुर्लभ शब्दहरूको प्रतिनिधित्व गर्न राम्रो काम गर्छ।\n",
"\n",
"![CBoW र स्किप-ग्राम एल्गोरिदमहरू शब्दहरूलाई भेक्टरमा रूपान्तरण गर्ने तरिका देखाउने चित्र।](../../../../../translated_images/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6f0f5de66427e8a6eda63809356114e28fb1fa5f4a83ebda7.ne.png)\n",
"\n",
"Google News डेटासेटमा प्रि-ट्रेन गरिएको word2vec एम्बेडिङसँग प्रयोग गर्न, हामी **gensim** लाइब्रेरी प्रयोग गर्न सक्छौं। तल हामी 'neural' शब्दसँग सबैभन्दा मिल्दो शब्दहरू फेला पार्छौं।\n",
"\n",
"> **Note:** जब तपाईं पहिलो पटक शब्द भेक्टरहरू सिर्जना गर्नुहुन्छ, तिनीहरू डाउनलोड गर्न केही समय लाग्न सक्छ!\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import gensim.downloader as api\n",
"w2v = api.load('word2vec-google-news-300')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"neuronal -> 0.7804799675941467\n",
"neurons -> 0.7326500415802002\n",
"neural_circuits -> 0.7252851724624634\n",
"neuron -> 0.7174385190010071\n",
"cortical -> 0.6941086649894714\n",
"brain_circuitry -> 0.6923246383666992\n",
"synaptic -> 0.6699118614196777\n",
"neural_circuitry -> 0.6638563275337219\n",
"neurochemical -> 0.6555314064025879\n",
"neuronal_activity -> 0.6531826257705688\n"
]
}
],
"source": [
"for w,p in w2v.most_similar('neural'):\n",
" print(f\"{w} -> {p}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी शब्दबाट भेक्टर एम्बेडिङहरू पनि गणना गर्न सक्छौं, जसलाई वर्गीकरण मोडेल प्रशिक्षणमा प्रयोग गर्न सकिन्छ (स्पष्टताको लागि हामी भेक्टरका पहिलो २० घटकहरू मात्र देखाउँछौं):\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
" dtype=float32)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.word_vec('play')[:20]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('queen', 0.7118192911148071)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"CBoW र Skip-Grams दुबै \"predictive\" embeddings हुन्, किनकि यी केवल स्थानीय सन्दर्भहरूलाई मात्र ध्यानमा राख्छन्। Word2Vec ले विश्वव्यापी सन्दर्भको फाइदा उठाउँदैन।\n",
"\n",
"**FastText** ले Word2Vec मा आधारित भएर प्रत्येक शब्द र शब्दभित्र पाइने अक्षर n-grams को लागि भेक्टर प्रतिनिधित्वहरू सिक्छ। प्रतिनिधित्वहरूको मानहरू प्रत्येक प्रशिक्षण चरणमा एक भेक्टरमा औसत गरिन्छ। यसले पूर्व-प्रशिक्षणमा धेरै अतिरिक्त गणना थपे पनि, यसले शब्द embeddings लाई उप-शब्द जानकारी समेट्न सक्षम बनाउँछ।\n",
"\n",
"अर्को विधि, **GloVe**, सह-अवस्थित म्याट्रिक्सको विचारलाई उपयोग गर्दछ, सह-अवस्थित म्याट्रिक्सलाई अधिक अभिव्यक्तिपूर्ण र गैर-रेखीय शब्द भेक्टरहरूमा विघटन गर्न न्युरल विधिहरू प्रयोग गर्दछ।\n",
"\n",
"तपाईं embeddings लाई FastText र GloVe मा परिवर्तन गरेर उदाहरणसँग खेल्न सक्नुहुन्छ, किनकि gensim ले विभिन्न शब्द embedding मोडेलहरूलाई समर्थन गर्दछ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PyTorch मा प्रि-ट्रेन गरिएको एम्बेडिङहरू प्रयोग गर्दै\n",
"\n",
"हामी माथिको उदाहरणलाई संशोधन गरेर हाम्रो एम्बेडिङ लेयरको म्याट्रिक्सलाई Word2Vec जस्ता अर्थपूर्ण एम्बेडिङहरूद्वारा पहिले नै भरिएको बनाउन सक्छौं। हामीले ध्यान दिनुपर्छ कि प्रि-ट्रेन गरिएको एम्बेडिङको शब्दावली र हाम्रो पाठ कर्पसको शब्दावली सम्भवतः मेल खाने छैन, त्यसैले हामी हराएका शब्दहरूको लागि तौलहरूलाई र्यान्डम मानहरूद्वारा आरम्भ गर्नेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Embedding size: 300\n",
"Populating matrix, this will take some time...Done, found 41080 words, 54732 words missing\n"
]
}
],
"source": [
"embed_size = len(w2v.get_vector('hello'))\n",
"print(f'Embedding size: {embed_size}')\n",
"\n",
"net = EmbedClassifier(vocab_size,embed_size,len(classes))\n",
"\n",
"print('Populating matrix, this will take some time...',end='')\n",
"found, not_found = 0,0\n",
"for i,w in enumerate(vocab.get_itos()):\n",
" try:\n",
" net.embedding.weight[i].data = torch.tensor(w2v.get_vector(w))\n",
" found+=1\n",
" except:\n",
" net.embedding.weight[i].data = torch.normal(0.0,1.0,(embed_size,))\n",
" not_found+=1\n",
"\n",
"print(f\"Done, found {found} words, {not_found} words missing\")\n",
"net = net.to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6359375\n",
"6400: acc=0.68109375\n",
"9600: acc=0.7067708333333333\n",
"12800: acc=0.723671875\n",
"16000: acc=0.73625\n",
"19200: acc=0.7463541666666667\n",
"22400: acc=0.7560714285714286\n"
]
},
{
"data": {
"text/plain": [
"(214.1013875559821, 0.7626759436980166)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो अवस्थामा, हामीले शुद्धतामा ठूलो वृद्धि देख्दैनौं, जुन सम्भवतः धेरै फरक शब्दावलीका कारण हो। \n",
"विभिन्न शब्दावलीको समस्यालाई समाधान गर्न, हामी निम्न समाधानहरू प्रयोग गर्न सक्छौं: \n",
"* हाम्रो शब्दावलीमा आधारित word2vec मोडेल पुनः-प्रशिक्षण गर्नुहोस् \n",
"* प्रि-ट्रेन गरिएको word2vec मोडेलको शब्दावली प्रयोग गरेर हाम्रो डेटासेट लोड गर्नुहोस्। डेटासेट लोड गर्दा प्रयोग गरिने शब्दावली निर्दिष्ट गर्न सकिन्छ। \n",
"\n",
"दोस्रो विधि सजिलो देखिन्छ, विशेष गरी किनभने PyTorch `torchtext` फ्रेमवर्कमा embeddings को लागि बिल्ट-इन समर्थन छ। उदाहरणका लागि, हामी GloVe-आधारित शब्दावली निम्न तरिकाले निर्माण गर्न सक्छौं: \n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|█████████▉| 399999/400000 [00:15<00:00, 25411.14it/s]\n"
]
}
],
"source": [
"vocab = torchtext.vocab.GloVe(name='6B', dim=50)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"लोड गरिएको शब्दकोशमा निम्न आधारभूत कार्यहरू छन्:\n",
"* `vocab.stoi` शब्दकोशले हामीलाई शब्दलाई यसको शब्दकोश सूचकांकमा परिवर्तन गर्न अनुमति दिन्छ\n",
"* `vocab.itos` यसको उल्टो गर्छ - नम्बरलाई शब्दमा परिवर्तन गर्छ\n",
"* `vocab.vectors` एम्बेडिङ भेक्टरहरूको एरे हो, त्यसैले कुनै शब्द `s` को एम्बेडिङ प्राप्त गर्न हामीले `vocab.vectors[vocab.stoi[s]]` प्रयोग गर्नुपर्छ\n",
"\n",
"यहाँ एम्बेडिङहरूलाई परिमार्जन गरेर समीकरण **kind-man+woman = queen** प्रदर्शन गर्ने उदाहरण छ (यसलाई काम गर्नका लागि मैले थोरै गुणांक समायोजन गर्नुपर्‍यो):\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'queen'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get the vector corresponding to kind-man+woman\n",
"qvec = vocab.vectors[vocab.stoi['king']]-vocab.vectors[vocab.stoi['man']]+1.3*vocab.vectors[vocab.stoi['woman']]\n",
"# find the index of the closest embedding vector \n",
"d = torch.sum((vocab.vectors-qvec)**2,dim=1)\n",
"min_idx = torch.argmin(d)\n",
"# find the corresponding word\n",
"vocab.itos[min_idx]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले ती एम्बेडिङहरू प्रयोग गरेर वर्गीकरणकर्ता प्रशिक्षण गर्न, पहिलो चरणमा हाम्रो डेटासेटलाई GloVe शब्दावली प्रयोग गरेर एन्कोड गर्न आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def offsetify(b):\n",
" # first, compute data tensor from all sequences\n",
" x = [torch.tensor(encode(t[1],voc=vocab)) for t in b] # pass the instance of vocab to encode function!\n",
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
" o = [0] + [len(t) for t in x]\n",
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
" return ( \n",
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
" torch.cat(x), # text \n",
" o\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जस्तो कि हामीले माथि देख्यौं, सबै भेक्टर एम्बेडिङहरू `vocab.vectors` म्याट्रिक्समा संग्रहित छन्। यसले ती वजनहरूलाई एम्बेडिङ तहको वजनहरूमा साधारण प्रतिलिपि गरेर लोड गर्न अत्यन्त सजिलो बनाउँछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"net = EmbedClassifier(len(vocab),len(vocab.vectors[0]),len(classes))\n",
"net.embedding.weight.data = vocab.vectors\n",
"net = net.to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.6271875\n",
"6400: acc=0.68078125\n",
"9600: acc=0.7030208333333333\n",
"12800: acc=0.71984375\n",
"16000: acc=0.7346875\n",
"19200: acc=0.7455729166666667\n",
"22400: acc=0.7529464285714286\n"
]
},
{
"data": {
"text/plain": [
"(35.53972978646833, 0.7575175943698017)"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)\n",
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो डाटासेटका केही शब्दहरू प्रि-ट्रेन गरिएको GloVe शब्दकोशमा नभएको कारणले गर्दा हामीले शुद्धतामा उल्लेखनीय वृद्धि देख्न नसकेको मुख्य कारणहरू मध्ये एक हो, र त्यसैले ती शब्दहरूलाई मूलतः बेवास्ता गरिएको छ। यस तथ्यलाई पार गर्नका लागि, हामी हाम्रो डाटासेटमा आफ्नै एम्बेडिङहरू प्रशिक्षण गर्न सक्छौं।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सन्दर्भगत एम्बेडिङहरू\n",
"\n",
"Word2Vec जस्ता परम्परागत प्रीट्रेन गरिएको एम्बेडिङ प्रतिनिधित्वहरूको एउटा मुख्य सीमाबद्धता भनेको शब्द अर्थ अस्पष्टताको समस्या हो। यद्यपि प्रीट्रेन गरिएको एम्बेडिङहरूले शब्दहरूको सन्दर्भमा केही अर्थ समेट्न सक्छन्, कुनै पनि शब्दको सबै सम्भावित अर्थ एउटै एम्बेडिङमा समेटिन्छ। यसले डाउनस्ट्रीम मोडेलहरूमा समस्या उत्पन्न गर्न सक्छ, किनभने धेरै शब्दहरू, जस्तै 'play' शब्द, प्रयोग गरिएको सन्दर्भ अनुसार फरक अर्थ राख्छन्।\n",
"\n",
"उदाहरणका लागि, 'play' शब्दले यी दुई वाक्यहरूमा निकै फरक अर्थ राख्छ:\n",
"- म थिएटरमा एउटा **play** हेर्न गएँ।\n",
"- जोन आफ्ना साथीहरूसँग **play** गर्न चाहन्छ।\n",
"\n",
"माथिका प्रीट्रेन गरिएको एम्बेडिङहरूले 'play' शब्दका यी दुवै अर्थहरू एउटै एम्बेडिङमा प्रतिनिधित्व गर्छन्। यस सीमाबद्धतालाई पार गर्नका लागि, हामीले **भाषा मोडेल**मा आधारित एम्बेडिङहरू निर्माण गर्न आवश्यक छ, जुन ठूलो पाठको संग्रहमा प्रशिक्षित गरिएको हुन्छ र *जान्दछ* कि शब्दहरू विभिन्न सन्दर्भहरूमा कसरी राख्न सकिन्छ। सन्दर्भगत एम्बेडिङहरूको चर्चा यस ट्युटोरियलको दायराभन्दा बाहिर पर्छ, तर हामी यसबारे भाषा मोडेलहरूको कुरा गर्दा अर्को युनिटमा फर्कनेछौं।\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"
},
"kernelspec": {
"display_name": "py37_pytorch",
"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": "f50b026abce5cf36783a560ea72cb9b1",
"translation_date": "2025-08-28T09:47:38+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,695 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## एम्बेडिङहरू\n",
"\n",
"हाम्रो अघिल्लो उदाहरणमा, हामी उच्च-आयामीय bag-of-words भेक्टरहरूमा काम गर्यौं जसको लम्बाइ `vocab_size` थियो, र हामीले कम-आयामीय positional representation भेक्टरहरूलाई sparse one-hot representation मा स्पष्ट रूपमा परिवर्तन गर्यौं। यो one-hot representation मेमोरी-प्रभावकारी छैन। साथै, प्रत्येक शब्दलाई एक-अर्काबाट स्वतन्त्र रूपमा व्यवहार गरिन्छ, जसले गर्दा one-hot encoded भेक्टरहरूले शब्दहरू बीचको अर्थपूर्ण समानताहरू व्यक्त गर्दैनन्।\n",
"\n",
"यस इकाईमा, हामी **News AG** डेटासेटको अन्वेषण जारी राख्नेछौं। सुरु गर्नका लागि, डेटा लोड गरौं र अघिल्लो इकाईबाट केही परिभाषाहरू प्राप्त गरौं।\n"
]
},
{
"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",
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### एम्बेडिङ भनेको के हो?\n",
"\n",
"**एम्बेडिङ** को विचार भनेको शब्दहरूलाई तिनीहरूको अर्थपूर्ण अर्थ झल्काउने कम-आयामीय घना भेक्टरहरूद्वारा प्रतिनिधित्व गर्नु हो। हामी पछि अर्थपूर्ण शब्द एम्बेडिङ कसरी निर्माण गर्ने भन्ने छलफल गर्नेछौं, तर अहिलेको लागि एम्बेडिङलाई शब्द भेक्टरको आयाम घटाउने तरिका भनेर सोचौं। \n",
"\n",
"त्यसैले, एम्बेडिङ लेयरले शब्दलाई इनपुटको रूपमा लिन्छ, र निर्दिष्ट गरिएको `embedding_size` को आउटपुट भेक्टर उत्पादन गर्छ। यो केही हदसम्म `Dense` लेयरसँग मिल्दोजुल्दो छ, तर एक-हट इन्कोड गरिएको भेक्टरलाई इनपुटको रूपमा लिने सट्टा, यो शब्द नम्बर लिन सक्षम छ।\n",
"\n",
"हाम्रो नेटवर्कको पहिलो लेयरको रूपमा एम्बेडिङ लेयर प्रयोग गरेर, हामी ब्याग-ऑफ-वर्ड्स मोडेलबाट **एम्बेडिङ ब्याग** मोडेलमा स्विच गर्न सक्छौं, जहाँ हामी पहिलो पटक हाम्रो पाठको प्रत्येक शब्दलाई सम्बन्धित एम्बेडिङमा रूपान्तरण गर्छौं, र त्यसपछि ती सबै एम्बेडिङहरूमा केही समग्र कार्य गणना गर्छौं, जस्तै `sum`, `average` वा `max`। \n",
"\n",
"![पाँच अनुक्रम शब्दहरूको लागि एम्बेडिङ वर्गीकरण देखाउने छवि।](../../../../../translated_images/embedding-classifier-example.b77f021a7ee67eeec8e68bfe11636c5b97d6eaa067515a129bfb1d0034b1ac5b.ne.png)\n",
"\n",
"हाम्रो वर्गीकरण न्युरल नेटवर्क निम्न लेयरहरू समावेश गर्दछ:\n",
"\n",
"* `TextVectorization` लेयर, जसले स्ट्रिङलाई इनपुटको रूपमा लिन्छ, र टोकन नम्बरहरूको टेन्सर उत्पादन गर्छ। हामी केही उपयुक्त शब्दावली आकार `vocab_size` निर्दिष्ट गर्नेछौं, र कम-प्रयोग गरिएका शब्दहरूलाई बेवास्ता गर्नेछौं। इनपुट आकार 1 हुनेछ, र आउटपुट आकार $n$ हुनेछ, किनभने हामी $n$ टोकनहरू परिणामको रूपमा प्राप्त गर्नेछौं, प्रत्येकमा 0 देखि `vocab_size` सम्मका नम्बरहरू समावेश हुनेछन्।\n",
"* `Embedding` लेयर, जसले $n$ नम्बरहरू लिन्छ, र प्रत्येक नम्बरलाई दिइएको लम्बाइको घना भेक्टरमा घटाउँछ (हाम्रो उदाहरणमा 100)। यसरी, $n$ आकारको इनपुट टेन्सरलाई $n\\times 100$ टेन्सरमा रूपान्तरण गरिनेछ। \n",
"* एग्रिगेसन लेयर, जसले पहिलो अक्षको साथमा यस टेन्सरको औसत लिन्छ, अर्थात् यो विभिन्न शब्दहरूका लागि सबै $n$ इनपुट टेन्सरहरूको औसत गणना गर्नेछ। यो लेयर कार्यान्वयन गर्न, हामी `Lambda` लेयर प्रयोग गर्नेछौं, र यसमा औसत गणना गर्ने कार्य पास गर्नेछौं। आउटपुटको आकार 100 हुनेछ, र यो सम्पूर्ण इनपुट अनुक्रमको संख्यात्मक प्रतिनिधित्व हुनेछ।\n",
"* अन्तिम `Dense` रेखीय वर्गीकरणकर्ता।\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" text_vectorization (TextVec (None, None) 0 \n",
" torization) \n",
" \n",
" embedding (Embedding) (None, None, 100) 3000000 \n",
" \n",
" lambda (Lambda) (None, 100) 0 \n",
" \n",
" dense (Dense) (None, 4) 404 \n",
" \n",
"=================================================================\n",
"Total params: 3,000,404\n",
"Trainable params: 3,000,404\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"vocab_size = 30000\n",
"batch_size = 128\n",
"\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,input_shape=(1,))\n",
"\n",
"model = keras.models.Sequential([\n",
" vectorizer, \n",
" keras.layers.Embedding(vocab_size,100),\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`summary` प्रिन्टआउटमा, **output shape** स्तम्भमा पहिलो टेन्सर आयाम `None` मिनिब्याच आकारलाई जनाउँछ, र दोस्रो आयाम टोकन अनुक्रमको लम्बाइलाई जनाउँछ। मिनिब्याचमा रहेका सबै टोकन अनुक्रमहरूको लम्बाइ फरक-फरक हुन्छ। यसलाई कसरी व्यवस्थापन गर्ने भन्ने कुरा हामी अर्को खण्डमा छलफल गर्नेछौं।\n",
"\n",
"अब नेटवर्कलाई प्रशिक्षण गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 20s 20ms/step - loss: 0.7891 - acc: 0.8155 - val_loss: 0.4470 - val_acc: 0.8642\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x22255515100>"
]
},
"execution_count": 4,
"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",
"print(\"Training vectorizer\")\n",
"vectorizer.adapt(ds_train.take(500).map(extract_text))\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',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": {
"nteract": {
"transient": {
"deleting": false
}
}
},
"source": [
"> **नोट** कि हामी डेटा को उपसेटको आधारमा भेक्टराइजर निर्माण गर्दैछौं। यो प्रक्रिया छिटो बनाउनको लागि गरिएको हो, र यसले यस्तो स्थिति निम्त्याउन सक्छ जहाँ हाम्रो पाठका सबै टोकनहरू शब्दकोशमा उपस्थित नहुन सक्छन्। यस्तो अवस्थामा, ती टोकनहरू बेवास्ता गरिनेछ, जसले अलिकति कम शुद्धता परिणाम दिन सक्छ। तर, वास्तविक जीवनमा पाठको उपसेटले प्रायः राम्रो शब्दकोश अनुमान प्रदान गर्दछ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### भिन्न आकारका भेरिएबल अनुक्रमहरूसँग व्यवहार गर्ने\n",
"\n",
"आउनुहोस्, मिनिब्याचहरूमा प्रशिक्षण कसरी हुन्छ भन्ने कुरा बुझौं। माथिको उदाहरणमा, इनपुट टेन्सरको आयाम 1 छ, र हामी 128-लामो मिनिब्याचहरू प्रयोग गर्छौं, जसले गर्दा टेन्सरको वास्तविक आकार $128 \\times 1$ हुन्छ। तर, प्रत्येक वाक्यमा टोकनहरूको संख्या फरक हुन्छ। यदि हामी `TextVectorization` लेयरलाई एकल इनपुटमा लागू गर्छौं भने, टेक्स्ट कसरी टोकनाइज गरिएको छ भन्ने आधारमा फर्काइने टोकनहरूको संख्या फरक हुन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tf.Tensor([ 1 45], shape=(2,), dtype=int64)\n",
"tf.Tensor([ 112 1271 1 3 1747 158], shape=(6,), dtype=int64)\n"
]
}
],
"source": [
"print(vectorizer('Hello, world!'))\n",
"print(vectorizer('I am glad to meet you!'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"तर, जब हामी भेक्टराइजरलाई धेरै अनुक्रमहरूमा लागू गर्छौं, यसले आयताकार आकारको टेन्सर उत्पादन गर्नुपर्छ, त्यसैले यसले प्रयोग नगरिएका तत्वहरूलाई PAD टोकन (जसको हाम्रो अवस्थामा शून्य हो) ले भरिन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tf.Tensor: shape=(2, 6), dtype=int64, numpy=\n",
"array([[ 1, 45, 0, 0, 0, 0],\n",
" [ 112, 1271, 1, 3, 1747, 158]], dtype=int64)>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer(['Hello, world!','I am glad to meet you!'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यहाँ हामी एम्बेडिङहरू देख्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[[ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
" [ 2.57456154e-01, 2.79364467e-01, -2.03605562e-01, ...,\n",
" -2.07474351e-01, 8.31158683e-02, -2.03911960e-01],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02]],\n",
"\n",
" [[ 1.89674050e-01, 2.61548996e-01, -3.67433839e-02, ...,\n",
" -2.07366899e-01, -1.05442435e-01, -2.36952081e-01],\n",
" [ 6.16133213e-02, 1.80511594e-01, 9.77298319e-02, ...,\n",
" -5.46628237e-02, -1.07340455e-01, -1.06589928e-01],\n",
" [ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
" [-4.84890305e-02, -8.41715634e-02, 1.51529670e-01, ...,\n",
" 1.28192469e-01, -7.77286515e-02, 1.26041949e-01],\n",
" [-4.17212099e-02, -5.60694858e-02, 4.08860669e-02, ...,\n",
" 8.70475471e-02, 8.92383084e-02, 1.67974353e-01],\n",
" [ 2.85779923e-01, 4.57767487e-01, 4.52292450e-02, ...,\n",
" -1.97419018e-01, -2.04659685e-01, -2.79758364e-01]]],\n",
" dtype=float32)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.layers[1](vectorizer(['Hello, world!','I am glad to meet you!'])).numpy()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **नोट**: प्याडिङको मात्रा कम गर्नको लागि, केही अवस्थामा डेटासेटमा रहेका सबै अनुक्रमहरूलाई बढ्दो लम्बाइको क्रम (वा, अझ स्पष्ट रूपमा, टोकनहरूको संख्या) अनुसार क्रमबद्ध गर्नु उपयुक्त हुन्छ। यसले प्रत्येक मिनिब्याचमा समान लम्बाइका अनुक्रमहरू समावेश हुने सुनिश्चित गर्दछ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सेम्यान्टिक एम्बेडिङ: Word2Vec\n",
"\n",
"हाम्रो अघिल्लो उदाहरणमा, एम्बेडिङ लेयरले शब्दहरूलाई भेक्टर प्रतिनिधित्वमा म्याप गर्न सिकेको थियो, तर ती प्रतिनिधित्वहरूमा सेम्यान्टिक अर्थ थिएन। यदि हामीले यस्तो भेक्टर प्रतिनिधित्व सिक्न सक्यौं जसले समान शब्दहरू वा पर्यायवाची शब्दहरूलाई कुनै भेक्टर दूरी (जस्तै युक्लिडियन दूरी) को आधारमा नजिकको भेक्टरहरूसँग मेल खान्छ भने राम्रो हुने थियो।\n",
"\n",
"यसका लागि, हामीले हाम्रो एम्बेडिङ मोडेललाई [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) जस्ता प्रविधि प्रयोग गरेर ठूलो पाठ संग्रहमा प्रि-ट्रेन गर्न आवश्यक छ। यो शब्दहरूको वितरणात्मक प्रतिनिधित्व उत्पादन गर्न प्रयोग गरिने दुई मुख्य आर्किटेक्चरहरूमा आधारित छ:\n",
"\n",
" - **कन्टिन्युअस ब्याग-अफ-वर्ड्स** (CBoW), जहाँ हामी मोडेललाई वरपरको सन्दर्भबाट शब्दको भविष्यवाणी गर्न प्रशिक्षण दिन्छौं। दिइएको ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ मा, मोडेलको लक्ष्य $(W_{-2},W_{-1},W_1,W_2)$ बाट $W_0$ को भविष्यवाणी गर्नु हो।\n",
" - **कन्टिन्युअस स्किप-ग्राम** CBoW को विपरीत हो। मोडेलले वरपरको सन्दर्भ शब्दहरूको झ्याल प्रयोग गरेर वर्तमान शब्दको भविष्यवाणी गर्छ।\n",
"\n",
"CBoW छिटो हुन्छ, जबकि स्किप-ग्राम ढिलो भए पनि यो दुर्लभ शब्दहरूको प्रतिनिधित्व गर्न राम्रो काम गर्छ।\n",
"\n",
"![CBoW र स्किप-ग्राम एल्गोरिदमहरूलाई शब्दहरूलाई भेक्टरमा रूपान्तरण गर्न देखाउने छवि।](../../../../../translated_images/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6f0f5de66427e8a6eda63809356114e28fb1fa5f4a83ebda7.ne.png)\n",
"\n",
"Google News डेटासेटमा प्रि-ट्रेन गरिएको Word2Vec एम्बेडिङसँग प्रयोग गर्न, हामी **gensim** लाइब्रेरी प्रयोग गर्न सक्छौं। तल हामी 'neural' शब्दसँग सबैभन्दा मिल्दोजुल्दो शब्दहरू फेला पार्छौं।\n",
"\n",
"> **Note:** जब तपाईं पहिलो पटक शब्द भेक्टरहरू सिर्जना गर्नुहुन्छ, तिनीहरू डाउनलोड गर्न केही समय लाग्न सक्छ!\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import gensim.downloader as api\n",
"w2v = api.load('word2vec-google-news-300')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"neuronal -> 0.7804799675941467\n",
"neurons -> 0.7326500415802002\n",
"neural_circuits -> 0.7252851724624634\n",
"neuron -> 0.7174385190010071\n",
"cortical -> 0.6941086649894714\n",
"brain_circuitry -> 0.6923246383666992\n",
"synaptic -> 0.6699118614196777\n",
"neural_circuitry -> 0.6638563275337219\n",
"neurochemical -> 0.6555314064025879\n",
"neuronal_activity -> 0.6531826257705688\n"
]
}
],
"source": [
"for w,p in w2v.most_similar('neural'):\n",
" print(f\"{w} -> {p}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी शब्दबाट भेक्टर एम्बेडिङ पनि निकाल्न सक्छौं, जसलाई वर्गीकरण मोडेल प्रशिक्षणमा प्रयोग गर्न सकिन्छ। एम्बेडिङमा ३०० घटकहरू छन्, तर यहाँ स्पष्टताको लागि हामी भेक्टरका पहिलो २० घटकहरू मात्र देखाउँछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
" dtype=float32)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v['play'][:20]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"महान कुरा सेमान्टिक एम्बेडिङ्सको बारेमा भनेको तपाईंले सेमान्टिक्सको आधारमा भेक्टर इनकोडिङलाई परिमार्जन गर्न सक्नुहुन्छ। उदाहरणका लागि, हामी *राजा* र *महिला* शब्दहरूको भेक्टर प्रतिनिधित्वसँग सकेसम्म नजिक र *पुरुष* शब्दबाट सकेसम्म टाढा हुने शब्द खोज्न अनुरोध गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('queen', 0.7118192911148071)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"उपरोक्त उदाहरणले केही आन्तरिक GenSym जादू प्रयोग गर्दछ, तर आधारभूत तर्क वास्तवमै धेरै सरल छ। एम्बेडिङहरूको बारेमा रोचक कुरा यो हो कि तपाईं एम्बेडिङ भेक्टरहरूमा सामान्य भेक्टर अपरेशनहरू गर्न सक्नुहुन्छ, र त्यसले शब्दको **अर्थहरू**मा अपरेशनहरू प्रतिबिम्बित गर्दछ। उपरोक्त उदाहरणलाई भेक्टर अपरेशनहरूको रूपमा व्यक्त गर्न सकिन्छ: हामी **KING-MAN+WOMAN** सँग सम्बन्धित भेक्टर गणना गर्छौं (सम्बन्धित शब्दहरूको भेक्टर प्रतिनिधित्वमा `+` र `-` अपरेशनहरू गरिन्छ), र त्यसपछि उक्त भेक्टरसँग नजिकको शब्द शब्दकोशमा फेला पार्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'queen'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# get the vector corresponding to kind-man+woman\n",
"qvec = w2v['king']-1.7*w2v['man']+1.7*w2v['woman']\n",
"# find the index of the closest embedding vector \n",
"d = np.sum((w2v.vectors-qvec)**2,axis=1)\n",
"min_idx = np.argmin(d)\n",
"# find the corresponding word\n",
"w2v.index_to_key[min_idx]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **NOTE**: हामीले *man* र *woman* भेक्टरहरूमा सानो गुणांक थप्नुपरेको थियो - यसलाई हटाएर के हुन्छ हेर्न प्रयास गर्नुहोस्।\n",
"\n",
"निकटतम भेक्टर पत्ता लगाउन, हामीले TensorFlow को मेकानिजम प्रयोग गरेर हाम्रो भेक्टर र शब्दकोशमा रहेका सबै भेक्टरहरू बीचको दूरीको भेक्टर गणना गर्छौं, र त्यसपछि `argmin` प्रयोग गरेर न्यूनतम शब्दको सूचकांक पत्ता लगाउँछौं।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Word2Vec शब्दार्थलाई व्यक्त गर्नको लागि एक उत्कृष्ट तरिका जस्तो देखिन्छ, तर यसमा निम्न जस्ता धेरै कमजोरीहरू छन्:\n",
"\n",
"* CBoW र skip-gram मोडेलहरू **predictive embeddings** हुन्, र यीले केवल स्थानीय सन्दर्भलाई मात्र ध्यानमा राख्छन्। Word2Vec ले विश्वव्यापी सन्दर्भको फाइदा उठाउँदैन।\n",
"* Word2Vec ले शब्दको **morphology** लाई ध्यानमा राख्दैन, अर्थात् शब्दको अर्थ शब्दका विभिन्न भागहरू, जस्तै मूल (root), मा निर्भर हुन सक्छ भन्ने तथ्यलाई बेवास्ता गर्छ। \n",
"\n",
"**FastText** ले दोस्रो सीमालाई पार गर्न प्रयास गर्छ, र Word2Vec मा आधारित भएर प्रत्येक शब्द र त्यस शब्दभित्र पाइने character n-grams का लागि भेक्टर प्रतिनिधित्वहरू सिक्छ। यी प्रतिनिधित्वहरूको मानहरूलाई प्रत्येक प्रशिक्षण चरणमा एक भेक्टरमा औसत गरिन्छ। यसले पूर्व-प्रशिक्षणमा धेरै अतिरिक्त गणना थपे पनि, यसले शब्द embeddings लाई उप-शब्द जानकारीलाई समेट्न सक्षम बनाउँछ।\n",
"\n",
"अर्को विधि, **GloVe**, शब्द embeddings को लागि फरक दृष्टिकोण प्रयोग गर्छ, जुन word-context matrix को factorization मा आधारित छ। सुरुमा, यो एउटा ठूलो म्याट्रिक्स बनाउँछ जसले विभिन्न सन्दर्भहरूमा शब्दहरूको उपस्थितिको संख्या गन्छ, र त्यसपछि यो म्याट्रिक्सलाई कम आयाममा प्रतिनिधित्व गर्न प्रयास गर्छ जसले पुनर्निर्माण हानिलाई न्यूनतम बनाउँछ।\n",
"\n",
"gensim पुस्तकालयले ती शब्द embeddings लाई समर्थन गर्छ, र तपाईंले माथिको मोडेल लोड गर्ने कोड परिवर्तन गरेर तिनीहरूसँग प्रयोग गर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Keras मा pretrained embeddings प्रयोग गर्ने\n",
"\n",
"हामी माथिको उदाहरणलाई संशोधन गरेर हाम्रो embedding layer मा semantic embeddings, जस्तै Word2Vec, प्रयोग गर्न सक्दछौं। pretrained embedding र text corpus को शब्दावलीहरू प्रायः मेल नखाने सम्भावना हुन्छ, त्यसैले हामीलाई एउटा विकल्प छान्नुपर्छ। यहाँ हामी दुई सम्भावित विकल्पहरू अन्वेषण गर्छौं: tokenizer vocabulary प्रयोग गर्ने, र Word2Vec embeddings को vocabulary प्रयोग गर्ने।\n",
"\n",
"### Tokenizer vocabulary प्रयोग गर्ने\n",
"\n",
"Tokenizer vocabulary प्रयोग गर्दा, vocabulary का केही शब्दहरूको Word2Vec embeddings हुनेछ, र केही हराउनेछन्। हाम्रो vocabulary size `vocab_size` छ, र Word2Vec embedding vector को लम्बाइ `embed_size` छ भने, embedding layer को तौल म्याट्रिक्सको आकार `vocab_size`$\\times$`embed_size` हुनेछ। हामी यो म्याट्रिक्सलाई vocabulary मार्फत गएर भरनेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Embedding size: 300\n",
"Populating matrix, this will take some time...Done, found 4551 words, 784 words missing\n"
]
}
],
"source": [
"embed_size = len(w2v.get_vector('hello'))\n",
"print(f'Embedding size: {embed_size}')\n",
"\n",
"vocab = vectorizer.get_vocabulary()\n",
"W = np.zeros((vocab_size,embed_size))\n",
"print('Populating matrix, this will take some time...',end='')\n",
"found, not_found = 0,0\n",
"for i,w in enumerate(vocab):\n",
" try:\n",
" W[i] = w2v.get_vector(w)\n",
" found+=1\n",
" except:\n",
" # W[i] = np.random.normal(0.0,0.3,size=(embed_size,))\n",
" not_found+=1\n",
"\n",
"print(f\"Done, found {found} words, {not_found} words missing\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"शब्दहरू जुन Word2Vec शब्दकोशमा उपलब्ध छैनन्, हामी तिनीहरूलाई शून्यको रूपमा छोड्न सक्छौं, वा एउटा र्यान्डम भेक्टर सिर्जना गर्न सक्छौं।\n",
"\n",
"अब हामी प्रीट्रेन गरिएको वजनहरू सहितको एम्बेडिङ लेयर परिभाषित गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"emb = keras.layers.Embedding(vocab_size,embed_size,weights=[W],trainable=False)\n",
"model = keras.models.Sequential([\n",
" vectorizer, emb,\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 10s 10ms/step - loss: 1.1075 - acc: 0.7822 - val_loss: 0.9134 - val_acc: 0.8175\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x2220226ef10>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\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": [
"> **Note**: हामीले `Embedding` सिर्जना गर्दा `trainable=False` सेट गरेको देखिन्छ, जसको अर्थ हामी Embedding लेयरलाई पुनः प्रशिक्षण गरिरहेका छैनौं। यसले सटीकता अलि कम हुन सक्छ, तर प्रशिक्षणको गति बढाउँछ।\n",
"\n",
"### Embedding शब्दकोश प्रयोग गर्दै\n",
"\n",
"अघिल्लो विधिको एउटा समस्या भनेको TextVectorization र Embedding मा प्रयोग गरिएका शब्दकोशहरू फरक हुनु हो। यस समस्यालाई समाधान गर्न, हामी निम्न विकल्पहरू प्रयोग गर्न सक्छौं:\n",
"* हाम्रो शब्दकोशमा Word2Vec मोडेल पुनः प्रशिक्षण गर्नुहोस्।\n",
"* Pretrained Word2Vec मोडेलको शब्दकोशबाट हाम्रो डेटासेट लोड गर्नुहोस्। डेटासेट लोड गर्दा प्रयोग गरिने शब्दकोश लोड गर्ने क्रममा निर्दिष्ट गर्न सकिन्छ।\n",
"\n",
"दोस्रो विधि सजिलो देखिन्छ, त्यसैले यसलाई कार्यान्वयन गरौं। सबैभन्दा पहिले, हामी Word2Vec embeddings बाट लिइएको निर्दिष्ट शब्दकोशसहित `TextVectorization` लेयर सिर्जना गर्नेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"vocab = list(w2v.vocab.keys())\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(input_shape=(1,))\n",
"vectorizer.set_vocabulary(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Gensim शब्द एम्बेडिङ्स पुस्तकालयमा एउटा सुविधाजनक फङ्सन, `get_keras_embeddings`, समावेश छ, जसले तपाईंको लागि स्वचालित रूपमा सम्बन्धित Keras एम्बेडिङ्स तह सिर्जना गर्नेछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"938/938 [==============================] - 20s 14ms/step - loss: 1.3377 - acc: 0.4978 - val_loss: 1.2995 - val_acc: 0.5647\n",
"Epoch 2/5\n",
"938/938 [==============================] - 10s 10ms/step - loss: 1.2587 - acc: 0.5722 - val_loss: 1.2339 - val_acc: 0.5842\n",
"Epoch 3/5\n",
"938/938 [==============================] - 10s 10ms/step - loss: 1.1980 - acc: 0.5884 - val_loss: 1.1826 - val_acc: 0.5954\n",
"Epoch 4/5\n",
"938/938 [==============================] - 12s 13ms/step - loss: 1.1503 - acc: 0.6002 - val_loss: 1.1417 - val_acc: 0.6018\n",
"Epoch 5/5\n",
"938/938 [==============================] - 11s 12ms/step - loss: 1.1120 - acc: 0.6097 - val_loss: 1.1083 - val_acc: 0.6104\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x2220ccb81c0>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" vectorizer, \n",
" w2v.get_keras_embedding(train_embeddings=False),\n",
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
" keras.layers.Dense(4, activation='softmax')\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128),epochs=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले उच्च सटीकता देख्न नसक्नुको एक कारण भनेको हाम्रो डाटासेटका केही शब्दहरू प्रि-ट्रेन गरिएको GloVe शब्दकोशमा नभएका कारण हो, जसले गर्दा ती शब्दहरूलाई मूलतः बेवास्ता गरिन्छ। यसलाई समाधान गर्नका लागि, हामी हाम्रो डाटासेटमा आधारित आफ्नै एम्बेडिङहरू प्रशिक्षण गर्न सक्छौं।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## सन्दर्भात्मक एम्बेडिङहरू\n",
"\n",
"पारम्परिक प्रीट्रेन गरिएको एम्बेडिङ प्रतिनिधित्वहरू जस्तै Word2Vec को मुख्य सीमितता यो हो कि, यद्यपि तिनीहरूले शब्दको केही अर्थ समात्न सक्छन्, तिनीहरूले विभिन्न अर्थहरू बीच फरक छुट्याउन सक्दैनन्। यसले डाउनस्ट्रीम मोडेलहरूमा समस्या उत्पन्न गर्न सक्छ।\n",
"\n",
"उदाहरणका लागि, 'play' शब्दको यी दुई वाक्यहरूमा फरक अर्थ छ:\n",
"- म थिएटरमा एउटा **play** हेर्न गएँ।\n",
"- जोन आफ्ना साथीहरूसँग **play** गर्न चाहन्छ।\n",
"\n",
"हामीले चर्चा गरेका प्रीट्रेन गरिएको एम्बेडिङहरूले 'play' शब्दको दुवै अर्थलाई एउटै एम्बेडिङमा प्रतिनिधित्व गर्छ। यस सीमिततालाई पार गर्नका लागि, हामीलाई **भाषा मोडेल** मा आधारित एम्बेडिङहरू निर्माण गर्न आवश्यक छ, जुन ठूलो पाठको संग्रहमा प्रशिक्षित गरिएको हुन्छ, र *जान्दछ* कि शब्दहरू विभिन्न सन्दर्भहरूमा कसरी राख्न सकिन्छ। सन्दर्भात्मक एम्बेडिङहरूको चर्चा यस ट्युटोरियलको दायराभन्दा बाहिर छ, तर हामी यसबारे भाषा मोडेलहरूको कुरा गर्दा अर्को युनिटमा फर्कनेछौं।\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": "b859482be7f61d1eadc2c6a2720a37e4",
"translation_date": "2025-08-28T09:43:15+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,574 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "NXTSugt6ieXh"
},
"source": [
"## CBoW मोडेल प्रशिक्षण\n",
"\n",
"यो नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) को एक भाग हो।\n",
"\n",
"यस उदाहरणमा, हामी CBoW भाषा मोडेल प्रशिक्षण गरेर हाम्रो आफ्नै Word2Vec एम्बेडिङ स्पेस प्राप्त गर्ने प्रयास गर्नेछौं। हामी AG News डेटासेटलाई पाठको स्रोतको रूपमा प्रयोग गर्नेछौं।\n"
]
},
{
"cell_type": "code",
"source": [
"import torch\n",
"import torchtext\n",
"import os\n",
"import collections\n",
"import builtins\n",
"import random\n",
"import numpy as np"
],
"metadata": {
"id": "q-UiiJUKaxHj"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
],
"metadata": {
"id": "TFbR8CZaTZ1q"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"पहिले हामी हाम्रो डाटासेट लोड गरौं र टोकनाइजर र शब्दकोश परिभाषित गरौं। हामी गणनाहरूलाई केही सीमित गर्न `vocab_size` लाई 5000 मा सेट गर्नेछौं।\n"
],
"metadata": {
"id": "HIwC7lI5T-ov"
}
},
{
"cell_type": "code",
"source": [
"def load_dataset(ngrams = 1, min_freq = 1, vocab_size = 5000 , lines_cnt = 500):\n",
" tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
" print(\"Loading dataset...\")\n",
" test_dataset, train_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
" train_dataset = list(train_dataset)\n",
" test_dataset = list(test_dataset)\n",
" classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
" print('Building vocab...')\n",
" counter = collections.Counter()\n",
" for i, (_, line) in enumerate(train_dataset):\n",
" counter.update(torchtext.data.utils.ngrams_iterator(tokenizer(line),ngrams=ngrams))\n",
" if i == lines_cnt:\n",
" break\n",
" vocab = torchtext.vocab.Vocab(collections.Counter(dict(counter.most_common(vocab_size))), min_freq=min_freq)\n",
" return train_dataset, test_dataset, classes, vocab, tokenizer"
],
"metadata": {
"id": "wdZuygtgiuLG"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"train_dataset, test_dataset, _, vocab, tokenizer = load_dataset()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4d1nU1gsivGu",
"outputId": "949fe272-ae0e-49f5-c373-6703458b3a74"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"def encode(x, vocabulary, tokenizer = tokenizer):\n",
" return [vocabulary[s] for s in tokenizer(x)]"
],
"metadata": {
"id": "1XDYNhG8ToFV"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "LIlQk6_PaHVY"
},
"source": [
"## CBoW मोडेल\n",
"\n",
"CBoW ले $2N$ छिमेकी शब्दहरूको आधारमा एउटा शब्दको भविष्यवाणी गर्न सिक्छ। उदाहरणका लागि, जब $N=1$ हुन्छ, हामीले वाक्य *I like to train networks* बाट निम्न जोडीहरू प्राप्त गर्नेछौं: (like,I), (I, like), (to, like), (like,to), (train,to), (to, train), (networks, train), (train,networks)। यहाँ, पहिलो शब्द इनपुटको रूपमा प्रयोग गरिएको छिमेकी शब्द हो, र दोस्रो शब्द भविष्यवाणी गरिएको शब्द हो।\n",
"\n",
"अर्को शब्दको भविष्यवाणी गर्न नेटवर्क निर्माण गर्नका लागि, हामीले छिमेकी शब्दलाई इनपुटको रूपमा दिनुपर्नेछ, र शब्द नम्बरलाई आउटपुटको रूपमा प्राप्त गर्नुपर्नेछ। CBoW नेटवर्कको संरचना निम्न प्रकारको छ:\n",
"\n",
"* इनपुट शब्दलाई embedding layer मार्फत पठाइन्छ। यो embedding layer नै हाम्रो Word2Vec embedding हुनेछ, त्यसैले हामी यसलाई अलग रूपमा `embedder` भेरिएबलको रूपमा परिभाषित गर्नेछौं। यस उदाहरणमा हामी embedding size = 30 प्रयोग गर्नेछौं, यद्यपि तपाईं उच्च dimensions (वास्तविक word2vec मा 300 हुन्छ) प्रयोग गरेर परीक्षण गर्न चाहन सक्नुहुन्छ।\n",
"* Embedding vector लाई त्यसपछि एउटा linear layer मा पठाइन्छ जसले आउटपुट शब्दको भविष्यवाणी गर्नेछ। त्यसैले यसमा `vocab_size` neurons हुन्छ।\n",
"\n",
"आउटपुटको लागि, यदि हामी `CrossEntropyLoss` लाई loss function को रूपमा प्रयोग गर्छौं भने, हामीले एक-हट encoding बिना मात्र शब्द नम्बरहरूलाई अपेक्षित परिणामको रूपमा प्रदान गर्नुपर्नेछ।\n"
]
},
{
"cell_type": "code",
"source": [
"vocab_size = len(vocab)\n",
"\n",
"embedder = torch.nn.Embedding(num_embeddings = vocab_size, embedding_dim = 30)\n",
"model = torch.nn.Sequential(\n",
" embedder,\n",
" torch.nn.Linear(in_features = 30, out_features = vocab_size),\n",
")\n",
"\n",
"print(model)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "akKTcKQKkfl2",
"outputId": "da687e3e-a8ec-4c1a-e456-ab8cd6ac7dad"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Sequential(\n",
" (0): Embedding(5002, 30)\n",
" (1): Linear(in_features=30, out_features=5002, bias=True)\n",
")\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Nud6jgGPaHVa"
},
"source": [
"## प्रशिक्षण डेटा तयार गर्दै\n",
"\n",
"अब मुख्य कार्यलाई प्रोग्राम गरौं जसले पाठबाट CBoW शब्द जोडीहरू गणना गर्नेछ। यो कार्यले हामीलाई विन्डो साइज निर्दिष्ट गर्न अनुमति दिनेछ, र जोडीहरूको सेट - इनपुट र आउटपुट शब्दहरू फर्काउनेछ। ध्यान दिनुहोस् कि यो कार्य शब्दहरूमा मात्र होइन, भेक्टरहरू/टेन्सरहरूमा पनि प्रयोग गर्न सकिन्छ - जसले हामीलाई पाठलाई एन्कोड गर्न अनुमति दिनेछ, `to_cbow` कार्यमा पठाउनु अघि।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "x-dsXygOieXn",
"outputId": "c2218280-e540-40ba-9546-efe48d0d714f"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[['like', 'I'], ['to', 'I'], ['I', 'like'], ['to', 'like'], ['train', 'like'], ['I', 'to'], ['like', 'to'], ['train', 'to'], ['networks', 'to'], ['like', 'train'], ['to', 'train'], ['networks', 'train'], ['to', 'networks'], ['train', 'networks']]\n",
"[[232, 172], [5, 172], [172, 232], [5, 232], [0, 232], [172, 5], [232, 5], [0, 5], [1202, 5], [232, 0], [5, 0], [1202, 0], [5, 1202], [0, 1202]]\n"
]
}
],
"source": [
"def to_cbow(sent,window_size=2):\n",
" res = []\n",
" for i,x in enumerate(sent):\n",
" for j in range(max(0,i-window_size),min(i+window_size+1,len(sent))):\n",
" if i!=j:\n",
" res.append([sent[j],x])\n",
" return res\n",
"\n",
"print(to_cbow(['I','like','to','train','networks']))\n",
"print(to_cbow(encode('I like to train networks', vocab)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XVaaDLjaaHVb"
},
"source": [
"आउनुहोस् प्रशिक्षण डेटासेट तयार गरौं। हामी सबै समाचारहरू हेर्नेछौं, `to_cbow` कल गरेर शब्द जोडीहरूको सूची प्राप्त गर्नेछौं, र ती जोडीहरूलाई `X` र `Y` मा थप्नेछौं। समय बचतको लागि, हामी केवल पहिलो १k समाचार वस्तुहरूलाई विचार गर्नेछौं - यदि तपाईंलाई पर्खनको लागि थप समय छ र राम्रो एम्बेडिङ प्राप्त गर्न चाहनुहुन्छ भने तपाईं सजिलै यो सीमालाई हटाउन सक्नुहुन्छ :)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "54b-Gd9TieXo"
},
"outputs": [],
"source": [
"X = []\n",
"Y = []\n",
"for i, x in zip(range(10000), train_dataset):\n",
" for w1, w2 in to_cbow(encode(x[1], vocab), window_size = 5):\n",
" X.append(w1)\n",
" Y.append(w2)\n",
"\n",
"X = torch.tensor(X)\n",
"Y = torch.tensor(Y)"
]
},
{
"cell_type": "markdown",
"source": [
"हामी त्यो डाटालाई पनि एक डेटा सेटमा रूपान्तरण गर्नेछौं, र डाटालोडर सिर्जना गर्नेछौं:\n"
],
"metadata": {
"id": "cwWy0PzXWhN5"
}
},
{
"cell_type": "code",
"source": [
"class SimpleIterableDataset(torch.utils.data.IterableDataset):\n",
" def __init__(self, X, Y):\n",
" super(SimpleIterableDataset).__init__()\n",
" self.data = []\n",
" for i in range(len(X)):\n",
" self.data.append( (Y[i], X[i]) )\n",
" random.shuffle(self.data)\n",
"\n",
" def __iter__(self):\n",
" return iter(self.data)"
],
"metadata": {
"id": "mfoAcGPFZU8p"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "e4NQ_-5waHVc"
},
"source": [
"हामी त्यो डाटालाई पनि एक डाटासेटमा रूपान्तरण गर्नेछौं, र डाटालोडर बनाउनेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "AbLUcojlieXo"
},
"outputs": [],
"source": [
"ds = SimpleIterableDataset(X, Y)\n",
"dl = torch.utils.data.DataLoader(ds, batch_size = 256)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pKQr7sXeaHVc"
},
"source": [
"अब हामी वास्तविक प्रशिक्षण गरौं। हामी `SGD` अप्टिमाइजर उच्च लर्निङ रेटसँग प्रयोग गर्नेछौं। तपाईंले अन्य अप्टिमाइजरहरू, जस्तै `Adam`, प्रयोग गरेर पनि प्रयास गर्न सक्नुहुन्छ। सुरुमा हामी १० इपोक्सको लागि प्रशिक्षण गर्नेछौं - र यदि तपाईं अझ कम हानि चाहनुहुन्छ भने यो सेल पुन: चलाउन सक्नुहुन्छ।\n"
]
},
{
"cell_type": "code",
"source": [
"def train_epoch(net, dataloader, lr = 0.01, optimizer = None, loss_fn = torch.nn.CrossEntropyLoss(), epochs = None, report_freq = 1):\n",
" optimizer = optimizer or torch.optim.Adam(net.parameters(), lr = lr)\n",
" loss_fn = loss_fn.to(device)\n",
" net.train()\n",
"\n",
" for i in range(epochs):\n",
" total_loss, j = 0, 0, \n",
" for labels, features in dataloader:\n",
" optimizer.zero_grad()\n",
" features, labels = features.to(device), labels.to(device)\n",
" out = net(features)\n",
" loss = loss_fn(out, labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" total_loss += loss\n",
" j += 1\n",
" if i % report_freq == 0:\n",
" print(f\"Epoch: {i+1}: loss={total_loss.item()/j}\")\n",
"\n",
" return total_loss.item()/j"
],
"metadata": {
"id": "HeeCYKr_KF1w"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"train_epoch(net = model, dataloader = dl, optimizer = torch.optim.SGD(model.parameters(), lr = 0.1), loss_fn = torch.nn.CrossEntropyLoss(), epochs = 10)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "KVgwGtDHgDlT",
"outputId": "2447833f-f0e3-4566-c33d-addbfe2f451d"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Epoch: 1: loss=5.664632366860172\n",
"Epoch: 2: loss=5.632101973960962\n",
"Epoch: 3: loss=5.610399051405015\n",
"Epoch: 4: loss=5.594621561080262\n",
"Epoch: 5: loss=5.582538017415446\n",
"Epoch: 6: loss=5.572900234519603\n",
"Epoch: 7: loss=5.564951676341915\n",
"Epoch: 8: loss=5.558288112064614\n",
"Epoch: 9: loss=5.552576955031129\n",
"Epoch: 10: loss=5.547634165194347\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"5.547634165194347"
]
},
"metadata": {},
"execution_count": 16
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W8u2qXZmaHVd"
},
"source": [
"## Word2Vec प्रयोग गर्दै हेर्ने\n",
"\n",
"Word2Vec प्रयोग गर्नको लागि, हाम्रो शब्दकोशमा रहेका सबै शब्दहरूको लागि भेक्टरहरू निकालौं:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "r8TatcXjkU_t"
},
"outputs": [],
"source": [
"vectors = torch.stack([embedder(torch.tensor(vocab[s])) for s in vocab.itos], 0)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3OcX21UOaHVd"
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "bz6tAeLzieXp",
"outputId": "5b20850e-4342-45e9-f840-cfac2b4d61d8"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"tensor([-0.0915, 2.1224, -0.0281, -0.6819, 1.1219, 0.6458, -1.3704, -1.3314,\n",
" -1.1437, 0.4496, 0.2301, -0.3515, -0.8485, 1.0481, 0.4386, -0.8949,\n",
" 0.5644, 1.0939, -2.5096, 3.2949, -0.2601, -0.8640, 0.1421, -0.0804,\n",
" -0.5083, -1.0560, 0.9753, -0.5949, -1.6046, 0.5774],\n",
" grad_fn=<EmbeddingBackward>)\n"
]
}
],
"source": [
"paris_vec = embedder(torch.tensor(vocab['paris']))\n",
"print(paris_vec)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pHTJlaeYaHVd"
},
"source": [
"यो Word2Vec प्रयोग गरेर पर्यायवाची शब्दहरू खोज्न रोचक छ। तलको कार्यले दिइएको इनपुटको लागि `n` नजिकका शब्दहरू फिर्ता गर्नेछ। तिनीहरू फेला पार्न, हामी $|w_i - v|$ को मान गणना गर्छौं, जहाँ $v$ हाम्रो इनपुट शब्दसँग सम्बन्धित भेक्टर हो, र $w_i$ शब्दकोशमा रहेको $i$-औं शब्दको इनकोडिङ हो। त्यसपछि हामी एरेलाई क्रमबद्ध गर्छौं र `argsort` प्रयोग गरेर सम्बन्धित सूचकांकहरू फिर्ता गर्छौं, र सूचीका पहिलो `n` तत्वहरू लिन्छौं, जसले शब्दकोशमा नजिकका शब्दहरूको स्थानलाई इनकोड गर्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "NlZyi-_olFar",
"outputId": "b5dbb163-88c4-4d5a-eaf2-6751f700e98c"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['microsoft', 'quoted', 'lp', 'rate', 'top']"
]
},
"metadata": {},
"execution_count": 56
}
],
"source": [
"def close_words(x, n = 5):\n",
" vec = embedder(torch.tensor(vocab[x]))\n",
" top5 = np.linalg.norm(vectors.detach().numpy() - vec.detach().numpy(), axis = 1).argsort()[:n]\n",
" return [ vocab.itos[x] for x in top5 ]\n",
"\n",
"close_words('microsoft')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "-dQq7xeAln0U",
"outputId": "66f768c3-c248-4bfd-ce4f-c8ffc6d0dd0d"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['basketball', 'lot', 'sinai', 'states', 'healthdaynews']"
]
},
"metadata": {},
"execution_count": 51
}
],
"source": [
"close_words('basketball')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "fJXqK26b29sa",
"outputId": "78f0baba-ffd0-485a-dd87-0a12bedfd7fa"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['funds', 'travel', 'sydney', 'japan', 'business']"
]
},
"metadata": {},
"execution_count": 77
}
],
"source": [
"close_words('funds')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "My0VeTDd3Ji8"
},
"source": [
"## मुख्य कुरा\n",
"\n",
"CBoW जस्ता चतुर तरिकाहरू प्रयोग गरेर, हामी Word2Vec मोडेल प्रशिक्षण गर्न सक्छौं। तपाईंले skip-gram मोडेल पनि प्रशिक्षण गर्न प्रयास गर्न सक्नुहुन्छ, जसले केन्द्रिय शब्द दिइएको अवस्थामा छेउछाउका शब्दहरू अनुमान गर्न सिक्छ, र यसले कत्तिको राम्रो प्रदर्शन गर्छ हेर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छन्। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्त्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं। \n"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "CBoW-PyTorch.ipynb",
"provenance": []
},
"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"
},
"orig_nbformat": 4,
"gpuClass": "standard",
"coopTranslator": {
"original_hash": "36df28efe3fe40b6fb0a7fa48fe3ea82",
"translation_date": "2025-08-28T09:18:51+00:00",
"source_file": "lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 0
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,479 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# पुनरावर्ती न्यूरल नेटवर्कहरू\n",
"\n",
"अघिल्लो मोड्युलमा, हामीले पाठको धनी अर्थपूर्ण प्रतिनिधित्वहरू प्रयोग गरिरहेका थियौं, र इम्बेडिङ्सको माथि एउटा साधारण रेखीय वर्गीकरणकर्ता प्रयोग गरिरहेका थियौं। यो आर्किटेक्चरले वाक्यमा शब्दहरूको समग्र अर्थलाई समेट्छ, तर यसले शब्दहरूको **क्रम**लाई ध्यानमा राख्दैन, किनभने इम्बेडिङ्सको माथि गरिएको समग्र अपरेशनले मूल पाठबाट यो जानकारी हटाइदिन्छ। यी मोडेलहरूले शब्दहरूको क्रमलाई मोडेल गर्न नसक्ने भएकाले, तिनीहरूले पाठ उत्पादन (text generation) वा प्रश्न उत्तरजस्ता जटिल वा अस्पष्ट कार्यहरू समाधान गर्न सक्दैनन्।\n",
"\n",
"पाठ अनुक्रमको अर्थ समेट्नका लागि, हामीले अर्को न्यूरल नेटवर्क आर्किटेक्चर प्रयोग गर्नुपर्छ, जसलाई **पुनरावर्ती न्यूरल नेटवर्क** (recurrent neural network) वा RNN भनिन्छ। RNN मा, हामी हाम्रो वाक्यलाई नेटवर्कमा एक पटकमा एउटा प्रतीक (symbol) मार्फत पठाउँछौं, र नेटवर्कले केही **स्थिति** (state) उत्पादन गर्छ, जसलाई हामी अर्को प्रतीकसँग फेरि नेटवर्कमा पठाउँछौं।\n",
"\n",
"दिइएको टोकनहरूको अनुक्रम $X_0,\\dots,X_n$ को इनपुटको रूपमा, RNN ले न्यूरल नेटवर्क ब्लकहरूको अनुक्रम सिर्जना गर्छ, र यो अनुक्रमलाई अन्त्यसम्म ब्याक प्रोपोगेसन (back propagation) प्रयोग गरेर प्रशिक्षण दिन्छ। प्रत्येक नेटवर्क ब्लकले $(X_i,S_i)$ को जोडीलाई इनपुटको रूपमा लिन्छ, र परिणामस्वरूप $S_{i+1}$ उत्पादन गर्छ। अन्तिम स्थिति $S_n$ वा आउटपुट $X_n$ लाई रेखीय वर्गीकरणकर्तामा पठाइन्छ, जसले नतिजा उत्पादन गर्छ। सबै नेटवर्क ब्लकहरूले एउटै तौल (weights) साझा गर्छन्, र एक पटकको ब्याक प्रोपोगेसन पास प्रयोग गरेर अन्त्यसम्म प्रशिक्षण गरिन्छ।\n",
"\n",
"किनभने स्थिति भेक्टरहरू $S_0,\\dots,S_n$ नेटवर्कमार्फत पास गरिन्छन्, यसले शब्दहरू बीचको अनुक्रमिक निर्भरता सिक्न सक्षम हुन्छ। उदाहरणका लागि, जब *not* शब्द कतै अनुक्रममा देखा पर्छ, यसले स्थिति भेक्टरभित्रका केही तत्वहरूलाई नकार्न (negate) सिक्न सक्छ, जसले नकारात्मकता (negation) उत्पन्न गर्छ।\n",
"\n",
"> चित्रमा देखाइएका सबै RNN ब्लकहरूको तौल साझा गरिएकोले, एउटै चित्रलाई एउटा ब्लक (दायाँतर्फ) को रूपमा प्रतिनिधित्व गर्न सकिन्छ, जसमा पुनरावर्ती फिडब्याक लूप (recurrent feedback loop) हुन्छ, जसले नेटवर्कको आउटपुट स्थितिलाई इनपुटमा फिर्ता पठाउँछ।\n",
"\n",
"अब हेरौं, पुनरावर्ती न्यूरल नेटवर्कहरूले हाम्रो समाचार डेटासेटलाई वर्गीकृत गर्न कसरी मद्दत गर्न सक्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"from torchnlp import *\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_size = len(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## साधारण RNN वर्गीकरणकर्ता\n",
"\n",
"साधारण RNN को अवस्थामा, प्रत्येक पुनरावर्ती इकाई एक साधारण रेखीय नेटवर्क हो, जसले इनपुट भेक्टर र अवस्था भेक्टरलाई जोडेर लिन्छ, र नयाँ अवस्था भेक्टर उत्पादन गर्छ। PyTorch ले यस इकाईलाई `RNNCell` वर्गको रूपमा प्रतिनिधित्व गर्छ, र यस्ता कोषहरूको नेटवर्कलाई `RNN` तहको रूपमा।\n",
"\n",
"RNN वर्गीकरणकर्ता परिभाषित गर्नका लागि, हामी पहिले इनपुट शब्दावलीको आयाम घटाउनको लागि एक embedding तह लागू गर्नेछौं, र त्यसपछि यसको माथि RNN तह राख्नेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class RNNClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.rnn = torch.nn.RNN(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" x,h = self.rnn(x)\n",
" return self.fc(x.mean(dim=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Note:** यहाँ हामी सरलताको लागि अनट्रेन गरिएको एम्बेडिङ लेयर प्रयोग गर्छौं, तर अझ राम्रो नतिजाका लागि हामी प्रि-ट्रेन गरिएको एम्बेडिङ लेयर जस्तै Word2Vec वा GloVe एम्बेडिङ प्रयोग गर्न सक्छौं, जसको वर्णन अघिल्लो युनिटमा गरिएको छ। राम्रो बुझाइको लागि, तपाईंले यो कोडलाई प्रि-ट्रेन गरिएको एम्बेडिङसँग काम गर्न अनुकूल बनाउन चाहन सक्नुहुन्छ।\n",
"\n",
"हाम्रो केसमा, हामी प्याड गरिएको डाटा लोडर प्रयोग गर्नेछौं, जसले गर्दा प्रत्येक ब्याचमा समान लम्बाइको प्याड गरिएको सिक्वेन्सहरूको संख्या हुनेछ। RNN लेयरले एम्बेडिङ टेन्सरहरूको सिक्वेन्स लिन्छ, र दुई आउटपुट उत्पादन गर्छ:\n",
"* $x$ भनेको प्रत्येक चरणमा RNN सेलको आउटपुटहरूको सिक्वेन्स हो\n",
"* $h$ भनेको सिक्वेन्सको अन्तिम तत्वको लागि अन्तिम हिडन स्टेट हो\n",
"\n",
"त्यसपछि हामी पूर्ण रूपमा जडित लीनियर क्लासिफायर लागू गर्छौं ताकि वर्गहरूको संख्या प्राप्त गर्न सकियोस्।\n",
"\n",
"> **Note:** RNN हरूलाई ट्रेन गर्न निकै गाह्रो हुन्छ, किनभने RNN सेलहरू सिक्वेन्सको लम्बाइमा अन्रोल गरिसकेपछि, ब्याक प्रोपोगेसनमा संलग्न लेयरहरूको संख्या निकै ठूलो हुन्छ। त्यसैले हामीले सानो लर्निङ रेट चयन गर्नुपर्छ, र राम्रो नतिजा उत्पादन गर्न नेटवर्कलाई ठूलो डाटासेटमा ट्रेन गर्नुपर्छ। यसले धेरै समय लिन सक्छ, त्यसैले GPU प्रयोग गर्नु उपयुक्त हुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.3090625\n",
"6400: acc=0.38921875\n",
"9600: acc=0.4590625\n",
"12800: acc=0.511953125\n",
"16000: acc=0.5506875\n",
"19200: acc=0.57921875\n",
"22400: acc=0.6070089285714285\n",
"25600: acc=0.6304296875\n",
"28800: acc=0.6484027777777778\n",
"32000: acc=0.66509375\n",
"35200: acc=0.6790056818181818\n",
"38400: acc=0.6929166666666666\n",
"41600: acc=0.7035817307692308\n",
"44800: acc=0.7137276785714286\n",
"48000: acc=0.72225\n",
"51200: acc=0.73001953125\n",
"54400: acc=0.7372794117647059\n",
"57600: acc=0.7436631944444444\n",
"60800: acc=0.7503947368421052\n",
"64000: acc=0.75634375\n",
"67200: acc=0.7615773809523809\n",
"70400: acc=0.7662642045454545\n",
"73600: acc=0.7708423913043478\n",
"76800: acc=0.7751822916666666\n",
"80000: acc=0.7790625\n",
"83200: acc=0.7825\n",
"86400: acc=0.7858564814814815\n",
"89600: acc=0.7890513392857142\n",
"92800: acc=0.7920474137931034\n",
"96000: acc=0.7952708333333334\n",
"99200: acc=0.7982258064516129\n",
"102400: acc=0.80099609375\n",
"105600: acc=0.8037594696969697\n",
"108800: acc=0.8060569852941176\n"
]
}
],
"source": [
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)\n",
"net = RNNClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=0.001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## लामो छोटो समय स्मृति (LSTM)\n",
"\n",
"परम्परागत RNN को मुख्य समस्याहरू मध्ये एकलाई **vanishing gradients** समस्या भनिन्छ। किनभने RNN हरू एकै पटकको ब्याक-प्रोपागेसन पासमा अन्त-देखि-अन्तसम्म प्रशिक्षित गरिन्छन्, यसले नेटवर्कको पहिलो तहहरूमा त्रुटि फैलाउन कठिनाइ अनुभव गर्छ, जसका कारण नेटवर्कले टाढा टोकनहरू बीचको सम्बन्ध सिक्न सक्दैन। यस समस्यालाई समाधान गर्नका लागि **स्पष्ट अवस्था व्यवस्थापन**को परिचय गराउने एउटा तरिका भनेको **गेटहरू** प्रयोग गर्नु हो। यस प्रकारका दुई सबैभन्दा प्रख्यात आर्किटेक्चरहरू हुन्: **लामो छोटो समय स्मृति** (LSTM) र **गेटेड रिलेको इकाई** (GRU)।\n",
"\n",
"![लामो छोटो समय स्मृति सेलको उदाहरण देखाउने चित्र](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)\n",
"\n",
"LSTM नेटवर्क RNN जस्तै संरचित छ, तर यहाँ दुई अवस्थाहरू छन् जुन तहदेखि तहसम्म पास गरिन्छ: वास्तविक अवस्था $c$, र लुकेको भेक्टर $h$। प्रत्येक इकाईमा, लुकेको भेक्टर $h_i$ इनपुट $x_i$सँग जोडिन्छ, र तिनीहरूले **गेटहरू** मार्फत अवस्था $c$मा के हुन्छ भन्ने नियन्त्रण गर्छन्। प्रत्येक गेट एक न्युरल नेटवर्क हो जसमा सिग्मोइड सक्रियता हुन्छ (आउटपुट $[0,1]$को दायरामा), जसलाई अवस्था भेक्टरसँग गुणा गर्दा बिटवाइज मास्कको रूपमा सोच्न सकिन्छ। माथिको चित्रमा (बायाँदेखि दायाँ) निम्न गेटहरू छन्:\n",
"* **भुल्ने गेट** लुकेको भेक्टर लिन्छ र भेक्टर $c$का कुन-कुन कम्पोनेन्टहरू भुल्नुपर्छ र कुन-कुन पास गर्नुपर्छ भन्ने निर्धारण गर्छ। \n",
"* **इनपुट गेट** इनपुट र लुकेको भेक्टरबाट केही जानकारी लिन्छ, र यसलाई अवस्थामा समावेश गर्छ।\n",
"* **आउटपुट गेट** अवस्थालाई केही रेखीय तह मार्फत $\\tanh$ सक्रियता प्रयोग गरेर रूपान्तरण गर्छ, त्यसपछि लुकेको भेक्टर $h_i$ प्रयोग गरेर यसको केही कम्पोनेन्टहरू चयन गर्छ ताकि नयाँ अवस्था $c_{i+1}$ उत्पादन गर्न सकियोस्।\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 सेलको आन्तरिक संरचना जटिल देखिन्छ, PyTorch ले यस कार्यान्वयनलाई `LSTMCell` वर्गभित्र लुकाउँछ, र सम्पूर्ण LSTM तहलाई प्रतिनिधित्व गर्न `LSTM` वस्तु प्रदान गर्छ। त्यसैले, LSTM वर्गीकरणकर्ता कार्यान्वयन माथि देखिएको साधारण RNN जस्तै हुनेछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class LSTMClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" x,(h,c) = self.rnn(x)\n",
" return self.fc(h[-1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.259375\n",
"6400: acc=0.25859375\n",
"9600: acc=0.26177083333333334\n",
"12800: acc=0.2784375\n",
"16000: acc=0.313\n",
"19200: acc=0.3528645833333333\n",
"22400: acc=0.3965625\n",
"25600: acc=0.4385546875\n",
"28800: acc=0.4752777777777778\n",
"32000: acc=0.505375\n",
"35200: acc=0.5326704545454546\n",
"38400: acc=0.5557552083333334\n",
"41600: acc=0.5760817307692307\n",
"44800: acc=0.5954910714285714\n",
"48000: acc=0.6118333333333333\n",
"51200: acc=0.62681640625\n",
"54400: acc=0.6404779411764706\n",
"57600: acc=0.6520138888888889\n",
"60800: acc=0.662828947368421\n",
"64000: acc=0.673546875\n",
"67200: acc=0.6831547619047619\n",
"70400: acc=0.6917897727272727\n",
"73600: acc=0.6997146739130434\n",
"76800: acc=0.707109375\n",
"80000: acc=0.714075\n",
"83200: acc=0.7209134615384616\n",
"86400: acc=0.727037037037037\n",
"89600: acc=0.7326674107142858\n",
"92800: acc=0.7379633620689655\n",
"96000: acc=0.7433645833333333\n",
"99200: acc=0.7479032258064516\n",
"102400: acc=0.752119140625\n",
"105600: acc=0.7562405303030303\n",
"108800: acc=0.76015625\n",
"112000: acc=0.7641339285714286\n",
"115200: acc=0.7677777777777778\n",
"118400: acc=0.7711233108108108\n"
]
},
{
"data": {
"text/plain": [
"(0.03487814127604167, 0.7728)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = LSTMClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch(net,train_loader, lr=0.001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## प्याक गरिएको अनुक्रमहरू\n",
"\n",
"हाम्रो उदाहरणमा, हामीले मिनिब्याचका सबै अनुक्रमहरूलाई शून्य भेक्टरहरूद्वारा प्याड गर्नुपरेको थियो। यसले केही मेमोरीको खपत गराउँछ, तर RNNs को सन्दर्भमा, प्याड गरिएको इनपुट वस्तुहरूको लागि थप RNN सेलहरू सिर्जना गर्नु अझ महत्त्वपूर्ण हुन्छ, जसले प्रशिक्षणमा भाग लिन्छन् तर कुनै महत्त्वपूर्ण इनपुट जानकारी बोकेका हुँदैनन्। केवल वास्तविक अनुक्रम आकारमा RNN प्रशिक्षण गर्नु धेरै राम्रो हुनेछ।\n",
"\n",
"यसलाई गर्नको लागि, PyTorch मा प्याड गरिएको अनुक्रम भण्डारणको विशेष ढाँचा प्रस्तुत गरिएको छ। मानौं हामीसँग इनपुट प्याड गरिएको मिनिब्याच छ, जुन यस प्रकार देखिन्छ:\n",
"```\n",
"[[1,2,3,4,5],\n",
" [6,7,8,0,0],\n",
" [9,0,0,0,0]]\n",
"```\n",
"यहाँ 0 ले प्याड गरिएको मानहरूलाई प्रतिनिधित्व गर्छ, र इनपुट अनुक्रमहरूको वास्तविक लम्बाइ भेक्टर `[5,3,1]` हो।\n",
"\n",
"प्याड गरिएको अनुक्रमको साथ प्रभावकारी रूपमा RNN प्रशिक्षण गर्नको लागि, हामीले पहिलो समूहको RNN सेलहरू ठूलो मिनिब्याच (`[1,6,9]`) बाट प्रशिक्षण सुरु गर्न चाहन्छौं, तर त्यसपछि तेस्रो अनुक्रमको प्रक्रिया समाप्त गर्नुपर्छ, र छोटो मिनिब्याचहरू (`[2,7]`, `[3,8]`) को साथ प्रशिक्षण जारी राख्नुपर्छ। यसरी, प्याक गरिएको अनुक्रमलाई एक भेक्टरको रूपमा प्रतिनिधित्व गरिन्छ - हाम्रो केसमा `[1,6,9,2,7,3,8,4,5]`, र लम्बाइ भेक्टर (`[5,3,1]`), जसबाट हामी सजिलैसँग मूल प्याड गरिएको मिनिब्याच पुनर्निर्माण गर्न सक्छौं।\n",
"\n",
"प्याक गरिएको अनुक्रम उत्पादन गर्न, हामी `torch.nn.utils.rnn.pack_padded_sequence` फङ्सन प्रयोग गर्न सक्छौं। सबै पुनरावर्ती तहहरू, जस्तै RNN, LSTM र GRU, इनपुटको रूपमा प्याक गरिएको अनुक्रमलाई समर्थन गर्छन्, र प्याक गरिएको आउटपुट उत्पादन गर्छन्, जसलाई `torch.nn.utils.rnn.pad_packed_sequence` प्रयोग गरेर डिकोड गर्न सकिन्छ।\n",
"\n",
"प्याक गरिएको अनुक्रम उत्पादन गर्न सक्षम हुनको लागि, हामीले नेटवर्कमा लम्बाइ भेक्टर पास गर्न आवश्यक छ, र त्यसैले मिनिब्याचहरू तयार गर्नको लागि फरक फङ्सन आवश्यक छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def pad_length(b):\n",
" # build vectorized sequence\n",
" v = [encode(x[1]) for x in b]\n",
" # compute max length of a sequence in this minibatch and length sequence itself\n",
" len_seq = list(map(len,v))\n",
" l = max(len_seq)\n",
" return ( # tuple of three tensors - labels, padded features, length sequence\n",
" torch.LongTensor([t[0]-1 for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v]),\n",
" torch.tensor(len_seq)\n",
" )\n",
"\n",
"train_loader_len = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=pad_length, shuffle=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"वास्तविक नेटवर्क `LSTMClassifier` जस्तै हुनेछ, तर `forward` पासले पाड गरिएको मिनिब्याच र अनुक्रम लम्बाइहरूको भेक्टर दुवै प्राप्त गर्नेछ। एम्बेडिङ गणना गरेपछि, हामी प्याक गरिएको अनुक्रम गणना गर्छौं, यसलाई LSTM तहमा पास गर्छौं, र त्यसपछि परिणामलाई फेरी अनप्याक गर्छौं।\n",
"\n",
"> **Note**: हामी वास्तवमा अनप्याक गरिएको परिणाम `x` प्रयोग गर्दैनौं, किनभने हामी पछिल्लो गणनाहरूमा लुकेको तहबाट प्राप्त आउटपुट प्रयोग गर्छौं। त्यसैले, हामी यस कोडबाट अनप्याकिङ पूर्ण रूपमा हटाउन सक्छौं। हामीले यसलाई यहाँ राख्ने कारण भनेको तपाईंलाई यो कोड सजिलै परिमार्जन गर्न सक्षम बनाउनु हो, यदि तपाईंले नेटवर्क आउटपुटलाई थप गणनाहरूमा प्रयोग गर्न आवश्यक परे।\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class LSTMPackClassifier(torch.nn.Module):\n",
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
" super().__init__()\n",
" self.hidden_dim = hidden_dim\n",
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
"\n",
" def forward(self, x, lengths):\n",
" batch_size = x.size(0)\n",
" x = self.embedding(x)\n",
" pad_x = torch.nn.utils.rnn.pack_padded_sequence(x,lengths,batch_first=True,enforce_sorted=False)\n",
" pad_x,(h,c) = self.rnn(pad_x)\n",
" x, _ = torch.nn.utils.rnn.pad_packed_sequence(pad_x,batch_first=True)\n",
" return self.fc(h[-1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3200: acc=0.285625\n",
"6400: acc=0.33359375\n",
"9600: acc=0.3876041666666667\n",
"12800: acc=0.44078125\n",
"16000: acc=0.4825\n",
"19200: acc=0.5235416666666667\n",
"22400: acc=0.5559821428571429\n",
"25600: acc=0.58609375\n",
"28800: acc=0.6116666666666667\n",
"32000: acc=0.63340625\n",
"35200: acc=0.6525284090909091\n",
"38400: acc=0.668515625\n",
"41600: acc=0.6822596153846154\n",
"44800: acc=0.6948214285714286\n",
"48000: acc=0.7052708333333333\n",
"51200: acc=0.71521484375\n",
"54400: acc=0.7239889705882353\n",
"57600: acc=0.7315277777777778\n",
"60800: acc=0.7388486842105263\n",
"64000: acc=0.74571875\n",
"67200: acc=0.7518303571428572\n",
"70400: acc=0.7576988636363636\n",
"73600: acc=0.7628940217391305\n",
"76800: acc=0.7681510416666667\n",
"80000: acc=0.7728125\n",
"83200: acc=0.7772235576923077\n",
"86400: acc=0.7815393518518519\n",
"89600: acc=0.7857700892857142\n",
"92800: acc=0.7895043103448276\n",
"96000: acc=0.7930520833333333\n",
"99200: acc=0.7959072580645161\n",
"102400: acc=0.798994140625\n",
"105600: acc=0.802064393939394\n",
"108800: acc=0.8051378676470589\n",
"112000: acc=0.8077857142857143\n",
"115200: acc=0.8104600694444445\n",
"118400: acc=0.8128293918918919\n"
]
},
{
"data": {
"text/plain": [
"(0.029785829671223958, 0.8138166666666666)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = LSTMPackClassifier(vocab_size,64,32,len(classes)).to(device)\n",
"train_epoch_emb(net,train_loader_len, lr=0.001,use_pack_sequence=True)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **नोट:** तपाईंले प्रशिक्षण कार्यमा पास गरिएको `use_pack_sequence` प्यारामिटर देख्नुभएको हुन सक्छ। हाल, `pack_padded_sequence` कार्यले लम्बाइ अनुक्रम टेन्सरलाई CPU उपकरणमा हुन आवश्यक छ, र त्यसैले प्रशिक्षण कार्यले GPU मा लम्बाइ अनुक्रम डेटा सार्नबाट बच्नुपर्छ। तपाईं [`torchnlp.py`](../../../../../lessons/5-NLP/16-RNN/torchnlp.py) फाइलमा रहेको `train_emb` कार्यको कार्यान्वयन हेर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## द्विदिशात्मक र बहु-स्तरीय RNNs\n",
"\n",
"हाम्रा उदाहरणहरूमा, सबै पुनरावर्ती नेटवर्कहरू एक दिशामा काम गर्थे, अनुक्रमको सुरुबाट अन्त्यसम्म। यो स्वाभाविक देखिन्छ, किनकि यो हामीले पढ्ने र बोल्ने तरिकासँग मेल खान्छ। तर, धेरै व्यावहारिक अवस्थामा हामीसँग इनपुट अनुक्रममा जताततै पहुँच हुने सम्भावना हुन्छ, त्यसैले पुनरावर्ती गणना दुवै दिशामा चलाउनु उपयुक्त हुन सक्छ। यस्ता नेटवर्कहरूलाई **द्विदिशात्मक** RNNs भनिन्छ, र तिनीहरूलाई RNN/LSTM/GRU कन्स्ट्रक्टरमा `bidirectional=True` प्यारामिटर पास गरेर सिर्जना गर्न सकिन्छ।\n",
"\n",
"द्विदिशात्मक नेटवर्कसँग काम गर्दा, हामीलाई दुईवटा लुकेको अवस्था भेक्टरहरू चाहिन्छ, प्रत्येक दिशाका लागि एक। PyTorch ले ती भेक्टरहरूलाई दुई गुणा ठूलो आकारको एक भेक्टरको रूपमा इनकोड गर्छ, जुन धेरै सुविधाजनक छ, किनकि सामान्यत: तपाईंले प्राप्त लुकेको अवस्थालाई पूर्ण-सम्पर्कित रेखीय तहमा पास गर्नुहुन्छ, र तह सिर्जना गर्दा आकारको यो वृद्धि ध्यानमा राख्न मात्र आवश्यक हुन्छ।\n",
"\n",
"पुनरावर्ती नेटवर्क, एक-दिशात्मक होस् वा द्विदिशात्मक, अनुक्रमभित्रका केही ढाँचाहरू समात्छ, र तिनीहरूलाई अवस्था भेक्टरमा भण्डारण गर्न वा आउटपुटमा पास गर्न सक्छ। जस्तै कनभोल्युसनल नेटवर्कहरूमा, हामी पहिलो तहले निकालेका तल्लो-स्तरीय ढाँचाहरूबाट उच्च-स्तरीय ढाँचाहरू समात्न अर्को पुनरावर्ती तह माथि निर्माण गर्न सक्छौं। यसले हामीलाई **बहु-स्तरीय RNN** को अवधारणामा पुर्‍याउँछ, जसमा दुई वा बढी पुनरावर्ती नेटवर्कहरू हुन्छन्, जहाँ अघिल्लो तहको आउटपुटलाई अर्को तहमा इनपुटको रूपमा पास गरिन्छ।\n",
"\n",
"![बहु-स्तरीय लामो-छोटो-अवधि-स्मृति RNN देखाउने चित्र](../../../../../translated_images/multi-layer-lstm.dd975e29bb2a59fe58b429db833932d734c81f211cad2783797a9608984acb8c.ne.jpg)\n",
"\n",
"*फर्नान्डो लोपेजको [यो उत्कृष्ट पोस्ट](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) बाट चित्र*\n",
"\n",
"PyTorch ले यस्ता नेटवर्कहरू निर्माण गर्न सजिलो बनाउँछ, किनकि तपाईंले RNN/LSTM/GRU कन्स्ट्रक्टरमा `num_layers` प्यारामिटर पास गर्न मात्र आवश्यक हुन्छ, जसले स्वचालित रूपमा पुनरावृत्त तहहरूको निर्माण गर्छ। यसले लुकेको/अवस्था भेक्टरको आकार समानुपातिक रूपमा बढ्ने अर्थ पनि राख्छ, र पुनरावर्ती तहहरूको आउटपुट ह्यान्डल गर्दा तपाईंले यसलाई ध्यानमा राख्न आवश्यक हुन्छ।\n"
]
},
{
"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": {
"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": "522ee52ae3d5ae933e283286254e9a55",
"translation_date": "2025-08-28T09:38:55+00:00",
"source_file": "lessons/5-NLP/16-RNN/RNNPyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,460 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# पुनरावर्ती न्युरल नेटवर्कहरू\n",
"\n",
"अघिल्लो मोड्युलमा, हामीले पाठको समृद्ध अर्थपूर्ण प्रतिनिधित्वहरू कभर गरेका थियौं। हामीले प्रयोग गरिरहेको आर्किटेक्चरले वाक्यमा शब्दहरूको समग्र अर्थलाई समेट्छ, तर यो शब्दहरूको **क्रम**लाई ध्यानमा राख्दैन, किनभने एम्बेडिङ पछि हुने समग्र अपरेशनले मूल पाठबाट यो जानकारी हटाउँछ। यी मोडेलहरूले शब्दहरूको क्रमबद्धता प्रतिनिधित्व गर्न नसक्ने भएकाले, तिनीहरूले पाठ उत्पादन वा प्रश्न उत्तरजस्ता जटिल वा अस्पष्ट कार्यहरू समाधान गर्न सक्दैनन्।\n",
"\n",
"पाठ अनुक्रमको अर्थ समेट्न, हामी **पुनरावर्ती न्युरल नेटवर्क** भनिने न्युरल नेटवर्क आर्किटेक्चर प्रयोग गर्नेछौं। RNN प्रयोग गर्दा, हामी हाम्रो वाक्यलाई नेटवर्कमा एक पटकमा एक टोकन पास गर्छौं, र नेटवर्कले केही **स्थिति** उत्पादन गर्छ, जुन हामी अर्को टोकनसँग फेरि नेटवर्कमा पास गर्छौं।\n",
"\n",
"![पुनरावर्ती न्युरल नेटवर्क उत्पादनको उदाहरण देखाउने चित्र।](../../../../../translated_images/rnn.27f5c29c53d727b546ad3961637a267f0fe9ec5ab01f2a26a853c92fcefbb574.ne.png)\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",
"![लामो छोटो-अवधि स्मृति सेलको उदाहरण देखाउने छवि](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)\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",
"![बहु-स्तरीय लामो-छोटो-अवधि-स्मृति RNN देखाउने चित्र](../../../../../translated_images/multi-layer-lstm.dd975e29bb2a59fe58b429db833932d734c81f211cad2783797a9608984acb8c.ne.jpg)\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
}

View File

@ -0,0 +1,414 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# जेनेरेटिभ नेटवर्कहरू\n",
"\n",
"Recurrent Neural Networks (RNNs) र तिनका गेटेड सेल भेरियन्टहरू जस्तै Long Short Term Memory Cells (LSTMs) र Gated Recurrent Units (GRUs) ले भाषा मोडलिङको लागि एउटा मेकानिज्म प्रदान गरे, अर्थात् यीले शब्दहरूको क्रम सिक्न सक्छन् र अनुक्रममा आउने अर्को शब्दको भविष्यवाणी गर्न सक्छन्। यसले हामीलाई RNNs लाई **जेनेरेटिभ कार्यहरू** जस्तै साधारण पाठ उत्पादन, मेसिन अनुवाद, र यहाँसम्म कि छविको क्याप्शनिङको लागि प्रयोग गर्न अनुमति दिन्छ।\n",
"\n",
"पछिल्लो युनिटमा हामीले छलफल गरेको RNN आर्किटेक्चरमा, प्रत्येक RNN युनिटले अर्को लुकेको अवस्था (hidden state) उत्पादन गर्थ्यो। तर, हामी प्रत्येक पुनरावर्ती युनिटमा अर्को आउटपुट पनि थप्न सक्छौं, जसले हामीलाई एउटा **अनुक्रम** (जसको लम्बाइ मूल अनुक्रमसँग बराबर हुन्छ) उत्पादन गर्न अनुमति दिन्छ। अझै, हामी त्यस्ता RNN युनिटहरू प्रयोग गर्न सक्छौं जसले प्रत्येक चरणमा इनपुट स्वीकार्दैनन्, तर केवल कुनै सुरुवाती अवस्था भेक्टर लिन्छन्, र त्यसपछि आउटपुटहरूको अनुक्रम उत्पादन गर्छन्।\n",
"\n",
"यस नोटबुकमा, हामी सरल जेनेरेटिभ मोडेलहरूमा केन्द्रित हुनेछौं जसले हामीलाई पाठ उत्पादन गर्न मद्दत गर्छ। सरलताका लागि, आउनुहोस् **क्यारेक्टर-स्तरको नेटवर्क** निर्माण गरौं, जसले अक्षर-प्रति-अक्षर पाठ उत्पादन गर्छ। प्रशिक्षणको क्रममा, हामीले केही पाठ कर्पस लिनुपर्छ, र यसलाई अक्षर अनुक्रमहरूमा विभाजन गर्नुपर्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"import numpy as np\n",
"from torchnlp import *\n",
"train_dataset,test_dataset,classes,vocab = load_dataset()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## वर्णको शब्दकोश निर्माण\n",
"\n",
"वर्ण-स्तरको जनरेटिभ नेटवर्क निर्माण गर्न, हामीलाई पाठलाई शब्दहरूमा होइन, व्यक्तिगत वर्णहरूमा विभाजन गर्न आवश्यक छ। यो फरक टोकनाइजर परिभाषित गरेर गर्न सकिन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocabulary size = 82\n",
"Encoding of 'a' is 1\n",
"Character with code 13 is c\n"
]
}
],
"source": [
"def char_tokenizer(words):\n",
" return list(words) #[word for word in words]\n",
"\n",
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" counter.update(char_tokenizer(line))\n",
"vocab = torchtext.vocab.vocab(counter)\n",
"\n",
"vocab_size = len(vocab)\n",
"print(f\"Vocabulary size = {vocab_size}\")\n",
"print(f\"Encoding of 'a' is {vocab.get_stoi()['a']}\")\n",
"print(f\"Character with code 13 is {vocab.get_itos()[13]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले हाम्रो डाटासेटबाट पाठलाई कसरी एन्कोड गर्न सक्छौं भन्ने उदाहरण हेरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([ 0, 1, 2, 2, 3, 4, 5, 6, 3, 7, 8, 1, 9, 10, 3, 11, 2, 1,\n",
" 12, 3, 7, 1, 13, 14, 3, 15, 16, 5, 17, 3, 5, 18, 8, 3, 7, 2,\n",
" 1, 13, 14, 3, 19, 20, 8, 21, 5, 8, 9, 10, 22, 3, 20, 8, 21, 5,\n",
" 8, 9, 10, 3, 23, 3, 4, 18, 17, 9, 5, 23, 10, 8, 2, 2, 8, 9,\n",
" 10, 24, 3, 0, 1, 2, 2, 3, 4, 5, 9, 8, 8, 5, 25, 10, 3, 26,\n",
" 12, 27, 16, 26, 2, 27, 16, 28, 29, 30, 1, 16, 26, 3, 17, 31, 3, 21,\n",
" 2, 5, 9, 1, 23, 13, 32, 16, 27, 13, 10, 24, 3, 1, 9, 8, 3, 10,\n",
" 8, 8, 27, 16, 28, 3, 28, 9, 8, 8, 16, 3, 1, 28, 1, 27, 16, 6])"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def enc(x):\n",
" return torch.LongTensor(encode(x,voc=vocab,tokenizer=char_tokenizer))\n",
"\n",
"enc(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## जेनेरेटिभ RNN प्रशिक्षण\n",
"\n",
"हामी RNN लाई पाठ उत्पन्न गर्न प्रशिक्षण दिने तरिका निम्नानुसार हुनेछ। प्रत्येक चरणमा, हामी `nchars` लम्बाइको अक्षरहरूको श्रृंखला लिनेछौं, र प्रत्येक इनपुट अक्षरको लागि नेटवर्कलाई अर्को आउटपुट अक्षर उत्पन्न गर्न अनुरोध गर्नेछौं:\n",
"\n",
"![RNN ले 'HELLO' शब्द उत्पन्न गरिरहेको उदाहरण देखाउने छवि।](../../../../../translated_images/rnn-generate.56c54afb52f9781d63a7c16ea9c1b86cb70e6e1eae6a742b56b7b37468576b17.ne.png)\n",
"\n",
"वास्तविक परिदृश्यमा निर्भर गर्दै, हामीले केही विशेष अक्षरहरू पनि समावेश गर्न चाहन सक्छौं, जस्तै *end-of-sequence* `<eos>`। हाम्रो अवस्थामा, हामी केवल नेटवर्कलाई अन्तहीन पाठ उत्पन्न गर्न प्रशिक्षण दिन चाहन्छौं, त्यसैले हामी प्रत्येक श्रृंखलाको आकारलाई `nchars` टोकनहरूको बराबरमा स्थिर गर्नेछौं। तदनुसार, प्रत्येक प्रशिक्षण उदाहरण `nchars` इनपुटहरू र `nchars` आउटपुटहरू (जसले इनपुट श्रृंखलालाई एक प्रतीक बायाँ सिफ्ट गरेको हुन्छ) बाट बनेको हुनेछ। मिनिब्याचमा यस्ता धेरै श्रृंखलाहरू हुनेछन्।\n",
"\n",
"हामी मिनिब्याचहरू उत्पन्न गर्ने तरिका यस्तो हुनेछ: प्रत्येक समाचार पाठको लम्बाइ `l` लिनेछौं, र त्यसबाट सबै सम्भावित इनपुट-आउटपुट संयोजनहरू उत्पन्न गर्नेछौं (त्यहाँ `l-nchars` यस्ता संयोजनहरू हुनेछन्)। यी संयोजनहरूले एउटा मिनिब्याच बनाउनेछन्, र प्रत्येक प्रशिक्षण चरणमा मिनिब्याचहरूको आकार फरक हुनेछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(tensor([[ 0, 1, 2, ..., 28, 29, 30],\n",
" [ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" ...,\n",
" [20, 8, 21, ..., 1, 28, 1],\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16]]),\n",
" tensor([[ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" [ 2, 3, 4, ..., 1, 16, 26],\n",
" ...,\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16],\n",
" [ 5, 8, 9, ..., 27, 16, 6]]))"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nchars = 100\n",
"\n",
"def get_batch(s,nchars=nchars):\n",
" ins = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" outs = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" for i in range(len(s)-nchars):\n",
" ins[i] = enc(s[i:i+nchars])\n",
" outs[i] = enc(s[i+1:i+nchars+1])\n",
" return ins,outs\n",
"\n",
"get_batch(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी जेनरेटर नेटवर्क परिभाषित गरौं। यो कुनै पनि पुनरावर्ती सेलमा आधारित हुन सक्छ जुन हामीले अघिल्लो युनिटमा छलफल गरेका थियौं (साधारण, LSTM वा GRU)। हाम्रो उदाहरणमा, हामी LSTM प्रयोग गर्नेछौं।\n",
"\n",
"किनभने नेटवर्कले अक्षरहरूलाई इनपुटको रूपमा लिन्छ, र शब्दकोशको आकार धेरै सानो छ, हामीलाई embedding लेयरको आवश्यकता पर्दैन, one-hot-encoded इनपुट सिधै LSTM सेलमा जान सक्छ। तर, किनभने हामी अक्षरहरूको संख्या इनपुटको रूपमा पास गर्छौं, हामीले तिनीहरूलाई LSTM मा पास गर्नु अघि one-hot-encode गर्न आवश्यक छ। यो `forward` पासको क्रममा `one_hot` फंक्शन कल गरेर गरिन्छ। आउटपुट इन्कोडर भनेको एउटा linear लेयर हुनेछ जसले लुकेको अवस्थालाई one-hot-encoded आउटपुटमा रूपान्तरण गर्नेछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class LSTMGenerator(torch.nn.Module):\n",
" def __init__(self, vocab_size, hidden_dim):\n",
" super().__init__()\n",
" self.rnn = torch.nn.LSTM(vocab_size,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, vocab_size)\n",
"\n",
" def forward(self, x, s=None):\n",
" x = torch.nn.functional.one_hot(x,vocab_size).to(torch.float32)\n",
" x,s = self.rnn(x,s)\n",
" return self.fc(x),s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"प्रशिक्षणको क्रममा, हामीले उत्पन्न गरिएको पाठलाई नमूना बनाउन सक्षम हुन चाहन्छौं। त्यसका लागि, हामी `generate` नामक एक कार्य परिभाषित गर्नेछौं जसले प्रारम्भिक स्ट्रिङ `start` बाट सुरु गर्दै, लम्बाइ `size` को आउटपुट स्ट्रिङ उत्पादन गर्नेछ।\n",
"\n",
"यसले काम गर्ने तरिका निम्नानुसार छ। पहिलो, हामी सम्पूर्ण `start` स्ट्रिङलाई नेटवर्क मार्फत पास गर्नेछौं, र आउटपुट अवस्था `s` र अर्को भविष्यवाणी गरिएको अक्षर `out` लिनेछौं। किनभने `out` एक-हट एन्कोड गरिएको छ, हामी `argmax` लिन्छौं ताकि शब्दकोशमा अक्षर `nc` को सूचकांक प्राप्त गर्न सकियोस्, र `itos` प्रयोग गरेर वास्तविक अक्षर पत्ता लगाई अक्षरहरूको परिणामस्वरूप सूची `chars` मा थप्न सकियोस्। यो प्रक्रिया, एक अक्षर उत्पन्न गर्ने, `size` पटक दोहोर्याइन्छ ताकि आवश्यक संख्याको अक्षरहरू उत्पन्न गर्न सकियोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def generate(net,size=100,start='today '):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" nc = torch.argmax(out[0][-1])\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब प्रशिक्षण गरौं! प्रशिक्षण लूप हाम्रा अघिल्ला उदाहरणहरूजस्तै छ, तर यसपटक हामी सटीकता प्रिन्ट गर्ने सट्टा प्रत्येक १००० इपोक्समा नमूना गरिएको उत्पन्न पाठ प्रिन्ट गर्छौं।\n",
"\n",
"विशेष ध्यान हामीले कसरी हानि गणना गर्छौं भन्ने कुरामा दिनुपर्छ। हामीले एक-हट-एन्कोड गरिएको आउटपुट `out` र अपेक्षित पाठ `text_out` (जसले क्यारेक्टर इन्डेक्सहरूको सूची प्रतिनिधित्व गर्छ) दिइएको अवस्थामा हानि गणना गर्नुपर्छ। भाग्यवश, `cross_entropy` फंक्शनले पहिलो तर्कको रूपमा अनन्यस्त (unnormalized) नेटवर्क आउटपुट र दोस्रो तर्कको रूपमा वर्ग संख्या (class number) अपेक्षा गर्छ, जुन ठ्याक्कै हामीसँग छ। यसले मिनिब्याच साइजमा स्वचालित औसत गणना पनि गर्छ।\n",
"\n",
"हामीले `samples_to_train` नमूनाहरूद्वारा प्रशिक्षण सीमित गर्छौं, ताकि धेरै समय कुर्नु नपरोस्। हामी तपाईंलाई लामो समयसम्म प्रशिक्षण गर्ने प्रयास गर्न प्रोत्साहित गर्छौं, सम्भवतः केही इपोक्ससम्म (जसको लागि तपाईंले यो कोड वरिपरि अर्को लूप सिर्जना गर्नुपर्नेछ)।\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Current loss = 4.398899078369141\n",
"today sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr s\n",
"Current loss = 2.161320447921753\n",
"today and to the tor to to the tor to to the tor to to the tor to to the tor to to the tor to to the tor t\n",
"Current loss = 1.6722588539123535\n",
"today and the court to the could to the could to the could to the could to the could to the could to the c\n",
"Current loss = 2.423795223236084\n",
"today and a second to the conternation of the conternation of the conternation of the conternation of the \n",
"Current loss = 1.702607274055481\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.692358136177063\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.9722288846969604\n",
"today and the control the control the control the control the control the control the control the control \n",
"Current loss = 1.8705692291259766\n",
"today and the second to the second to the second to the second to the second to the second to the second t\n",
"Current loss = 1.7626899480819702\n",
"today and a security and a security and a security and a security and a security and a security and a secu\n",
"Current loss = 1.5574463605880737\n",
"today and the company and the company and the company and the company and the company and the company and \n",
"Current loss = 1.5620026588439941\n",
"today and the be that the be the be that the be the be that the be the be that the be the be that the be t\n"
]
}
],
"source": [
"net = LSTMGenerator(vocab_size,64).to(device)\n",
"\n",
"samples_to_train = 10000\n",
"optimizer = torch.optim.Adam(net.parameters(),0.01)\n",
"loss_fn = torch.nn.CrossEntropyLoss()\n",
"net.train()\n",
"for i,x in enumerate(train_dataset):\n",
" # x[0] is class label, x[1] is text\n",
" if len(x[1])-nchars<10:\n",
" continue\n",
" samples_to_train-=1\n",
" if not samples_to_train: break\n",
" text_in, text_out = get_batch(x[1])\n",
" optimizer.zero_grad()\n",
" out,s = net(text_in)\n",
" loss = torch.nn.functional.cross_entropy(out.view(-1,vocab_size),text_out.flatten()) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" if i%1000==0:\n",
" print(f\"Current loss = {loss.item()}\")\n",
" print(generate(net))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यो उदाहरणले पहिले नै राम्रो पाठ उत्पादन गर्छ, तर यसलाई अझ सुधार गर्न केही तरिकाहरू छन्:\n",
"\n",
"* **मिनिब्याच उत्पादनलाई अझ राम्रो बनाउनुहोस्।** हामीले प्रशिक्षणका लागि डाटा तयार गर्दा एउटा नमूनाबाट एउटा मिनिब्याच उत्पादन गर्‍यौं। यो आदर्श होइन, किनभने मिनिब्याचहरू सबै फरक आकारका हुन्छन्, र केही अवस्थामा त उत्पादन नै गर्न सकिँदैन, किनभने पाठ `nchars` भन्दा सानो हुन्छ। साथै, साना मिनिब्याचहरूले GPU लाई पर्याप्त रूपमा लोड गर्दैनन्। सबै नमूनाहरूबाट एउटा ठूलो पाठको टुक्रा लिनु, त्यसपछि सबै इनपुट-आउटपुट जोडीहरू उत्पादन गर्नु, तिनीहरूलाई शफल गर्नु, र समान आकारका मिनिब्याचहरू उत्पादन गर्नु अझ बुद्धिमानी हुनेछ।\n",
"\n",
"* **मल्टिलेयर LSTM।** 2 वा 3 तहका LSTM सेलहरू प्रयास गर्नु उपयुक्त हुन्छ। जस्तै हामीले अघिल्लो युनिटमा उल्लेख गर्‍यौं, LSTM को प्रत्येक तहले पाठबाट निश्चित ढाँचाहरू निकाल्छ। क्यारेक्टर-स्तरको जेनेरेटरको अवस्थामा, हामी अपेक्षा गर्न सक्छौं कि तल्लो LSTM तहले अक्षरहरूको समूह (syllables) निकाल्न जिम्मेवार हुनेछ, र माथिल्लो तहहरूले शब्द र शब्द संयोजनहरू निकाल्नेछन्। यो LSTM कन्स्ट्रक्टरमा तहहरूको संख्या (number-of-layers) को प्यारामिटर पास गरेर सजिलै कार्यान्वयन गर्न सकिन्छ।\n",
"\n",
"* तपाईंले **GRU युनिटहरू** प्रयोग गरेर पनि परीक्षण गर्न चाहन सक्नुहुन्छ, र कुन राम्रो प्रदर्शन गर्छ भनेर हेर्न सक्नुहुन्छ। साथै, **विभिन्न लुकेको तहको आकार (hidden layer sizes)** सँग पनि परीक्षण गर्न सक्नुहुन्छ। धेरै ठूलो लुकेको तहले ओभरफिटिंगको कारण दिन सक्छ (जस्तै, नेटवर्कले ठ्याक्कै पाठ सिक्नेछ), र सानो आकारले राम्रो नतिजा उत्पादन नगर्न सक्छ।\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",
"तर, यदि हामी अर्को अक्षरको लागि सम्भावना वितरणलाई हेर्‍यौं भने, केही उच्चतम सम्भावनाहरूको बीचको भिन्नता धेरै ठूलो नहुन सक्छ, जस्तै एउटा अक्षरको सम्भावना .२ हुन सक्छ, अर्कोको .१९, आदि। उदाहरणका लागि, '*play*' अनुक्रममा अर्को अक्षर खोज्दा, अर्को अक्षर समान रूपमा खाली ठाउँ वा **e** (जस्तै *player* शब्दमा) हुन सक्छ।\n",
"\n",
"यसले हामीलाई यो निष्कर्षमा पुर्‍याउँछ कि सधैं उच्च सम्भावना भएको अक्षर चयन गर्नु \"न्यायोचित\" हुँदैन, किनभने दोस्रो उच्चतम चयन गर्दा पनि अर्थपूर्ण पाठमा पुग्न सकिन्छ। यो बढी बुद्धिमानी हुन्छ कि नेटवर्कको आउटपुटले दिएको सम्भावना वितरणबाट अक्षरहरू **नमूना** गरियोस्।\n",
"\n",
"यो नमूना `multinomial` नामक कार्य प्रयोग गरेर गर्न सकिन्छ, जसले **multinomial distribution** लागू गर्छ। यो **नरम** पाठ उत्पादन कार्य निम्न रूपमा परिभाषित गरिएको छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Temperature = 0.3\n",
"Today and a company and complete an all the land the restrational the as a security and has provers the pay to and a report and the computer in the stand has filities and working the law the stations for a company and with the company and the final the first company and refight of the state and and workin\n",
"\n",
"--- Temperature = 0.8\n",
"Today he oniis its first to Aus bomblaties the marmation a to manan boogot that pirate assaid a relaid their that goverfin the the Cappets Ecrotional Assonia Cition targets it annight the w scyments Blamity #39;s TVeer Diercheg Reserals fran envyuil that of ster said access what succers of Dour-provelith\n",
"\n",
"--- Temperature = 1.0\n",
"Today holy they a 11 will meda a toket subsuaties, engins for Chanos, they's has stainger past to opening orital his thempting new Nattona was al innerforder advan-than #36;s night year his religuled talitatian what the but with Wednesday to Justment will wemen of Mark CCC Camp as Timed Nae wome a leaders\n",
"\n",
"--- Temperature = 1.3\n",
"Today gpone 2.5 fech atcusion poor cocles toparsdorM.cht Line Pamage put 43 his calt lowed to the book, that has authh-the silia rruch ailing to'ory andhes beutirsimi- Aefffive heading offil an auf eacklets is charged evis, Gunymy oy) Mony has it after-sloythyor loveId out filme, the Natabl -Najuntaxiggs \n",
"\n",
"--- Temperature = 1.8\n",
"Today plary, P.slan chly\\401 mardregationly #39;t 8.1Mide) closes ,filtcon alfly playin roven!\\grea.-QFBEP: Iss onfarchQ/itilia CCf Zivesigntwasta orce.-Peul-aw.uicrin of fuglinfsut aftaningwo, MIEX awayew Aice Woiduar Corvagiugge oppo esig ThusBratourid canthly-RyI.co lagitems\\eexciaishes.conBabntusmor I\n",
"\n"
]
}
],
"source": [
"def generate_soft(net,size=100,start='today ',temperature=1.0):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" #nc = torch.argmax(out[0][-1])\n",
" out_dist = out[0][-1].div(temperature).exp()\n",
" nc = torch.multinomial(out_dist,1)[0]\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)\n",
" \n",
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
" print(f\"--- Temperature = {i}\\n{generate_soft(net,size=300,start='Today ',temperature=i)}\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले **तापक्रम** नामक अर्को प्यारामिटर प्रस्तुत गरेका छौं, जसले उच्च सम्भावनामा कत्तिको कडाइका साथ टाँसिनुपर्छ भनेर संकेत गर्न प्रयोग गरिन्छ। यदि तापक्रम १. छ भने, हामी निष्पक्ष बहुपद नमूना लिन्छौं, र जब तापक्रम अनन्ततिर जान्छ - सबै सम्भावनाहरू समान हुन्छन्, र हामी अर्को अक्षर अनियमित रूपमा चयन गर्छौं। तलको उदाहरणमा, हामीले देख्न सक्छौं कि तापक्रम धेरै बढाउँदा पाठ अर्थहीन बन्छ, र जब यो नजिक हुन्छ, यो \"चक्रित\" कडा-उत्पन्न पाठ जस्तै देखिन्छ।\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": "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": "7673cd150d96c74c6d6011460094efb4",
"translation_date": "2025-08-28T09:16:21+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,493 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# जेनेरेटिभ नेटवर्कहरू\n",
"\n",
"Recurrent Neural Networks (RNNs) र तिनका गेटेड सेल भेरियन्टहरू जस्तै Long Short Term Memory Cells (LSTMs) र Gated Recurrent Units (GRUs) ले भाषा मोडलिङको लागि एक मेकानिज्म प्रदान गरे, अर्थात् तिनीहरूले शब्दहरूको क्रम सिक्न सक्छन् र अनुक्रममा अर्को शब्दको भविष्यवाणी गर्न सक्छन्। यसले हामीलाई RNNs लाई **जेनेरेटिभ कार्यहरू** जस्तै सामान्य पाठ उत्पादन, मेसिन अनुवाद, र यहाँसम्म कि छवि क्याप्शनिङको लागि प्रयोग गर्न अनुमति दिन्छ।\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": [
"हामीले **sequence को अन्त्य** जनाउनको लागि एउटा विशेष टोकन प्रयोग गर्न चाहन्छौं, जसलाई हामी `<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": []
},
{
"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/rnn-generate.56c54afb52f9781d63a7c16ea9c1b86cb70e6e1eae6a742b56b7b37468576b17.ne.png)\n",
"\n",
"हाम्रो अनुक्रमको अन्तिम अक्षरको लागि, हामी नेटवर्कलाई `<eos>` टोकन उत्पन्न गर्न अनुरोध गर्नेछौं।\n",
"\n",
"हामीले यहाँ प्रयोग गरिरहेको जनरेटिभ RNN को मुख्य भिन्नता भनेको हामी RNN को प्रत्येक चरणबाट आउटपुट लिनेछौं, न कि केवल अन्तिम सेलबाट। यो `return_sequences` प्यारामिटरलाई RNN सेलमा निर्दिष्ट गरेर हासिल गर्न सकिन्छ।\n",
"\n",
"त्यसैले, प्रशिक्षणको क्रममा, नेटवर्कमा इनपुट केही लम्बाइको एन्कोड गरिएको अक्षरहरूको अनुक्रम हुनेछ, र आउटपुट उही लम्बाइको अनुक्रम हुनेछ, तर एक तत्वले सिफ्ट गरिएको र `<eos>` द्वारा समाप्त गरिएको। मिनिब्याचमा यस्ता धेरै अनुक्रमहरू हुनेछन्, र हामीले सबै अनुक्रमहरूलाई मिलाउन **प्याडिङ** प्रयोग गर्नुपर्नेछ।\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",
"* पहिलोमा, हामी स्ट्रिङ टेन्सरबाट वास्तविक पाठ निकाल्छौं।\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 रूपान्तरण कार्यहरू बीचको भिन्नता बुझ्न अलि जटिल लाग्न सक्छ, र तपाईं सोच्न सक्नुहुन्छ कि किन हामीले डेटासेटलाई `fit` मा पठाउनु अघि सामान्य Python कार्यहरू प्रयोग गरेर रूपान्तरण गर्दैनौं। यद्यपि यो पक्कै गर्न सकिन्छ, `Dataset.map` प्रयोग गर्दा ठूलो फाइदा हुन्छ, किनभने डेटा रूपान्तरण पाइपलाइन Tensorflow को गणनात्मक ग्राफ प्रयोग गरेर कार्यान्वयन गरिन्छ, जसले GPU गणनाको फाइदा लिन्छ, र CPU/GPU बीच डेटा पास गर्नुपर्ने आवश्यकता कम गर्दछ।\n",
"\n",
"अब हामी हाम्रो generator नेटवर्क निर्माण गर्न सक्छौं र प्रशिक्षण सुरु गर्न सक्छौं। यो कुनै पनि पुनरावर्ती सेलमा आधारित हुन सक्छ जुन हामीले अघिल्लो इकाईमा छलफल गरेका थियौं (जस्तै, simple, LSTM वा GRU)। हाम्रो उदाहरणमा हामी LSTM प्रयोग गर्नेछौं।\n",
"\n",
"किनभने नेटवर्कले अक्षरहरूलाई इनपुटको रूपमा लिन्छ, र शब्दकोशको आकार धेरै सानो छ, हामीलाई embedding layer को आवश्यकता पर्दैन, one-hot-encoded इनपुट सिधै LSTM सेलमा जान सक्छ। आउटपुट लेयर `Dense` classifier हुनेछ, जसले LSTM को आउटपुटलाई one-hot-encoded टोकन नम्बरहरूमा रूपान्तरण गर्नेछ।\n",
"\n",
"यसका अतिरिक्त, किनभने हामी variable-length sequences संग काम गरिरहेका छौं, हामी `Masking` लेयर प्रयोग गर्न सक्छौं जसले स्ट्रिङको padded भागलाई बेवास्ता गर्ने मास्क सिर्जना गर्दछ। यो अनिवार्य रूपमा आवश्यक छैन, किनभने `<eos>` टोकन भन्दा परको सबै कुरामा हामी धेरै रुचि राख्दैनौं, तर हामी यस प्रकारको लेयरसँग अनुभव प्राप्त गर्नको लागि यसलाई प्रयोग गर्नेछौं। `input_shape` `(None, vocab_size)` हुनेछ, जहाँ `None` ले variable length को sequence संकेत गर्दछ, र आउटपुट आकार पनि `(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",
"* **अधिक पाठ**। हामीले हाम्रो कार्यका लागि केवल शीर्षकहरू प्रयोग गरेका छौं, तर तपाईं पूर्ण पाठसँग प्रयोग गर्न चाहनुहुन्छ। याद गर्नुहोस् कि RNNs लामो अनुक्रमहरू ह्यान्डल गर्न धेरै राम्रो छैनन्, त्यसैले तिनीहरूलाई छोटो वाक्यहरूमा विभाजन गर्नु वा निश्चित अनुक्रम लम्बाइ `num_chars` (जस्तै, 256) को पूर्वनिर्धारित मानमा सधैं प्रशिक्षण गर्नु उपयुक्त हुन्छ। तपाईं माथिको उदाहरणलाई यस्तो वास्तुकलामा परिवर्तन गर्न प्रयास गर्न सक्नुहुन्छ, [आधिकारिक Keras ट्यूटोरियल](https://keras.io/examples/generative/lstm_character_level_text_generation/) लाई प्रेरणाको रूपमा प्रयोग गर्दै।\n",
"* **बहु-स्तरीय LSTM**। LSTM को 2 वा 3 तह कोशिकाहरू प्रयास गर्नु उपयुक्त हुन्छ। जस्तै हामीले अघिल्लो इकाईमा उल्लेख गर्यौं, प्रत्येक 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",
"तर, यदि हामी अर्को अक्षरको सम्भावना वितरणलाई हेर्छौं भने, केही उच्चतम सम्भावनाहरूको बीचको अन्तर ठूलो नहुन सक्छ, जस्तै एउटा अक्षरको सम्भावना .२ हुन सक्छ भने अर्कोको .१९। उदाहरणका लागि, '*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": [
"हामीले **तापक्रम** नामक अर्को प्यारामिटर प्रस्तुत गरेका छौं, जसले उच्च सम्भावनामा कति दृढताका साथ टाँसिनुपर्छ भनेर संकेत गर्न प्रयोग गरिन्छ। यदि तापक्रम १. छ भने, हामी निष्पक्ष बहुपद नमूना लिन्छौं, र जब तापक्रम अनन्ततिर जान्छ - सबै सम्भावनाहरू समान हुन्छन्, र हामीले अर्को अक्षर अनियमित रूपमा चयन गर्छौं। तलको उदाहरणमा, हामीले देख्न सक्छौं कि जब हामी तापक्रम धेरै बढाउँछौं, पाठ अर्थहीन बन्छ, र जब यो नजिक जान्छ, यो \"चक्रित\" कडा-उत्पन्न पाठ जस्तो देखिन्छ।\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": "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-08-28T09:12:58+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,353 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ध्यान केन्द्रित गर्ने प्रणाली र ट्रान्सफर्मरहरू\n",
"\n",
"पुनरावर्ती नेटवर्कहरूको एक प्रमुख कमजोरी यो हो कि अनुक्रमका सबै शब्दहरूले नतिजामा समान प्रभाव पार्छन्। यसले नामित इकाई पहिचान (Named Entity Recognition) र मेसिन अनुवाद (Machine Translation) जस्ता अनुक्रम-देखि-अनुक्रम कार्यहरूको लागि मानक LSTM एन्कोडर-डिकोडर मोडेलहरूसँग उपयुक्त प्रदर्शन गर्न सक्दैन। वास्तविकतामा, इनपुट अनुक्रमका केही विशेष शब्दहरूले अन्य शब्दहरूको तुलनामा अनुक्रमिक नतिजाहरूमा बढी प्रभाव पार्छन्।\n",
"\n",
"मेसिन अनुवाद जस्ता अनुक्रम-देखि-अनुक्रम मोडेललाई विचार गर्नुहोस्। यो दुई पुनरावर्ती नेटवर्कहरूद्वारा कार्यान्वयन गरिन्छ, जहाँ एउटा नेटवर्क (**एन्कोडर**) इनपुट अनुक्रमलाई लुकेको अवस्थामा सङ्कुचित गर्छ, र अर्को नेटवर्क (**डिकोडर**) यस लुकेको अवस्थालाई अनुवादित नतिजामा विस्तार गर्छ। यस दृष्टिकोणको समस्या यो हो कि नेटवर्कको अन्तिम अवस्थाले वाक्यको सुरुवात सम्झन गाह्रो हुन्छ, जसले गर्दा लामो वाक्यहरूमा मोडेलको गुणस्तर कमजोर हुन्छ।\n",
"\n",
"**ध्यान केन्द्रित गर्ने प्रणालीहरू** (Attention Mechanisms) ले प्रत्येक इनपुट भेक्टरको सन्दर्भात्मक प्रभावलाई RNN को प्रत्येक आउटपुट भविष्यवाणीमा तौल दिने माध्यम प्रदान गर्छ। यसलाई कार्यान्वयन गर्ने तरिका भनेको इनपुट RNN का मध्यवर्ती अवस्थाहरू र आउटपुट RNN बीच छोटो मार्गहरू सिर्जना गर्नु हो। यसरी, आउटपुट प्रतीक $y_t$ उत्पन्न गर्दा, हामी सबै इनपुट लुकेका अवस्थाहरू $h_i$ लाई विभिन्न तौल गुणांक $\\alpha_{t,i}$ का साथ विचार गर्नेछौं।\n",
"\n",
"![एन्कोडर/डिकोडर मोडेलमा एडिटिभ ध्यान तह देखाउने छवि](../../../../../translated_images/encoder-decoder-attention.7a726296894fb567aa2898c94b17b3289087f6705c11907df8301df9e5eeb3de.ne.png)\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) मा एडिटिभ ध्यान प्रणाली भएको एन्कोडर-डिकोडर मोडेल, [यो ब्लग पोस्ट](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) बाट उद्धृत]*\n",
"\n",
"ध्यान म्याट्रिक्स $\\{\\alpha_{i,j}\\}$ ले इनपुटका निश्चित शब्दहरूले आउटपुट अनुक्रमको कुनै शब्द उत्पन्न गर्न कत्तिको भूमिका खेल्छन् भन्ने प्रतिनिधित्व गर्दछ। तल यस्तो म्याट्रिक्सको उदाहरण दिइएको छ:\n",
"\n",
"![RNNsearch-50 द्वारा फेला परेको नमूना संरेखण देखाउने छवि, Bahdanau - arviz.org बाट लिइएको](../../../../../translated_images/bahdanau-fig3.09ba2d37f202a6af11de6c82d2d197830ba5f4528d9ea430eb65fd3a75065973.ne.png)\n",
"\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) बाट लिइएको चित्र (Fig.3)*\n",
"\n",
"ध्यान केन्द्रित गर्ने प्रणालीहरू प्राकृतिक भाषा प्रशोधनमा हालको वा निकट भविष्यको उत्कृष्ट अवस्थाको लागि जिम्मेवार छन्। तर ध्यान थप्दा मोडेलका प्यारामिटरहरूको संख्या धेरै बढ्छ, जसले गर्दा RNN हरूसँग स्केलिङ समस्याहरू उत्पन्न हुन्छ। RNN हरूको स्केलिङको प्रमुख बाधा भनेको मोडेलहरूको पुनरावर्ती प्रकृतिले प्रशिक्षणलाई ब्याच र समानान्तर बनाउन चुनौतीपूर्ण बनाउँछ। RNN मा अनुक्रमका प्रत्येक तत्वलाई क्रमिक रूपमा प्रशोधन गर्नुपर्छ, जसले गर्दा यसलाई सजिलै समानान्तर बनाउन सकिँदैन।\n",
"\n",
"ध्यान केन्द्रित गर्ने प्रणालीहरूको अपनत्व र यस बाधाले आज हामीले BERT देखि OpenGPT3 सम्म प्रयोग गर्ने उत्कृष्ट ट्रान्सफर्मर मोडेलहरूको सिर्जना गर्‍यो।\n",
"\n",
"## ट्रान्सफर्मर मोडेलहरू\n",
"\n",
"प्रत्येक अघिल्लो भविष्यवाणीको सन्दर्भलाई अर्को मूल्याङ्कन चरणमा अगाडि बढाउने सट्टा, **ट्रान्सफर्मर मोडेलहरू** ले **स्थानगत एन्कोडिङहरू** र ध्यान प्रणाली प्रयोग गरेर दिइएको इनपुटको सन्दर्भलाई प्रदान गरिएको पाठको झ्यालभित्र समेट्छ। तलको छविले कसरी स्थानगत एन्कोडिङहरूले ध्यान प्रणालीसँग मिलेर झ्यालभित्रको सन्दर्भ समेट्न सक्छ भन्ने देखाउँछ।\n",
"\n",
"![ट्रान्सफर्मर मोडेलहरूमा मूल्याङ्कन कसरी गरिन्छ भन्ने देखाउने एनिमेटेड GIF।](../../../../../lessons/5-NLP/18-Transformers/images/transformer-animated-explanation.gif)\n",
"\n",
"किनभने प्रत्येक इनपुट स्थानलाई स्वतन्त्र रूपमा प्रत्येक आउटपुट स्थानमा म्याप गरिन्छ, ट्रान्सफर्मरहरूले RNN हरूको तुलनामा राम्रो समानान्तर गर्न सक्छन्, जसले गर्दा धेरै ठूलो र अभिव्यक्तिपूर्ण भाषा मोडेलहरू सक्षम हुन्छन्। प्रत्येक ध्यान हेडले शब्दहरू बीचका विभिन्न सम्बन्धहरू सिक्न प्रयोग गर्न सकिन्छ, जसले प्राकृतिक भाषा प्रशोधनका कार्यहरू सुधार गर्छ।\n",
"\n",
"**BERT** (Bidirectional Encoder Representations from Transformers) एक धेरै ठूलो बहु-तह ट्रान्सफर्मर नेटवर्क हो, जसमा *BERT-base* का लागि १२ तहहरू र *BERT-large* का लागि २४ तहहरू छन्। मोडेललाई पहिलो पटक ठूलो पाठ डाटाको कर्पस (WikiPedia + पुस्तकहरू) मा असुपरभाइज्ड प्रशिक्षण (वाक्यमा लुकेका शब्दहरूको भविष्यवाणी) प्रयोग गरेर पूर्व-प्रशिक्षण गरिन्छ। पूर्व-प्रशिक्षणको क्रममा मोडेलले महत्त्वपूर्ण स्तरको भाषा बुझाइ प्राप्त गर्छ, जसलाई अन्य डाटासेटहरूसँग फाइन ट्युनिङ गरेर उपयोग गर्न सकिन्छ। यस प्रक्रियालाई **ट्रान्सफर लर्निङ** भनिन्छ।\n",
"\n",
"![http://jalammar.github.io/illustrated-bert/ बाट चित्र](../../../../../translated_images/jalammarBERT-language-modeling-masked-lm.34f113ea5fec4362e39ee4381aab7cad06b5465a0b5f053a0f2aa05fbe14e746.ne.png)\n",
"\n",
"BERT, DistilBERT, BigBird, OpenGPT3 जस्ता ट्रान्सफर्मर आर्किटेक्चरका धेरै भेरिएसनहरू छन्, जसलाई फाइन ट्युन गर्न सकिन्छ। [HuggingFace package](https://github.com/huggingface/) ले यी आर्किटेक्चरहरूलाई PyTorch का साथ प्रशिक्षण गर्नका लागि रिपोजिटरी प्रदान गर्दछ।\n",
"\n",
"## पाठ वर्गीकरणका लागि BERT प्रयोग गर्दै\n",
"\n",
"हेरौं, कसरी हामी पूर्व-प्रशिक्षित BERT मोडेललाई हाम्रो परम्परागत कार्य समाधान गर्न प्रयोग गर्न सक्छौं: अनुक्रम वर्गीकरण। हामी हाम्रो मूल AG News डाटासेट वर्गीकृत गर्नेछौं।\n",
"\n",
"पहिले, HuggingFace लाइब्रेरी र हाम्रो डाटासेट लोड गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"from torchnlp import *\n",
"import transformers\n",
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
"vocab_len = len(vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले प्रि-ट्रेन गरिएको BERT मोडेल प्रयोग गर्ने भएकाले, हामीलाई विशेष टोकनाइजर प्रयोग गर्न आवश्यक हुनेछ। पहिलो चरणमा, हामी प्रि-ट्रेन गरिएको BERT मोडेलसँग सम्बन्धित टोकनाइजर लोड गर्नेछौं।\n",
"\n",
"HuggingFace लाइब्रेरीमा प्रि-ट्रेन गरिएको मोडेलहरूको संग्रह छ, जसलाई तपाईं `from_pretrained` फङ्सनहरूमा तिनीहरूको नामहरू तर्कको रूपमा उल्लेख गरेर सजिलै प्रयोग गर्न सक्नुहुन्छ। मोडेलका लागि आवश्यक सबै बाइनरी फाइलहरू स्वतः डाउनलोड हुनेछ।\n",
"\n",
"तर, केही अवस्थामा तपाईंलाई आफ्नै मोडेलहरू लोड गर्न आवश्यक पर्न सक्छ। यस्तो अवस्थामा, तपाईंले टोकनाइजरका लागि आवश्यक प्यारामिटरहरू, मोडेल प्यारामिटरहरू भएको `config.json` फाइल, बाइनरी वेटहरू लगायतका सबै सम्बन्धित फाइलहरू समावेश भएको डाइरेक्टरी निर्दिष्ट गर्न सक्नुहुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# To load the model from Internet repository using model name. \n",
"# Use this if you are running from your own copy of the notebooks\n",
"bert_model = 'bert-base-uncased' \n",
"\n",
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
"# prepared all required files for you.\n",
"bert_model = './bert'\n",
"\n",
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
"\n",
"MAX_SEQ_LEN = 128\n",
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`tokenizer` वस्तुमा `encode` कार्य हुन्छ जसलाई पाठलाई सिधै एन्कोड गर्न प्रयोग गर्न सकिन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[101, 1052, 22123, 2953, 2818, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer.encode('PyTorch is a great framework for NLP')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"त्यसपछि, प्रशिक्षणको क्रममा डाटा पहुँच गर्न प्रयोग गरिने इटरेटरहरू सिर्जना गरौं। किनभने BERT ले आफ्नो नै कोडिङ्ग फङ्सन प्रयोग गर्दछ, हामीले पहिले परिभाषित गरेको `padify` जस्तै एक padding फङ्सन परिभाषित गर्न आवश्यक हुनेछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def pad_bert(b):\n",
" # b is the list of tuples of length batch_size\n",
" # - first element of a tuple = label, \n",
" # - second = feature (text sequence)\n",
" # build vectorized sequence\n",
" v = [tokenizer.encode(x[1]) for x in b]\n",
" # compute max length of a sequence in this minibatch\n",
" l = max(map(len,v))\n",
" return ( # tuple of two tensors - labels and features\n",
" torch.LongTensor([t[0] for t in b]),\n",
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
" )\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, collate_fn=pad_bert, shuffle=True)\n",
"test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=8, collate_fn=pad_bert)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो अवस्थामा, हामी `bert-base-uncased` नामको प्रि-ट्रेन गरिएको BERT मोडेल प्रयोग गर्नेछौं। `BertForSequenceClassfication` प्याकेज प्रयोग गरेर मोडेल लोड गरौं। यसले सुनिश्चित गर्दछ कि हाम्रो मोडेलसँग पहिले नै वर्गीकरणको लागि आवश्यक आर्किटेक्चर छ, अन्तिम क्लासिफायर सहित। तपाईंले चेतावनी सन्देश देख्नुहुनेछ जसले अन्तिम क्लासिफायरको वजनहरू आरम्भ गरिएको छैन भनेर जनाउँछ, र मोडेललाई प्रि-ट्रेनिङ आवश्यक पर्नेछ - यो पूर्ण रूपमा ठीक छ, किनभने हामीले गर्न लागेको कुरा यही हो!\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Some weights of the model checkpoint at ./bert were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']\n",
"- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
"- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
"Some weights of BertForSequenceClassification were not initialized from the model checkpoint at ./bert and are newly initialized: ['classifier.weight', 'classifier.bias']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
]
}
],
"source": [
"model = transformers.BertForSequenceClassification.from_pretrained(bert_model,num_labels=4).to(device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी प्रशिक्षण सुरु गर्न तयार छौं! किनभने BERT पहिले नै प्रि-ट्रेन गरिएको छ, हामी सुरुवातमा सानो learning rate प्रयोग गर्न चाहन्छौं ताकि प्रारम्भिक weights बिग्रन नजाओस्।\n",
"\n",
"सबै कठिन काम `BertForSequenceClassification` मोडेलले गर्छ। जब हामी प्रशिक्षण डाटामा मोडेललाई कल गर्छौं, यसले इनपुट मिनिब्याचको लागि loss र नेटवर्क आउटपुट दुवै फिर्ता गर्छ। हामी loss लाई parameter optimization को लागि प्रयोग गर्छौं (`loss.backward()` ले backward pass गर्छ), र `out` लाई प्रशिक्षण accuracy गणना गर्न प्रयोग गर्छौं, जुन `argmax` प्रयोग गरेर प्राप्त गरिएको labels `labs` लाई अपेक्षित `labels` सँग तुलना गरेर गणना गरिन्छ।\n",
"\n",
"प्रक्रियालाई नियन्त्रण गर्न, हामी loss र accuracy लाई केही iterations सम्म जम्मा गर्छौं, र प्रत्येक `report_freq` प्रशिक्षण चक्रहरूमा तिनीहरूलाई प्रिन्ट गर्छौं।\n",
"\n",
"यो प्रशिक्षण सम्भवतः धेरै समय लाग्न सक्छ, त्यसैले हामी iterations को संख्या सीमित गर्छौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loss = 1.1254194641113282, Accuracy = 0.585\n",
"Loss = 0.6194715118408203, Accuracy = 0.83\n",
"Loss = 0.46665248870849607, Accuracy = 0.8475\n",
"Loss = 0.4309701919555664, Accuracy = 0.8575\n",
"Loss = 0.35427074432373046, Accuracy = 0.8825\n",
"Loss = 0.3306886291503906, Accuracy = 0.8975\n",
"Loss = 0.30340143203735354, Accuracy = 0.8975\n",
"Loss = 0.26139299392700194, Accuracy = 0.915\n",
"Loss = 0.26708646774291994, Accuracy = 0.9225\n",
"Loss = 0.3667240524291992, Accuracy = 0.8675\n"
]
}
],
"source": [
"optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)\n",
"\n",
"report_freq = 50\n",
"iterations = 500 # make this larger to train for longer time!\n",
"\n",
"model.train()\n",
"\n",
"i,c = 0,0\n",
"acc_loss = 0\n",
"acc_acc = 0\n",
"\n",
"for labels,texts in train_loader:\n",
" labels = labels.to(device)-1 # get labels in the range 0-3 \n",
" texts = texts.to(device)\n",
" loss, out = model(texts, labels=labels)[:2]\n",
" labs = out.argmax(dim=1)\n",
" acc = torch.mean((labs==labels).type(torch.float32))\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" acc_loss += loss\n",
" acc_acc += acc\n",
" i+=1\n",
" c+=1\n",
" if i%report_freq==0:\n",
" print(f\"Loss = {acc_loss.item()/c}, Accuracy = {acc_acc.item()/c}\")\n",
" c = 0\n",
" acc_loss = 0\n",
" acc_acc = 0\n",
" iterations-=1\n",
" if not iterations:\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"तपाईं देख्न सक्नुहुन्छ (विशेष गरी यदि तपाईं पुनरावृत्तिहरूको संख्या बढाउनुहुन्छ र पर्याप्त समय पर्खनुहुन्छ) कि BERT वर्गीकरणले हामीलाई धेरै राम्रो शुद्धता दिन्छ! यसको कारण BERT ले भाषा संरचनालाई पहिले नै राम्रोसँग बुझिसकेको छ, र हामीले अन्तिम वर्गीकरणलाई मात्र सुधार गर्न आवश्यक छ। तर, किनभने BERT ठूलो मोडेल हो, सम्पूर्ण प्रशिक्षण प्रक्रिया लामो समय लिन्छ, र गम्भीर कम्प्युटेशनल शक्ति आवश्यक पर्छ! (GPU, र सम्भवतः एकभन्दा बढी GPU).\n",
"\n",
"> **Note:** हाम्रो उदाहरणमा, हामीले सबैभन्दा सानो प्रि-ट्रेन गरिएको BERT मोडेल प्रयोग गरिरहेका छौं। ठूला मोडेलहरू छन् जसले सम्भवतः अझ राम्रो नतिजा दिन सक्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मोडेलको प्रदर्शन मूल्याङ्कन गर्दै\n",
"\n",
"अब हामी हाम्रो मोडेलको प्रदर्शन परीक्षण डाटासेटमा मूल्याङ्कन गर्न सक्छौं। मूल्याङ्कन लूप प्रशिक्षण लूपसँग धेरै मिल्दोजुल्दो छ, तर हामीले `model.eval()` कल गरेर मोडेललाई मूल्याङ्कन मोडमा स्विच गर्न बिर्सनु हुँदैन।\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Final accuracy: 0.9047029702970297\n"
]
}
],
"source": [
"model.eval()\n",
"iterations = 100\n",
"acc = 0\n",
"i = 0\n",
"for labels,texts in test_loader:\n",
" labels = labels.to(device)-1 \n",
" texts = texts.to(device)\n",
" _, out = model(texts, labels=labels)[:2]\n",
" labs = out.argmax(dim=1)\n",
" acc += torch.mean((labs==labels).type(torch.float32))\n",
" i+=1\n",
" if i>iterations: break\n",
" \n",
"print(f\"Final accuracy: {acc.item()/i}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य कुरा\n",
"\n",
"यस युनिटमा, हामीले **transformers** पुस्तकालयबाट प्रि-ट्रेन गरिएको भाषा मोडेल लिनु र यसलाई हाम्रो पाठ वर्गीकरण कार्यमा अनुकूलन गर्नु कति सजिलो छ भन्ने देख्यौं। यसैगरी, BERT मोडेलहरूलाई इकाई निकासी, प्रश्न उत्तर, र अन्य NLP कार्यहरूको लागि प्रयोग गर्न सकिन्छ।\n",
"\n",
"Transformer मोडेलहरू NLP मा हालको अत्याधुनिक प्रविधिको प्रतिनिधित्व गर्छन्, र प्रायः अवस्थामा, जब तपाईं अनुकूल NLP समाधानहरू कार्यान्वयन गर्न थाल्नुहुन्छ, यो पहिलो समाधान हुनुपर्छ जससँग तपाईंले प्रयोग गर्न सुरु गर्नुहुन्छ। तर, यदि तपाईं उन्नत न्यूरल मोडेलहरू निर्माण गर्न चाहनुहुन्छ भने, यस मोड्युलमा छलफल गरिएका पुनरावर्ती न्यूरल नेटवर्कहरूको आधारभूत सिद्धान्तहरू बुझ्नु अत्यन्त महत्त्वपूर्ण छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटि वा अशुद्धि हुन सक्छ। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्त्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न कुनै पनि गलतफहमी वा गलत व्याख्याका लागि हामी जिम्मेवार हुने छैनौं।\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py37_pytorch",
"language": "python",
"name": "conda-env-py37_pytorch-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.7"
},
"coopTranslator": {
"original_hash": "753865967678a92dbce7d7efbd36d980",
"translation_date": "2025-08-28T09:23:47+00:00",
"source_file": "lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,819 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ध्यान मेकानिज्म र ट्रान्सफर्मरहरू\n",
"\n",
"पुनरावर्ती नेटवर्कहरूको एक प्रमुख कमजोरी यो हो कि अनुक्रमका सबै शब्दहरूले नतिजामा समान प्रभाव पार्छन्। यसले नामित इकाई पहिचान र मेसिन अनुवाद जस्ता अनुक्रम-देखि-अनुक्रम कार्यहरूको लागि मानक LSTM एन्कोडर-डिकोडर मोडेलहरूसँग उपयुक्त प्रदर्शन प्रदान गर्दैन। वास्तविकतामा, इनपुट अनुक्रमका केही विशेष शब्दहरूले अन्य शब्दहरूको तुलनामा अनुक्रमिक आउटपुटमा बढी प्रभाव पार्छन्।\n",
"\n",
"मेसिन अनुवाद जस्ता अनुक्रम-देखि-अनुक्रम मोडेललाई विचार गर्नुहोस्। यो दुई पुनरावर्ती नेटवर्कहरूद्वारा कार्यान्वयन गरिन्छ, जहाँ एउटा नेटवर्क (**एन्कोडर**) इनपुट अनुक्रमलाई लुकेको अवस्थामा सङ्कुचित गर्छ, र अर्को नेटवर्क (**डिकोडर**) यस लुकेको अवस्थालाई अनुवादित नतिजामा विस्तार गर्छ। यस दृष्टिकोणको समस्या यो हो कि नेटवर्कको अन्तिम अवस्थाले वाक्यको सुरुवात सम्झन गाह्रो मान्छ, जसले गर्दा लामो वाक्यहरूमा मोडेलको गुणस्तर कमजोर हुन्छ।\n",
"\n",
"**ध्यान मेकानिज्महरू** RNN को प्रत्येक आउटपुट भविष्यवाणीमा प्रत्येक इनपुट भेक्टरको सन्दर्भात्मक प्रभावलाई तौल दिने माध्यम प्रदान गर्छन्। यसलाई कार्यान्वयन गर्ने तरिका भनेको इनपुट RNN का मध्यवर्ती अवस्थाहरू र आउटपुट RNN बीच छोटो मार्गहरू सिर्जना गर्नु हो। यसरी, आउटपुट प्रतीक $y_t$ उत्पन्न गर्दा, हामी सबै इनपुट लुकेका अवस्थाहरू $h_i$ लाई विभिन्न तौल गुणांक $\\alpha_{t,i}$ का साथ विचार गर्नेछौं।\n",
"\n",
"![एन्कोडर/डिकोडर मोडेलमा एडिटिभ ध्यान तह देखाउने छवि](../../../../../translated_images/encoder-decoder-attention.7a726296894fb567aa2898c94b17b3289087f6705c11907df8301df9e5eeb3de.ne.png)\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) मा एडिटिभ ध्यान मेकानिज्म भएको एन्कोडर-डिकोडर मोडेल, [यो ब्लग पोस्ट](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) बाट उद्धृत]*\n",
"\n",
"ध्यान म्याट्रिक्स $\\{\\alpha_{i,j}\\}$ ले इनपुटका निश्चित शब्दहरूले आउटपुट अनुक्रमको कुनै शब्द उत्पन्न गर्न कत्तिको भूमिका खेल्छन् भन्ने प्रतिनिधित्व गर्दछ। तल यस्तो म्याट्रिक्सको उदाहरण दिइएको छ:\n",
"\n",
"![RNNsearch-50 द्वारा फेला परेको नमूना एलाइनमेन्ट देखाउने छवि, Bahdanau - arviz.org बाट लिइएको](../../../../../translated_images/bahdanau-fig3.09ba2d37f202a6af11de6c82d2d197830ba5f4528d9ea430eb65fd3a75065973.ne.png)\n",
"\n",
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) बाट लिइएको चित्र (Fig.3)*\n",
"\n",
"ध्यान मेकानिज्महरू प्राकृतिक भाषा प्रशोधनमा हालको वा निकट भविष्यको उत्कृष्ट अवस्थाको लागि जिम्मेवार छन्। ध्यान थप्दा मोडेल प्यारामिटरहरूको संख्या धेरै बढ्छ, जसले गर्दा RNN हरूसँग स्केलिङ समस्याहरू देखा पर्छ। RNN हरूको स्केलिङको प्रमुख बाधा भनेको मोडेलहरूको पुनरावर्ती प्रकृतिले प्रशिक्षणलाई ब्याच र समानान्तर बनाउन चुनौतीपूर्ण बनाउँछ। RNN मा अनुक्रमका प्रत्येक तत्वलाई क्रमिक रूपमा प्रशोधन गर्नुपर्छ, जसले गर्दा यसलाई सजिलै समानान्तर बनाउन सकिँदैन।\n",
"\n",
"ध्यान मेकानिज्महरूको अपनत्व र यस बाधाले आज हामीले BERT देखि OpenGPT3 सम्म प्रयोग गर्ने उत्कृष्ट ट्रान्सफर्मर मोडेलहरूको सिर्जनालाई जन्म दियो।\n",
"\n",
"## ट्रान्सफर्मर मोडेलहरू\n",
"\n",
"प्रत्येक अघिल्लो भविष्यवाणीको सन्दर्भलाई अर्को मूल्याङ्कन चरणमा अगाडि बढाउने सट्टा, **ट्रान्सफर्मर मोडेलहरू** ले **पोजिसनल इन्कोडिङहरू** र **ध्यान** प्रयोग गरेर दिइएको इनपुटको सन्दर्भलाई प्रदान गरिएको पाठको झ्यालभित्र समेट्छन्। तलको छविले पोजिसनल इन्कोडिङहरू र ध्यानले कसरी झ्यालभित्रको सन्दर्भ समेट्न सक्छ भन्ने देखाउँछ।\n",
"\n",
"![ट्रान्सफर्मर मोडेलहरूमा मूल्याङ्कनहरू कसरी गरिन्छ भन्ने देखाउने एनिमेटेड GIF।](../../../../../lessons/5-NLP/18-Transformers/images/transformer-animated-explanation.gif)\n",
"\n",
"किनभने प्रत्येक इनपुट स्थितिलाई स्वतन्त्र रूपमा प्रत्येक आउटपुट स्थितिमा म्याप गरिन्छ, ट्रान्सफर्मरहरूले RNN हरूको तुलनामा राम्रो समानान्तर गर्न सक्छन्, जसले गर्दा धेरै ठूलो र अझ अभिव्यक्तिपूर्ण भाषा मोडेलहरू सक्षम बनाउँछ। प्रत्येक ध्यान हेडले शब्दहरू बीचका विभिन्न सम्बन्धहरू सिक्न प्रयोग गर्न सकिन्छ, जसले प्राकृतिक भाषा प्रशोधनका कार्यहरूमा सुधार ल्याउँछ।\n",
"\n",
"## साधारण ट्रान्सफर्मर मोडेल निर्माण\n",
"\n",
"Keras मा बिल्ट-इन ट्रान्सफर्मर तह समावेश छैन, तर हामी आफैं बनाउन सक्छौं। पहिलेझैं, हामी AG News डेटासेटको पाठ वर्गीकरणमा केन्द्रित हुनेछौं, तर यो उल्लेख गर्न लायक छ कि ट्रान्सफर्मर मोडेलहरूले अझ कठिन NLP कार्यहरूमा उत्कृष्ट नतिजा देखाउँछन्।\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()\n",
"\n",
"def extract_text(x):\n",
" return x['title']+' '+x['description']\n",
"\n",
"def tupelize(x):\n",
" return (extract_text(x),x['label'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Keras मा नयाँ लेयरहरूले `Layer` वर्गलाई सबक्लास गर्नुपर्छ, र `call` मेथड कार्यान्वयन गर्नुपर्छ। सुरु गरौं **Positional Embedding** लेयरबाट। हामी [Keras को आधिकारिक डकुमेन्टेसनबाट केही कोड](https://keras.io/examples/nlp/text_classification_with_transformer/) प्रयोग गर्नेछौं। हामीले सबै इनपुट सिक्वेन्सहरूलाई `maxlen` लम्बाइमा प्याड गर्नेछौं भन्ने मान्नेछौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class TokenAndPositionEmbedding(keras.layers.Layer):\n",
" def __init__(self, maxlen, vocab_size, embed_dim):\n",
" super(TokenAndPositionEmbedding, self).__init__()\n",
" self.token_emb = keras.layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)\n",
" self.pos_emb = keras.layers.Embedding(input_dim=maxlen, output_dim=embed_dim)\n",
" self.maxlen = maxlen\n",
"\n",
" def call(self, x):\n",
" maxlen = self.maxlen\n",
" positions = tf.range(start=0, limit=maxlen, delta=1)\n",
" positions = self.pos_emb(positions)\n",
" x = self.token_emb(x)\n",
" return x+positions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यो तह दुईवटा `Embedding` तहहरूबाट बनेको छ: टोकनहरूलाई एम्बेड गर्न (जसरी हामीले पहिले चर्चा गरिसकेका छौं) र टोकनको स्थानहरूलाई एम्बेड गर्न। टोकन स्थानहरू `tf.range` प्रयोग गरेर 0 देखि `maxlen` सम्मको प्राकृतिक संख्याहरूको क्रमको रूपमा सिर्जना गरिन्छ, र त्यसपछि एम्बेडिङ तहमा पठाइन्छ। दुईवटा परिणामस्वरूप प्राप्त एम्बेडिङ भेक्टरहरूलाई जोडिन्छ, जसले इनपुटको स्थानगत-एम्बेड गरिएको प्रतिनिधित्व उत्पादन गर्दछ, जसको आकार `maxlen`$\\times$`embed_dim` हुन्छ।\n",
"\n",
"अब, हामी ट्रान्सफर्मर ब्लक कार्यान्वयन गरौं। यसले पहिले परिभाषित गरिएको एम्बेडिङ तहको आउटपुटलाई लिनेछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"class TransformerBlock(keras.layers.Layer):\n",
" def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):\n",
" super(TransformerBlock, self).__init__()\n",
" self.att = keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim, name='attn')\n",
" self.ffn = keras.Sequential(\n",
" [keras.layers.Dense(ff_dim, activation=\"relu\"), keras.layers.Dense(embed_dim),]\n",
" )\n",
" self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
" self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
" self.dropout1 = keras.layers.Dropout(rate)\n",
" self.dropout2 = keras.layers.Dropout(rate)\n",
"\n",
" def call(self, inputs, training):\n",
" attn_output = self.att(inputs, inputs)\n",
" attn_output = self.dropout1(attn_output, training=training)\n",
" out1 = self.layernorm1(inputs + attn_output)\n",
" ffn_output = self.ffn(out1)\n",
" ffn_output = self.dropout2(ffn_output, training=training)\n",
" return self.layernorm2(out1 + ffn_output)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब, हामी पूर्ण ट्रान्सफर्मर मोडेल परिभाषित गर्न तयार छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"text_vectorization (TextVect (None, 256) 0 \n",
"_________________________________________________________________\n",
"token_and_position_embedding (None, 256, 32) 648192 \n",
"_________________________________________________________________\n",
"transformer_block (Transform (None, 256, 32) 10656 \n",
"_________________________________________________________________\n",
"global_average_pooling1d (Gl (None, 32) 0 \n",
"_________________________________________________________________\n",
"dropout_2 (Dropout) (None, 32) 0 \n",
"_________________________________________________________________\n",
"dense_2 (Dense) (None, 20) 660 \n",
"_________________________________________________________________\n",
"dropout_3 (Dropout) (None, 20) 0 \n",
"_________________________________________________________________\n",
"dense_3 (Dense) (None, 4) 84 \n",
"=================================================================\n",
"Total params: 659,592\n",
"Trainable params: 659,592\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"embed_dim = 32 # Embedding size for each token\n",
"num_heads = 2 # Number of attention heads\n",
"ff_dim = 32 # Hidden layer size in feed forward network inside transformer\n",
"maxlen = 256\n",
"vocab_size = 20000\n",
"\n",
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_sequence_length=maxlen, input_shape=(1,)),\n",
" TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim),\n",
" TransformerBlock(embed_dim, num_heads, ff_dim),\n",
" keras.layers.GlobalAveragePooling1D(),\n",
" keras.layers.Dropout(0.1),\n",
" keras.layers.Dense(20, activation=\"relu\"),\n",
" keras.layers.Dropout(0.1),\n",
" keras.layers.Dense(4, activation=\"softmax\")\n",
"])\n",
"\n",
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training tokenizer\n",
"938/938 [==============================] - 45s 39ms/step - loss: 0.4978 - acc: 0.8068 - val_loss: 0.2808 - val_acc: 0.9124\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9c2427a0d0>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"print('Training tokenizer')\n",
"model.layers[0].adapt(ds_train.map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## BERT ट्रान्सफर्मर मोडेलहरू\n",
"\n",
"**BERT** (Bidirectional Encoder Representations from Transformers) एक धेरै ठूलो बहु-स्तरीय ट्रान्सफर्मर नेटवर्क हो जसमा *BERT-base* का लागि १२ तहहरू र *BERT-large* का लागि २४ तहहरू छन्। यो मोडेललाई पहिलो चरणमा ठूलो पाठ डाटाको संग्रह (WikiPedia + किताबहरू) मा असुपरभाइज्ड तालिम (वाक्यमा लुकेका शब्दहरूको भविष्यवाणी गर्दै) प्रयोग गरेर प्रि-ट्रेन गरिन्छ। प्रि-ट्रेनिङको क्रममा मोडेलले भाषाको गहिरो समझ हासिल गर्छ, जसलाई अन्य डाटासेटहरूसँग फाइन ट्युनिङ गरेर उपयोग गर्न सकिन्छ। यस प्रक्रियालाई **ट्रान्सफर लर्निङ** भनिन्छ।\n",
"\n",
"![picture from http://jalammar.github.io/illustrated-bert/](../../../../../translated_images/jalammarBERT-language-modeling-masked-lm.34f113ea5fec4362e39ee4381aab7cad06b5465a0b5f053a0f2aa05fbe14e746.ne.png)\n",
"\n",
"BERT, DistilBERT, BigBird, OpenGPT3 लगायतका ट्रान्सफर्मर आर्किटेक्चरका धेरै भेरिएसनहरू छन् जसलाई फाइन ट्युन गर्न सकिन्छ।\n",
"\n",
"अब हामी प्रि-ट्रेन गरिएको BERT मोडेललाई हाम्रो परम्परागत क्रम वर्गीकरण समस्याको समाधानका लागि कसरी प्रयोग गर्न सकिन्छ भन्ने कुरा हेर्नेछौं। हामी [official documentation](https://www.tensorflow.org/text/tutorials/classify_text_with_bert) बाट केही विचार र कोड लिनेछौं।\n",
"\n",
"प्रि-ट्रेन गरिएको मोडेलहरू लोड गर्नका लागि, हामी **Tensorflow hub** प्रयोग गर्नेछौं। पहिलो चरणमा, BERT-विशेष भेक्टराइजर लोड गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"ename": "ModuleNotFoundError",
"evalue": "No module named 'tensorflow_text'",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_41180/4216669875.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_text\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_hub\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mvectorizer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mKerasLayer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'tensorflow_text'"
]
}
],
"source": [
"import tensorflow_text \n",
"import tensorflow_hub as hub\n",
"vectorizer = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'input_type_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
" dtype=int32)>,\n",
" 'input_word_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[ 101, 1045, 2293, 19081, 102, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0]], dtype=int32)>,\n",
" 'input_mask': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
" array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
" dtype=int32)>}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer(['I love transformers'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यो महत्त्वपूर्ण छ कि तपाईले त्यही भेक्टराइजर प्रयोग गर्नुहोस् जुन मूल नेटवर्कलाई तालिम दिन प्रयोग गरिएको थियो। साथै, BERT भेक्टराइजरले तीनवटा कम्पोनेन्टहरू फिर्ता गर्छ:\n",
"* `input_word_ids`, जुन इनपुट वाक्यको लागि टोकन नम्बरहरूको क्रम हो\n",
"* `input_mask`, जसले क्रमको कुन भाग वास्तविक इनपुट हो र कुन भाग प्याडिङ हो भनेर देखाउँछ। यो `Masking` तहले उत्पादन गर्ने मास्कसँग मिल्दोजुल्दो छ\n",
"* `input_type_ids` भाषा मोडलिङ कार्यहरूको लागि प्रयोग गरिन्छ, र एउटै क्रममा दुईवटा इनपुट वाक्यहरू निर्दिष्ट गर्न अनुमति दिन्छ।\n",
"\n",
"त्यसपछि, हामी BERT फिचर एक्स्ट्र्याक्टरलाई इनस्ट्यान्सियेट गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"bert = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-128_A-2/1')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pooled_output -> (1, 128)\n",
"encoder_outputs -> 4\n",
"sequence_output -> (1, 128, 128)\n",
"default -> (1, 128)\n"
]
}
],
"source": [
"z = bert(vectorizer(['I love transformers']))\n",
"for i,x in z.items():\n",
" print(f\"{i} -> { len(x) if isinstance(x, list) else x.shape }\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"त्यसैले, BERT लेयरले केही उपयोगी नतिजाहरू फर्काउँछ:\n",
"* `pooled_output` अनुक्रममा सबै टोकनहरूको औसत निकाल्ने परिणाम हो। यसलाई सम्पूर्ण नेटवर्कको बौद्धिक अर्थपूर्ण एम्बेडिङको रूपमा हेर्न सकिन्छ। यो हाम्रो अघिल्लो मोडेलमा `GlobalAveragePooling1D` लेयरको आउटपुटसँग समान छ।\n",
"* `sequence_output` अन्तिम ट्रान्सफर्मर लेयरको आउटपुट हो (यो माथिको मोडेलमा `TransformerBlock` को आउटपुटसँग मेल खान्छ)।\n",
"* `encoder_outputs` सबै ट्रान्सफर्मर लेयरहरूको आउटपुटहरू हुन्। किनकि हामीले 4-लेयर BERT मोडेल लोड गरेका छौं (जसको नाममा `4_H` समावेश छ भन्ने कुराबाट तपाईं अनुमान गर्न सक्नुहुन्छ), यसमा 4 टेन्सरहरू छन्। अन्तिम टेन्सर `sequence_output` जस्तै हो।\n",
"\n",
"अब हामी अन्त्य-देखि-अन्त्य वर्गीकरण मोडेल परिभाषित गर्नेछौं। हामी *functional model definition* प्रयोग गर्नेछौं, जहाँ हामी मोडेल इनपुट परिभाषित गर्छौं, र त्यसपछि यसको आउटपुट गणना गर्न अभिव्यक्तिहरूको श्रृंखला प्रदान गर्छौं। हामी BERT मोडेलको वजनहरूलाई non-trainable बनाउनेछौं, र केवल अन्तिम वर्गीकरणकर्ता मात्र प्रशिक्षण गर्नेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"__________________________________________________________________________________________________\n",
"Layer (type) Output Shape Param # Connected to \n",
"==================================================================================================\n",
"input_1 (InputLayer) [(None,)] 0 \n",
"__________________________________________________________________________________________________\n",
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
"__________________________________________________________________________________________________\n",
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
" keras_layer[0][1] \n",
" keras_layer[0][2] \n",
"__________________________________________________________________________________________________\n",
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
"__________________________________________________________________________________________________\n",
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
"==================================================================================================\n",
"Total params: 4,782,981\n",
"Trainable params: 516\n",
"Non-trainable params: 4,782,465\n",
"__________________________________________________________________________________________________\n"
]
}
],
"source": [
"inp = keras.Input(shape=(),dtype=tf.string)\n",
"x = vectorizer(inp)\n",
"x = bert(x)\n",
"x = keras.layers.Dropout(0.1)(x['pooled_output'])\n",
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
"model = keras.models.Model(inp,out)\n",
"bert.trainable = False\n",
"model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 528s 559ms/step - loss: 0.8056 - acc: 0.6983 - val_loss: 0.5953 - val_acc: 0.7888\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9bb1e36d00>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यद्यपि थोरै ट्रेन गर्न सकिने प्यारामिटरहरू छन्, प्रक्रिया निकै ढिलो छ, किनकि BERT फिचर एक्स्ट्र्याक्टर कम्प्युटेशनल रूपमा भारी छ। यस्तो देखिन्छ कि हामीले उचित शुद्धता प्राप्त गर्न सकेनौं, या त ट्रेनिङको कमीका कारण, या मोडेल प्यारामिटरहरूको अभावका कारण।\n",
"\n",
"अब BERT को वजनहरू अनफ्रिज गरेर यसलाई पनि ट्रेन गर्ने प्रयास गरौं। यसका लागि धेरै सानो लर्निङ रेट आवश्यक छ, साथै **warmup** सहितको अधिक सावधानीपूर्वक ट्रेनिङ रणनीति चाहिन्छ, **AdamW** अप्टिमाइजर प्रयोग गरेर। हामी `tf-models-official` प्याकेज प्रयोग गरेर अप्टिमाइजर बनाउनेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"__________________________________________________________________________________________________\n",
"Layer (type) Output Shape Param # Connected to \n",
"==================================================================================================\n",
"input_1 (InputLayer) [(None,)] 0 \n",
"__________________________________________________________________________________________________\n",
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
"__________________________________________________________________________________________________\n",
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
" keras_layer[0][1] \n",
" keras_layer[0][2] \n",
"__________________________________________________________________________________________________\n",
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
"__________________________________________________________________________________________________\n",
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
"==================================================================================================\n",
"Total params: 4,782,981\n",
"Trainable params: 4,782,980\n",
"Non-trainable params: 1\n",
"__________________________________________________________________________________________________\n",
"938/938 [==============================] - 629s 664ms/step - loss: 0.6344 - acc: 0.7658 - val_loss: 0.4876 - val_acc: 0.8247\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f9bb0bd0070>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from official.nlp import optimization \n",
"bert.trainable=True\n",
"model.summary()\n",
"epochs = 3\n",
"opt = optimization.create_optimizer(\n",
" init_lr=3e-5,\n",
" num_train_steps=epochs*len(ds_train),\n",
" num_warmup_steps=0.1*epochs*len(ds_train),\n",
" optimizer_type='adamw')\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer=opt)\n",
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जसरी तपाईंले देख्न सक्नुहुन्छ, प्रशिक्षण प्रक्रिया अलि ढिलो हुन्छ - तर तपाईंले केही इपोक्स (५-१०) को लागि मोडेललाई प्रशिक्षण गरेर पहिले प्रयोग गरिएका तरिकाहरूसँग तुलना गर्दै उत्कृष्ट नतिजा प्राप्त गर्न प्रयास गर्न सक्नुहुन्छ।\n",
"\n",
"## Huggingface Transformers पुस्तकालय\n",
"\n",
"Transformer मोडेलहरू प्रयोग गर्ने अर्को धेरै सामान्य (र अलि सरल) तरिका [HuggingFace प्याकेज](https://github.com/huggingface/) हो, जसले विभिन्न NLP कार्यहरूको लागि सरल निर्माण ब्लकहरू प्रदान गर्दछ। यो Tensorflow र PyTorch दुबैका लागि उपलब्ध छ, जुन अर्को धेरै लोकप्रिय न्यूरल नेटवर्क फ्रेमवर्क हो।\n",
"\n",
"> **Note**: यदि तपाईंलाई Transformers पुस्तकालय कसरी काम गर्छ भनेर हेर्नमा चासो छैन भने - तपाईं यो नोटबुकको अन्त्यसम्म जान सक्नुहुन्छ, किनभने यहाँ माथि गरिएका कुराहरूभन्दा धेरै फरक केही देखिने छैन। हामी BERT मोडेललाई फरक पुस्तकालय र धेरै ठूलो मोडेल प्रयोग गरेर प्रशिक्षण गर्ने उही चरणहरू दोहोर्याउनेछौं। त्यसैले, यो प्रक्रियामा केही लामो प्रशिक्षण समावेश हुन्छ, त्यसैले तपाईंले केवल कोड हेर्न चाहन सक्नुहुन्छ।\n",
"\n",
"हेरौं, हाम्रो समस्या [Huggingface Transformers](http://huggingface.co) प्रयोग गरेर कसरी समाधान गर्न सकिन्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"पहिलो कुरा हामीले गर्ने भनेको प्रयोग गर्न चाहेको मोडेल चयन गर्नु हो। केही बिल्ट-इन मोडेलहरूका अतिरिक्त, Huggingface मा [अनलाइन मोडेल रिपोजिटरी](https://huggingface.co/models) उपलब्ध छ, जहाँ तपाईं समुदायद्वारा बनाइएका धेरै प्रि-ट्रेन गरिएको मोडेलहरू फेला पार्न सक्नुहुन्छ। ती सबै मोडेलहरू केवल मोडेलको नाम प्रदान गरेर लोड र प्रयोग गर्न सकिन्छ। मोडेलका लागि आवश्यक सबै बाइनरी फाइलहरू स्वचालित रूपमा डाउनलोड हुनेछन्।\n",
"\n",
"कहिलेकाहीँ तपाईंलाई आफ्नै मोडेलहरू लोड गर्न आवश्यक पर्न सक्छ, यस्तो अवस्थामा तपाईंले सबै सम्बन्धित फाइलहरू समावेश भएको डाइरेक्टरी निर्दिष्ट गर्न सक्नुहुन्छ, जसमा टोकनाइजरका लागि प्यारामिटरहरू, `config.json` फाइलमा मोडेलका प्यारामिटरहरू, बाइनरी वेटहरू आदि समावेश हुन्छन्।\n",
"\n",
"मोडेलको नामबाट, हामी मोडेल र टोकनाइजर दुवैलाई इनिसियलाइज गर्न सक्छौं। टोकनाइजरबाट सुरु गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import transformers\n",
"\n",
"# To load the model from Internet repository using model name. \n",
"# Use this if you are running from your own copy of the notebooks\n",
"bert_model = 'bert-base-uncased' \n",
"\n",
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
"# prepared all required files for you.\n",
"#bert_model = './bert'\n",
"\n",
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
"\n",
"MAX_SEQ_LEN = 128\n",
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`tokenizer` वस्तुमा `encode` कार्य हुन्छ जसलाई पाठलाई सिधै एन्कोड गर्न प्रयोग गर्न सकिन्छ:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[101, 23435, 12314, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer.encode('Tensorflow is a great framework for NLP')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामी टोकनाइजरलाई अनुक्रमलाई मोडेलमा पास गर्न उपयुक्त तरिकामा एन्कोड गर्न प्रयोग गर्न सक्छौं, जस्तै `token_ids`, `input_mask` क्षेत्रहरू समावेश गरेर। हामीले `return_tensors='tf'` तर्क प्रदान गरेर Tensorflow टेन्सरहरू चाहन्छौं भनेर पनि निर्दिष्ट गर्न सक्छौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'input_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[ 101, 7592, 1010, 2045, 102]], dtype=int32)>, 'token_type_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[0, 0, 0, 0, 0]], dtype=int32)>, 'attention_mask': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[1, 1, 1, 1, 1]], dtype=int32)>}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer(['Hello, there'],return_tensors='tf')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो अवस्थामा, हामीले `bert-base-uncased` नामक प्रि-ट्रेन गरिएको BERT मोडेल प्रयोग गर्नेछौं। *Uncased* ले मोडेल केस-इन्सेन्सिटिभ (अक्षरको ठूला-साना फरक नमान्ने) भएको जनाउँछ।\n",
"\n",
"मोडेललाई प्रशिक्षण गर्दा, हामीले टोकनाइज गरिएको अनुक्रम इनपुटको रूपमा प्रदान गर्नुपर्छ, त्यसैले हामी डाटा प्रशोधन पाइपलाइन डिजाइन गर्नेछौं। किनभने `tokenizer.encode` एउटा Python फङ्सन हो, हामी यसलाई अघिल्लो युनिटमा जस्तै `py_function` प्रयोग गरेर कल गर्ने समान तरिका अपनाउनेछौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"def process(x):\n",
" return tokenizer.encode(x.numpy().decode('utf-8'),return_tensors='tf',padding='max_length',max_length=MAX_SEQ_LEN,truncation=True)[0]\n",
"\n",
"def process_fn(x):\n",
" s = x['title']+' '+x['description']\n",
" e = tf.py_function(process,inp=[s],Tout=(tf.int32))\n",
" e.set_shape(MAX_SEQ_LEN)\n",
" return e,x['label']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी `BertForSequenceClassification` प्याकेज प्रयोग गरेर वास्तविक मोडेल लोड गर्न सक्छौं। यसले सुनिश्चित गर्दछ कि हाम्रो मोडेलसँग वर्गीकरणको लागि आवश्यक आर्किटेक्चर पहिले नै छ, अन्तिम वर्गीकरणकर्ता सहित। तपाईंले चेतावनी सन्देश देख्नुहुनेछ जसले अन्तिम वर्गीकरणकर्ताका तौलहरू आरम्भ गरिएको छैन भनी जनाउँछ, र मोडेललाई पूर्व-प्रशिक्षण आवश्यक पर्छ - यो पूर्ण रूपमा ठीक छ, किनभने हामीले गर्न लागेको कुरा यही हो!\n"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"model = transformers.TFBertForSequenceClassification.from_pretrained(bert_model,num_labels=4,output_attentions=False)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"tf_bert_for_sequence_classification_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"bert (TFBertMainLayer) multiple 109482240 \n",
"_________________________________________________________________\n",
"dropout_75 (Dropout) multiple 0 \n",
"_________________________________________________________________\n",
"classifier (Dense) multiple 3076 \n",
"=================================================================\n",
"Total params: 109,485,316\n",
"Trainable params: 109,485,316\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"जस्तो कि तपाईंले `summary()` बाट देख्न सक्नुहुन्छ, मोडेलमा लगभग ११० मिलियन प्यारामिटरहरू छन्! सम्भवतः, यदि हामी सानो डेटासेटमा साधारण वर्गीकरण कार्य चाहन्छौं भने, हामी BERT बेस लेयरलाई प्रशिक्षण गर्न चाहँदैनौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"tf_bert_for_sequence_classification_1\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"bert (TFBertMainLayer) multiple 109482240 \n",
"_________________________________________________________________\n",
"dropout_75 (Dropout) multiple 0 \n",
"_________________________________________________________________\n",
"classifier (Dense) multiple 3076 \n",
"=================================================================\n",
"Total params: 109,485,316\n",
"Trainable params: 3,076\n",
"Non-trainable params: 109,482,240\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.layers[0].trainable = False\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामी प्रशिक्षण सुरु गर्न तयार छौं!\n",
"\n",
"> **Note**: पूर्ण-स्तरको BERT मोडेल प्रशिक्षण गर्न धेरै समय लाग्न सक्छ! त्यसैले हामी यसलाई पहिलो ३२ ब्याचहरूका लागि मात्र प्रशिक्षण गर्नेछौं। यो केवल मोडेल प्रशिक्षण कसरी सेटअप गरिन्छ भन्ने देखाउनको लागि हो। यदि तपाईं पूर्ण-स्तरको प्रशिक्षण प्रयास गर्न इच्छुक हुनुहुन्छ भने - `steps_per_epoch` र `validation_steps` प्यारामिटरहरू हटाउनुहोस्, र प्रतीक्षा गर्न तयार हुनुहोस्!\n"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32/32 [==============================] - 142s 4s/step - loss: 1.3896 - acc: 0.2500 - val_loss: 1.3863 - val_acc: 0.2480\n"
]
},
{
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7f1d40a4b6a0>"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.compile('adam','sparse_categorical_crossentropy',['acc'])\n",
"tf.get_logger().setLevel('ERROR')\n",
"model.fit(ds_train.map(process_fn).batch(32),validation_data=ds_test.map(process_fn).batch(32),steps_per_epoch=32,validation_steps=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"यदि तपाईं iterations को संख्या बढाउनुहुन्छ, पर्याप्त समय पर्खनुहुन्छ, र धेरै epochs को लागि प्रशिक्षण गर्नुहुन्छ भने, तपाईं अपेक्षा गर्न सक्नुहुन्छ कि BERT वर्गीकरणले हामीलाई सबैभन्दा राम्रो accuracy दिन्छ! यसको कारण BERT ले पहिले नै भाषाको संरचना राम्रोसँग बुझिसकेको छ, र हामीलाई केवल अन्तिम classifier लाई fine-tune गर्न आवश्यक छ। तर, किनभने BERT ठूलो मोडेल हो, सम्पूर्ण प्रशिक्षण प्रक्रिया लामो समय लाग्छ, र गम्भीर computational शक्ति आवश्यक पर्छ! (GPU, र सम्भवतः एकभन्दा बढी GPU).\n",
"\n",
"> **Note:** हाम्रो उदाहरणमा, हामीले सबैभन्दा सानो pre-trained BERT मोडेलमध्ये एक प्रयोग गरिरहेका छौं। ठूला मोडेलहरू छन् जसले सम्भवतः अझ राम्रो नतिजा दिन सक्छ।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य कुरा\n",
"\n",
"यस इकाईमा, हामीले **ट्रान्सफर्मरहरू** मा आधारित धेरै हालसालैका मोडल आर्किटेक्चरहरू हेरेका छौं। हामीले तिनीहरूलाई हाम्रो पाठ वर्गीकरण कार्यका लागि प्रयोग गरेका छौं, तर त्यस्तै गरी, BERT मोडलहरूलाई इकाई निकाल्ने, प्रश्न उत्तर दिने, र अन्य NLP कार्यहरूको लागि पनि प्रयोग गर्न सकिन्छ।\n",
"\n",
"ट्रान्सफर्मर मोडलहरू NLP मा हालको अत्याधुनिक प्रविधि प्रतिनिधित्व गर्छन्, र प्रायः अवस्थामा, जब तपाईंले अनुकूल NLP समाधानहरू कार्यान्वयन गर्न थाल्नुहुन्छ, यो पहिलो समाधान हुनुपर्छ जससँग तपाईंले प्रयोग गर्न थाल्नुहुन्छ। तर, यदि तपाईं उन्नत न्यूरल मोडलहरू निर्माण गर्न चाहनुहुन्छ भने, यस मोड्युलमा छलफल गरिएका पुनरावर्ती न्यूरल नेटवर्कहरूको आधारभूत सिद्धान्तहरू बुझ्नु अत्यन्त महत्त्वपूर्ण छ।\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"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"
},
"kernelspec": {
"display_name": "py38_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"
},
"coopTranslator": {
"original_hash": "ab59c532409774988ab875f2260e8e53",
"translation_date": "2025-08-28T09:28:07+00:00",
"source_file": "lessons/5-NLP/18-Transformers/TransformersTF.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,490 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# नामित इकाई मान्यता (NER)\n",
"\n",
"यो नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) बाट लिइएको हो।\n",
"\n",
"यस उदाहरणमा, हामी [Annotated Corpus for Named Entity Recognition](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus) डाटासेटमा आधारित NER मोडेल कसरी प्रशिक्षण गर्ने भनेर सिक्नेछौं। अघि बढ्नु अघि, कृपया [ner_dataset.csv](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus?resource=download&select=ner_dataset.csv) फाइललाई हालको डाइरेक्टरीमा डाउनलोड गर्नुहोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from tensorflow import keras\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## डेटासेट तयार गर्दै\n",
"\n",
"हामी डेटासेटलाई एक डेटा फ्रेममा पढेर सुरु गर्नेछौं। यदि तपाईं Pandas प्रयोग गर्ने बारेमा थप जान्न चाहनुहुन्छ भने, हाम्रो [Data Science for Beginners](http://aka.ms/datascience-beginners) को [डेटा प्रशोधनको पाठ](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python) हेर्नुहोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Sentence #</th>\n",
" <th>Word</th>\n",
" <th>POS</th>\n",
" <th>Tag</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Sentence: 1</td>\n",
" <td>Thousands</td>\n",
" <td>NNS</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>NaN</td>\n",
" <td>of</td>\n",
" <td>IN</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>demonstrators</td>\n",
" <td>NNS</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>NaN</td>\n",
" <td>have</td>\n",
" <td>VBP</td>\n",
" <td>O</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>NaN</td>\n",
" <td>marched</td>\n",
" <td>VBN</td>\n",
" <td>O</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Sentence # Word POS Tag\n",
"0 Sentence: 1 Thousands NNS O\n",
"1 NaN of IN O\n",
"2 NaN demonstrators NNS O\n",
"3 NaN have VBP O\n",
"4 NaN marched VBN O"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv('ner_dataset.csv',encoding='unicode-escape')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['O', 'B-geo', 'B-gpe', 'B-per', 'I-geo', 'B-org', 'I-org', 'B-tim',\n",
" 'B-art', 'I-art', 'I-per', 'I-gpe', 'I-tim', 'B-nat', 'B-eve',\n",
" 'I-eve', 'I-nat'], dtype=object)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tags = df.Tag.unique()\n",
"tags"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'O'"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"id2tag = dict(enumerate(tags))\n",
"tag2id = { v : k for k,v in id2tag.items() }\n",
"\n",
"id2tag[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"अब हामीले शब्दावलीसँग पनि त्यही गर्न आवश्यक छ। सरलताका लागि, हामी शब्दको आवृत्तिलाई ध्यानमा नदिई शब्दावली बनाउनेछौं; वास्तविक जीवनमा तपाईंले Keras भेक्टराइजर प्रयोग गर्न चाहनुहुन्छ, र शब्दहरूको संख्या सीमित गर्न चाहनुहुन्छ।\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"vocab = set(df['Word'].apply(lambda x: x.lower()))\n",
"id2word = { i+1 : v for i,v in enumerate(vocab) }\n",
"id2word[0] = '<UNK>'\n",
"vocab.add('<UNK>')\n",
"word2id = { v : k for k,v in id2word.items() }"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले प्रशिक्षणको लागि वाक्यहरूको डेटासेट बनाउन आवश्यक छ। आउनुहोस् मूल डेटासेटमा लूप गरौं र सबै व्यक्तिगत वाक्यहरूलाई `X` (शब्दहरूको सूची) र `Y` (टोकनहरूको सूची) मा अलग गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"X,Y = [],[]\n",
"s,t = [],[]\n",
"for i,row in df[['Sentence #','Word','Tag']].iterrows():\n",
" if pd.isna(row['Sentence #']):\n",
" s.append(row['Word'])\n",
" t.append(row['Tag'])\n",
" else:\n",
" if len(s)>0:\n",
" X.append(s)\n",
" Y.append(t)\n",
" s,t = [row['Word']],[row['Tag']]\n",
"X.append(s)\n",
"Y.append(t)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"([10386,\n",
" 23515,\n",
" 4134,\n",
" 29620,\n",
" 7954,\n",
" 13583,\n",
" 21193,\n",
" 12222,\n",
" 27322,\n",
" 18258,\n",
" 5815,\n",
" 15880,\n",
" 5355,\n",
" 25242,\n",
" 31327,\n",
" 18258,\n",
" 27067,\n",
" 23515,\n",
" 26444,\n",
" 14412,\n",
" 358,\n",
" 26551,\n",
" 5011,\n",
" 30558],\n",
" [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0])"
]
},
"execution_count": 93,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def vectorize(seq):\n",
" return [word2id[x.lower()] for x in seq]\n",
"\n",
"def tagify(seq):\n",
" return [tag2id[x] for x in seq]\n",
"\n",
"Xv = list(map(vectorize,X))\n",
"Yv = list(map(tagify,Y))\n",
"\n",
"Xv[0], Yv[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"सरलताका लागि, हामी सबै वाक्यहरूलाई अधिकतम लम्बाइसम्म 0 टोकनहरूद्वारा भरपर्दछौं। वास्तविक जीवनमा, हामीले अझ चतुर रणनीति प्रयोग गर्न चाहन सक्छौं, र केवल एक मिनिब्याचभित्र अनुक्रमहरूलाई भरपर्दछौं।\n"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
"X_data = keras.preprocessing.sequence.pad_sequences(Xv,padding='post')\n",
"Y_data = keras.preprocessing.sequence.pad_sequences(Yv,padding='post')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## टोकन वर्गीकरण नेटवर्क परिभाषित गर्दै\n",
"\n",
"हामी टोकन वर्गीकरणको लागि दुई-तह द्विदिशात्मक LSTM नेटवर्क प्रयोग गर्नेछौं। अन्तिम LSTM तहको प्रत्येक आउटपुटमा घना वर्गीकरणकर्ता लागू गर्नको लागि, हामी `TimeDistributed` निर्माण प्रयोग गर्नेछौं, जसले प्रत्येक चरणमा LSTM का प्रत्येक आउटपुटमा एउटै घना तह दोहोर्याउँछ:\n"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_3\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" embedding_4 (Embedding) (None, 104, 300) 9545400 \n",
" \n",
" bidirectional_6 (Bidirectio (None, 104, 200) 320800 \n",
" nal) \n",
" \n",
" bidirectional_7 (Bidirectio (None, 104, 200) 240800 \n",
" nal) \n",
" \n",
" time_distributed_3 (TimeDis (None, 104, 17) 3417 \n",
" tributed) \n",
" \n",
"=================================================================\n",
"Total params: 10,110,417\n",
"Trainable params: 10,110,417\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"maxlen = X_data.shape[1]\n",
"vocab_size = len(vocab)\n",
"num_tags = len(tags)\n",
"model = keras.models.Sequential([\n",
" keras.layers.Embedding(vocab_size, 300, input_length=maxlen),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
" keras.layers.TimeDistributed(keras.layers.Dense(num_tags, activation='softmax'))\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हाम्रो डेटासेटको लागि हामीले स्पष्ट रूपमा `maxlen` निर्दिष्ट गरिरहेका छौं - यदि हामी चाहन्छौं कि नेटवर्कले भिन्न लम्बाइका अनुक्रमहरूलाई ह्यान्डल गर्न सकोस्, भने नेटवर्क परिभाषा गर्दा हामीलाई अझ चतुर हुन आवश्यक छ।\n",
"\n",
"अब हामी मोडेललाई प्रशिक्षण दिनेछौं। गति बढाउनका लागि, हामी केवल एक इपोकका लागि प्रशिक्षण दिनेछौं, तर तपाईं लामो समयसम्म प्रशिक्षण प्रयास गर्न सक्नुहुन्छ। साथै, तपाईंले डेटासेटको केही भागलाई प्रशिक्षण डेटासेटको रूपमा अलग गर्न चाहनुहुन्छ, ताकि मान्यताको शुद्धता अवलोकन गर्न सकियोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1499/1499 [==============================] - 740s 488ms/step - loss: 0.0667 - acc: 0.9841\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x16f0bb2a310>"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.fit(X_data,Y_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## परिणाम परीक्षण गर्दै\n",
"\n",
"अब हाम्रा इकाई पहिचान मोडेलले एउटा नमूना वाक्यमा कसरी काम गर्छ हेर्न प्रयास गरौं:\n"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {},
"outputs": [],
"source": [
"sent = 'John Smith went to Paris to attend a conference in cancer development institute'\n",
"words = sent.lower().split()\n",
"v = keras.preprocessing.sequence.pad_sequences([[word2id[x] for x in words]],padding='post',maxlen=maxlen)\n",
"res = model(v)[0]"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"john -> B-per\n",
"smith -> I-per\n",
"went -> O\n",
"to -> O\n",
"paris -> B-geo\n",
"to -> O\n",
"attend -> O\n",
"a -> O\n",
"conference -> O\n",
"in -> O\n",
"cancer -> B-org\n",
"development -> I-org\n",
"institute -> I-org\n"
]
}
],
"source": [
"r = np.argmax(res.numpy(),axis=1)\n",
"for i,w in zip(r,words):\n",
" print(f\"{w} -> {id2tag[i]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## मुख्य कुरा\n",
"\n",
"सामान्य LSTM मोडेलले पनि NER मा राम्रो नतिजा देखाउँछ। तर, अझ राम्रो नतिजा प्राप्त गर्नका लागि, तपाईंले BERT जस्ता ठूला प्रि-ट्रेन गरिएको भाषा मोडेलहरू प्रयोग गर्न चाहनुहुन्छ। Huggingface Transformers लाइब्रेरी प्रयोग गरेर NER को लागि BERT प्रशिक्षण गर्ने प्रक्रिया [यहाँ](https://huggingface.co/course/chapter7/2?fw=pt) वर्णन गरिएको छ।\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": "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"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "254d25052dcca4ef84f59a05f2935bdc",
"translation_date": "2025-08-28T09:32:00+00:00",
"source_file": "lessons/5-NLP/19-NER/NER-TF.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,326 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## OpenAI GPT संग प्रयोग गर्ने\n",
"\n",
"यो नोटबुक [AI for Beginners Curriculum](http://aka.ms/ai-beginners) को हिस्सा हो।\n",
"\n",
"यस नोटबुकमा, हामी Hugging Face को `transformers` लाइब्रेरी प्रयोग गरेर OpenAI-GPT मोडेलसँग कसरी खेल्न सकिन्छ भनेर अन्वेषण गर्नेछौं।\n",
"\n",
"अब ढिलासुस्ती नगरी, टेक्स्ट जनरेट गर्ने पाइपलाइन तयार गरौं र सुरु गरौं!\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n",
"Downloading model.safetensors: 100%|██████████| 479M/479M [04:28<00:00, 1.78MB/s] \n",
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\huggingface_hub\\file_download.py:133: UserWarning: `huggingface_hub` cache-system uses symlinks by default to efficiently store duplicated files but your machine does not support them in C:\\Users\\bethanycheum\\.cache\\huggingface\\hub. Caching files will still work but in a degraded version that might require more space on your disk. This warning can be disabled by setting the `HF_HUB_DISABLE_SYMLINKS_WARNING` environment variable. For more details, see https://huggingface.co/docs/huggingface_hub/how-to-cache#limitations.\n",
"To support symlinks on Windows, you either need to activate Developer Mode or to run Python as an administrator. In order to see activate developer mode, see this article: https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development\n",
" warnings.warn(message)\n",
"Some weights of OpenAIGPTLMHeadModel were not initialized from the model checkpoint at openai-gpt and are newly initialized: ['position_ids']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
"Downloading (…)neration_config.json: 100%|██████████| 74.0/74.0 [00:00<00:00, 48.8kB/s]\n",
"Downloading (…)olve/main/vocab.json: 100%|██████████| 816k/816k [00:00<00:00, 1.76MB/s]\n",
"Downloading (…)olve/main/merges.txt: 100%|██████████| 458k/458k [00:00<00:00, 1.11MB/s]\n",
"Downloading (…)/main/tokenizer.json: 100%|██████████| 1.27M/1.27M [00:00<00:00, 2.12MB/s]\n",
"Xformers is not installed correctly. If you want to use memory_efficient_attention to accelerate training use the following command to install Xformers\n",
"pip install xformers.\n"
]
},
{
"data": {
"text/plain": [
"[{'generated_text': \"Hello! I am a neural network, and I want to say that i apologize for not coming to you yourself, for not helping you, and that i was too busy getting dressed and studying for a midterm. you know, the kind where the teachers are like that and they come in pairs with their boyfriends, but not with theirs. it's true, that i have had a girlfriend, and i'm only going on wednesdays and thursdays because i was too busy with college, but maybe\"},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that we have been blessed with a wonderful gift ; no one of us has died at all. and our spirits are strong, very strong. in one very lucky moment of luck for you, all has been given direction and destiny, and for us there are no more mysteries. the earth has been chosen for you, and that earth is now ours, and you must be forever in our hearts. \" \\n the words, as one,'},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that if you would just turn and face the general, you would have a nice day. \" \\n \" sure thing, \" said one of the soldiers, and started to run. the rest of the soldiers followed, shouting. the general turned to general zulu, raising his arm. the general said something in his native language, and the general immediately started to run. zulu started to move toward the wall, with the'},\n",
" {'generated_text': 'Hello! I am a neural network, and I want to say that i am not a doctor but an anthropologist to you, a specialist, a specialist in the field of astrobiological biology, and that i am very much involved in this investigation. i am not sure, i am not certain, but i can confirm your conclusions and therefore i will go to the top. i have a colleague who has just returned from this expedition and his findings confirm that you are a specialist. that is, he'},\n",
" {'generated_text': \"Hello! I am a neural network, and I want to say that everyone here is in agreement that no matter how many times i say to myself,'he was never a man of action on the battlefield,'or'he 'll never take a chance at killing any civilians,'or'he 'll never let his men go undefended against enemy forces of this caliber,'or'that's just what i need in a day like today. \\n you see, there are only three groups that\"}]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from transformers import pipeline\n",
"\n",
"model_name = 'openai-gpt' \n",
"\n",
"generator = pipeline('text-generation', model=model_name)\n",
"\n",
"generator(\"Hello! I am a neural network, and I want to say that\", max_length=100, num_return_sequences=5)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## प्रॉम्प्ट इन्जिनियरिङ\n",
"\n",
"केही समस्याहरूमा, सही प्रॉम्प्टहरू डिजाइन गरेर तपाईं openai-gpt को जेनेरेशन तुरुन्तै प्रयोग गर्न सक्नुहुन्छ। तलका उदाहरणहरू हेर्नुहोस्:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'Synonyms of a word cat: the same cat i used to stare at, and you in'},\n",
" {'generated_text': 'Synonyms of a word cat: cat of the woods, cat of the hills, cat of'},\n",
" {'generated_text': 'Synonyms of a word cat: you! \\n \" it\\'s a girl. \" i said'},\n",
" {'generated_text': \"Synonyms of a word cat: big cat. but how come, we didn't hear it\"},\n",
" {'generated_text': 'Synonyms of a word cat: \" mea - o - c \" which makes them sound'}]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"Synonyms of a word cat:\", max_length=20, num_return_sequences=5)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive this is so horrible - > positive that your brother is gay - >'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i will bring this on you -, < positive am i, i'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i have self - esteem i must take it - : \\n - -'},\n",
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative this is - : \\n if it were true that the devil would have'},\n",
" {'generated_text': \"I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive i have you - > positive it's a bad thing, > positive\"}]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this ->\", max_length=40, num_return_sequences=5)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'Translate English to French: cat => chat, dog => chien, student => new and unusual. there were no more words to be'},\n",
" {'generated_text': 'Translate English to French: cat => chat, dog => chien, student => student \\n his eyes were huge in his lean face as'},\n",
" {'generated_text': \"Translate English to French: cat => chat, dog => chien, student => the teacher's words, their words, their words.\"}]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"Translate English to French: cat => chat, dog => chien, student => \", top_k=50, max_length=30, num_return_sequences=3)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'People who liked the movie The Matrix also liked it, and there was the movie of the first man after us. \\n i wanted to laugh at how stupid these stupid actors were. no, they were'},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and the film was the result. and that's when the man in the story was brought into reality, after a few decades. \\n a\"},\n",
" {'generated_text': 'People who liked the movie The Matrix also liked the movie the matrix, because there was a very old movie movie called the matrix, where there was a great super hero, and the super hero came out'},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie that didn't have a chance to pay cash, if they could afford it. most often they got a good deal and a lot of money,\"},\n",
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and i didn't seem to have the same problem. \\n i 'd met the other half of my family. i spent most of my time\"}]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"generator(\"People who liked the movie The Matrix also liked \", max_length=40, num_return_sequences=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## पाठ नमूना रणनीतिहरू\n",
"\n",
"अहिलेसम्म हामीले साधारण **लोभी** नमूना रणनीति प्रयोग गर्दै आएका छौं, जहाँ हामीले सबैभन्दा उच्च सम्भावनाको आधारमा अर्को शब्द चयन गरेका थियौं। यसरी यो काम गर्छ: \n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my friend, a young man, sprawled across the bed in his bed. \\n \" hi, i\\'m mike eptirard. \" \\n there was silence on the other side of the door. i listened for any trace of life but there was nothing. my heart began to pound, i was starting to sweat, i took out my wallet'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my mother on the bed, hugging her legs to her chest and sobbing. i saw my dad and mother from the corner of my eye. \\n elfin face was covered in tears as i entered the room. my dad and mother also wept ; just as they did every other time i came to work. but this time, they had different faces'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw the room had changed because it was dark. it still smelled like a hospital. a new light shined through from a vent in the ceiling. i found myself in a bathroom and a small room with a sink and a wall of glass. the bathroom billion years ago. not so different from all of the rest of the apartment. \\n now...'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a large woman with dark hair and pale skin. she was asleep, but i noticed a faint movement of her face. i could sense she was awake. i got up and walked over to her. \\n \" hello miss. i am inspector michael o\\'dell ; we are investigating the case against you. i wanted to ask if you were the'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw i had an empty table and three empty chairs. that was all i needed. i had left a note on a table in the center of the room and had a pen in hand. \" \\n \" i think what you were doing was something he was doing to her. \" \\n \" yeah, \" i nodded with a grin. \" i'}]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,num_return_sequences=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**बिम सर्च** जनरेटरलाई पाठ उत्पादनका विभिन्न दिशाहरू (*बिमहरू*) अन्वेषण गर्न अनुमति दिन्छ, र उच्च समग्र स्कोर भएका दिशाहरू चयन गर्दछ। तपाईं `num_beams` प्यारामिटर प्रदान गरेर बिम सर्च गर्न सक्नुहुन्छ। तपाईंले `no_repeat_ngram_size` पनि निर्दिष्ट गर्न सक्नुहुन्छ ताकि दिइएको आकारका n-grams दोहोर्याउन मोडेललाई दण्डित गर्न सकियोस्।\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting in a chair with his head in his hands. he didn\\'t look up as i approached. \\n \" excuse me, sir, \" i said. \" can i help you? \" \\n the man looked up at me. his eyes were red - rimmed and his face was pale, as if he hadn\\'t slept in days'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a desk in the middle of the room. he had his back to me, so i couldn\\'t see what he was doing. \" \\n \" what did he look like? \" i asked as i sat down on the bed next to her. \\n she took a deep breath and looked at me with tears in her eyes'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the bed, reading a book. she looked up at me and smiled. \\n \" hi, \" she said. \" can i help you? \" \\n i sat down next to her and looked around the room. the walls were white, and there was a large window in the middle of the wall that looked out on'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a table in the middle of the room. he looked up as i walked in, and when he saw me, he got up and walked over to me. \\n \" can i help you? \" he asked as he put his hand on the small of my back and led me to a chair at the other end of'},\n",
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the edge of her bed, reading a book. she looked up at me and smiled. \\n \" hello, \" she said. \" can i help you? \" \\n i didn\\'t know what to say, so i just sat down in the chair next to the bed and looked at her. her hair was dark brown'}]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,num_return_sequences=5,num_beams=10,no_repeat_ngram_size=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**नमूना चयन**ले मोडेलले फर्काएको सम्भाव्यता वितरण प्रयोग गरेर अर्को शब्द गैर-निर्धारित रूपमा चयन गर्दछ। तपाईं `do_sample=True` प्यारामिटर प्रयोग गरेर नमूना चयन चालु गर्न सक्नुहुन्छ। तपाईं `temperature` पनि निर्दिष्ट गर्न सक्नुहुन्छ, जसले मोडेललाई बढी वा कम निर्धारणात्मक बनाउँछ।\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw her. she was on the bed, but she looked very different. \\n \" honey, what\\'s the matter? \" i asked. \\n she sat up. \" i can\\'t believe it\\'s real. i\\'ve been dreaming about you for the last two days. \" \\n \" i can\\'t believe it either. i guess that\\'s how'}]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
"generator(prompt,max_length=100,do_sample=True,temperature=0.8)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"हामीले नमूना बनाउँदा थप दुई प्यारामिटरहरू प्रदान गर्न सक्छौं: \n",
"* `top_k` ले नमूना प्रयोग गर्दा विचार गर्नुपर्ने शब्द विकल्पहरूको संख्या निर्दिष्ट गर्दछ। यसले हाम्रो पाठमा अजीब (कम सम्भावना भएका) शब्दहरू प्राप्त गर्ने सम्भावना कम गर्छ। \n",
"* `top_p` पनि यस्तै छ, तर हामी सबैभन्दा सम्भावित शब्दहरूको सानो उपसमूह चयन गर्छौं, जसको कुल सम्भावना p भन्दा ठूलो हुन्छ। \n",
"\n",
"यी प्यारामिटरहरू थपेर प्रयोग गर्न स्वतन्त्र महसुस गर्नुहोस्। \n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## आफ्नो मोडेलहरूलाई फाइन-ट्युन गर्नुहोस्\n",
"\n",
"तपाईं आफ्नो डेटासेटमा [आफ्नो मोडेललाई फाइन-ट्युन](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/fine-tuning?pivots=programming-language-studio?WT.mc_id=academic-77998-bethanycheum) गर्न सक्नुहुन्छ। यसले तपाईंलाई पाठको शैली समायोजन गर्न अनुमति दिनेछ, जबकि भाषा मोडेलको मुख्य भागलाई कायम राख्नेछ।\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": "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.10.11"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "d4ff89615d38924a55594f16d6d20678",
"translation_date": "2025-08-28T09:30:34+00:00",
"source_file": "lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,49 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## असाइनमेन्ट: डायोफेन्टाइन समीकरणहरू\n",
"\n",
"> यो असाइनमेन्ट [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) को हिस्सा हो र [यो पोस्ट](https://habr.com/post/128704/) बाट प्रेरित छ।\n",
"\n",
"तपाईंको लक्ष्य तथाकथित **डायोफेन्टाइन समीकरण** समाधान गर्नु हो - जसमा पूर्णांक मूलहरू र पूर्णांक गुणांकहरू हुन्छन्। उदाहरणका लागि, तलको समीकरणलाई विचार गर्नुहोस्:\n",
"\n",
"$$a+2b+3c+4d=30$$\n",
"\n",
"तपाईंले यस्तो पूर्णांक मूलहरू $a$,$b$,$c$,$d\\in\\mathbb{N}$ पत्ता लगाउनुपर्छ जसले यो समीकरणलाई सन्तुष्ट पार्छ।\n",
"\n",
"सुझावहरू:\n",
"1. मूलहरूलाई [0;30] को अन्तरालमा विचार गर्न सक्नुहुन्छ।\n",
"1. जीनको रूपमा, मूल मानहरूको सूची प्रयोग गर्न विचार गर्नुहोस्।\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**अस्वीकरण**: \nयो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरी अनुवाद गरिएको हो। हामी यथासम्भव सटीकता सुनिश्चित गर्न प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटि वा अशुद्धता हुन सक्छ। यसको मूल भाषामा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्त्वपूर्ण जानकारीका लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुने छैनौं।\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
},
"orig_nbformat": 4,
"coopTranslator": {
"original_hash": "a967e1fa1e11ab2b6467b19349a4a9aa",
"translation_date": "2025-08-28T07:26:40+00:00",
"source_file": "lessons/6-Other/21-GeneticAlgorithms/Diophantine.ipynb",
"language_code": "ne"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More