Trước khi đi sâu tìm hiểu về Attention ta sẽ xem xét một chút về mô
hình Sequence to Sequence và lý do vì sao
attention lại được áp dụng cho mô hình này. Tôi có đọc nhiều bài viết trên mạng và thấy có
nhiều người cho rằng Sequence to Sequence model là một trường hợp đặc biệt của
Auto-Encoder, hay là một mô hình học sâu, tuy nhiên đây là một nhầm lẫn tai hại
về khái niệm. Thực tế việc sử dụng Auto-Encoder chỉ là một trong những giải
pháp giải quyết các vấn đề về Sequence to Sequence, tuy nhiên thì đây là giải pháp được dùng phổ biến và hiệu quả nhất hiện nay, do đó trong bài viết này chúng ta ngầm hiểu Sequence to Sequence model cũng chính là Auto-Encoder model.
Sequence to Sequence Models
Sequence to Sequence models là một lớp các mô hình được đề xuất để giải
quyết các lớp bài toán liên quan đến chuỗi như: Dịch máy, nhận dạng tiếng nói,
tổng hợp tiếng nói,…
- Dịch Máy (Machine Translation): Là hệ thống tự động dịch văn bản từ ngôn ngữ nguồn sang ngôn ngữ đích.
Hình 1: Ví dụ về dịch máy
- Tổng hợp tiếng nói: Là hệ thống tự động chuyển văn bản thành tiếng nói.
Hình 2: Ví dụ về tổng hợp tiếng nói
- Nhận dạng tiếng: nói là hệ thống tự động nhận dạng văn bản từ tiếng nói.
Hình 3: Ví dụ về nhận dạng tiếng nói
Ứng dụng của Sequence to Sequence model là rất rộng rãi, do đó cũng sẽ có rất nhiều loại mô hình khác nhau thuộc lớp mô hình này, tuy nhiên bài viết này chúng ta sẽ chỉ tập trung vào các mô hình Sequence to Sequence dựa trên mạng nơ ron học sâu. Lần đầu tiên được giới thiệu năm 2014 bởi nhóm nghiên cứu của google trong bài báo Sequence to Sequence Learning with Neural Networks [1], một mô hình Sequence to Sequence chuyển hóa một chuỗi đầu vào thành một véc tơ có chiều dài cố định, sau đó sử dụng một mạng LSTM để giải mã véc tơ này thành chuỗi đích. Điểm nhấn của bài báo này là đề xuất một kiến trúc cho phép chuỗi đầu vào và chuỗi đầu ra không cần phải có cùng độ dài, bằng cách sử dụng mô hình gồm có một Encoder và một Decoder (tương tự như hình 4).
Hình 4: Encoder - Decoder [2]
Mô hình gồm hai phần chính: Encoder và Decoder. Trong đó
Encoder sẽ chuyển hóa chuỗi đầu vào thành một véc tơ cố định, và Decoder sử dụng
véc tơ cố định này để tạo thành chuỗi đầu ra.
Hiện nay có rất nhiều biến thể với các kiến trúc khác nhau của Encoder, tuy nhiên ở đây tôi sẽ chỉ giới thiệu một kiến trúc đơn giản nhất sử dụng RNN. Với chuỗi đầu vào như “What are you doing ?”, RNN duyệt qua từng phần tử của chuỗi đầu vào, ở mỗi thời điểm (tạm gọi là mỗi time step) RNN nhận vào một phần tử của chuỗi và trạng thái ẩn (hidden state) của thời điểm (time step) trước đó. Đến cuối cùng, véc tơ trạng thái ẩn đầu ra của RNN sau khi duyệt qua phần tử cuối cùng cũng sẽ là véc tơ đầu ra của Encoder. Véc tơ cuối cùng này có nhiều tên gọi như Encoder vector, Thought vector, Context vector,... Nó được coi là chứa các thông tin được tóm gọn lại của chuỗi đầu vào.
Hình 5: Mô hình Sequence to Sequence trong dịch máy
Decoder cũng sử dụng RNN để giải mã Encoder vector. Ở thời điểm đầu tiên Decoder nhận đầu vào là Encoder véc tơ và _START token (_START và _END là hai phần tử đặc biệt dùng để đánh dấu điểm bắt đầu và kết thúc câu), sau đó ở các thời điểm tiếp theo RNN sẽ lấy đầu ra của thời điểm trước cùng với véc tơ trạng thái ẩn của thời điểm trước làm đầu vào, và cứ tiếp tục như vậy đến khi đầu ra của RNN là _END thì kết thúc. Xem trên hình 5 một ví dụ cụ thể của mô hình này trong dịch máy, với đầu vào là Encoder vector và _START trải qua một loạt các time steps (thời điểm) ta sẽ có đầu ra chuỗi “O1, O2, O3, O4, O5”, nếu đúng như mong muốn thì các chuỗi này sẽ chính là “Bạn đang làm gì thế”. Để cho quá trình huấn luyện nhanh hội tụ, khi huấn luyện người ta hay sử dụng một kỹ thuật là “Teacher Forcing”, trong đó tại các thời điểm thì đầu vào của RNN sử dụng chính các đầu ra thực tế của thời điểm trước thay vì sử dụng đầu ra dự đoán được. Trên hình 5, các đường nét đứt chính là biểu diễn của việc sử dụng các đầu ra thực tế của thời điểm trước làm đầu vào cho RNN chứ không dùng các đầu ra dự đoán ở các đường nét liền, cụ thể khi huấn luyện tại thời điểm thứ 2 ta sử dụng “Bạn” làm đầu vào cho RNN chứ không phải là “O1”.
Mô hình Sequence to Sequence dựa trên Auto Encoder được trình bày ở trên tuy đã giải quyết bài toán chuyển hóa chuỗi đầu vào thành chuỗi đầu ra có độ dài khác nhau, tuy nhiên nó tồn tại rất nhiều hạn chế. Dễ thấy nhất đó là việc sử dụng mạng RNN Encoder duyệt qua từng phần từ của chuỗi đầu vào và rồi lấy ra véc tơ trạng thái ẩn của mạng này ở thời điểm cuối cùng, và hi vọng rằng nó sẽ nhớ hết những thông tin cần thiết của chuỗi đầu vào trước khi chuyển hóa thành chuỗi đầu ra, điều này thật ngây thơ. Với những chuỗi dài, sau khi duyệt qua hàng loạt các phần thì thông tin ở những phần đầu sẽ bị “quên”, và đôi khi lại nhớ những thứ không cần nhớ. Do đó “Attention” sinh ra chính là để giải quyết những nhược điểm này [3].
Attention
Ý tưởng phía sau Attention là gì?
Để hiểu được điều này ta quay lại ví dụ phía trên khi dịch
“What are you doing ?” từ tiếng Anh sang “Bạn đang làm gì thế ?” trong tiếng Việt.
Ví dụ từ “bạn” trong tiếng Việt là dịch nghĩa của từ “you” trong tiếng anh, thì thời điểm khi dự đoán từ “bạn” rõ ràng rằng chúng ta sẽ phải chú ý nhiều hơn
vào từ “you” ở chuỗi đầu vào. Tương tự khi dự đoán từ “làm” thì từ “doing”
trong câu đầu vào sẽ được chú ý nhiều hơn. Cơ chế Attention sinh ra chính là dựa trên nhận
định này.
Từ ý tưởng trên khi đưa vào áp dụng trong mô hình Sequence to Sequence, thay vì chỉ sử dụng duy nhất véc tơ trạng thái ẩn cuối cùng làm đầu vào cho Decoder thì ta lưu lại và sử dụng véc tơ trạng thái ẩn tại tất cả các thời điểm khi duyệt chuỗi đầu vào. Sau đó khi Decoder tiến hành giải mã, thì từng thời điểm ta sẽ dành sự chú ý cao hơn vào những véc tơ trạng thái ẩn liên quan đại diện cho các phần tương ứng của chuỗi đầu vào. Chi tiết hơn về cách hoạt động của Attention sẽ được giải thích ngay sau đây.
Cách hoạt động của Attention
Trước khi đi vào những những công thức chi tiết về Attention, chúng ta cùng dạo qua chu trình hoạt động. Như đã nói ở trên, để hiện thực hóa ý tưởng
về sự chú ý “Attention”, trong mô hình Sequence to Sequence thay vì chỉ giữ lại
véc tơ trạng thái ẩn cuối cùng của Encoder, ta giữ lại toàn bộ các véc tơ trạng
thái ẩn tại tất cả các thời điểm.
Hình 6: Attention
Như trên hình 6, ta giữ lại toàn bộ véc tơ trạng thái ẩn từ h1 đến h5 của Encoder. Đưa toàn bộ các véc tơ trạng thái ẩn qua một Attention Layer, Attention Layer này có thể đơn giản chỉ là một mạng nơ ron lan truyền tiến (Feed forward neural networks), nhận đầu vào là tất cả các véc tơ trạng thái ẩn của Encoder và véc tơ trạng thái ẩn tại thời điểm trước của Decoder (Chính là Si-1 của RNN layer). Đầu ra sẽ là các hệ số “a1, a2, a3, a4, a5” tương ứng với các véc tơ trạng thái ẩn. Các hệ số này thể hiện mức độ chú ý của Decoder ở thời điểm hiện tại vào từng trạng thái ẩn. Đưa các hệ số này qua một lớp Softmax để chuẩn hóa thành các trọng số của sự chú ý (Attention weights), và đảm bảo các tính chất:
- Toàn bộ các trọng số nằm trong khoảng 0,1.
- Tổng các trọng số bằng 1.
Xét ví dụ trên hình 6, tại thời điểm “i” của Decoder giả sử
các trọng số e1=0.1, e2=0.6, e3=0.15, e4=0.1, e5=0.05. Khi đó, thời điểm
Decoder dự đoán Yi
phải dành sự chú ý nhiều hơn vào h2 vì e2 là lớn nhất. Các trọng số “ej” có thể được coi là xác xuất tại
thời điểm “i” Decoder chú ý nhiều hơn vào véc tơ trạng thái ẩn hj (hay cũng là chú ý
nhiều hơn vào phần tử đầu vào thứ j).
Context vector sẽ được tính bằng cách lấy tổng của các tích
giữa véc tơ trạng thái ẩn và các véc tơ trọng số:
Lấy Context vector ghép nối trực tiếp với đầu ra của Decoder ở thời điểm trước (Yi-1)
và đưa vào làm đầu vào cho Decoder ở thời điểm hiện tại. Sau đó, Decoder sẽ tạo
thành véc tơ đầu ra Yi và véc tơ trạng thái ẩn Si, cả hai
đều được sử dụng trong thời điểm tiếp theo.
Chú ý: Ở thời
điểm đầu tiên, khi chưa có Si-1 thì véc tơ trạng thái ẩn cuối cùng của
Encoder có thể được dùng thay thế.
Nào giờ cùng nhìn chi tiết hơn vào các công thức toán nhé
Trong quá
trình tính yi, Decoder sử dụng một hàm phi tuyến a(.) (Những hàm
phi tuyến được nhắc đến trong bài đều là những hàm có thể học được và khả vi) để tính các trọng số ai,j
tương ứng với mỗi hj tại thời điểm i của
Decoder. Hàm a(.) thông thường được xấp xỉ bằng một mạng nơ ron lan truyền tiến (Chính
là Attention Layer trên hình 6) với hàm hàm kích hoạt là hàm tanh, tuy nhiên thì cũng có nhiều loại
hàm khác được sử dụng cho những mục đích khác nhau. Những trọng số này sau đó được chuẩn hóa bởi một
lớp softmax để tạo thành phân bố xác suất trên chuỗi véc tơ h[5].
Trong đó ei,j
là trọng số đã được chuẩn hóa tương ứng với hj tại thời điểm i, và T
là độ dài của chuỗi đầu vào. Context vector được tính dựa trên tổng của tích
các hj và trọng số ei,j tương ứng của nó theo công thức
sau:
Cuối cùng
Decoder tính si và sau đó là yi dựa trên si-1,
yi-1 và ci:
Trong đó
f(.) được xấp xỉ bằng một mạng RNN, và g(.) là một hàm phi tuyến tạo đầu ra của
Decoder từ các véc tơ trạng thái ẩn của mạng RNN.
Một số cách phân loại Attention
Trong các
bài toán Sequence to Sequence người ta sử dụng rất nhiều loại Attention khác
nhau tùy theo mục đích của từng bài toán. Phần dưới đây tôi sẽ chỉ giới thiệu
hai cách phân loại cơ bản để các bạn có cái nhìn tổng quan về các hướng áp dụng
từng loại Attention (Nguồn tham khảo cách phân loại tại [6]).
Global Attention and Local Attention
Global
Attention thì giống như Attention tôi trình bày phía trên, nó sử dụng toàn bộ
véc tơ trạng thái ẩn đầu ra của Encoder trong từng thời điểm của Decoder, nhược
điểm của việc này là đôi khi mang nhiều thông tin dư thừa và tốn kém trong tính
toán.
Local
Attention tiếp cận theo một cách khác, trong đó một vài véc tơ trạng thái ẩn nằm
trong một cửa sổ nhất định được sử dụng. Cửa sổ này có điểm trung tâm là “p” đại
diện cho véc tơ trạng thái ẩn thứ p, và độ rộng là D tương ứng với D trạng thái
ẩn trong cửa sổ.
Hard Attention and Soft Attention
Theo Xu et al.[7] Soft Attention là khi Context vector véc tơ ci được tính bằng tổng có trọng số của các véc tơ trạng thái ẩn đầu ra của Encoder (hidden states). Với Hard Attention, thay vì lấy trung bình trọng số của tất cả các véc tơ trạng thái ẩn, thì sử dụng attention score để chọn ra véc tơ ẩn thích hợp nhất. Hard Attention thường được huấn luyện bằng cách sử dụng ReinForcement-Learning, còn Soft Attention thường dùng Gradient Decense kết hợp với Backpropagation. Dưới đây là chi tiết về hai Attention này :
References
[1] I. Sutskever, O. Vinyals, and Q. V. Le,
“Sequence to Sequence Learning with Neural Networks,” in Advances in Neural
Information Processing Systems 27, Z. Ghahramani, M. Welling, C. Cortes, N.
D. Lawrence, and K. Q. Weinberger, Eds. Curran Associates, Inc., 2014, pp.
3104–3112.
[2] S. Kostadinov, “Understanding
Encoder-Decoder Sequence to Sequence Model,” Medium, Nov. 10, 2019.
https://towardsdatascience.com/understanding-encoder-decoder-sequence-to-sequence-model-679e04af4346
(accessed Aug. 22, 2020).
[3] H. Lamba, “Intuitive Understanding of
Attention Mechanism in Deep Learning,” Medium, May 09, 2019. https://towardsdatascience.com/intuitive-understanding-of-attention-mechanism-in-deep-learning-6c9482aecf4f
(accessed Aug. 23, 2020).
[4] D. Bahdanau, K. Cho, and Y. Bengio,
“Neural Machine Translation by Jointly Learning to Align and Translate,” arXiv:1409.0473
[cs, stat], May 2016, Accessed: Aug. 24, 2020. [Online]. Available:
http://arxiv.org/abs/1409.0473.
[5] C. Raffel, M.-T. Luong, P. J. Liu, R. J.
Weiss, and D. Eck, “Online and Linear-Time Attention by Enforcing Monotonic
Alignments,” arXiv:1704.00784 [cs], Jun. 2017, Accessed: Aug. 27, 2020.
[Online]. Available: http://arxiv.org/abs/1704.00784.
[6] M. Venkatachalam, “Attention in Neural
Networks,” Medium, Jul. 07, 2019.
https://towardsdatascience.com/attention-in-neural-networks-e66920838742
(accessed Aug. 23, 2020).
Bài viết của bạn rất hay, rất dễ hiểu. Cảm ơn bạn!
Trả lờiXóaCảm ơn bạn.
XóaĐọc mấy bài về Attentin, tới bài này mới hiểu được chút xíu, thank you
Trả lờiXóaBài viết rất dễ hiểu, cảm ơn tác giả!
Trả lờiXóaNếu kích thước chuỗi đầu vào input khác với kích thước chuỗi đầu ra thì sao bạn?
Trả lờiXóaKhi đó kích thước attention layer sẽ bằng với kích thước chuỗi input, nhung sẽ khác với kích thước của output. Như vậy trong công thức tính context của bạn sẽ không đủ e cho h hoặc không đủ cho e. Vậy mình phải làm sao?
Tại mỗi decoder step thì chỉ có một decoder output vector Si được đưa vào cùng với các hidden states của encoder làm input cho attention thôi. Nên về cơ bản chuỗi đầu vào và đầu ra có đội dài khác nhau cũng không vấn đề gì.
Xóa