725 lines
44 KiB
Plaintext
725 lines
44 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",
|
|
"\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 వేల రికార్డుల కోసం మాత్రమే శిక్షణ ఇస్తున్నాము (ఒక పూర్తి ఎపోక్ కన్నా తక్కువ), కానీ మీరు శిక్షణను కొనసాగించవచ్చు, అనేక ఎపోక్స్ కోసం శిక్షణ ఇస్తే ఫంక్షన్ రాయవచ్చు, మరియు అధిక ఖచ్చితత్వాన్ని సాధించడానికి లెర్నింగ్ రేట్ పారామీటర్తో ప్రయోగాలు చేయవచ్చు. మీరు సుమారు 90% ఖచ్చితత్వం సాధించగలుగుతారు.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### ఎంబెడ్డింగ్బ్యాగ్ లేయర్ మరియు వేరియబుల్-లెంగ్త్ సీక్వెన్స్ ప్రాతినిధ్యం\n",
|
|
"\n",
|
|
"మునుపటి ఆర్కిటెక్చర్లో, మినీబ్యాచ్లోకి సరిపడేలా అన్ని సీక్వెన్స్లను ఒకే పొడవు చేయడానికి ప్యాడ్ చేయాల్సి ఉండేది. ఇది వేరియబుల్ పొడవు సీక్వెన్స్లను ప్రాతినిధ్యం చేయడానికి అత్యంత సమర్థవంతమైన విధానం కాదు - మరో విధానం అంటే **ఆఫ్సెట్** వెక్టర్ ఉపయోగించడం, ఇది ఒక పెద్ద వెక్టర్లో నిల్వ ఉన్న అన్ని సీక్వెన్స్ల ఆఫ్సెట్లను కలిగి ఉంటుంది.\n",
|
|
"\n",
|
|
"\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) — ఈ ఆర్కిటెక్చర్లో, మోడల్ను చుట్టుపక్కల ఉన్న సందర్భం నుండి ఒక పదాన్ని అంచనా వేయడానికి శిక్షణ ఇస్తారు. 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",
|
|
"\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",
|
|
"* మన పదసంపదపై 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 పదసంపదలో లేవని, అందువల్ల అవి ప్రాథమికంగా నిర్లక్ష్యం చేయబడ్డాయని ఉంది. ఈ సమస్యను అధిగమించడానికి, మేము మా డేటాసెట్పై మా స్వంత ఎంబెడ్డింగ్స్ను శిక్షణ ఇవ్వవచ్చు.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## సందర్భానుసారమైన ఎంబెడ్డింగ్స్\n",
|
|
"\n",
|
|
"సాంప్రదాయ ప్రీట్రెయిన్డ్ ఎంబెడ్డింగ్ ప్రాతినిధ్యాల ముఖ్యమైన పరిమితి వర్డ్2వెక్ వంటి వాటిలో పదార్థ భావ వివేచన సమస్య. ప్రీట్రెయిన్డ్ ఎంబెడ్డింగ్స్ కొన్ని సందర్భాలలో పదాల అర్థాన్ని పట్టుకోవచ్చు, కానీ ఒక పదం యొక్క అన్ని సాధ్యమైన అర్థాలు ఒకే ఎంబెడ్డింగ్లో సంకేతీకరించబడతాయి. ఇది డౌన్స్ట్రీమ్ మోడల్స్లో సమస్యలు కలిగించవచ్చు, ఎందుకంటే 'play' వంటి అనేక పదాలు ఉపయోగించే సందర్భం ఆధారంగా వేర్వేరు అర్థాలు కలిగి ఉంటాయి.\n",
|
|
"\n",
|
|
"ఉదాహరణకు, 'play' అనే పదం ఈ రెండు వాక్యాలలో పూర్తిగా వేర్వేరు అర్థాలు కలిగి ఉంటుంది:\n",
|
|
"- నేను థియేటర్లో ఒక **play** కి వెళ్లాను.\n",
|
|
"- జాన్ తన స్నేహితులతో **play** చేయాలనుకుంటున్నాడు.\n",
|
|
"\n",
|
|
"పైన ఉన్న ప్రీట్రెయిన్డ్ ఎంబెడ్డింగ్స్ ఈ రెండు అర్థాలను ఒకే ఎంబెడ్డింగ్లో ప్రతిబింబిస్తాయి. ఈ పరిమితిని అధిగమించడానికి, పెద్ద టెక్స్ట్ కార్పస్పై శిక్షణ పొందిన **భాషా మోడల్** ఆధారంగా ఎంబెడ్డింగ్స్ నిర్మించాలి, ఇది పదాలు వివిధ సందర్భాలలో ఎలా కలిపి వాడవచ్చో *తెలుసుకుంటుంది*. ఈ ట్యుటోరియల్లో సందర్భానుసారమైన ఎంబెడ్డింగ్స్ గురించి చర్చించడం పరిధి వెలుపల, కానీ భాషా మోడల్స్ గురించి తదుపరి యూనిట్లో మాట్లాడేటప్పుడు మళ్లీ వాటిని పరిశీలిస్తాము.\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:44:03+00:00",
|
|
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
|
|
"language_code": "te"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
} |