.. 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)*