Chuyển đến nội dung chính

Convolution Augmented Transformer (Conformer) trong ASR và TTS

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

Connectionist Temporal Classification

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.
Cả hai vấn đề trên đều có thể được giải quyết bởi phương pháp phân loại CTC (Connectionist Temporal Classification). Để thấy rõ hơn, ta sẽ đi sâu vào bài toán nhận dạng chữ viết tay, một ví dụ của hệ thống này được minh họa trên hình 1.
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 đề :
  • 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
CTC có thể giải quyết cả ba vấn đề trên:
  • 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.
Xem ví dụ sau:
  • '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.
Điều này đảm bảo được rằng tất cả những ký tự lặp sát nhau ban đầu luôn được ngăn cách bởi ký tự blank. Và sau đó trong quá trình nhận dạng, ta có thể co hết những ký tự lặp sát nhau thành một, bỏ đi các ký tự blank mà vẫn đảm bảo tính đúng đắn của kết quả.

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.
Hình 4: Ma trận Alignments đầu ra của mạng CTC.
Ta gọi y là chuỗi đầu ra của mạng, khi đó y_k^t là kết quả của ký tự 'k' tại thời điểm 't'. Phân phối các đầu ra y_k^t thuộc tập {L^{'T}} 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:
Công thức 1
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: {L^{'T}} \mapsto {L^{ \le T}} với {L^{ \le T}} 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
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:
Công thức 3
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:
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 l \in {L^T}.
  • 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)).
Ví dụ minh họa trên hình 4, các ký tự là {a, b, -} và có 5 time-steps. Áp dụng Best Path Decoding ta được: tại time-step t0, ký tự hợp lý nhất là 'a', tương tự với t1, t2, cũng vậy. Ký tự blank có xác suất cao nhất tại time-step t3, còn time-step t4 là 'b'. Đường dẫn hợp lý sẽ là 'aaa-b'. Bây giờ ta bỏ các ký tự lặp và ký tự blank được kết quả cuối cùng là 'ab'.
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

Nhận xét

  1. Bài viết bổ ích, thanks tác giả

    Trả lờiXóa
  2. Hi a, e là Tuấn trước cùng team Voice với a nè.
    Đâ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,...)

    Trả lờiXóa
    Trả lời
    1. Cảm ơn đóng góp của em nhé, có thời gian anh nhất đính sẽ đọc.

      Xóa
  3. Bà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

Đăng nhận xét

Bài đăng phổ biến từ blog này

Attention Mechanism

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 S equence to S equence 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

Convolution Augmented Transformer (Conformer) trong ASR và TTS

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

Tổng hợp tiếng nói sử dụng mô hình Markov ẩn

Trong hai mươi năm trở lại đây, tổng hợp tiếng nói dựa trên mô hình Markov ẩn là một trong những hướng tiếp cận được nghiên cứu rộng rãi nhất cho đến khi các mô hình dựa trên mạng nơ ron học sâu xuất hiện. Trước khi đến với các mô hình học sâu, chúng ta cùng xem qua mô hình đã làm mưa làm gió mấy chục năm qua. Vậy mô hình Markov ẩn là gì? Hình 1: Mô hình Markov ẩn với ba trạng thái Mô hình Markov ẩn (HMM: Hidden Markov Model) là một mô hình máy trạng thái, mô hình này cho phép chúng ta xem xét đến hai thành phần là sự kiện quan sát được và các sự kiện ẩn. Ví dụ trong nhận dạng tiếng nói thì sự kiện quan sát được là các đặc trưng âm học của tiếng nói, còn sự kiện ẩn là các từ.  Một mô hình markov ẩn như biểu diễn trên hình 1 thường gồm có các thành phần chính sau:  Q = q1,q2,,,qN: Q là tập của N trạng thái A = a11,a12,,,,ann: A là ma trận chuyển trạng thái với aij là xác xuất chuyển từ trạng thái i sang trạng thái j, và ta có  O = o1,o2,,,,oT: O là một chuỗi T các qua