15.7 Žodžių panašumas ir analogija
15.4 skyrelis apmokėme word2vec modelį mažame duomenų rinkinyje ir pritaikėme jį semantiškai panašiems žodžiams duotam žodžiui rasti. Praktikoje žodžių vektorius, iš anksto apmokytus dideliuose tekstynuose, galima taikyti tolesnėms natūraliosios kalbos apdorojimo užduotims, kurios bus aptartos vėliau 16 skyrelis. Kad paprastai parodytume iš anksto apmokytų žodžių vektorių semantiką iš didelių tekstynų, pritaikykime juos žodžių panašumo ir analogijos užduotims.
from d2l import mxnet as d2l
from mxnet import np, npx
import os
npx.set_np()
from d2l import torch as d2l
import torch
from torch import nn
import os
15.7.1 Iš anksto apmokytų žodžių vektorių įkėlimas
Toliau išvardyti iš anksto apmokyti GloVe įterpiniai, kurių dimensija 50, 100 ir 300, kuriuos galima atsisiųsti iš GloVe svetainės. Iš anksto apmokyti fastText įterpiniai prieinami keliomis kalbomis. Čia nagrinėjame vieną angliškąją versiją (300 dimensijų „wiki.en“), kurią galima atsisiųsti iš fastText svetainės.
#@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')
Kad įkeltume šiuos iš anksto apmokytus GloVe ir fastText įterpinius, apibrėžiame šią klasę TokenEmbedding.
#@save
class TokenEmbedding:
"""Token Embedding."""
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 = ['<unk>'], []
data_dir = d2l.download_extract(embedding_name)
# GloVe website: https://nlp.stanford.edu/projects/glove/
# fastText website: 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:]]
# Skip header information, such as the top row in fastText
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, d2l.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[d2l.tensor(indices)]
return vecs
def __len__(self):
return len(self.idx_to_token)
Toliau įkeliame
50 dimensijų GloVe įterpinius
(iš anksto apmokytus Wikipedia poaibyje).
Kuriant TokenEmbedding egzempliorių,
nurodytą įterpinių failą reikia atsisiųsti, jei jis
dar nebuvo atsisiųstas.
glove_6b50d = TokenEmbedding('glove.6b.50d')
Išveskite žodyno dydį. Žodyne yra 400000 žodžių (teksto vienetų) ir specialus nežinomo teksto vieneto simbolis.
len(glove_6b50d)
Galime gauti žodžio indeksą žodyne ir atvirkščiai.
glove_6b50d.token_to_idx['beautiful'], glove_6b50d.idx_to_token[3367]
15.7.2 Iš anksto apmokytų žodžių vektorių taikymas
Naudodami įkeltus GloVe vektorius, parodysime jų semantiką pritaikydami juos šioms žodžių panašumo ir analogijos užduotims.
15.7.2.1 Žodžių panašumas
Panašiai kaip 15.4.3 skyrelis,
kad rastume semantiškai panašius žodžius
duotam žodžiui
remiantis žodžių vektorių
kosinuso panašumais,
įgyvendiname šią funkciją knn
( artimiausių kaimynų).
def knn(W, x, k):
# Add 1e-9 for numerical stability
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]
def knn(W, x, k):
# Add 1e-9 for numerical stability
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]
Tada
ieškome panašių žodžių
naudodami iš anksto apmokytus žodžių vektorius
iš TokenEmbedding egzemplioriaus embed.
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:]): # Exclude the input word
print(f'cosine sim={float(c):.3f}: {embed.idx_to_token[int(i)]}')
Iš anksto apmokytų žodžių vektorių žodyne
glove_6b50d yra 400000 žodžių ir specialus nežinomo teksto vieneto simbolis.
Neįtraukdami įvesties žodžio ir nežinomo teksto vieneto,
šiame žodyne
raskime
tris semantiškai panašiausius žodžius
žodžiui „chip“.
get_similar_tokens('chip', 3, glove_6b50d)
Toliau išvedami panašūs žodžiai žodžiams „baby“ ir „beautiful“.
get_similar_tokens('baby', 3, glove_6b50d)
get_similar_tokens('beautiful', 3, glove_6b50d)
15.7.2.2 Žodžių analogija
Be panašių žodžių paieškos, žodžių vektorius taip pat galime taikyti žodžių analogijos užduotims. Pavyzdžiui, „man“ : „woman“ :: „son“ : „daughter“ yra žodžių analogijos forma: „man“ yra „woman“, kaip „son“ yra „daughter“. Konkrečiau, žodžių analogijos užbaigimo užduotį galima apibrėžti taip: žodžių analogijai , turint pirmuosius tris žodžius , ir , raskite . Žodžio vektorių pažymėkime . Kad užbaigtume analogiją, rasime žodį, kurio vektorius yra panašiausias į rezultatą.
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])] # Remove unknown words
Patikrinkime „vyriškas–moteriškas“ analogiją naudodami įkeltus žodžių vektorius.
get_analogy('man', 'woman', 'son', glove_6b50d)
Toliau užbaigiama „sostinė–šalis“ analogija: „beijing“ : „china“ :: „tokyo“ : „japan“. Tai parodo iš anksto apmokytų žodžių vektorių semantiką.
get_analogy('beijing', 'china', 'tokyo', glove_6b50d)
„Būdvardis–aukščiausiojo laipsnio būdvardis“ analogijai, pavyzdžiui, „bad“ : „worst“ :: „big“ : „biggest“, matome, kad iš anksto apmokyti žodžių vektoriai gali užfiksuoti sintaksinę informaciją.
get_analogy('bad', 'worst', 'big', glove_6b50d)
Kad parodytume iš anksto apmokytuose žodžių vektoriuose užfiksuotą būtojo laiko sąvoką, sintaksę galime patikrinti naudodami „esamasis laikas–būtasis laikas“ analogiją: „do“ : „did“ :: „go“ : „went“.
get_analogy('do', 'did', 'go', glove_6b50d)
15.7.3 Santrauka
- Praktikoje žodžių vektorius, iš anksto apmokytus dideliuose tekstynuose, galima taikyti tolesnėms natūraliosios kalbos apdorojimo užduotims.
- Iš anksto apmokytus žodžių vektorius galima taikyti žodžių panašumo ir analogijos užduotims.
15.7.4 Pratimai
- Išbandykite fastText rezultatus naudodami
TokenEmbedding('wiki.en'). - Kai žodynas yra labai didelis, kaip galime greičiau rasti panašius žodžius arba užbaigti žodžių analogiją?
