.. raw:: html
.. _sec_synonyms:
Tìm kiếm từ Đồng nghĩa và Loại suy
==================================
.. raw:: html
Trong :numref:`sec_word2vec_pretraining` ta đã huấn luyện mô hình
embedding từ word2vec trên tập dữ liệu cỡ nhỏ và tìm kiếm các từ đồng
nghĩa sử dụng độ tương tự cô-sin giữa các vector từ. Trong thực tế, các
vector từ được tiền huấn luyện trên kho ngữ liệu cỡ lớn thường được áp
dụng cho các bài toán xử lý ngôn ngữ tự nhiên cụ thể. Phần này sẽ trình
bày cách sử dụng các vector từ đã tiền huấn luyện để tìm các từ đồng
nghĩa và các loại suy (*analogy*). Ta sẽ tiếp tục áp dụng các vector từ
được tiền huấn luyện trong các phần sau.
.. code:: python
from d2l import mxnet as d2l
from mxnet import np, npx
import os
npx.set_np()
.. raw:: html
Sử dụng các Vector Từ đã được Tiền Huấn luyện
---------------------------------------------
.. raw:: html
Dưới đây là các embedding GloVe đã được tiền huấn luyện với kích thước
chiều là 50, 100, và 300, có thể được tải từ `trang web
GloVe `__. Các embedding cho
fastText được tiền huấn luyện trên nhiều ngôn ngữ. Ở đây, ta quan tâm
tới phiên bản cho tiếng Anh (“wiki.en” có chiều là 300) có thể được tải
từ `trang web fastText `__.
.. 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
Ta định nghĩa lớp ``TokenEmbedding`` để nạp các embedding GloVe và
fastText ở trên.
.. code:: python
#@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 = [''], []
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, 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
Tiếp theo, ta sử dụng embedding GloVe có chiều là 50 được tiền huấn
luyện trên tập con của Wikipedia. Embedding tương ứng của từ sẽ được tự
động tải về khi tạo một thực thể ``TokenEmbedding`` lần đầu.
.. code:: python
glove_6b50d = TokenEmbedding('glove.6b.50d')
.. parsed-literal::
:class: output
Downloading ../data/glove.6B.50d.zip from http://d2l-data.s3-accelerate.amazonaws.com/glove.6B.50d.zip...
.. raw:: html
Ta có thể in ra kích thước từ điển. Từ điển chứa :math:`400,000` từ và
một token đặc biệt cho các từ không biết.
.. code:: python
len(glove_6b50d)
.. parsed-literal::
:class: output
400001
.. raw:: html
Ta có thể lấy chỉ số của một từ trong từ điển, hoặc ngược lại tra từ
tương ứng với chỉ số cho trước.
.. code:: python
glove_6b50d.token_to_idx['beautiful'], glove_6b50d.idx_to_token[3367]
.. parsed-literal::
:class: output
(3367, 'beautiful')
.. raw:: html
Áp dụng các Vector Từ đã được Tiền huấn luyện
---------------------------------------------
.. raw:: html
Dưới đây, ta minh họa việc áp dụng các vector từ đã được tiền huấn luyện
sử dụng Glove làm ví dụ.
.. raw:: html
Tìm các từ đồng nghĩa
~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
Tại đây, ta lập trình lại thuật toán tìm các từ đồng nghĩa bằng độ tương
tự cô-sin giữa hai vector trong :numref:`sec_word2vec`.
.. raw:: html
Để sử dụng lại logic tìm kiếm :math:`k` láng giềng gần nhất
(:math:`k`\ *-nearest neighbors*) khi tìm kiếm các từ loại suy, ta đóng
gói phần này một cách tách biệt trong hàm ``knn`` .
.. code:: python
def knn(W, x, k):
# The added 1e-9 is 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]
.. raw:: html
Kế tiếp, ta tìm kiếm các từ đồng nghĩa nhờ tiền huấn luyện thực thể
vector từ ``embed``.
.. 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:]): # Remove input words
print(f'cosine sim={float(c):.3f}: {embed.idx_to_token[int(i)]}')
.. raw:: html
Từ điển vector từ được tiền huấn luyện ``glove_6b50d`` đã tạo chứa
400,000 từ và một token các từ không biết. Loại trừ những từ đầu vào và
những từ không biết, ta tìm kiếm ba từ có nghĩa gần với từ “chip”.
.. code:: python
get_similar_tokens('chip', 3, glove_6b50d)
.. parsed-literal::
:class: output
cosine sim=0.856: chips
cosine sim=0.749: intel
cosine sim=0.749: electronics
.. raw:: html
Kế tiếp, ta tìm các từ gần nghĩa với “baby” và “beautiful”.
.. code:: python
get_similar_tokens('baby', 3, glove_6b50d)
.. parsed-literal::
:class: output
cosine sim=0.839: babies
cosine sim=0.800: boy
cosine sim=0.792: girl
.. code:: python
get_similar_tokens('beautiful', 3, glove_6b50d)
.. parsed-literal::
:class: output
cosine sim=0.921: lovely
cosine sim=0.893: gorgeous
cosine sim=0.830: wonderful
.. raw:: html
Tìm kiếm các Loại suy
~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
Bên cạnh việc tìm kiếm các từ đồng nghĩa, ta cũng có thể sử dụng các
vector từ đã tiền huấn luyện để tìm kiếm các loại suy giữa các từ. Ví
dụ, “man”:“woman”::“son”:“daughter” là một loại suy, “man (nam)” với
“woman (nữ)” giống như “son (con trai)” với “daughter (con gái)”. Bài
toán tìm kiếm loại suy có thể được định nghĩa như sau: với bốn từ trong
quan hệ loại suy :math:`a : b :: c : d`, cho trước ba từ :math:`a`,
:math:`b` và :math:`c`, ta muốn tìm từ :math:`d`. Giả sử, vector từ cho
từ :math:`w` là :math:`\text{vec}(w)`. Để giải quyết bài toán loại suy,
ta cần tìm vector từ gần nhất với vector là kết quả của
:math:`\text{vec}(c)+\text{vec}(b)-\text{vec}(a)`.
.. 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])] # Remove unknown words
.. raw:: html
Kiểm tra quan hệ loại suy “nam giới - nữ giới”.
.. code:: python
get_analogy('man', 'woman', 'son', glove_6b50d)
.. parsed-literal::
:class: output
'daughter'
.. raw:: html
Loại suy “thủ đô-quốc gia”: từ “beijing” với từ “china” tương tự như từ
“tokyo” với từ nào? Đáp án là “japan”.
.. code:: python
get_analogy('beijing', 'china', 'tokyo', glove_6b50d)
.. parsed-literal::
:class: output
'japan'
.. raw:: html
Loại suy “tính từ - tính từ so sánh nhất”: từ “bad” với từ “worst” tương
tự như từ “big” với từ nào? Đáp án là “biggest”.
.. code:: python
get_analogy('bad', 'worst', 'big', glove_6b50d)
.. parsed-literal::
:class: output
'biggest'
.. raw:: html
Loại suy “động từ thì hiện tại - động từ thì quá khứ”: từ “do” với từ
“did” tương tự như từ “go” với từ nào? Đáp án là “went”.
.. code:: python
get_analogy('do', 'did', 'go', glove_6b50d)
.. parsed-literal::
:class: output
'went'
Tóm tắt
-------
.. raw:: html
- Các vector từ được tiền huấn luyện trên kho ngữ liệu cỡ lớn thường
được áp dụng cho các tác vụ xử lý ngôn ngữ tự nhiên.
- Ta có thể sử dụng các vector từ được tiền huấn luyện để tìm kiếm các
từ đồng nghĩa và các loại suy.
Bài tập
-------
.. raw:: html
1. Hãy kiểm tra kết quả với fastText bằng cách sử dụng
``TokenEmbedding('wiki.en')``.
2. Nếu từ điển quá lớn, ta có thể tăng tốc tìm kiếm các từ đồng nghĩa và
các loại suy bằng cách nào?
Thảo luận
---------
- Tiếng Anh: `MXNet `__
- Tiếng Việt: `Diễn đàn Machine Learning Cơ
Bản `__
Những người thực hiện
---------------------
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Nguyễn Văn Quang
- Nguyễn Mai Hoàng Long
- Lê Khắc Hồng Phúc
- Phạm Hồng Vinh
- Nguyễn Văn Cường
*Lần cập nhật gần nhất: 12/09/2020. (Cập nhật lần cuối từ nội dung gốc:
01/07/2020)*