AI-For-Beginners/translations/kn/lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb

726 lines
45 KiB
Plaintext

{
"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/kn/embedding-classifier-example.b77f021a7ee67eee.webp)\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",
"ಇದನ್ನು datasource ಗೆ `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": [
"> **ಗಮನಿಸಿ**: ಸಮಯದ ಕಾರಣಕ್ಕಾಗಿ ನಾವು ಇಲ್ಲಿ ಕೇವಲ 25,000 ದಾಖಲೆಗಳಿಗಾಗಿ ತರಬೇತಿ ನೀಡುತ್ತಿದ್ದೇವೆ (ಒಂದು ಪೂರ್ಣ ಎಪೋಕ್‌ಗಿಂತ ಕಡಿಮೆ), ಆದರೆ ನೀವು ತರಬೇತಿಯನ್ನು ಮುಂದುವರೆಸಬಹುದು, ಹಲವಾರು ಎಪೋಕ್‌ಗಳಿಗಾಗಿ ತರಬೇತಿ ನೀಡಲು ಫಂಕ್ಷನ್ ಬರೆಯಬಹುದು ಮತ್ತು ಹೆಚ್ಚಿನ ನಿಖರತೆಯನ್ನು ಸಾಧಿಸಲು ಲರ್ನಿಂಗ್ ರೇಟ್ ಪರಿಮಾಣದೊಂದಿಗೆ ಪ್ರಯೋಗ ಮಾಡಬಹುದು. ನೀವು ಸುಮಾರು 90% ನಿಖರತೆಯನ್ನು ತಲುಪಬಹುದು.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EmbeddingBag ಲೇಯರ್ ಮತ್ತು ಬದಲಾಗುವ ಉದ್ದದ ಕ್ರಮದ ಪ್ರತಿನಿಧಾನ\n",
"\n",
"ಹಿಂದಿನ ವಾಸ್ತುಶಿಲ್ಪದಲ್ಲಿ, ನಾವು ಎಲ್ಲಾ ಕ್ರಮಗಳನ್ನು ಒಂದೇ ಉದ್ದಕ್ಕೆ ಪ್ಯಾಡ್ ಮಾಡಬೇಕಾಗಿತ್ತು ताकि ಅವುಗಳನ್ನು ಒಂದು ಮಿನಿಬ್ಯಾಚ್‌ಗೆ ಹೊಂದಿಸಬಹುದು. ಇದು ಬದಲಾಗುವ ಉದ್ದದ ಕ್ರಮಗಳನ್ನು ಪ್ರತಿನಿಧಿಸುವ ಅತ್ಯಂತ ಪರಿಣಾಮಕಾರಿ ವಿಧಾನವಲ್ಲ - ಇನ್ನೊಂದು ವಿಧಾನವೆಂದರೆ **offset** ವೆಕ್ಟರ್ ಅನ್ನು ಬಳಸುವುದು, ಇದು ಒಂದು ದೊಡ್ಡ ವೆಕ್ಟರ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾದ ಎಲ್ಲಾ ಕ್ರಮಗಳ ಆಫ್‌ಸೆಟ್‌ಗಳನ್ನು ಹಿಡಿದಿರುತ್ತದೆ.\n",
"\n",
"![offset ಕ್ರಮದ ಪ್ರತಿನಿಧಾನವನ್ನು ತೋರಿಸುವ ಚಿತ್ರ](../../../../../translated_images/kn/offset-sequence-representation.eb73fcefb29b46ee.webp)\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": [
"## ಅರ್ಥಾತ್ಮಕ ಎम्बೆಡ್ಡಿಂಗ್‌ಗಳು: Word2Vec\n",
"\n",
"ನಮ್ಮ ಹಿಂದಿನ ಉದಾಹರಣೆಯಲ್ಲಿ, ಮಾದರಿ ಎम्बೆಡ್ಡಿಂಗ್ ಲೇಯರ್ ಪದಗಳನ್ನು ವೆಕ್ಟರ್ ಪ್ರತಿನಿಧಿಸುವಿಕೆಗೆ ಕಲಿತುಕೊಂಡಿತು, ಆದರೆ ಈ ಪ್ರತಿನಿಧಾನಕ್ಕೆ ಹೆಚ್ಚು ಅರ್ಥಾತ್ಮಕ ಅರ್ಥ ಇರಲಿಲ್ಲ. ಸಮಾನಾರ್ಥಕ ಪದಗಳು ಅಥವಾ ಸಮಾನಾರ್ಥಕ ಪದಗಳು ಕೆಲವು ವೆಕ್ಟರ್ ದೂರ (ಉದಾ. ಯೂಕ್ಲಿಡಿಯನ್ ದೂರ) ಅರ್ಥದಲ್ಲಿ ಪರಸ್ಪರ ಹತ್ತಿರ ಇರುವ ವೆಕ್ಟರ್‌ಗಳಿಗೆ ಹೊಂದಿಕೊಳ್ಳುವಂತಹ ವೆಕ್ಟರ್ ಪ್ರತಿನಿಧಾನವನ್ನು ಕಲಿಯುವುದು ಉತ್ತಮವಾಗಿರುತ್ತದೆ.\n",
"\n",
"ಅದಕ್ಕಾಗಿ, ನಾವು ನಮ್ಮ ಎम्बೆಡ್ಡಿಂಗ್ ಮಾದರಿಯನ್ನು ನಿರ್ದಿಷ್ಟ ರೀತಿಯಲ್ಲಿ ದೊಡ್ಡ ಪಠ್ಯ ಸಂಗ್ರಹದ ಮೇಲೆ ಪೂರ್ವ-ಪ್ರಶಿಕ್ಷಣ ಮಾಡಬೇಕಾಗುತ್ತದೆ. ಅರ್ಥಾತ್ಮಕ ಎम्बೆಡ್ಡಿಂಗ್‌ಗಳನ್ನು ತರಬೇತುಗೊಳಿಸುವ ಮೊದಲ ವಿಧಾನಗಳಲ್ಲಿ ಒಂದನ್ನು [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) ಎಂದು ಕರೆಯುತ್ತಾರೆ. ಇದು ಪದಗಳ ವಿತರಿತ ಪ್ರತಿನಿಧಾನವನ್ನು ಉತ್ಪಾದಿಸಲು ಬಳಸುವ ಎರಡು ಮುಖ್ಯ ವಾಸ್ತುಶಿಲ್ಪಗಳ ಮೇಲೆ ಆಧಾರಿತವಾಗಿದೆ:\n",
"\n",
" - **ನಿರಂತರ ಬ್ಯಾಗ್-ಆಫ್-ವರ್ಡ್ಸ್** (CBoW) — ಈ ವಾಸ್ತುಶಿಲ್ಪದಲ್ಲಿ, ನಾವು ಸುತ್ತಲೂ ಇರುವ ಸಂದರ್ಭದಿಂದ ಒಂದು ಪದವನ್ನು ಊಹಿಸಲು ಮಾದರಿಯನ್ನು ತರಬೇತುಗೊಳಿಸುತ್ತೇವೆ. n-ಗ್ರಾಮ್ $(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/kn/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6.webp)\n",
"\n",
"Google News ಡೇಟಾಸೆಟ್‌ನಲ್ಲಿ ಪೂರ್ವ-ಪ್ರಶಿಕ್ಷಿತ word2vec ಎम्बೆಡ್ಡಿಂಗ್‌ನೊಂದಿಗೆ ಪ್ರಯೋಗ ಮಾಡಲು, ನಾವು **gensim** ಗ್ರಂಥಾಲಯವನ್ನು ಬಳಸಬಹುದು. ಕೆಳಗೆ 'neural' ಗೆ ಅತ್ಯಂತ ಸಮಾನವಾದ ಪದಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲಾಗಿದೆ\n",
"\n",
"> **Note:** ನೀವು ಮೊದಲ ಬಾರಿಗೆ word vectors ರಚಿಸುವಾಗ, ಅವುಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡುವುದು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು!\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": [
"ಸಾಮರ್ಥ್ಯ ಎಂಬೆಡ್ಡಿಂಗ್‌ಗಳ ಬಗ್ಗೆ ಅದ್ಭುತವಾದ ವಿಷಯವೆಂದರೆ ನೀವು ವೆಕ್ಟರ್ ಎನ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಯಂತ್ರಿಸಿ ಅರ್ಥವನ್ನು ಬದಲಾಯಿಸಬಹುದು. ಉದಾಹರಣೆಗೆ, ನಾವು ಒಂದು ಪದವನ್ನು ಹುಡುಕಬಹುದು, ಅದರ ವೆಕ್ಟರ್ ಪ್ರತಿನಿಧಾನವು *king* ಮತ್ತು *woman* ಪದಗಳಿಗೆ ಸಾಧ್ಯವಾದಷ್ಟು ಹತ್ತಿರವಾಗಿರಬೇಕು ಮತ್ತು *man* ಪದದಿಂದ ಸಾಧ್ಯವಾದಷ್ಟು ದೂರವಾಗಿರಬೇಕು:\n"
]
},
{
"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-ಗ್ರಾಮ್‌ಗಳಿಗಾಗಿ ವೆಕ್ಟರ್ ಪ್ರತಿನಿಧಾನಗಳನ್ನು ಕಲಿಯುತ್ತದೆ. ಪ್ರತಿನಿಧಾನದ ಮೌಲ್ಯಗಳನ್ನು ಪ್ರತಿ ತರಬೇತಿ ಹಂತದಲ್ಲಿ ಒಟ್ಟಾರೆ ಒಂದು ವೆಕ್ಟರ್ ಆಗಿ ಸರಾಸರಿ ಮಾಡಲಾಗುತ್ತದೆ. ಇದರಿಂದ ಪೂರ್ವ-ತರಬೇತಿಗೆ ಹೆಚ್ಚಿನ ಗಣನೆ ಸೇರಿದ್ದರೂ, ಪದ ಎम्बೆಡ್ಡಿಂಗ್‌ಗಳು ಉಪ-ಪದ ಮಾಹಿತಿಯನ್ನು ಸಂಕೇತಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ.\n",
"\n",
"ಮತ್ತೊಂದು ವಿಧಾನ, **GloVe**, ಸಹ-ಘಟನೆಯ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಎಂಬ ಕಲ್ಪನೆಯನ್ನು ಉಪಯೋಗಿಸಿ, ಸಹ-ಘಟನೆಯ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಅನ್ನು ಹೆಚ್ಚು ಅಭಿವ್ಯಕ್ತಿಪೂರ್ಣ ಮತ್ತು ರೇಖೀಯವಲ್ಲದ ಪದ ವೆಕ್ಟರ್‌ಗಳಾಗಿ ವಿಭಜಿಸಲು ನ್ಯೂರಲ್ ವಿಧಾನಗಳನ್ನು ಬಳಸುತ್ತದೆ.\n",
"\n",
"gensim ವಿವಿಧ ಪದ ಎम्बೆಡ್ಡಿಂಗ್ ಮಾದರಿಗಳನ್ನು ಬೆಂಬಲಿಸುವುದರಿಂದ, ನೀವು ಉದಾಹರಣೆಯಲ್ಲಿನ ಎम्बೆಡ್ಡಿಂಗ್‌ಗಳನ್ನು FastText ಮತ್ತು GloVe ಗೆ ಬದಲಾಯಿಸಿ ಪ್ರಯೋಗಿಸಬಹುದು.\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": [
"ಈಗ ನಮ್ಮ ಮಾದರಿಯನ್ನು ತರಬೇತುಗೊಳಿಸೋಣ. ಮಾದರಿಯನ್ನು ತರಬೇತುಗೊಳಿಸಲು ತೆಗೆದುಕೊಳ್ಳುವ ಸಮಯ ಹಿಂದಿನ ಉದಾಹರಣೆಯಿಗಿಂತ ಬಹಳ ಹೆಚ್ಚು ಇರುವುದನ್ನು ಗಮನಿಸಿ, ಇದಕ್ಕೆ ಕಾರಣ ದೊಡ್ಡ ಎಂಬೆಡ್ಡಿಂಗ್ ಲೇಯರ್ ಗಾತ್ರ ಮತ್ತು ಅದರಿಂದ ಉಂಟಾಗುವ ಹೆಚ್ಚಿನ ಪರಿಮಾಣಗಳ ಸಂಖ್ಯೆ. ಇದಲ್ಲದೆ, ಇದರಿಂದಾಗಿ, ನಾವು ಓವರ್‌ಫಿಟಿಂಗ್ ತಪ್ಪಿಸಲು ಹೆಚ್ಚು ಉದಾಹರಣೆಗಳ ಮೇಲೆ ನಮ್ಮ ಮಾದರಿಯನ್ನು ತರಬೇತುಗೊಳಿಸಬೇಕಾಗಬಹುದು.\n"
]
},
{
"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": [
"ಈಗ ನಮ್ಮ ಮಾದರಿಯನ್ನು ತರಬೇತಿ ಮಾಡೋಣ ಮತ್ತು ನಾವು ಉತ್ತಮ ಫಲಿತಾಂಶಗಳನ್ನು ಪಡೆಯುತ್ತೇವೆಯೇ ನೋಡೋಣ:\n"
]
},
{
"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 ಶಬ್ದಕೋಶದಲ್ಲಿ ಇಲ್ಲದಿರುವುದು, ಆದ್ದರಿಂದ ಅವುಗಳನ್ನು ಮೂಲತಃ ನಿರ್ಲಕ್ಷಿಸಲಾಗುತ್ತದೆ. ಈ ಸತ್ಯವನ್ನು ಮೀರಿ ಹೋಗಲು, ನಾವು ನಮ್ಮ ಡೇಟಾಸೆಟ್‌ನಲ್ಲಿ ನಮ್ಮದೇ embeddings ಅನ್ನು ತರಬೇತಿಮಾಡಬಹುದು.\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<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**ಅಸ್ವೀಕಾರ**: \nಈ ದಸ್ತಾವೇಜು AI ಅನುವಾದ ಸೇವೆ [Co-op Translator](https://github.com/Azure/co-op-translator) ಬಳಸಿ ಅನುವಾದಿಸಲಾಗಿದೆ. ನಾವು ನಿಖರತೆಯಿಗಾಗಿ ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದರೂ, ಸ್ವಯಂಚಾಲಿತ ಅನುವಾದಗಳಲ್ಲಿ ತಪ್ಪುಗಳು ಅಥವಾ ಅಸತ್ಯತೆಗಳು ಇರಬಹುದು ಎಂದು ದಯವಿಟ್ಟು ಗಮನಿಸಿ. ಮೂಲ ಭಾಷೆಯಲ್ಲಿರುವ ಮೂಲ ದಸ್ತಾವೇಜನ್ನು ಅಧಿಕೃತ ಮೂಲವಾಗಿ ಪರಿಗಣಿಸಬೇಕು. ಪ್ರಮುಖ ಮಾಹಿತಿಗಾಗಿ, ವೃತ್ತಿಪರ ಮಾನವ ಅನುವಾದವನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾಗುತ್ತದೆ. ಈ ಅನುವಾದ ಬಳಕೆಯಿಂದ ಉಂಟಾಗುವ ಯಾವುದೇ ತಪ್ಪು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವಿಕೆ ಅಥವಾ ತಪ್ಪು ವಿವರಣೆಗಳಿಗೆ ನಾವು ಹೊಣೆಗಾರರಾಗುವುದಿಲ್ಲ.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "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-11-26T01:47:48+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
"language_code": "kn"
}
},
"nbformat": 4,
"nbformat_minor": 2
}