Conformer Chú ý: Mọi người nên tìm hiểu kỹ về Transformer và Multi-head Self Attention trước khi đọc bài này. Câu hỏi cho người đọc: Có cần thiết áp dụng Macron-style và Relative Position Encoding cho Conformer trong các bài toán xử lý tiếng nói hay không? ASR Conformer Trước khi đi vào phần chính, chúng ta sẽ lướt qua xem hướng tiếp cận đang cho hiệu quả cao nhất trong nhận dạng tiếng nói, RNN-Transducer và những biến thể cải tiến của nó. Mô hình chung của một Neural RNN-Transducer được biểu diễn trong hình 1. Hình 1: Neural Transducer [1] Trong đó, Predictor và Encoder có thể được xây dựng bởi nhiều kiến trúc khác nhau như RNNs, LSTM hay Transformer để đưa ra các biểu diễn trung gian của các chuỗi đầu vào. Với Predictor là biểu diễn của chuỗi văn bản (label), và Encoder là biểu diễn của chuỗi audio-frame. Cùng với Predictor và Encoder, RNN-T loss được sử dụng để cực đại hóa tổng xác suất của mọi alignment giữa audio đầu vào và văn bản đầu ra, từ đó giúp cho mô hình học được alignme
Nếu bạn muốn xây dựng một chương trình nhận dạng tiếng nói hoặc chữ viết thì mạng nơ ron là một trong những lựa chọn tốt nhất, vì ở thời điểm hiện tại nó cho thấy kết quả tốt hơn hẳn các phương pháp khác. Trong trường hợp này Connectionist Temporal Classification là một lựa chọn hợp lý và giải quyết được hầu hết các vấn đề gặp phải.
Bài viết "An Intuitive Explanation of Connectionist Temporal Classification" của tác giả Harald Scheidl đăng trên Medium đã giải thích cặn kẽ và rất dễ hiểu, do đó tôi sẽ dựa trên phần lớn bài viết này, chỉnh sửa và thêm góc nhìn toán học để các bạn có thể hiểu cặn kẽ vấn đề.
Mạng nơ ron học sâu áp dụng cho các bài toán nhận dạng thường bao gồm các Convolution Layers (CNN) để trích ra các chuỗi đặc trưng và các Recurrent Layers (RNN) để luân chuyển những thông tin xuyên suốt chuỗi đầu vào theo thời gian. Các điểm số đầu ra của mỗi ký tự (hoặc âm vị) trong chuỗi đầu vào được biểu diễn đơn giản bởi một ma trận. Với ma trận này có hai điều cần làm:
- Train: Tính toán giá trị mất mát (Loss) để huấn luyện mô hình.
- Infer: Tìm ra văn bản đầu ra hoặc chuỗi đầu ra mong muốn từ đầu vào là audio hoặc ảnh tùy theo bài toán.
Hình 1: Tổng quan về áp dụng mạng nơ ron cho nhận dạng chữ viết tay. |
Tại sao lại chọn CTC
Tất nhiên là chúng ta có thể tự tạo bộ dữ liệu bằng tay, xác định xem vị trí của mỗi frame trong ảnh tương ứng với ký tự nào (xem hình 2), và sau đó huấn luyện mô hình mạng nơ ron với đầu ra là character-score cho mỗi frame để nhận dạng ký tự từ bộ dữ liệu này. Tuy nhiên, điều này tồn tại hai vấn đề :
CTC có thể giải quyết cả ba vấn đề trên:
- Bạn sẽ phải tốn rất nhiều thời gian ( với chán nản nữa 😂) để gán nhãn dữ liệu ở mức ký tự.
- Bạn chỉ lấy được duy nhất character-score (Có thể coi là xác suất xuất hiện của ký tự với frame hiện tại) và do đó cần thêm một vài xử lý nữa để tìm được văn bản cuối cùng. Vấn đề nảy sinh ở đây là một ký tự có thể xuất hiện ở nhiều frame liên tiếp, ví dụ như trên hình 2 kết quả nhận được là 'ttooo' vì o và t trải dài trên nhiều frame. Để đơn giản, chỉ cần xóa bỏ các ký tự lặp lại các ký tự trước nó, kết quả nhận được sẽ là 'to'. Nhưng làm sao để giải quyết trường hợp 'too'? khi đó việc xóa bỏ sẽ làm kết quả bị sai.
Hình 2: Gán nhãn cho mỗi fra |
- Chúng ta chỉ cần cho CTC biết đoạn văn bản nào tương ứng với hình ảnh hiện tại, và không cần phải quan tâm là ký tự nào tương ứng với những frame nào. CTC sẽ tự học điều này.
- Không cần thêm những xử lý sau khi nhận được văn bản đầu ra.
Vậy CTC hoạt động như thế nào?
Như đã nói phía trên, chúng ta không muốn phải đi gán nhãn từng frame cho từng ảnh (từ giờ sẽ gọi mỗi frame là time-step). Với CTC, mạng nơ ron sẽ được huấn luyện và điều chỉnh dựa trên hàm CTC loss. Hàm CTC loss nhận đầu vào là ma trận đầu ra của mạng nơ ron (thể hiện điểm số hoặc xác xuất phân loại từng kí tự theo từng time-step) và văn bản tương ứng với hình ảnh. Vậy, làm sao để mô hình biết được rằng khi nào ký tự xuất hiện, và nó xuất hiện trong bao nhiêu time-step? Yeah, mô hình không hề biết mà thay vào đó, nó sẽ thử tất cả các Alignments (Cũng có thể hiểu là các đường đi có thể nối các chuỗi ký tự dọc theo các frame đã xuất hiện) của văn bản tương ứng với hình ảnh, và lấy tổng xác suất cả các alignments này. Như vậy, xác suất xuất hiện của văn bản sẽ cao nếu tổng xác suất đạt giá trị cao, khi đó loss sẽ thấp.
Encoding the text
Phần đầu tiên ta đã nêu một trong những lý do CTC được lựa chọn đó là giải quyết các vấn đề về lặp ký tự (ví dụ như từ 'too'). Vấn đề này được giải quyết bằng cách chèn thêm một ký tự đặc biệt gọi là blank, thông thường ký tự được chọn làm blank là '-'. Với bộ ký tự L và ký tự blank, ta sử dụng một số tiêu chí sau trong quá trình mã hóa văn bản (Encoding text) để giải quyết vấn đề lặp ký tự.
- Khi mã hóa văn bản, ký tự blank có thể được thêm nhiều lần, vào bất cứ đâu. Kỹ tự này sẽ bị xóa khi decode (hay khi nhận dạng).
- Tất cả những ký tự lặp lại ký tự lặp sát nhau cần phải được thêm blank vào giữa chúng, ví dụ hello → hel-lo hoặc hel--lo. Thêm nữa, có thể thêm bao nhiêu ký tự (Cả blank lẫn không blank) tùy thích.
- 'to' → '---tttooo', hoặc '-t-o' hoặc 'to'.
- 'too' → '---ttto-o' hoặc ''-t-o-o-', hoặc 'to-o'. Tuy nhiên, luôn phải có ký tự blank ở giữa hai ký tự 'o' liền nhau ban đầu.
Tính Loss
Như đã biết, đầu ra của mạng nơ ron trong CTC là một ma trận chứa xác suất xuất hiện của mỗi ký tự tương ứng với mỗi time-step, một ví dụ nhỏ của ma trận này trên hình 3: Trong đó có hai time-step là t0 và t1, ba ký tự là 'a', 'b', và blank '-'. Với mỗi time-step tổng xác suất sẽ là 1.
Hình 3: Ma trận đầu ra của mạng nơ ron trong CTC. |
Xác suất mỗi alignment (hay đường dẫn) được tính bằng cách nhân tất cả các xác suất của mỗi ký tự dọc theo alignment đó lại với nhau. Với ví dụ trên, xác suất của đường dẫn (path) 'aa' là 0.4*0.4=0.16 trong khi đó 0.4*0.6 = 0.24 là xác suất của 'a-' và 0.6*0.4=0.24 là '-a'. Để tính được xác suất của cả văn bản, ta cộng tổng tất cả các xác suất của của mỗi alignments hay đường dẫn hình thành nên văn bản này. Quay lại ví dụ trên: Văn bản đầu vào là 'a', ta phải tính tất cả các aligments có độ dài là 2 (vì ma trận có 2 time-step), đó là: 'aa', 'a-', '-a'. Suy ra tổng xác suất của các alignments trên bằng 0.4*0.4 + 0.4*0.6 + 0.6*0.4 = 0.64, đây cũng là xác suất của văn bản 'a'. Nếu văn bản đầu vào là rỗng "", thì chỉ có duy nhất một alginment tương ứng với nó: '--', alignment này có xác suất là 0.6*0.6 = 0.36.
Một cách kỹ càng hơn, ta thấy rằng 0.64 chính là xác xuất xuất hiện của văn bản 'a', nhưng đây không phải là loss. Loss đơn giản là negative logarithm của xác xuất này. Giá trị loss sẽ được lan truyền ngược thông qua mạng nơ ron khi đó tham số của mạng sẽ được cập nhật.
Nhìn ở góc độ toán học
Gọi L là một tập tất cả các ký tự trong bảng chữ cái, Z là tập tất cả các chuỗi có thể hình thành từ các ký tự trong tập L. Còn X là tập tất cả các chuỗi số thực, hay chính là đặc trưng đầu vào của quá trình nhận dạng. Mục tiêu của bài toán là huấn luyện bộ Temporal classifier h: X → Z để phân loại chuỗi đầu ra dựa vào chuỗi đầu vào x trong X. Trong mạng CTC, tại mỗi time-step đầu ra của mạng là kết quả của lớp softmax có số phần tử chính là số ký tự có trong L cộng thêm với một ký tự blank. Hay nói cách khác, đầu ra của mạng CTC là xác xuất phân loại ký tự trong {L + blank}. Hình 4 minh họa ma trận đầu ra cuối cùng (sau tất cả các time-step) của mạng nơ ron CTC.
Ta gọi y là chuỗi đầu ra của mạng, khi đó là kết quả của ký tự 'k' tại thời điểm 't'. Phân phối các đầu ra thuộc tập chứa các chuỗi có độ dài T trên tập chữ cái L' = L ⋃ {blank}. Và xác suất một alignment như sau:
Trong đó: π là alignment (hay đường dẫn). Ẩn sâu trong công thức trên là giả định rằng đầu ra của mạng nơ ron tại mỗi thời điểm là độc lập có điều khiện, điều này được đảm bảo bằng cách yêu cầu không tồn tại kết nối phản hồi ở lớp đầu ra đến chính nó hoặc chính mạng nơ ron.
Tiếp theo để tìm ra kết quả cuối cùng, ta định nghĩa một biến đối many-to-one map B: với là tập của tất cả các chuỗi ký tự có độ dài nhỏ hơn hoặc bằng T. Map B chỉ đơn giản là loại bỏ các ký tự blank và ký tự lặp lại: Ví dụ: B(a-b-b) → abb hay B(aa-bb-b) → abb, từ đó ta có thể tính xác suất của một chuỗi 'l' trong tập Z theo công thức:
Từ công thức trên, đầu ra của bộ phân loại là chuỗi ký tự gần đúng nhất:
Cuối cùng hàm Loss được lựa chọn để đạt Maximum Likelihood. Hay nói cách khác, khi tối thiểu hóa hàm Loss ta sẽ đạt cực đại hóa Log Likelihood, vì lý do đó hàm mục tiêu sẽ là Negative Log Likelihood:
Hình 4: Ma trận Alignments đầu ra của mạng CTC. |
Công thức 1 |
Tiếp theo để tìm ra kết quả cuối cùng, ta định nghĩa một biến đối many-to-one map B: với là tập của tất cả các chuỗi ký tự có độ dài nhỏ hơn hoặc bằng T. Map B chỉ đơn giản là loại bỏ các ký tự blank và ký tự lặp lại: Ví dụ: B(a-b-b) → abb hay B(aa-bb-b) → abb, từ đó ta có thể tính xác suất của một chuỗi 'l' trong tập Z theo công thức:
Công thức 2 |
Công thức 3 |
Công thức 4 |
Decoding
Sau khi đã huấn luyện thành công mô hình, chắc hẳn bạn sẽ muốn dùng nó vào việc nhận dạng những ảnh chưa từng thấy khi huấn luyện? Yeah, phần trên đã nói cách để tìm xác suất của một chuỗi ký tự với một hình ảnh đầu vào. Nhưng lần này, sẽ không có chuỗi ký tự nào hết việc của chúng ta chính là tìm ra chuỗi đó, một thuật toán nhanh và đơn giản đó là 'Best Path Decoding' bao gồm hai bước:
Hình 4: Đầu ra của mạng nơ ron. Đường nét đứt biểu diễn đường dẫn hợp lý nhất. |
- Tại mỗi time-step, tìm ký tự có xác suất lớn nhất và kết hợp chúng lại với nhau thành đường dẫn (hay alignment) hợp lý nhất, xem công thức (3) với .
- Loại bỏ các ký tự trùng nhau và ký tự blank để đạt được kết quả cuối cùng, chính là B(h(x)).
Best Path Decoding là một phương pháp tìm kiếm dựa trên xấp xỉ, do đó dễ dàng để tìm ra trường hợp mà nó trả về kết quả sai: Như trong ví dụ đầu tiên trên Hình 3, áp dụng thuật toán Best Path Decoding ta được đường dẫn tối ưu là '--' có xác suất 0.6*0.6=0.36. Tuy nhiên đây là kết quả sai , kết quả đúng đáng ra phải là 'a' với xác suất 0.64. Mặc dù vậy thuật toán xấp xỉ này vẫn cho kết quả tốt trong thực tế, và chạy rất nhanh. Có nhiều tuật toán decoder cho kết quả tốt hơn như Beam-Search, Token Passing,...
Tổng Kết
Trên đây ta đã đi qua một cách khải quát, giản lược về Connectionist Temporal Classification và cách mà nó được áp dụng vào các bài toán nhận dạng. Hi vọng bạn đọc sẽ có được cái nhìn cơ bản về phương pháp này, dễ dàng áp dụng được vào trong bài toán của bản thân.
Tài liệu tham khảo
1. Graves, A.,
Fernandez, S., Gomez, F., Schmidhuber, J.: Connectionist Temporal
Classification: Labelling Unsegmented Sequence Data with Recurrent Neural
Networks. 8
2. Scheidl,
H.: An Intuitive Explanation of Connectionist Temporal Classification,
https://towardsdatascience.com/intuitively-understanding-connectionist-temporal-classification-3797e43a86c
3. Giới
thiệu về Connectionist Temporal Classification (CTC) (Phần 1),
https://viblo.asia/p/gioi-thieu-ve-connectionist-temporal-classification-ctc-phan-1-ORNZqj08l0n
Bài viết bổ ích, thanks tác giả
Trả lờiXóaDễ hiểu quá!
Trả lờiXóaHi a, e là Tuấn trước cùng team Voice với a nè.
Trả lờiXóaĐây là các ý tưởng e đóng góp nếu a muốn viết các phần khác, chuyên sâu hơn về CTC:
- Thuật toán forward-backward để tính CTC loss trong khi training: công thức quy hoạch động giúp tìm xác suất các path mong muốn một cách nhanh nhất, do không gian tìm kiếm rất lớn nên cần có thuật toán chạy nhanh để giúp việc training khả thi
- Chi tiết về thuật toán beam search và có thể kết hợp LM score cho các bài toán dự đoán văn bản (như nhận dạng tiếng nói, chữ viết tay,...)
Cảm ơn đóng góp của em nhé, có thời gian anh nhất đính sẽ đọc.
XóaBài viết rất dễ hiểu. Nhiều bài viết khác đọc hoài không hiểu. Cám ơn bạn rất nhiều.
Trả lờiXóa