.. raw:: html
.. raw:: html
.. raw:: html
.. _sec_language_model:
Mô hình Ngôn ngữ và Tập dữ liệu
===============================
.. raw:: html
:numref:`sec_text_preprocessing` đã trình bày cách ánh xạ dữ liệu văn
bản sang token, những token này có thể được xem như một chuỗi thời gian
của các quan sát rời rạc. Giả sử văn bản độ dài :math:`T` có dãy token
là :math:`x_1, x_2, \ldots, x_T`, thì
:math:`x_t`\ (:math:`1 \leq t \leq T`) có thể coi là đầu ra (hoặc nhãn)
tại bước thời gian :math:`t`. Khi đã có chuỗi thời gian trên, mục tiêu
của mô hình ngôn ngữ là ước tính xác suất của
.. math:: p(x_1, x_2, \ldots, x_T).
.. raw:: html
Mô hình ngôn ngữ vô cùng hữu dụng. Chẳng hạn, một mô hình lý tưởng có
thể tự tạo ra văn bản tự nhiên, chỉ bằng cách chọn một từ :math:`w_t`
tại thời điểm :math:`t` với
:math:`w_t \sim p(w_t \mid w_{t-1}, \ldots, w_1)`. Khác hoàn toàn với
việc chỉ gõ phím ngẫu nhiên như trong định lý con khỉ vô hạn (*infinite
monkey theorem*), văn bản được sinh ra từ mô hình này giống ngôn ngữ tự
nhiên, giống tiếng Anh chẳng hạn. Hơn nữa, mô hình đủ khả năng tạo ra
một đoạn hội thoại có ý nghĩa mà chỉ cần dựa vào đoạn hội thoại trước
đó. Trên thực tế, còn rất xa để thiết kế được hệ thống như vậy, vì mô
hình sẽ cần *hiểu* văn bản hơn là chỉ tạo ra nội dung đúng ngữ pháp.
.. raw:: html
Tuy nhiên, mô hình ngôn ngữ vẫn rất hữu dụng ngay cả khi còn hạn chế.
Chẳng hạn, cụm từ “nhận dạng giọng nói” và “nhân gian rộng lối” có phát
âm khá giống nhau. Điều này có thể gây ra sự mơ hồ trong việc nhận dạng
giọng nói, nhưng có thể dễ dàng được giải quyết với một mô hình ngôn
ngữ. Mô hình sẽ loại bỏ ngay phương án thứ hai do mang ý nghĩa kì lạ.
Tương tự, một thuật toán tóm tắt tài liệu nên phân biệt được rằng câu
“chó cắn người” xuất hiện thường xuyên hơn nhiều so với “người cắn chó”,
hay như “Cháu muốn ăn bà ngoại” nghe khá kinh dị trong khi “Cháu muốn
ăn, bà ngoại” lại là bình thường.
.. raw:: html
.. raw:: html
.. raw:: html
Ước tính một Mô hình Ngôn ngữ
-----------------------------
.. raw:: html
Làm thế nào để mô hình hóa một tài liệu hay thậm chí là một chuỗi các
từ? Ta có thể sử dụng cách phân tích đã dùng trong mô hình chuỗi ở phần
trước. Bắt đầu bằng việc áp dụng quy tắc xác suất cơ bản sau:
.. math:: p(w_1, w_2, \ldots, w_T) = p(w_1) \prod_{t=2}^T p(w_t \mid w_1, \ldots, w_{t-1}).
.. raw:: html
Ví dụ, xác suất của chuỗi văn bản chứa bốn token bao gồm các từ và dấu
chấm câu được tính như sau:
.. raw:: html
.. math:: p(\mathrm{Statistics}, \mathrm{is}, \mathrm{fun}, \mathrm{.}) = p(\mathrm{Statistics}) p(\mathrm{is} \mid \mathrm{Statistics}) p(\mathrm{fun} \mid \mathrm{Statistics}, \mathrm{is}) p(\mathrm{.} \mid \mathrm{Statistics}, \mathrm{is}, \mathrm{fun}).
.. raw:: html
Để tính toán mô hình ngôn ngữ, ta cần tính xác suất các từ và xác suất
có điều kiện của một từ khi đã có vài từ trước đó. Đây chính là các tham
số của mô hình ngôn ngữ. Ở đây chúng ta giả định rằng, tập dữ liệu huấn
luyện là một kho ngữ liệu lớn, chẳng hạn như là tất cả các mục trong
Wikipedia của `Dự án
Gutenberg `__, hoặc tất
cả văn bản được đăng trên mạng. Xác suất riêng lẻ của từng từ có thể
tính bằng tần suất của từ đó trong tập dữ liệu huấn luyện.
.. raw:: html
Ví dụ, :math:`p(\mathrm{Statistics})` có thể được tính là xác suất của
bất kỳ câu nào bắt đầu bằng “statistics”. Một cách thiếu chính xác hơn
là đếm tất cả số lần xuất hiện của ”statistics” và chia số lần đó cho
tổng số từ trong kho ngữ liệu văn bản. Cách làm này khá hiệu quả, đặc
biệt là với các từ xuất hiện thường xuyên. Tiếp theo, ta tính
.. math:: \hat{p}(\mathrm{is} \mid \mathrm{Statistics}) = \frac{n(\mathrm{Statistics, is})}{n(\mathrm{Statistics})}.
.. raw:: html
Ở đây :math:`n(w)` và :math:`n(w, w')` lần lượt là số lần xuất hiện của
các từ đơn và cặp từ ghép. Đáng tiếc là việc ước tính xác suất của một
cặp từ thường khó khăn hơn, bởi vì sự xuất hiện của cặp từ “Statistics
is” hiếm khi xảy ra hơn. Đặc biệt, với các cụm từ ít đi cùng nhau, rất
khó tìm đủ số lần xuất hiện để ước tính chính xác. Mọi thứ thậm chí sẽ
khó hơn đối với các cụm ba từ trở lên. Sẽ có nhiều cụm ba từ hợp lý mà
hầu như không hề xuất hiện trong tập dữ liệu. Trừ khi có giải pháp để
đánh trọng số khác không cho các tổ hợp từ đó, nếu không sẽ không thể sử
dụng chúng trong một mô hình ngôn ngữ. Nếu kích thước tập dữ liệu nhỏ
hoặc nếu các từ rất hiếm, chúng ta thậm chí có thể không tìm thấy nổi
một lần xuất hiện của các tổ hợp từ đó.
.. raw:: html
.. raw:: html
.. raw:: html
Một kỹ thuật phổ biến là làm mượt Laplace (*Laplace smoothing*). Chúng
ta đã biết kỹ thuật này khi thảo luận về Naive Bayes trong
:numref:`sec_naive_bayes`, với giải pháp là cộng thêm một hằng số nhỏ
vào tất cả các số đếm như sau
.. math::
\begin{aligned}
\hat{p}(w) & = \frac{n(w) + \epsilon_1/m}{n + \epsilon_1}, \\
\hat{p}(w' \mid w) & = \frac{n(w, w') + \epsilon_2 \hat{p}(w')}{n(w) + \epsilon_2}, \\
\hat{p}(w'' \mid w',w) & = \frac{n(w, w',w'') + \epsilon_3 \hat{p}(w',w'')}{n(w, w') + \epsilon_3}.
\end{aligned}
.. raw:: html
Ở đây các hệ số :math:`\epsilon_i > 0` xác định mức độ ảnh hưởng của
chuỗi ngắn hơn khi ước tính chuỗi dài hơn, :math:`m` là tổng số từ trong
tập văn bản. Công thức trên là một biến thể khá nguyên thủy của kỹ thuật
làm mượt Kneser-Ney và Bayesian phi tham số. Xem
:cite:`Wood.Gasthaus.Archambeau.ea.2011` để biết thêm chi tiết. Thật
không may, các mô hình như vậy là bất khả thi vì những lý do sau. Đầu
tiên, chúng ta cần lưu trữ tất cả các số đếm. Thứ hai, các mô hình hoàn
toàn bỏ qua ý nghĩa của các từ. Chẳng hạn, danh từ *“mèo”(“cat”)* và
tính từ *“thuộc về mèo”(“feline”)* nên xuất hiện trong các ngữ cảnh có
liên quan đến nhau. Rất khó để thêm các ngữ cảnh bổ trợ vào các mô hình
đó, trong khi các mô hình ngôn ngữ dựa trên học sâu hoàn toàn có thể làm
được. Cuối cùng, các chuỗi từ dài gần như hoàn toàn mới lạ, do đó một mô
hình chỉ đơn giản đếm tần số của các chuỗi từ đã thấy trước đó sẽ hoạt
động rất kém.
.. raw:: html
.. raw:: html
.. raw:: html
Mô hình Markov và :math:`n`-grams
---------------------------------
.. raw:: html
Trước khi thảo luận các giải pháp sử dụng học sâu, chúng ta sẽ giải
thích một số thuật ngữ và khái niệm. Hãy nhớ lại mô hình Markov đề cập ở
phần trước, và áp dụng để mô hình hóa ngôn ngữ. Một phân phối trên các
chuỗi thỏa mãn điều kiện Markov bậc nhất nếu
:math:`p(w_{t+1} \mid w_t, \ldots, w_1) = p(w_{t+1} \mid w_t)`. Những
bậc cao hơn tương ứng với những chuỗi phụ thuộc dài hơn. Do đó chúng ta
có thể áp dụng các phép xấp xỉ để mô hình hóa một chuỗi:
.. math::
\begin{aligned}
p(w_1, w_2, w_3, w_4) &= p(w_1) p(w_2) p(w_3) p(w_4),\\
p(w_1, w_2, w_3, w_4) &= p(w_1) p(w_2 \mid w_1) p(w_3 \mid w_2) p(w_4 \mid w_3),\\
p(w_1, w_2, w_3, w_4) &= p(w_1) p(w_2 \mid w_1) p(w_3 \mid w_1, w_2) p(w_4 \mid w_2, w_3).
\end{aligned}
.. raw:: html
Các công thức xác suất liên quan đến một, hai và ba biến được gọi là các
mô hình unigram, bigram và trigram. Sau đây, chúng ta sẽ tìm hiểu cách
thiết kế các mô hình tốt hơn.
.. raw:: html
.. raw:: html
.. raw:: html
Thống kê Ngôn ngữ Tự nhiên
--------------------------
.. raw:: html
Hãy cùng xem mô hình hoạt động thế nào trên dữ liệu thực tế. Chúng ta sẽ
xây dựng bộ từ vựng dựa trên tập dữ liệu “cỗ máy thời gian” tương tự như
ở :numref:`sec_text_preprocessing` và in ra :math:`10` từ có tần suất
xuất hiện cao nhất.
.. code:: python
from d2l import mxnet as d2l
from mxnet import np, npx
import random
npx.set_np()
tokens = d2l.tokenize(d2l.read_time_machine())
vocab = d2l.Vocab(tokens)
print(vocab.token_freqs[:10])
.. parsed-literal::
:class: output
[('the', 2261), ('', 1282), ('i', 1267), ('and', 1245), ('of', 1155), ('a', 816), ('to', 695), ('was', 552), ('in', 541), ('that', 443)]
.. raw:: html
Có thể thấy những từ xuất hiện nhiều nhất không có gì đáng chú ý. Các từ
này được gọi là `từ dừng (stop
words) `__ và vì thế chúng
thường được lọc ra. Dù vậy, những từ này vẫn có nghĩa và ta vẫn sẽ sử
dụng chúng. Tuy nhiên, rõ ràng là tần số của từ suy giảm khá nhanh. Từ
phổ biến thứ :math:`10` xuất hiện ít hơn, chỉ bằng :math:`1/5` lần so
với từ phổ biến nhất. Để hiểu rõ hơn, chúng ta sẽ vẽ đồ thị tần số của
từ.
.. code:: python
freqs = [freq for token, freq in vocab.token_freqs]
d2l.plot(freqs, xlabel='token: x', ylabel='frequency: n(x)',
xscale='log', yscale='log')
.. figure:: output_language-models-and-dataset_vn_c9ad2e_3_0.svg
.. raw:: html
Chúng ta đang tiến gần tới một đặc điểm cơ bản: tần số của từ suy giảm
nhanh chóng theo một cách được xác định rõ. Ngoại trừ bốn từ đầu tiên
(‘the’, ‘i’, ‘and’, ‘of’), tất cả các từ còn lại đi theo một đường thẳng
trên biểu đồ thang log. Theo đó các từ tuân theo định luật
`Zipf `__, tức là tần suất
xuất hiện của từ được xác định bởi
.. math::
n(x) \propto (x + c)^{-\alpha} \text{ và~do~đó }
\log n(x) = -\alpha \log (x+c) + \mathrm{const.}
.. raw:: html
Điều này khiến chúng ta cần suy nghĩ kĩ khi mô hình hóa các từ bằng cách
đếm và kỹ thuật làm mượt. Rốt cuộc, chúng ta sẽ ước tính quá cao những
từ có tần suất xuất hiện thấp. Vậy còn các tổ hợp từ khác như 2-gram,
3-gram và nhiều hơn thì sao? Hãy xem liệu tần số của bigram có tương tự
như unigram hay không.
.. code:: python
bigram_tokens = [[pair for pair in zip(
line[:-1], line[1:])] for line in tokens]
bigram_vocab = d2l.Vocab(bigram_tokens)
print(bigram_vocab.token_freqs[:10])
.. parsed-literal::
:class: output
[(('of', 'the'), 297), (('in', 'the'), 161), (('i', 'had'), 126), (('and', 'the'), 104), (('i', 'was'), 104), (('the', 'time'), 97), (('it', 'was'), 94), (('to', 'the'), 81), (('as', 'i'), 75), (('of', 'a'), 69)]
.. raw:: html
.. raw:: html
.. raw:: html
Có một điều đáng chú ý ở đây. 9 trong số 10 cặp từ thường xuyên xuất
hiện là các từ dừng và chỉ có một là liên quan đến cuốn sách — cặp từ
“the time”. Hãy xem tần số của trigram có tương tự hay không.
.. code:: python
trigram_tokens = [[triple for triple in zip(line[:-2], line[1:-1], line[2:])]
for line in tokens]
trigram_vocab = d2l.Vocab(trigram_tokens)
print(trigram_vocab.token_freqs[:10])
.. parsed-literal::
:class: output
[(('the', 'time', 'traveller'), 53), (('the', 'time', 'machine'), 24), (('the', 'medical', 'man'), 22), (('it', 'seemed', 'to'), 14), (('it', 'was', 'a'), 14), (('i', 'began', 'to'), 13), (('i', 'did', 'not'), 13), (('i', 'saw', 'the'), 13), (('here', 'and', 'there'), 12), (('i', 'could', 'see'), 12)]
.. raw:: html
Cuối cùng, hãy quan sát biểu đồ tần số token của các mô hình: unigram,
bigram, và trigram.
.. code:: python
bigram_freqs = [freq for token, freq in bigram_vocab.token_freqs]
trigram_freqs = [freq for token, freq in trigram_vocab.token_freqs]
d2l.plot([freqs, bigram_freqs, trigram_freqs], xlabel='token',
ylabel='frequency', xscale='log', yscale='log',
legend=['unigram', 'bigram', 'trigram'])
.. figure:: output_language-models-and-dataset_vn_c9ad2e_9_0.svg
.. raw:: html
Có vài điều khá thú vị ở biểu đồ này. Thứ nhất, ngoài unigram, các cụm
từ cũng tuân theo định luật Zipf, với số mũ thấp hơn tùy vào chiều dài
cụm từ. Thứ hai, số lượng các n-gram độc nhất là không nhiều. Điều này
có thể liên quan đến số lượng lớn các cấu trúc trong ngôn ngữ. Thứ ba,
rất nhiều n-gram hiếm khi xuất hiện, khiến phép làm mượt Laplace không
thích hợp để xây dựng mô hình ngôn ngữ. Thay vào đó, chúng ta sẽ sử dụng
các mô hình học sâu.
.. raw:: html
Chuẩn bị Dữ liệu Huấn luyện
---------------------------
.. raw:: html
Giả sử cần sử dụng mạng nơ-ron để huấn luyện mô hình ngôn ngữ. Với tính
chất tuần tự của dữ liệu chuỗi, làm thế nào để đọc ngẫu nhiên các
mini-batch gồm các mẫu và nhãn? Ví dụ đơn giản trong
:numref:`sec_sequence` đã giới thiệu một cách thực hiện. Hãy tổng quát
hóa cách làm này một chút.
.. raw:: html
:numref:`fig_timemachine_5gram`, biểu diễn các cách để chia một câu
thành các 5-gram, ở đây mỗi token là một ký tự. Ta có thể chọn tùy ý độ
dời ở vị trí bắt đầu.
.. raw:: html
.. raw:: html
.. raw:: html
.. _fig_timemachine_5gram:
.. figure:: ../img/timemachine-5gram.svg
Các độ dời khác nhau dẫn đến các chuỗi con khác nhau khi phân tách
văn bản.
.. raw:: html
Chúng ta nên chọn giá trị độ dời nào? Trong thực tế, tất cả các giá trị
đó đều tốt như nhau. Nhưng nếu chọn tất cả các giá trị độ dời, dữ liệu
sẽ khá dư thừa do trùng lặp lẫn nhau, đặc biệt trong trường hợp các
chuỗi rất dài. Việc chỉ chọn một tập ngẫu nhiên các vị trí đầu cũng
không tốt vì không đảm bảo sẽ bao quát đồng đều cả mảng. Ví dụ, nếu lấy
ngẫu nhiên có hoàn lại :math:`n` phần tử từ một tập có :math:`n` phần
tử, xác suất một phần tử cụ thể không được chọn là
:math:`(1-1/n)^n \to e^{-1}`. Nghĩa là ta không thể kỳ vọng vào sự bao
quát đồng đều, ngay cả khi hoán vị ngẫu nhiên một tập giá trị độ dời.
Thay vào đó, có thể sử dụng một cách đơn giản để có được cả tính *bao
quát* và tính *ngẫu nhiên*, đó là: chọn một độ dời ngẫu nhiên, sau đó sử
dụng tuần tự các giá trị tiếp theo. Điều này được mô tả trong phép lấy
mẫu ngẫu nhiên và phép phân tách tuần tự dưới đây.
.. raw:: html
.. raw:: html
.. raw:: html
Lấy Mẫu Ngẫu nhiên
~~~~~~~~~~~~~~~~~~
.. raw:: html
Đoạn mã sau tạo ngẫu nhiên một minibatch dữ liệu. Ở đây, kích thước
batch ``batch_size`` biểu thị số mẫu trong mỗi minibatch, ``num_steps``
biểu thị chiều dài mỗi mẫu (là số bước thời gian trong trường hợp chuỗi
thời gian). Trong phép lấy mẫu ngẫu nhiên, mỗi mẫu là một chuỗi tùy ý
được lấy ra từ chuỗi gốc. Hai minibatch ngẫu nhiên liên tiếp không nhất
thiết phải liền kề nhau trong chuỗi góc. Mục tiêu của ta là dự đoán phần
tử tiếp theo dựa trên các phần tử đã thấy cho đến hiện tại, do đó nhãn
của một mẫu chính là mẫu đó dịch chuyển sang phải một phần tử.
.. code:: python
# Saved in the d2l package for later use
def seq_data_iter_random(corpus, batch_size, num_steps):
# Offset the iterator over the data for uniform starts
corpus = corpus[random.randint(0, num_steps):]
# Subtract 1 extra since we need to account for label
num_examples = ((len(corpus) - 1) // num_steps)
example_indices = list(range(0, num_examples * num_steps, num_steps))
random.shuffle(example_indices)
def data(pos):
# This returns a sequence of the length num_steps starting from pos
return corpus[pos: pos + num_steps]
# Discard half empty batches
num_batches = num_examples // batch_size
for i in range(0, batch_size * num_batches, batch_size):
# Batch_size indicates the random examples read each time
batch_indices = example_indices[i:(i+batch_size)]
X = [data(j) for j in batch_indices]
Y = [data(j + 1) for j in batch_indices]
yield np.array(X), np.array(Y)
.. raw:: html
Hãy tạo ra một chuỗi từ 0 đến 29, rồi sinh các minibatch từ chuỗi đó với
kích thước batch là 2 và số bước thời gian là 6. Nghĩa là tùy vào độ
dời, ta có thể sinh tối đa 4 hoặc 5 cặp :math:`(x, y)`. Với kích thước
batch bằng 2, ta thu được 2 minibatch.
.. code:: python
my_seq = list(range(30))
for X, Y in seq_data_iter_random(my_seq, batch_size=2, num_steps=6):
print('X: ', X, '\nY:', Y)
.. parsed-literal::
:class: output
X: [[ 0. 1. 2. 3. 4. 5.]
[18. 19. 20. 21. 22. 23.]]
Y: [[ 1. 2. 3. 4. 5. 6.]
[19. 20. 21. 22. 23. 24.]]
X: [[12. 13. 14. 15. 16. 17.]
[ 6. 7. 8. 9. 10. 11.]]
Y: [[13. 14. 15. 16. 17. 18.]
[ 7. 8. 9. 10. 11. 12.]]
.. raw:: html
.. raw:: html
.. raw:: html
Phân tách Tuần tự
~~~~~~~~~~~~~~~~~
.. raw:: html
Ngoài phép lấy mẫu ngẫu nhiên từ chuỗi gốc, chúng ta cũng có thể làm hai
minibatch ngẫu nhiên liên tiếp có vị trí liền kề nhau trong chuỗi gốc.
.. code:: python
# Saved in the d2l package for later use
def seq_data_iter_consecutive(corpus, batch_size, num_steps):
# Offset for the iterator over the data for uniform starts
offset = random.randint(0, num_steps)
# Slice out data - ignore num_steps and just wrap around
num_indices = ((len(corpus) - offset - 1) // batch_size) * batch_size
Xs = np.array(corpus[offset:offset+num_indices])
Ys = np.array(corpus[offset+1:offset+1+num_indices])
Xs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)
num_batches = Xs.shape[1] // num_steps
for i in range(0, num_batches * num_steps, num_steps):
X = Xs[:, i:(i+num_steps)]
Y = Ys[:, i:(i+num_steps)]
yield X, Y
.. raw:: html
Sử dụng các đối số như ở trên, ta sẽ in đầu vào ``X`` và nhãn ``Y`` cho
mỗi minibatch sau khi phân tách tuần tự. Hai minibatch liên tiếp sẽ có
vị trí trên chuỗi ban đầu liền kề nhau.
.. code:: python
for X, Y in seq_data_iter_consecutive(my_seq, batch_size=2, num_steps=6):
print('X: ', X, '\nY:', Y)
.. parsed-literal::
:class: output
X: [[ 1. 2. 3. 4. 5. 6.]
[15. 16. 17. 18. 19. 20.]]
Y: [[ 2. 3. 4. 5. 6. 7.]
[16. 17. 18. 19. 20. 21.]]
X: [[ 7. 8. 9. 10. 11. 12.]
[21. 22. 23. 24. 25. 26.]]
Y: [[ 8. 9. 10. 11. 12. 13.]
[22. 23. 24. 25. 26. 27.]]
.. raw:: html
Hãy gộp hai hàm lấy mẫu theo hai cách trên vào một lớp để duyệt dữ liệu
trong Gluon ở các phần sau.
.. code:: python
# Saved in the d2l package for later use
class SeqDataLoader:
"""A iterator to load sequence data."""
def __init__(self, batch_size, num_steps, use_random_iter, max_tokens):
if use_random_iter:
self.data_iter_fn = d2l.seq_data_iter_random
else:
self.data_iter_fn = d2l.seq_data_iter_consecutive
self.corpus, self.vocab = d2l.load_corpus_time_machine(max_tokens)
self.batch_size, self.num_steps = batch_size, num_steps
def __iter__(self):
return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps)
.. raw:: html
Cuối cùng, ta sẽ viết hàm ``load_data_time_machine`` trả về cả iterator
dữ liệu và bộ từ vựng để sử dụng như các hàm ``load_data`` khác.
.. code:: python
# Saved in the d2l package for later use
def load_data_time_machine(batch_size, num_steps, use_random_iter=False,
max_tokens=10000):
data_iter = SeqDataLoader(
batch_size, num_steps, use_random_iter, max_tokens)
return data_iter, data_iter.vocab
.. raw:: html
Tóm tắt
-------
.. raw:: html
- Mô hình ngôn ngữ là một kĩ thuật quan trọng trong xử lý ngôn ngữ tự
nhiên.
- :math:`n`-gram là một mô hình khá tốt để xử lý các chuỗi dài bằng
cách cắt giảm số phụ thuộc.
- Vấn đề của các chuỗi dài là chúng rất hiếm hoặc thậm chí không bao
giờ xuất hiện.
- Định luật Zipf không chỉ mô tả phân phối từ 1-gram mà còn cả các
:math:`n`-gram khác.
- Có nhiều cấu trúc trong ngôn ngữ nhưng tần suất xuất hiện lại không
đủ cao, để xử lý các tổ hợp từ hiếm ta sử dụng làm mượt Laplace.
- Hai giải pháp chủ yếu cho bài toán phân tách chuỗi là lấy mẫu ngẫu
nhiên và phân tách tuần tự.
- Nếu tài liệu đủ dài, việc lãng phí một chút và loại bỏ các minibatch
rỗng một nửa là điều chấp nhận được.
.. raw:: html
Bài tập
-------
.. raw:: html
1. Giả sử có :math:`100.000` từ trong tập dữ liệu huấn luyện. Mô hình
4-gram cần phải lưu trữ bao nhiêu tần số của từ đơn và cụm từ liền
kề?
2. Hãy xem lại các ước lượng xác suất đã qua làm mượt. Tại sao chúng
không chính xác? Gợi ý: chúng ta đang xử lý một chuỗi liền kề chứ
không phải riêng lẻ.
3. Bạn sẽ mô hình hóa một cuộc đối thoại như thế nào?
4. Hãy ước tính luỹ thừa của định luật Zipf cho 1-gram, 2-gram, và
3-gram.
5. Hãy thử tìm các cách lấy mẫu minibatch khác.
6. Tại sao việc lấy giá trị độ dời ngẫu nhiên lại là một ý tưởng hay?
- Liệu việc đó có làm các chuỗi dữ liệu văn bản tuân theo phân phối
đều một cách hoàn hảo không?
- Phải làm gì để có phân phối đều hơn?
7. Những vấn đề gì sẽ nảy sinh khi lấy mẫu minibatch từ một câu hoàn
chỉnh? Có lợi ích gì khi lấy mẫu một câu hoàn chỉnh?
.. raw:: html
.. raw:: html
Thảo luận
---------
- `Tiếng Anh `__
- `Tiếng Việt `__
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 Cường
- Lê Khắc Hồng Phúc
- Nguyễn Lê Quang Nhật
- Đinh Đắc
- Nguyễn Văn Quang
- Phạm Hồng Vinh
- Nguyễn Cảnh Thướng
- Phạm Minh Đức