.. _sec_synonyms: Sözcük Benzerliği ve Benzeşim ============================= :numref:`sec_word2vec_pretraining` içinde, küçük bir veri kümesi üzerinde bir word2vec modelini eğittik ve bunu bir girdi sözcüğü için anlamsal olarak benzer kelimeleri bulmak için uyguladık. Uygulamada, büyük külliyatlar üzerinde önceden eğitilmiş kelime vektörleri, daha sonra :numref:`chap_nlp_app` içinde ele alınacak olan doğal dil işleme görevlerine uygulanabilir. Büyük külliyatlardan önceden eğitilmiş kelime vektörlerinin anlamını basit bir şekilde göstermek için, bunları sözcük benzerliğü ve benzeşimi görevlerine uygulayalım. .. raw:: html
mxnetpytorch
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python import os from d2l import mxnet as d2l from mxnet import np, npx npx.set_np() .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python import os import torch from torch import nn from d2l import torch as d2l .. raw:: html
.. raw:: html
Önceden Eğitilmiş Sözcük Vektörlerini Yükleme --------------------------------------------- Aşağıda, `GloVe web sitesinden `__ indirilebilen 50, 100 ve 300 boyutlarında önceden eğitilmiş GloVe gömme listeleri verilmektedir. Önceden eğitilmiş fastText gömmeleri birden çok dilde mevcuttur. Burada indirilebilen bir İngilizce sürümünü düşünelim (300-boyutlu "wiki.en") `fastText websitesi `__. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save d2l.DATA_HUB['glove.6b.50d'] = (d2l.DATA_URL + 'glove.6B.50d.zip', '0b8703943ccdb6eb788e6f091b8946e82231bc4d') #@save d2l.DATA_HUB['glove.6b.100d'] = (d2l.DATA_URL + 'glove.6B.100d.zip', 'cd43bfb07e44e6f27cbcc7bc9ae3d80284fdaf5a') #@save d2l.DATA_HUB['glove.42b.300d'] = (d2l.DATA_URL + 'glove.42B.300d.zip', 'b5116e234e9eb9076672cfeabf5469f3eec904fa') #@save d2l.DATA_HUB['wiki.en'] = (d2l.DATA_URL + 'wiki.en.zip', 'c1816da3821ae9f43899be655002f6c723e91b88') .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save d2l.DATA_HUB['glove.6b.50d'] = (d2l.DATA_URL + 'glove.6B.50d.zip', '0b8703943ccdb6eb788e6f091b8946e82231bc4d') #@save d2l.DATA_HUB['glove.6b.100d'] = (d2l.DATA_URL + 'glove.6B.100d.zip', 'cd43bfb07e44e6f27cbcc7bc9ae3d80284fdaf5a') #@save d2l.DATA_HUB['glove.42b.300d'] = (d2l.DATA_URL + 'glove.42B.300d.zip', 'b5116e234e9eb9076672cfeabf5469f3eec904fa') #@save d2l.DATA_HUB['wiki.en'] = (d2l.DATA_URL + 'wiki.en.zip', 'c1816da3821ae9f43899be655002f6c723e91b88') .. raw:: html
.. raw:: html
Bu önceden eğitilmiş GloVe ve fastText gömmelerini yüklemek için aşağıdaki ``TokenEmbedding`` sınıfını tanımlıyoruz. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class TokenEmbedding: """Andıç Gömme.""" def __init__(self, embedding_name): self.idx_to_token, self.idx_to_vec = self._load_embedding( embedding_name) self.unknown_idx = 0 self.token_to_idx = {token: idx for idx, token in enumerate(self.idx_to_token)} def _load_embedding(self, embedding_name): idx_to_token, idx_to_vec = [''], [] data_dir = d2l.download_extract(embedding_name) # GloVe websitesi: https://nlp.stanford.edu/projects/glove/ # fastText websitesi: https://fasttext.cc/ with open(os.path.join(data_dir, 'vec.txt'), 'r') as f: for line in f: elems = line.rstrip().split(' ') token, elems = elems[0], [float(elem) for elem in elems[1:]] # fastText'teki en üst satır gibi başlık bilgilerini atla if len(elems) > 1: idx_to_token.append(token) idx_to_vec.append(elems) idx_to_vec = [[0] * len(idx_to_vec[0])] + idx_to_vec return idx_to_token, np.array(idx_to_vec) def __getitem__(self, tokens): indices = [self.token_to_idx.get(token, self.unknown_idx) for token in tokens] vecs = self.idx_to_vec[np.array(indices)] return vecs def __len__(self): return len(self.idx_to_token) .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python #@save class TokenEmbedding: """Andıç Gömme.""" def __init__(self, embedding_name): self.idx_to_token, self.idx_to_vec = self._load_embedding( embedding_name) self.unknown_idx = 0 self.token_to_idx = {token: idx for idx, token in enumerate(self.idx_to_token)} def _load_embedding(self, embedding_name): idx_to_token, idx_to_vec = [''], [] data_dir = d2l.download_extract(embedding_name) # GloVe websitesi: https://nlp.stanford.edu/projects/glove/ # fastText websitesi: https://fasttext.cc/ with open(os.path.join(data_dir, 'vec.txt'), 'r') as f: for line in f: elems = line.rstrip().split(' ') token, elems = elems[0], [float(elem) for elem in elems[1:]] # fastText'teki en üst satır gibi başlık bilgilerini atla if len(elems) > 1: idx_to_token.append(token) idx_to_vec.append(elems) idx_to_vec = [[0] * len(idx_to_vec[0])] + idx_to_vec return idx_to_token, torch.tensor(idx_to_vec) def __getitem__(self, tokens): indices = [self.token_to_idx.get(token, self.unknown_idx) for token in tokens] vecs = self.idx_to_vec[torch.tensor(indices)] return vecs def __len__(self): return len(self.idx_to_token) .. raw:: html
.. raw:: html
Aşağıda 50 boyutlu GloVe gömmelerini yüklüyoruz (Wikipedia alt kümesi üzerinde önceden eğitilmiş). ``TokenEmbedding`` örneğini oluştururken, belirtilen gömme dosyasının henüz yoksa indirilmesi gerekir. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python glove_6b50d = TokenEmbedding('glove.6b.50d') .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python glove_6b50d = TokenEmbedding('glove.6b.50d') .. raw:: html
.. raw:: html
Sözcük dağarcığı boyutunu çıktılayın. Sözcük bilgisi 400000 kelime (belirteç) ve özel bir bilinmeyen belirteci içerir. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python len(glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 400001 .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python len(glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 400001 .. raw:: html
.. raw:: html
Sözcük hazinesinde bir kelimenin indeksini alabiliriz ve tersi de geçerlidir. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python glove_6b50d.token_to_idx['beautiful'], glove_6b50d.idx_to_token[3367] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (3367, 'beautiful') .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python glove_6b50d.token_to_idx['beautiful'], glove_6b50d.idx_to_token[3367] .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output (3367, 'beautiful') .. raw:: html
.. raw:: html
Önceden Eğitilmiş Sözcük Vektörlerini Uygulama ---------------------------------------------- Yüklenen GloVe vektörlerini kullanarak, anlamlarını aşağıdak sözcük benzerliği ve benzeşim görevlerine uygulayarak göstereceğiz. Sözcük Benzerliği ~~~~~~~~~~~~~~~~~ :numref:`subsec_apply-word-embed` içindekine benzer şekilde, sözcük vektörleri arasındaki kosinüs benzerliklerine dayanan bir girdi sözcüğü için anlamsal olarak benzer kelimeleri bulmak için aşağıdaki ``knn`` (:math:`k` en yakın komşu) işlevini uygularız. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def knn(W, x, k): # Sayısal kararlılık için 1e-9 ekleyin cos = np.dot(W, x.reshape(-1,)) / ( np.sqrt(np.sum(W * W, axis=1) + 1e-9) * np.sqrt((x * x).sum())) topk = npx.topk(cos, k=k, ret_typ='indices') return topk, [cos[int(i)] for i in topk] .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def knn(W, x, k): # Sayısal kararlılık için 1e-9 ekleyin cos = torch.mv(W, x.reshape(-1,)) / ( torch.sqrt(torch.sum(W * W, axis=1) + 1e-9) * torch.sqrt((x * x).sum())) _, topk = torch.topk(cos, k=k) return topk, [cos[int(i)] for i in topk] .. raw:: html
.. raw:: html
Daha sonra, ``TokenEmbedding`` örneğinden önceden eğitilmiş sözcük vektörlerini kullanarak benzer kelimeleri ararız. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def get_similar_tokens(query_token, k, embed): topk, cos = knn(embed.idx_to_vec, embed[[query_token]], k + 1) for i, c in zip(topk[1:], cos[1:]): # Girdi sözcüğünü hariç tut print(f'cosine sim={float(c):.3f}: {embed.idx_to_token[int(i)]}') .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def get_similar_tokens(query_token, k, embed): topk, cos = knn(embed.idx_to_vec, embed[[query_token]], k + 1) for i, c in zip(topk[1:], cos[1:]): # Girdi sözcüğünü hariç tut print(f'cosine sim={float(c):.3f}: {embed.idx_to_token[int(i)]}') .. raw:: html
.. raw:: html
``glove_6b50d``'teki önceden eğitilmiş kelime vektörlerinin kelime dağarcığı 400000 kelime ve özel bir bilinmeyen belirteç içerir. Girdi kelimesi ve bilinmeyen belirteci hariç, bu kelime arasında "chip (çip))" kelimesine en anlamsal olarak benzer üç kelimeyi bulalım. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('chip', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.856: chips cosine sim=0.749: intel cosine sim=0.749: electronics .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('chip', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.856: chips cosine sim=0.749: intel cosine sim=0.749: electronics .. raw:: html
.. raw:: html
Aşağıda "baby (bebek)" ve " beautiful (güzel)" kelimelerinin benzerleri çıktılanır. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('baby', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.839: babies cosine sim=0.800: boy cosine sim=0.792: girl .. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('beautiful', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.921: lovely cosine sim=0.893: gorgeous cosine sim=0.830: wonderful .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('baby', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.839: babies cosine sim=0.800: boy cosine sim=0.792: girl .. raw:: latex \diilbookstyleinputcell .. code:: python get_similar_tokens('beautiful', 3, glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output cosine sim=0.921: lovely cosine sim=0.893: gorgeous cosine sim=0.830: wonderful .. raw:: html
.. raw:: html
Kelime Benzeşimi ~~~~~~~~~~~~~~~~ Benzer kelimeleri bulmanın yanı sıra, kelime vektörlerini kelime benzetme görevlerine de uygulayabiliriz. Örneğin, "erkek":"kadın"::"oğul":"kız" bir kelime benzetme şeklidir: "erkek" ile "kadın", "kız" ile "oğul" benzerdir. Daha özel olarak, kelime benzeşim tamamlama görevi şu şekilde tanımlanabilir: Bir kelime benzeşimi :math:`a : b :: c : d` için, ilk üç kelime olan :math:`a`, :math:`b` ve :math:`c` verildiğinde, :math:`d` bulunsun. :math:`w` kelimesinin vektörünü :math:`\text{vec}(w)` ile belirtilsin. Benzetmeyi tamamlamak için, vektörü :math:`\text{vec}(c)+\text{vec}(b)-\text{vec}(a)` sonucuna en çok benzeyen kelimeyi bulacağız. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def get_analogy(token_a, token_b, token_c, embed): vecs = embed[[token_a, token_b, token_c]] x = vecs[1] - vecs[0] + vecs[2] topk, cos = knn(embed.idx_to_vec, x, 1) return embed.idx_to_token[int(topk[0])] # Bilinmeyen kelimeleri çıkar .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python def get_analogy(token_a, token_b, token_c, embed): vecs = embed[[token_a, token_b, token_c]] x = vecs[1] - vecs[0] + vecs[2] topk, cos = knn(embed.idx_to_vec, x, 1) return embed.idx_to_token[int(topk[0])] # Bilinmeyen kelimeleri çıkar .. raw:: html
.. raw:: html
Yüklü kelime vektörlerini kullanarak "erkek-kadın" benzeşimini doğrulayalım. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('man', 'woman', 'son', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'daughter' .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('man', 'woman', 'son', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'daughter' .. raw:: html
.. raw:: html
Aşağıdaki bir "başkent-ülke" benzeşimini tamamlar: "Pekin":"Çin"::"Tokyo":"Japonya". Bu, önceden eğitilmiş kelime vektörlerindeki anlamı gösterir. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('beijing', 'china', 'tokyo', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'japan' .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('beijing', 'china', 'tokyo', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'japan' .. raw:: html
.. raw:: html
"Kötü":"en kötü"::"büyük":"en büyük" gibi "sıfat-üstün sıfat" benzetme için, önceden eğitilmiş kelime vektörlerinin sözdizimsel bilgileri yakalayabileceğini görebiliriz. .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('bad', 'worst', 'big', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'biggest' .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('bad', 'worst', 'big', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'biggest' .. raw:: html
.. raw:: html
Önceden eğitilmiş kelime vektörlerinde geçmiş zaman kavramını göstermek için, sözdizimini “şimdiki zaman - geçmiş zaman” benzetmesini kullanarak test edebiliriz: "yap (do)":“yaptım (did)"::"go (git)":"went (gittim)". .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('do', 'did', 'go', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'went' .. raw:: html
.. raw:: html
.. raw:: latex \diilbookstyleinputcell .. code:: python get_analogy('do', 'did', 'go', glove_6b50d) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output 'went' .. raw:: html
.. raw:: html
Özet ---- - Uygulamada, büyük külliyatlar üzerinde önceden eğitilmiş kelime vektörleri doğal dil işleme görevlerine uygulanabilir. - Önceden eğitilmiş kelime vektörleri kelime benzerliği ve benzeşimi görevlerine uygulanabilir. Alıştırmalar ------------ 1. ``TokenEmbedding('wiki.en')`` kullanarak fastText sonuçlarını test edin. 2. Kelime dağarcığı son derece büyük olduğunda, benzer kelimeleri nasıl bulabiliriz veya bir kelime benzeşimini daha hızlı tamamlayabiliriz? .. raw:: html
.. raw:: html
`Tartışmalar `__ .. raw:: html
.. raw:: html
`Tartışmalar `__ .. raw:: html
.. raw:: html