Mẫu html ngữ nghĩa

Có một nhược điểm rất lớn đối với đại diện này, bên cạnh việc nó lớn đến mức nào. Về cơ bản, nó coi tất cả các từ là các thực thể độc lập không có mối quan hệ nào với nhau. Những gì chúng tôi thực sự muốn là một số khái niệm về sự giống nhau giữa các từ. Tại sao?

Giả sử chúng ta đang xây dựng một mô hình ngôn ngữ. Giả sử chúng ta đã thấy những câu

  • Nhà toán học chạy đến cửa hàng

  • Nhà vật lý chạy đến cửa hàng

  • Nhà toán học giải bài toán mở

trong dữ liệu đào tạo của chúng tôi. Bây giờ, giả sử chúng ta nhận được một câu mới chưa từng thấy trong dữ liệu đào tạo của mình

  • Nhà vật lý giải bài toán mở

Mô hình ngôn ngữ của chúng tôi có thể làm tốt câu này, nhưng sẽ không tốt hơn nhiều nếu chúng tôi có thể sử dụng hai sự kiện sau

  • Chúng ta đã thấy nhà toán học và nhà vật lý có cùng vai trò trong một câu. Bằng cách nào đó họ có một mối quan hệ ngữ nghĩa

  • Chúng ta đã thấy nhà toán học trong cùng một vai trò trong câu mới chưa được nhìn thấy này như chúng ta đang thấy nhà vật lý

và sau đó suy luận rằng nhà vật lý thực sự phù hợp với câu mới chưa từng thấy? . chúng tôi muốn nói đến sự giống nhau về ngữ nghĩa, không chỉ đơn giản là có các biểu diễn chính tả tương tự. Đó là một kỹ thuật để chống lại sự thưa thớt của dữ liệu ngôn ngữ, bằng cách kết nối các dấu chấm giữa những gì chúng ta đã thấy và những gì chúng ta chưa thấy. Tất nhiên, ví dụ này dựa trên một giả định ngôn ngữ cơ bản. rằng các từ xuất hiện trong các ngữ cảnh tương tự có liên quan với nhau về mặt ngữ nghĩa. Đây được gọi là giả thuyết phân phối

Nhận nhúng từ dày đặc

Làm thế nào chúng ta có thể giải quyết vấn đề này? . Ví dụ: chúng tôi thấy rằng cả nhà toán học và nhà vật lý đều có thể chạy, vì vậy có thể chúng tôi cho những từ này điểm cao cho thuộc tính ngữ nghĩa “có thể chạy”. Nghĩ về một số thuộc tính khác và tưởng tượng xem bạn có thể cho điểm một số từ phổ biến về những thuộc tính đó như thế nào

Nếu mỗi thuộc tính là một thứ nguyên, thì chúng ta có thể cung cấp cho mỗi từ một vectơ, như thế này

\[ q_\text{nhà toán học} = \left[ \overbrace{2. 3}^\text{có thể chạy}, \overbrace{9. 4}^\text{thích cà phê}, \overbrace{-5. 5}^\text{chuyên ngành Vật lý}, \dots \right]\]

\[ q_\text{nhà vật lý} = \left[ \overbrace{2. 5}^\text{có thể chạy}, \overbrace{9. 1}^\text{thích cà phê}, \overbrace{6. 4}^\text{chuyên ngành Vật lý}, \dots \right]\]

Sau đó, chúng ta có thể có được một biện pháp tương tự giữa những từ này bằng cách làm

\[\text{Tính tương tự}(\text{nhà vật lý}, \text{nhà toán học}) = q_\text{nhà vật lý} \cdot q_\text{nhà toán học} \]

Mặc dù phổ biến hơn là chuẩn hóa theo độ dài

\[ \text{Tính tương tự}(\text{nhà vật lý}, \text{nhà toán học}) = \frac{q_\text{nhà vật lý} \cdot q_\text{nhà toán học}} {\. q_\text{nhà vật lý} \. \. q_\text{nhà toán học} \. } = \cos (\phi)\]

Trong đó \(\phi\) là góc giữa hai vectơ. Theo cách đó, các từ cực kỳ giống nhau (các từ có phần nhúng chỉ theo cùng một hướng) sẽ có độ tương tự 1. Các từ cực kỳ khác nhau nên có độ tương đồng -1.

Bạn có thể coi các vectơ one-hot thưa thớt từ đầu phần này là trường hợp đặc biệt của các vectơ mới này mà chúng tôi đã xác định, trong đó mỗi từ về cơ bản có độ tương tự bằng 0 và chúng tôi đã gán cho mỗi từ một thuộc tính ngữ nghĩa duy nhất nào đó. Các vectơ mới này dày đặc, có nghĩa là các mục nhập của chúng (thường) khác không

Nhưng những vectơ mới này là một nỗi đau lớn. bạn có thể nghĩ ra hàng nghìn thuộc tính ngữ nghĩa khác nhau có thể liên quan đến việc xác định tính tương đồng và bạn sẽ đặt giá trị của các thuộc tính khác nhau như thế nào? . Vậy tại sao không chỉ để từ nhúng là tham số trong mô hình của chúng tôi và sau đó được cập nhật trong quá trình đào tạo? . Về nguyên tắc, chúng ta sẽ có một số thuộc tính ngữ nghĩa tiềm ẩn mà mạng có thể học. Lưu ý rằng từ nhúng có thể sẽ không thể hiểu được. Đó là, mặc dù với các vectơ được tạo thủ công ở trên, chúng ta có thể thấy rằng các nhà toán học và vật lý giống nhau ở chỗ họ đều thích cà phê, nếu chúng ta cho phép một mạng lưới thần kinh học các phép nhúng và thấy rằng cả nhà toán học và vật lý đều có giá trị lớn trong . Chúng giống nhau ở một số khía cạnh ngữ nghĩa tiềm ẩn, nhưng điều này có lẽ không có cách giải thích nào đối với chúng tôi

Tóm lại, nhúng từ là sự thể hiện *ngữ nghĩa* của một từ, mã hóa thông tin ngữ nghĩa một cách hiệu quả có thể liên quan đến nhiệm vụ hiện tại. Bạn cũng có thể nhúng những thứ khác. một phần của thẻ lời nói, cây phân tích cú pháp, bất cứ thứ gì. Ý tưởng nhúng tính năng là trung tâm của lĩnh vực này

Nhúng từ trong Pytorch

Trước khi chúng ta đến với một ví dụ và bài tập đã làm việc, một số lưu ý nhanh về cách sử dụng các phần nhúng trong Pytorch và trong lập trình học sâu nói chung. Tương tự như cách chúng ta xác định chỉ mục duy nhất cho mỗi từ khi tạo vectơ one-hot, chúng ta cũng cần xác định chỉ mục cho mỗi từ khi sử dụng nhúng. Đây sẽ là những chìa khóa trong một bảng tra cứu. Nghĩa là, các phần nhúng được lưu trữ dưới dạng \(. V. \times D\) ma trận, trong đó \(D\) là thứ nguyên của phần nhúng, sao cho . Trong tất cả mã của tôi, ánh xạ từ từ sang chỉ mục là từ điển có tên word_to_ix. \(i\) has its embedding stored in the \(i\)’th row of the matrix. In all of my code, the mapping from words to indices is a dictionary named word_to_ix.

Mô-đun cho phép bạn sử dụng nhúng là ngọn đuốc. nn. Nhúng, có hai đối số. kích thước từ vựng và kích thước của các phần nhúng

Để lập chỉ mục vào bảng này, bạn phải sử dụng đèn pin. LongTensor (vì các chỉ số là số nguyên, không phải số float)

# Author: Robert Guthrie

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)


word_to_ix = {"hello": 0, "world": 1}
embeds = nn.Embedding(2, 5)  # 2 words in vocab, 5 dimensional embeddings
lookup_tensor = torch.tensor([word_to_ix["hello"]], dtype=torch.long)
hello_embed = embeds(lookup_tensor)
print(hello_embed)

tensor([[ 0.6614,  0.2669,  0.0617,  0.6213, -0.4519]],
       grad_fn=)

Một ví dụ. Mô hình hóa ngôn ngữ N-Gram

Hãy nhớ rằng trong một mô hình ngôn ngữ n-gram, cho một chuỗi các từ \(w\) , chúng tôi muốn tính toán

\[P(w_i. w_{i-1}, w_{i-2}, \dots, w_{i-n+1} ) \]

Trong đó \(w_i\) là từ thứ i của dãy.

Trong ví dụ này, chúng tôi sẽ tính toán hàm mất mát trên một số ví dụ đào tạo và cập nhật các tham số bằng lan truyền ngược

CONTEXT_SIZE = 2
EMBEDDING_DIM = 10
# We will use Shakespeare Sonnet 2
test_sentence = """When forty winters shall besiege thy brow,
And dig deep trenches in thy beauty's field,
Thy youth's proud livery so gazed on now,
Will be a totter'd weed of small worth held:
Then being asked, where all thy beauty lies,
Where all the treasure of thy lusty days;
To say, within thine own deep sunken eyes,
Were an all-eating shame, and thriftless praise.
How much more praise deserv'd thy beauty's use,
If thou couldst answer 'This fair child of mine
Shall sum my count, and make my old excuse,'
Proving his beauty by succession thine!
This were to be new made when thou art old,
And see thy blood warm when thou feel'st it cold.""".split()
# we should tokenize the input, but we will ignore that for now
# build a list of tuples.
# Each tuple is ([ word_i-CONTEXT_SIZE, ..., word_i-1 ], target word)
ngrams = [
    (
        [test_sentence[i - j - 1] for j in range(CONTEXT_SIZE)],
        test_sentence[i]
    )
    for i in range(CONTEXT_SIZE, len(test_sentence))
]
# Print the first 3, just so you can see what they look like.
print(ngrams[:3])

vocab = set(test_sentence)
word_to_ix = {word: i for i, word in enumerate(vocab)}


class NGramLanguageModeler(nn.Module):

    def __init__(self, vocab_size, embedding_dim, context_size):
        super(NGramLanguageModeler, self).__init__()
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.linear1 = nn.Linear(context_size * embedding_dim, 128)
        self.linear2 = nn.Linear(128, vocab_size)

    def forward(self, inputs):
        embeds = self.embeddings(inputs).view((1, -1))
        out = F.relu(self.linear1(embeds))
        out = self.linear2(out)
        log_probs = F.log_softmax(out, dim=1)
        return log_probs


losses = []
loss_function = nn.NLLLoss()
model = NGramLanguageModeler(len(vocab), EMBEDDING_DIM, CONTEXT_SIZE)
optimizer = optim.SGD(model.parameters(), lr=0.001)

for epoch in range(10):
    total_loss = 0
    for context, target in ngrams:

        # Step 1. Prepare the inputs to be passed to the model (i.e, turn the words
        # into integer indices and wrap them in tensors)
        context_idxs = torch.tensor([word_to_ix[w] for w in context], dtype=torch.long)

        # Step 2. Recall that torch *accumulates* gradients. Before passing in a
        # new instance, you need to zero out the gradients from the old
        # instance
        model.zero_grad()

        # Step 3. Run the forward pass, getting log probabilities over next
        # words
        log_probs = model(context_idxs)

        # Step 4. Compute your loss function. (Again, Torch wants the target
        # word wrapped in a tensor)
        loss = loss_function(log_probs, torch.tensor([word_to_ix[target]], dtype=torch.long))

        # Step 5. Do the backward pass and update the gradient
        loss.backward()
        optimizer.step()

        # Get the Python number from a 1-element Tensor by calling tensor.item()
        total_loss += loss.item()
    losses.append(total_loss)
print(losses)  # The loss decreased every iteration over the training data!

# To get the embedding of a particular word, e.g. "beauty"
print(model.embeddings.weight[word_to_ix["beauty"]])

[(['forty', 'When'], 'winters'), (['winters', 'forty'], 'shall'), (['shall', 'winters'], 'besiege')]
[517.997193813324, 515.3646864891052, 512.7484903335571, 510.1485164165497, 507.56221628189087, 504.9897267818451, 502.4295496940613, 499.87967133522034, 497.3393235206604, 494.8069131374359]
tensor([ 0.2199, -0.5751,  1.4575,  1.7721, -2.0176,  0.4216,  0.5747, -1.7962,
         1.2480,  1.2744], grad_fn=)

Bài tập. Máy tính nhúng Word. Túi từ liên tục

Mô hình Túi từ liên tục (CBOW) thường được sử dụng trong học sâu NLP. Đó là một mô hình cố gắng dự đoán các từ trong ngữ cảnh của một vài từ trước và một vài từ sau từ mục tiêu. Điều này khác với mô hình hóa ngôn ngữ, vì CBOW không tuần tự và không nhất thiết phải mang tính xác suất. Thông thường, CBOW được sử dụng để đào tạo nhanh các nhúng từ và các nhúng này được sử dụng để khởi tạo các nhúng của một số mô hình phức tạp hơn. Thông thường, điều này được gọi là nhúng trước. Nó hầu như luôn giúp hiệu suất một vài phần trăm