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

726 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Gömülü Temsiller\n",
"\n",
"Önceki örneğimizde, `vocab_size` uzunluğunda yüksek boyutlu kelime torbası vektörleri üzerinde çalıştık ve düşük boyutlu konumsal temsil vektörlerinden seyrek tekil temsil (one-hot representation) vektörlerine açıkça dönüştürme yapıyorduk. Bu tekil temsil yöntemi bellek açısından verimli değildir, ayrıca her kelime birbirinden bağımsız olarak ele alınır, yani tekil kodlanmış vektörler kelimeler arasındaki herhangi bir anlamsal benzerliği ifade etmez.\n",
"\n",
"Bu bölümde, **News AG** veri setini keşfetmeye devam edeceğiz. Başlamak için, verileri yükleyelim ve önceki not defterinden bazı tanımları alalım.\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": [
"## Gömme Nedir?\n",
"\n",
"**Gömme** fikri, kelimeleri daha düşük boyutlu yoğun vektörlerle temsil etmektir; bu vektörler bir kelimenin anlamsal anlamını bir şekilde yansıtır. Daha sonra anlamlı kelime gömmelerinin nasıl oluşturulacağını tartışacağız, ancak şimdilik gömmeleri bir kelime vektörünün boyutunu düşürmenin bir yolu olarak düşünelim.\n",
"\n",
"Bu nedenle, gömme katmanı bir kelimeyi girdi olarak alır ve belirli bir `embedding_size` boyutunda bir çıktı vektörü üretir. Bir anlamda, `Linear` katmanına çok benzer, ancak bir kelimeyi tekil kodlanmış bir vektör olarak almak yerine, kelime numarasını girdi olarak alabilir.\n",
"\n",
"Ağımızda ilk katman olarak gömme katmanını kullanarak, kelime torbasından **gömme torbası** modeline geçebiliriz. Bu modelde, metnimizdeki her kelimeyi ilgili gömmeye dönüştürürüz ve ardından bu gömmeler üzerinde `sum`, `average` veya `max` gibi bir toplama fonksiyonu hesaplarız.\n",
"\n",
"![Beş sıralı kelime için bir gömme sınıflandırıcıyı gösteren görsel.](../../../../../translated_images/tr/embedding-classifier-example.b77f021a7ee67eee.webp)\n",
"\n",
"Sınıflandırıcı sinir ağımız, gömme katmanı ile başlayacak, ardından toplama katmanı ve en üstte doğrusal bir sınıflandırıcı ile devam edecektir:\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": [
"### Değişken Dizi Boyutuyla Çalışmak\n",
"\n",
"Bu mimarinin bir sonucu olarak, ağımıza minibatch'ler belirli bir şekilde oluşturulmalıdır. Önceki bölümde, bag-of-words kullanırken, bir minibatch'teki tüm BoW tensörleri, metin dizimizin gerçek uzunluğundan bağımsız olarak eşit boyutta `vocab_size` idi. Kelime gömme yöntemine geçtiğimizde, her bir metin örneğinde değişken sayıda kelimeyle karşılaşırız ve bu örnekleri minibatch'lere birleştirirken bazı doldurma işlemleri uygulamamız gerekir.\n",
"\n",
"Bu, veri kaynağına `collate_fn` fonksiyonunu sağlayarak yapılabilir:\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": [
"### Gömülü sınıflandırıcıyı eğitme\n",
"\n",
"Artık uygun bir veri yükleyici tanımladığımıza göre, önceki bölümde tanımladığımız eğitim fonksiyonunu kullanarak modeli eğitebiliriz:\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": [
"> **Not**: Burada yalnızca zaman açısından 25k kayıt (bir tam epoch'tan daha az) için eğitim yapıyoruz, ancak eğitime devam edebilir, birkaç epoch için eğitim yapmak üzere bir fonksiyon yazabilir ve daha yüksek doğruluk elde etmek için öğrenme oranı parametresiyle deneyler yapabilirsiniz. Yaklaşık %90 doğruluğa ulaşabilmelisiniz.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EmbeddingBag Katmanı ve Değişken Uzunluklu Dizi Temsili\n",
"\n",
"Önceki mimaride, dizileri bir minibatch'e sığdırmak için hepsini aynı uzunlukta doldurmamız gerekiyordu. Bu, değişken uzunluklu dizileri temsil etmenin en verimli yolu değildir - başka bir yaklaşım, tüm dizilerin bir büyük vektördeki offsetlerini tutan bir **offset** vektörü kullanmak olabilir.\n",
"\n",
"![Offset dizi temsilini gösteren bir görüntü](../../../../../translated_images/tr/offset-sequence-representation.eb73fcefb29b46ee.webp)\n",
"\n",
"> **Not**: Yukarıdaki resimde karakter dizisi gösteriyoruz, ancak örneğimizde kelime dizileriyle çalışıyoruz. Ancak, dizileri offset vektörüyle temsil etme genel prensibi aynı kalır.\n",
"\n",
"Offset temsiliyle çalışmak için [`EmbeddingBag`](https://pytorch.org/docs/stable/generated/torch.nn.EmbeddingBag.html) katmanını kullanıyoruz. Bu katman `Embedding` katmanına benzer, ancak içerik vektörü ve offset vektörünü giriş olarak alır ve ayrıca `mean`, `sum` veya `max` olabilen bir ortalama katmanı içerir.\n",
"\n",
"İşte `EmbeddingBag` kullanan değiştirilmiş bir ağ:\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": [
"Veri kümesini eğitime hazırlamak için, offset vektörünü hazırlayacak bir dönüşüm fonksiyonu sağlamamız gerekiyor:\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": [
"Önceki tüm örneklerden farklı olarak, ağımız artık iki parametre kabul ediyor: veri vektörü ve ofset vektörü, bunlar farklı boyutlardadır. Benzer şekilde, veri yükleyicimiz de bize 2 yerine 3 değer sağlıyor: hem metin hem de ofset vektörleri özellik olarak sağlanıyor. Bu nedenle, eğitim fonksiyonumuzu buna uygun şekilde biraz ayarlamamız gerekiyor:\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": [
"## Anlamsal Gömüler: Word2Vec\n",
"\n",
"Önceki örneğimizde, modelin gömme katmanı kelimeleri vektör temsiline eşlemeyi öğrendi, ancak bu temsil çok fazla anlamsal anlam taşımıyordu. Benzer kelimelerin veya eş anlamlıların, belirli bir vektör mesafesi (örneğin, öklid mesafesi) açısından birbirine yakın olan vektörlere karşılık geldiği bir vektör temsili öğrenmek güzel olurdu.\n",
"\n",
"Bunu yapmak için, gömme modelimizi büyük bir metin koleksiyonu üzerinde özel bir şekilde önceden eğitmemiz gerekiyor. Anlamsal gömüleri eğitmenin ilk yöntemlerinden biri [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) olarak adlandırılır. Bu yöntem, kelimelerin dağıtılmış bir temsilini üretmek için kullanılan iki ana mimariye dayanır:\n",
"\n",
" - **Sürekli kelime torbası** (CBoW) — Bu mimaride, modeli çevresel bağlamdan bir kelime tahmin etmeye eğitiriz. $$(W_{-2},W_{-1},W_0,W_1,W_2)$$ ngrami verildiğinde, modelin amacı $W_0$'ı $$(W_{-2},W_{-1},W_1,W_2)$$'den tahmin etmektir.\n",
" - **Sürekli atlama-gramı** CBoW'un tersidir. Model, bağlam kelimelerinin çevresel penceresini kullanarak mevcut kelimeyi tahmin eder.\n",
"\n",
"CBoW daha hızlıdır, ancak atlama-gramı daha yavaş olmasına rağmen nadir kelimeleri temsil etmede daha iyi bir iş çıkarır.\n",
"\n",
"![Kelimeyi vektörlere dönüştürmek için hem CBoW hem de Skip-Gram algoritmalarını gösteren bir görüntü.](../../../../../translated_images/tr/example-algorithms-for-converting-words-to-vectors.fbe9207a726922f6.webp)\n",
"\n",
"Google News veri seti üzerinde önceden eğitilmiş word2vec gömüsünü denemek için **gensim** kütüphanesini kullanabiliriz. Aşağıda 'neural' kelimesine en benzer kelimeleri buluyoruz.\n",
"\n",
"> **Not:** İlk kez kelime vektörleri oluşturduğunuzda, bunları indirmek biraz zaman alabilir!\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": [
"Kelimeden vektör gömmeleri de hesaplayabiliriz, sınıflandırma modeli eğitiminde kullanılmak üzere (açıklık için yalnızca vektörün ilk 20 bileşenini gösteriyoruz):\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": [
"Semantik gömmelerle ilgili harika şey, vektör kodlamasını manipüle ederek anlamı değiştirebilmenizdir. Örneğin, *kral* ve *kadın* kelimelerine mümkün olduğunca yakın, *adam* kelimesinden ise olabildiğince uzak olan bir kelime bulmayı isteyebiliriz:\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": [
"Hem CBoW hem de Skip-Grams, yalnızca yerel bağlamları dikkate aldıkları için \"tahmin edici\" gömülerdir. Word2Vec, global bağlamdan yararlanmaz.\n",
"\n",
"**FastText**, Word2Vec'in üzerine inşa edilerek her kelime için ve kelime içindeki karakter n-gramları için vektör temsilleri öğrenir. Bu temsillerin değerleri, her eğitim adımında bir vektörde ortalanır. Bu, ön eğitim sırasında ek bir hesaplama yükü getirirken, kelime gömülerinin alt kelime bilgilerini kodlamasını sağlar.\n",
"\n",
"Başka bir yöntem olan **GloVe**, eş oluşum matrisinin fikrinden yararlanır ve eş oluşum matrisini daha ifade edici ve doğrusal olmayan kelime vektörlerine ayırmak için sinirsel yöntemler kullanır.\n",
"\n",
"Gensim, birkaç farklı kelime gömme modelini desteklediği için gömüleri FastText ve GloVe olarak değiştirerek örnekle oynayabilirsiniz.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PyTorch'ta Önceden Eğitilmiş Gömülüleri Kullanma\n",
"\n",
"Yukarıdaki örneği, gömme katmanımızdaki matrisi Word2Vec gibi anlamsal gömülerle önceden dolduracak şekilde değiştirebiliriz. Önceden eğitilmiş gömülerin ve metin korpusumuzun kelime dağarcıklarının muhtemelen eşleşmeyeceğini göz önünde bulundurmamız gerekiyor, bu yüzden eksik kelimeler için ağırlıkları rastgele değerlerle başlatacağız:\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": [
"Şimdi modelimizi eğitelim. Modeli eğitmek için gereken sürenin, daha büyük gömme katmanı boyutu ve dolayısıyla çok daha yüksek parametre sayısı nedeniyle önceki örneğe kıyasla önemli ölçüde daha uzun olduğunu unutmayın. Ayrıca, bu nedenle aşırı öğrenmeyi önlemek istiyorsak modelimizi daha fazla örnek üzerinde eğitmemiz gerekebilir.\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": [
"Bizim durumumuzda, doğrulukta büyük bir artış görmüyoruz, bu muhtemelen oldukça farklı kelime dağarcıklarından kaynaklanıyor. \n",
"Farklı kelime dağarcığı sorununu aşmak için aşağıdaki çözümlerden birini kullanabiliriz:\n",
"* Kelime dağarcığımız üzerinde word2vec modelini yeniden eğitmek\n",
"* Veri setimizi önceden eğitilmiş word2vec modelinin kelime dağarcığı ile yüklemek. Veri setini yüklemek için kullanılan kelime dağarcığı yükleme sırasında belirtilebilir.\n",
"\n",
"İkinci yaklaşım daha kolay görünüyor, özellikle de PyTorch `torchtext` framework'ünün gömülü destek içerdiği için. Örneğin, GloVe tabanlı bir kelime dağarcığını şu şekilde oluşturabiliriz:\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": [
"Yüklenen kelime dağarcığı aşağıdaki temel işlemleri içerir:\n",
"* `vocab.stoi` sözlüğü, bir kelimeyi sözlük indeksine dönüştürmemizi sağlar\n",
"* `vocab.itos` bunun tersini yapar - bir sayıyı kelimeye dönüştürür\n",
"* `vocab.vectors`, gömme vektörlerinin dizisidir, bu nedenle bir kelimenin `s` gömme vektörünü almak için `vocab.vectors[vocab.stoi[s]]` kullanmamız gerekir\n",
"\n",
"İşte **kind-man+woman = queen** denklemini göstermek için gömme vektörleriyle yapılan bir manipülasyon örneği (çalışması için katsayıyı biraz ayarlamam gerekti):\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": [
"Bu gömüler kullanılarak sınıflandırıcıyı eğitmek için, öncelikle veri setimizi GloVe kelime dağarcığını kullanarak kodlamamız gerekiyor:\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": [
"Yukarıda gördüğümüz gibi, tüm vektör gömmeleri `vocab.vectors` matrisinde saklanır. Bu, bu ağırlıkları gömme katmanının ağırlıklarına basit bir kopyalama ile yüklemeyi oldukça kolaylaştırır:\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": [
"Şimdi modelimizi eğitelim ve daha iyi sonuçlar alıp almadığımıza bakalım:\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": [
"Veri setimizdeki bazı kelimelerin önceden eğitilmiş GloVe sözlüğünde bulunmaması ve dolayısıyla esasen göz ardı edilmesi, doğrulukta önemli bir artış görmememizin nedenlerinden biridir. Bu durumu aşmak için, kendi veri setimiz üzerinde kendi gömme yöntemlerimizi eğitebiliriz.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bağlamsal Gömüler\n",
"\n",
"Word2Vec gibi geleneksel önceden eğitilmiş gömü temsillerinin en önemli sınırlamalarından biri, kelime anlamı ayrımının zorluğudur. Önceden eğitilmiş gömüler, kelimelerin bağlamdaki anlamlarının bir kısmını yakalayabilse de, bir kelimenin tüm olası anlamları aynı gömüye kodlanır. Bu durum, 'play' gibi birçok kelimenin kullanıldıkları bağlama bağlı olarak farklı anlamlara sahip olması nedeniyle, sonraki modellerde sorunlara yol açabilir.\n",
"\n",
"Örneğin, 'play' kelimesi şu iki farklı cümlede oldukça farklı anlamlara sahiptir:\n",
"- Tiyatroda bir **oyuna** gittim.\n",
"- John arkadaşlarıyla **oyun** oynamak istiyor.\n",
"\n",
"Yukarıdaki önceden eğitilmiş gömüler, 'play' kelimesinin her iki anlamını da aynı gömüde temsil eder. Bu sınırlamayı aşmak için, kelimelerin farklı bağlamlarda nasıl bir araya gelebileceğini *bilen* ve büyük bir metin derlemi üzerinde eğitilmiş olan **dil modeli** temelinde gömüler oluşturmamız gerekir. Bağlamsal gömüleri tartışmak bu eğitimin kapsamı dışında olsa da, bir sonraki bölümde dil modellerini ele alırken bu konuya geri döneceğiz.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Feragatname**: \nBu belge, AI çeviri hizmeti [Co-op Translator](https://github.com/Azure/co-op-translator) kullanılarak çevrilmiştir. Doğruluk için çaba göstersek de, otomatik çevirilerin hata veya yanlışlık içerebileceğini lütfen unutmayın. Belgenin orijinal dili, yetkili kaynak olarak kabul edilmelidir. Kritik bilgiler için profesyonel insan çevirisi önerilir. Bu çevirinin kullanımından kaynaklanan yanlış anlamalar veya yanlış yorumlamalardan sorumlu değiliz.\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-28T14:31:48+00:00",
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
"language_code": "tr"
}
},
"nbformat": 4,
"nbformat_minor": 2
}