.. raw:: html
.. raw:: html
.. raw:: html
.. _sec_seq2seq_attention:
Chuỗi sang Chuỗi áp dụng Cơ chế Tập trung
=========================================
.. raw:: html
Trong phần này, chúng ta thêm cơ chế tập trung vào mô hình chuỗi sang
chuỗi (seq2seq) giới thiệu trong :numref:`sec_seq2seq` để gộp các
trạng thái theo trọng số tương ứng một cách tường minh.
:numref:`fig_s2s_attention` mô tả kiến trúc mô hình thực hiện mã hóa
và giải mã tại bước thời gian :math:`t`. Bộ nhớ của tầng tập trung ở đây
bao gồm tất cả thông tin mà bộ mã hóa đã được học—đầu ra của bộ mã hóa
tại từng bước thời gian. Trong quá trình giải mã, đầu ra của bộ giải mã
tại bước thời gian trước đó :math:`t-1` được sử dụng làm câu truy vấn.
Đầu ra của mô hình tập trung có thể được hiểu là thông tin ngữ cảnh của
chuỗi, phần ngữ cảnh này được ghép nối với đầu vào của bộ giải mã
:math:`D_t` và kết quả được đưa vào bộ giải mã.
.. raw:: html
.. _fig_s2s_attention:
.. figure:: ../img/seq2seq_attention.svg
Quá trình giải mã tại bước thời gian thứ 2 trong mô hình chuỗi sang
chuỗi áp dụng cơ chế tập trung.
.. raw:: html
Để minh họa kiến trúc tổng thể của mô hình seq2seq áp dụng cơ chế tập
trung, cấu trúc tầng của bộ mã hóa và bộ giải mã được mô tả trong
:numref:`fig_s2s_attention_details`.
.. raw:: html
.. _fig_s2s_attention_details:
.. figure:: ../img/seq2seq-attention-details.svg
Các tầng trong mô hình chuỗi sang chuỗi áp dụng cơ chế tập trung.
.. code:: python
from d2l import mxnet as d2l
from mxnet import np, npx
from mxnet.gluon import rnn, nn
npx.set_np()
.. raw:: html
.. raw:: html
.. raw:: html
Bộ Giải mã
----------
.. raw:: html
Do bộ mã hóa của mô hình seq2seq áp dụng cơ chế tập trung giống với bộ
mã hóa của ``Seq2SeqEncoder`` trong :numref:`sec_seq2seq` nên ở phần
này, chúng ta sẽ chỉ tập trung vào bộ giải mã. Ta thêm tầng tập trung
MLP (``MLPAttention``) có cùng kích thước ẩn với tầng LSTM trong bộ giải
mã. Sau đó ta khởi tạo trạng thái của bộ giải mã bằng cách truyền vào ba
đầu ra thu được từ bộ mã hóa:
.. raw:: html
- **Đầu ra của bộ mã hóa tại tất cả các bước thời gian**: được sử dụng
như bộ nhớ của tầng tập trung có cùng các khóa và giá trị;
.. raw:: html
- **Trạng thái ẩn của bộ mã hóa tại bước thời gian cuối cùng**: được sử
dụng làm trạng thái ẩn ban đầu của bộ giải mã;
.. raw:: html
- **Độ dài hợp lệ của bộ mã hóa**: để tầng tập trung có thể bỏ qua
những token đệm có trong đầu ra của bộ mã hóa.
.. raw:: html
Ở mỗi bước thời gian trong quá trình giải mã, ta sử dụng trạng thái ẩn
của tầng RNN cuối cùng làm câu truy vấn cho tầng tập trung. Đầu ra của
mô hình tập trung sau đó được ghép nối với vector embedding đầu vào để
đưa vào tầng RNN. Mặc dù trạng thái ẩn của tầng RNN cũng chứa thông tin
từ bộ giải mã ở các bước thời gian trước đó nhưng đầu ra của tầng tập
trung sẽ lựa chọn các đầu ra của bộ mã hóa một cách tường minh dựa vào
``enc_valid_len``\ nhằm loại bỏ những thông tin không liên quan.
.. raw:: html
Hãy cùng lập trình bộ giải mã ``Seq2SeqAttentionDecoder`` và xem xét sự
khác biệt của nó so với bộ giải mã trong mô hình seq2seq ở
:numref:`sec_seq2seq_decoder`.
.. code:: python
class Seq2SeqAttentionDecoder(d2l.Decoder):
def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
dropout=0, **kwargs):
super(Seq2SeqAttentionDecoder, self).__init__(**kwargs)
self.attention_cell = d2l.MLPAttention(num_hiddens, dropout)
self.embedding = nn.Embedding(vocab_size, embed_size)
self.rnn = rnn.LSTM(num_hiddens, num_layers, dropout=dropout)
self.dense = nn.Dense(vocab_size, flatten=False)
def init_state(self, enc_outputs, enc_valid_len, *args):
outputs, hidden_state = enc_outputs
# Transpose outputs to (batch_size, seq_len, num_hiddens)
return (outputs.swapaxes(0, 1), hidden_state, enc_valid_len)
def forward(self, X, state):
enc_outputs, hidden_state, enc_valid_len = state
X = self.embedding(X).swapaxes(0, 1)
outputs = []
for x in X:
# query shape: (batch_size, 1, num_hiddens)
query = np.expand_dims(hidden_state[0][-1], axis=1)
# context has same shape as query
context = self.attention_cell(
query, enc_outputs, enc_outputs, enc_valid_len)
# Concatenate on the feature dimension
x = np.concatenate((context, np.expand_dims(x, axis=1)), axis=-1)
# Reshape x to (1, batch_size, embed_size + num_hiddens)
out, hidden_state = self.rnn(x.swapaxes(0, 1), hidden_state)
outputs.append(out)
outputs = self.dense(np.concatenate(outputs, axis=0))
return outputs.swapaxes(0, 1), [enc_outputs, hidden_state,
enc_valid_len]
.. raw:: html
Giờ ta có thể chạy thử mô hình seq2seq áp dụng cơ chế tập trung. Để nhất
quán khi so sánh với mô hình không áp dụng cơ chế tập trung trong
:numref:`sec_seq2seq`, những siêu tham số ``vocab_size``,
``embed_size``, ``num_hiddens``, và ``num_layers`` sẽ được giữ nguyên.
Kết quả, ta thu được đầu ra của bộ giải mã có cùng kích thước nhưng khác
về cấu trúc trạng thái.
.. code:: python
encoder = d2l.Seq2SeqEncoder(vocab_size=10, embed_size=8,
num_hiddens=16, num_layers=2)
encoder.initialize()
decoder = Seq2SeqAttentionDecoder(vocab_size=10, embed_size=8,
num_hiddens=16, num_layers=2)
decoder.initialize()
X = np.zeros((4, 7))
state = decoder.init_state(encoder(X), None)
out, state = decoder(X, state)
out.shape, len(state), state[0].shape, len(state[1]), state[1][0].shape
.. parsed-literal::
:class: output
((4, 7, 10), 3, (4, 7, 16), 2, (2, 4, 16))
.. raw:: html
.. raw:: html
.. raw:: html
Huấn luyện
----------
.. raw:: html
Chúng ta hãy xây dựng một mô hình đơn giản sử dụng cùng một bộ siêu tham
số và hàm mất mát để huấn luyện như :numref:`sec_seq2seq_training`. Từ
kết quả, ta thấy tầng tập trung được thêm vào mô hình không tạo ra cải
thiện đáng kể nào do các chuỗi trong tập huấn luyện khá ngắn. Bởi chi
phí tính toán tốn thêm từ các tầng tập trung trong bộ mã hóa và bộ giải
mã, mô hình này họat động chậm hơn nhiều so với mô hình seq2seq không áp
dụng tập trung.
.. code:: python
embed_size, num_hiddens, num_layers, dropout = 32, 32, 2, 0.0
batch_size, num_steps = 64, 10
lr, num_epochs, ctx = 0.005, 200, d2l.try_gpu()
src_vocab, tgt_vocab, train_iter = d2l.load_data_nmt(batch_size, num_steps)
encoder = d2l.Seq2SeqEncoder(
len(src_vocab), embed_size, num_hiddens, num_layers, dropout)
decoder = Seq2SeqAttentionDecoder(
len(tgt_vocab), embed_size, num_hiddens, num_layers, dropout)
model = d2l.EncoderDecoder(encoder, decoder)
d2l.train_s2s_ch9(model, train_iter, lr, num_epochs, ctx)
.. parsed-literal::
:class: output
loss 0.033, 3874.4 tokens/sec on gpu(0)
.. figure:: output_seq2seq-attention_vn_6a9836_7_1.svg
.. raw:: html
Cuối cùng, ta hãy thử dự đoán một vài mẫu dưới đây.
.. code:: python
for sentence in ['Go .', 'Wow !', "I'm OK .", 'I won !']:
print(sentence + ' => ' + d2l.predict_s2s_ch9(
model, sentence, src_vocab, tgt_vocab, num_steps, ctx))
.. parsed-literal::
:class: output
Go . => va !
Wow ! => !
I'm OK . => je vous ai .
I won ! => j'ai gagné !
.. raw:: html
Tóm tắt
-------
.. raw:: html
- Mô hình seq2seq áp dụng cơ chế tập trung thêm một tầng tập trung vào
mô hình seq2seq ban đầu.
- Bộ giải mã của mô hình seq2seq áp dụng cơ chế tập trung được truyền
vào ba đầu ra từ bộ mã hóa: đầu ra của bộ mã hóa tại tất cả các bước
thời gian, trạng thái ẩn của bộ mã hóa tại bước thời gian cuối cùng,
độ dài hợp lệ của bộ mã hóa.
.. raw:: html
Bài tập
-------
.. raw:: html
1. So sánh ``Seq2SeqAttentionDecoder`` và ``Seq2seqDecoder`` bằng cách
sử dụng cùng bộ tham số và kiểm tra giá trị hàm mất mát.
2. Bạn hãy thử suy nghĩ liệu có trường hợp nào mà
``Seq2SeqAttentionDecoder`` vượt trội hơn ``Seq2seqDecoder``?
.. 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
- Đỗ Trường Giang
- Nguyễn Văn Quang
- Nguyễn Văn Cường
- Lê Khắc Hồng Phúc
- Phạm Hồng Vinh