Phác họa bài post:
ⓐ
Text-to-Speech?
ⓑ Approach?
(Cách tiếp cận)
ⓒ Đo chất lượng
mô hình
ⓓ Khái niệm
vocoder.
ⓔ Biến hóa
vocoder.
ⓕ Cách tiếp cận
theo tư duy Machine Learning.
ⓖ Một vài
thách thức đối với text-to-speech.
-
Để giúp anh/chị
quyết định có đọc tiếp hay không, tôi xin phép cung cấp các thông tin liên quan
đến bài post này như sau:
·
Chủ
đề: Khoa học thường thức
(80%), Machine Learning (20%)
·
Tính
thời sự: Tháng 5 năm
2019.
·
Thời
gian đọc: 7 phút, không
tính thời gian uống cà phê.
-
Xin phép anh/chị,
hôm nay chúng ta đàm đạo về “máy nói”, nhưng chỉ giới hạn trong khuôn khổ là
“máy nói theo văn bản”: “text-to-speech” (TTS). Nghĩa là chúng ta không
đi quá xa về “máy nói”: người đối thoại với máy, người hỏi – máy trả lời, “máy
diễn thuyết”, … Chỉ đơn giản là cho một đoạn văn bản và xin mời “máy đọc đoạn
văn bản đấy”. Tất nhiên, trước hết máy phải đọc đúng, đọc rõ, sau nữa đọc càng hay
thì càng tốt.
🗎→🔈
ⓐ Text-to-Speech?
Một cách giản
lược, chúng ta có thể hình dung quy trình biến đổi “văn bản-thành-giọng nói”
như sau:
·
Giả
thiết chúng ta có một đoạn văn bản. Đoạn văn bản này có thể chứa các con số hoặc
từ viết tắt. Nếu có con số hoặc từ viết tắt thì trước hết chúng ta phải biến
chúng thành “lời”. Ví dụ, “12” thành “mười hai”; “TW” thành “trung ương”.
(Công đoạn này được đặt tên là “chuẩn hóa văn bản”: text normalization.)
-
·
Tiếp
theo, người ta tách văn bản thành từng từ, phiên âm từng từ và phối các phiên
âm thành các đoạn có ngữ điệu, ví dụ: cụm từ, mệnh đề, câu văn. Đến đây, đoạn
văn bản được biến thành một dãy các đoạn mã phiên âm (phonetic transcription).
(Công đoạn này được đặt tên là “chuyển đổi văn bản thành phiên âm”: text-to-phoneme.)
-
·
Căn
cứ vào đoạn mã phiên âm, người ta cho phát ra thành âm thanh, ra loa.
(Công đoạn này có tên là “bộ tổng hợp”: synthesizer.)
-
🗎→🔈
ⓑ Approach?
(Cách tiếp cận)
Tiếp theo, chúng ta bàn chi tiết hơn các
giải pháp cho “text-to-speech”. Khi nói đến các giải pháp TTS, người ta
thường quan tâm đến 2 yêu cầu rất cơ bản về chất lượng. Đó là:
·
Dễ
hiểu (intelligibility): chúng ta phải hiểu được “máy nói” một cách dễ
dàng. “Dễ hiểu” ở đây không có ý về ngữ nghĩa câu văn mà là phát âm nghe dễ hiểu.
·
Tính
tự nhiên (naturalness): “máy nói” giống như người nói.
Có
rất nhiều cách để biến “văn bản-thành-giọng nói”. Dưới góc độ các giải pháp
“kinh điển”, xin phép anh/chị bàn về 2 cách tiếp cận: ghép âm và máy tự tạo giọng
nói.
·
➡
Ghép âm (concatenation synthesis).
Phương thức tổng hợp này là ghép (xâu chuỗi) các đoạn “người nói” đã được ghi
âm lại với nhau. Cách này rõ ràng là đạt được mức độ tự nhiên cao. Tuy nhiên sự
biến thiên trong giọng nói của đoạn trước không dễ gì khớp với sự biến thiên
trong đoạn tiếp theo ngay sau đó nên thường xảy ra hiện tượng “lệch sóng” giữa
2 đoạn liền nhau. Cùng chung cách ghép âm, có 3 cách tiếp cận.
1.
Tuyển
chọn đơn nguyên âm thanh (Unit selection
synthesis). Theo cách này, đầu tiên người ta thiết lập một cơ sở dữ
liệu (CSDL) về “lời nói” được ghi âm. Trong quá trình thiết lập CSDL, mỗi một
câu nói được tách ra thành các “đơn nguyên” (đơn vị phát âm). Các “đơn nguyên”
có thể là đơn âm (phone), cặp âm (diphone), bán âm (half-phone),
âm tiết (syllable), hình vị (morpheme), từ (word), cụm từ
(phrase), câu (sentence). Mỗi một bản ghi của CSDL còn có một số
thuộc tính khác đi kèm như âm độ (pitch), thời lượng, vị trí của âm tiết,
các âm vị trước, sau âm tiết. Ngoài phần ghi âm, người ta còn lưu sóng và phổ của
phần ghi âm để có thể dễ dàng khảo sát đoạn ghi âm bằng đồ thị.
-
Làm thế nào để chuyển đổi văn bản thành giọng nói? Cách làm: bộ tổng hợp (synthesizer)
chia đoạn văn bản thành các “đơn nguyên”. Mỗi một “đơn nguyên” phải tương ứng với
một bản ghi trong CSDL nói trên. Sau khi thay các “đơn nguyên” bằng các đoạn
ghi âm, kết quả là đoạn văn bản được chuyển thành một chuỗi các các đoạn ghi âm
nối tiếp nhau được lấy ra từ CSDL. Việc của máy là cho “phát thanh” chuỗi các các
đoạn ghi âm này.
-
Ở trên, tôi chưa đề cập đến thuật toán chuyển văn bản thành chuỗi “đơn nguyên”.
Một văn bản có thể chuyển thành rất nhiều chuỗi “đơn nguyên” khác nhau. Nghĩa
là có rất nhiều chuỗi “đơn nguyên” khác nhau cùng “nói” một đoạn văn bản. Vậy
chuỗi nào là tối ưu? Để biết được chuỗi nào là tối ưu người ta căn cứ vào hàm
đánh giá (cost function). Chuỗi nào có tổng “giá” thấp nhất, chuỗi đó là
tối ưu.
-
Về mặt nguyên tắc, cách tiếp cận này đạt độ tự nhiên cao nhất, vì các đoạn ghi
âm trong CSDL là ghi lời nói của người thật. Tuy nhiên, chúng ta vẫn phải tính
đến vấn đề khớp nối giữa 2 đoạn ghi âm. Chú ý rằng, đây là khớp nối giữa 2 đoạn
sóng phát âm. Trong thực tế, biên độ cuối của đoạn sóng đứng đằng trước (của
“đơn nguyên” trước) thường sẽ không khớp với biên độ đầu của đoạn sóng tiếp
theo (của “đơn nguyên” sau). Đây là hiện tượng xô lệch âm thanh. Vì vậy, vẫn phải
cần có sự can thiệp của xử lý tín hiệu số (digital signal processing - DSP)
nhằm làm mịn đoạn sóng ở chỗ khớp nối – tức là giảm thiểu mức xô lệch âm thanh. Chúng ta cũng lưu ý rằng càng có nhiều DSP
thì mức độ tự nhiên càng giảm. Muốn DSP ít can thiệp thì CSDL cần có các đơn
nguyên dài hơn, ghi âm bằng lời nói tự nhiên, để tránh hiện tượng xô lệch âm
thanh. Khi thêm các đơn nguyên dài như vậy, CSDL phải rất lớn và hàm đánh giá (cost
function) chạy chậm hơn. [Tham khảo ở đây.]
-
2.
Cặp
âm (Diphone synthesis). Trước khi bàn
đến cách tiếp cận này, chúng ta tìm hiểu qua khái niệm về cặp âm (diphone)?
Trong ngữ âm, diphone là cặp đơn âm đi liên kề nhau khi phát âm. Ví dụ,
từ diphone, trong tiếng Anh, khi phiên âm chúng ta được: [daɪfəʊn]. Dưới
góc độ cặp âm, đoạn phiên âm [daɪfəʊn] gồm các cặp âm sau: [da], [aɪ], [ɪf], [fə],
[əʊ], [ʊn].
-
Trở lại với phương pháp tiếp cận. Đối với một ngôn ngữ, người ta thiết lập một
CSDL gồm tất cả các cặp âm (diphone) có thể có. Về mặt nguyên tắc, nếu
ngôn ngữ đó có P đơn âm thì sẽ có P2 cặp âm. Tuy
nhiên, trên thực tế không phải cặp đơn âm nào cũng đi liền với nhau được. Ví dụ,
tiếng Tây Ban Nha có 800 cặp âm, còn tiếng Đức có 2.500 cặp âm.
-
Lại nói về việc phân tích văn bản thành phát âm. Chúng ta thấy, một từ bất kỳ
trong ngôn ngữ, khi phiên âm, là một chuỗi ghép của các cặp âm (diphone).
Người ta chia đoạn văn bản thành từng câu. Và câu là tổ hợp của các từ. Kết quả
là, khi phiên âm, đoạn văn bản biến thành một chuỗi các cặp âm.
-
Chú ý rằng các cặp âm “chồng lên nhau” (overlap). Trong ví dụ về phiên
âm từ diphone thì cặp [da] chồng lên cặp [aɪ], cặp [aɪ] lại chồng lên cặp
[ɪf], … Vì vậy, để ghép các cặp âm, người ta cần đến các thuật toán xử lý tín
hiệu số (DSP) như PSOLA (Pitch Synchronous Overlap and Add), MBROLA (Multi-Band
Resynthesis OverLap Add). Trong thực tế, giải pháp diphone synthesis
về mặt thương mại không hấp dẫn, chủ yếu chỉ để dùng trong nghiên cứu.
-
3.
Theo
lĩnh vực cụ thể (Domain-specific synthesis).
Cách làm của phương pháp này là ghép các từ (hoặc cụm từ) được thu âm từ trước.
Có vẻ như cách tiếp cận này giống với tuyển chọn đơn nguyên âm thanh (unit
selection synthesis)? Đúng, về mặt nguyên tắc là giống nhau. Tuy nhiên, do
số từ (cụm từ) rất ít (cỡ vài chục đơn nguyên) nên thuật toán ghép không cần
hàm đánh giá mục tiêu và không cần thuật toán tìm chuỗi tối ưu.
Khác với 2 phương pháp 1. và 2., cách ghép này không bị hiện tượng xô lệch âm
thanh hay hiện tượng chồng âm: có một khoảng lặng ngắn giữa 2 từ (cụm từ).
-
Dùng ở đâu? Ở các phòng đợi xếp hàng chờ đến lượt (ngân hàng, phòng khám),
thông báo tàu, xe hay thông báo ở trong các thang máy, …
-
·
➡
Máy tự tạo giọng nói (formant synthesis /
parametric TTS). Cách tiếp cận này không sử dụng tiếng người mà giọng
nói được tạo ra từ máy (artificial speech). Căn cứ vào các tham số của phát
âm (như tần số cơ bản, dao động tuần hoàn của ngữ âm, thời lượng, …) máy tự tạo
ra sóng âm thanh với “âm tiếng nói bằng máy” tương ứng. Phương pháp này còn được
gọi là bộ tổng hợp dựa trên quy tắc (rules-based synthesis).
-
Cách tiếp cận này tất nhiên cho kết quả “thiếu tự nhiên”. Bằng máy mà (tiếng
nói được tạo ra từ các công thức toán học), chả tự nhiên tý nào! 😊 Bù lại, người ta đánh giá giải pháp này
“nghe được”, ngay cả khi “máy nói” nhanh. Người ta có thể điều chỉnh tốc độ
nói, âm thanh cao thấp bằng cách thay đổi tham số. Ngoài ra, phần mềm tương đối
nhẹ, cần rất ít bộ nhớ và có thể dễ dàng “nhúng” vào các hệ thống tự động hóa.
Chúng ta có thể lập trình được “máy nói” theo ý muốn: nhịp điệu, thanh sắc, … [Tham
khảo ở đây.]
-
🗎→🔈
ⓒ Đo chất lượng mô hình
Bây giờ chúng
ta bàn đến cách đo chất lượng mô hình. Khi nghiên cứu một vấn đề nào đó, cộng đồng
nghiên cứu thường đề xuất các thước đo chất lượng. Thước đo này giúp chúng ta
đánh giá một giải pháp nào đó tốt đến mức độ nào. Lấy ví dụ. Trong dịch máy (Machine
Translation), chúng ta có thước đo BLEU. Giải pháp nào đạt BLEU cao là giải
pháp đó tốt. Trong nghiên cứu “speech-to-text”, chúng ta có thước đo
WER. Giải pháp nào có WER nhỏ thì giải pháp đó tốt. Các thước đo BLEU và WER có
một tính chất rất quan trọng: đây là các thước đo khách quan (objective).
Nghĩa là không có một tổ chức hay cá nhân nào đứng ra đo, mà thước đo này có
công thức, có cách tính tự động: máy đo.
-
Thế còn đối với
vấn đề “text-to-speech” thì thế nào? Rất đáng tiếc là cho đến thời điểm
hiện nay, chưa ai đề xuất ra được thước đo khách quan nào cả. Nghĩa là chưa có
một công thức hay cách tính tự động bằng máy, máy “nghe thử” và cho kết quả
đánh giá. Như vậy, chỉ còn cách duy nhất là cần đến con người để đánh giá chất
lượng. Đây là thước đo chủ quan (subjective).
-
Vấn đề còn lại
là tổ chức như thế nào để “thuê” được nhóm người đánh giá chất lượng kết quả
nghiên cứu một cách “không thiên kiến”, “không bị tác động lẫn nhau”? “Không
thiên kiến” nghĩa là người đánh giá không biết sản phẩm nghiên cứu đấy là của
ai, của công ty nào. “Không bị tác động lẫn nhau” nghĩa là nhóm người đánh giá
không biết nhau. Trả lời cho câu hỏi này, tôi thấy phần lớn các công ty công
nghệ tổ chức thuê ngoài theo mô hình có tên gọi là Amazon Mechanical Turk
(MTurk). Đây là một hình thức thuộc dòng crowdsource (nguồn cộng đồng), crowdworker
(lao động cộng đồng). Mô hình này do Jeff
Bezos, ông chủ của
Amazon đề xướng. Đại ý là người ta thuê ngoài “lao động cộng đồng” thông qua một
giao diện (Application Programming Interface - API) trên mạng Internet. Người
“lao động cộng đồng” (crowdworker) chỉ biết đến giao diện và không biết
nhau. (Không biết trên diễn đàn này liệu
đã có anh/chị nào tham gia Mturk chưa nhỉ? 😊)
Gốc của cụm từ Mechanical Turk:
là máy cơ chơi cờ vua tự động – máy có thể chơi cờ vua với người (từ năm 1770 đến
năm 1854). Thực tế đây chỉ là trò bịp, vì nấp đằng sau máy vẫn là một người thật.
Có lẽ vì vậy mà Jeff Bezos đã lấy cụm từ này, vì đằng sau giao diện (tưởng như
là tự động) vẫn là con người.
-
Trong trường hợp
đo chất lượng synthesizer, người ta yêu cầu đánh giá chất lượng theo 5 mức:
|
5 |
Excellent |
|
4 |
Good |
|
3 |
Fair |
|
2 |
Poor |
|
1 |
Bad |
Giả thiết người
ta thuê N người đánh giá, và có kết quả lần lượt là R1, R2,
…, RN. Từ đó, người ta tính ra điểm số trải nghiệm bình quân có tên
viết tắt là MOS:
MOS (Mean Opinion
Score) = (R1 + R2 + … + RN)/N.
Như vậy, MOS đạt
tối đa là 5.0 và tối thiểu là 1.0. Thước đo MOS vẫn còn nhiều tranh luận, nhưng
có lẽ chúng ta khỏi tốn thời gian vào các tranh luận này.
⚠ Khi
đọc các bài báo về “text-to-speech”, chúng ta thường thấy người ta đánh
giá mô hình thông qua điểm MOS. Nếu điểm MOS đạt trên 4.3 là rất tốt rồi đấy!
🗎→🔈
ⓓ Khái niệm vocoder.
Vocoder là ghép của phần đầu từ voice
với phần đuôi từ encoder – tạm dịch nghĩa là bộ mã hóa giọng nói.
Đặt trong tổng thể của synthesizer thì vocoder chính là “phát
thanh” của synthesizer. Quan trọng hơn, chất lượng của vocoder gần
như quyết định của chất lượng của synthesizer.
Gốc của vocoder
là mã hóa nguồn phát, truyền phần mã hóa đó qua đường truyền viễn thông và đầu
nhận thông tin đường truyền có trách nhiệm giải mã tín hiệu nhận được và phát
ra loa. (Vocoder được Homer Dudley tại Bell Labs phát minh
vào năm 1938.) Anh/chị nếu có ai tò mò về nguyên lý của vocoder thì tham
khảo đường link tôi đã dẫn ở trên.
-
Bàn thêm về
ngôn từ. Trong bài nhàn đàm này, chúng ta thống nhất coi vocoder là phát
thanh của synthesizer. Và chúng ta dùng luôn từ vocoder, khỏi phải
dịch sang tiếng Việt.
<Mở ngoặc>
Theo quan điểm của riêng cá nhân tôi, nhiều từ chúng ta nên chấp nhận để nguyên
gốc tiếng Anh, chấp nhận “nhập khẩu” một số từ. Lý do: nếu chúng ta cứ cố ép phải
dịch thì kết quả là, trong nhiều trường hợp, bản dịch thường khó hiểu và tệ hại
hơn, thậm chí còn bị hiểu nhầm. Mà ngay như từ “vocoder” cũng không có
trong từ điển Anh-Anh đâu.
<Đóng ngoặc>
-
🗎→🔈
ⓔ Biến hóa vocoder.
Như đã đề cập ở
trên, “tiếng máy nói” được tạo ra bằng cách ghép các đoạn ghi âm (concatenation
synthesis) hoặc được tạo ra dựa trên các công thức toán học (parametric
TTS).
Bây giờ chúng
ta đặt vấn đề. Giả sử chúng ta muốn thay giọng nam bằng giọng nữ, hoặc chúng ta
muốn thay giọng theo vùng miền (Bắc, Trung, Nam) thì làm thế nào? Nếu theo
phương pháp của concatenation synthesis thì đành phải thay hết các đoạn
ghi âm. Ví dụ, để có 10 giọng nói khác nhau thì chúng ta phải lập 10 CSDL khác
nhau về giọng nói tương ứng. Cách làm này cũng được, mặc dù hơi mất công. Nhưng
liệu có cách nào khác không?
-
Tiếp theo, tôi
muốn nói băng sang chuyện khác, rồi trở lại trả lời câu hỏi trên. Nếu anh/chị
không có hứng thú đọc thì xin bỏ qua phần tôi đánh dấu “<Bên lề>”.
Bên lề ▼
Tháng
8/2013, tác giả Alex Graves đăng bài Generating
Sequences With Recurrent Neural Networks (tạo chuỗi bằng mạng RNN). Tác giả liên tưởng cấu trúc mạng
RNN (Recurrent Neural Network) với sự phát sinh của chuỗi. Lấy ví dụ. Con
người suy luận dựa trên hiểu biết về quá khứ. Khi anh/chị đọc bài post này, anh/chị
hiểu từng từ dựa trên sự hiểu biết của anh/chị về những từ trước đó. Rõ ràng là
như vậy. Anh/chị không vứt bỏ mọi thứ và bắt đầu suy nghĩ lại từ đầu. Dòng suy
nghĩ của anh/chị có tính phát sinh liên tục: cái sau dựa vào chuỗi của những
cái trước đó. Để hiểu từ đang đọc, bằng một cách nào đó, chúng ta “liên kết” với
các từ đứng đằng trước, thậm chí là các từ đứng ở đầu bài post.
↓
Dựa
vào tính chất này, tác giả thiết kế mô hình tạo chuỗi: phần tử tiếp theo của
chuỗi là một “suy diễn dự đoán” từ các phần tử trước đó. Nghĩa là phần tử tiếp
theo là “tiếp diễn” một cách có quy luật của các phần tử trước. Thực hiện việc
này bằng cách nào? Tác giả sử dụng mô hình mạng LSTM (LSTM là một dạng đặc biệt
của RNN) để tạo chuỗi. Tất nhiên, trước khi tạo chuỗi, mô hình cần được huấn
luyện với một tập dữ liệu. Bài báo thử nghiệm với 2 loại dữ liệu: dữ liệu văn bản
và nét chữ viết tay.
-
Trường
hợp đầu tiên, nếu dữ liệu là tập hợp các văn bản thì khi tạo chuỗi, chúng ta
thu được điều gì có ý nghĩa? Mời anh/chị tham khảo bài này, anh/chị sẽ thấy rằng mô hình tạo chuỗi
văn bản bắt chước được “văn phong” của tập văn bản dùng để huấn luyện nó! Tác
giả bài báo (Andrej Karpathy) thuyết minh rằng mô hình có thể bắt chước
được phong cách viết bài luận của Paul Graham, văn phong viết kịch của Shakespeare,
bắt chước cấu trúc cú pháp của Wikipedia, cách viết công thức rất phức hợp
của Latex, phong cách viết mã nguồn của Linux. Chú ý rằng, chuỗi
do mạng tạo ra có nội dung vô nghĩa, nhưng cái chính là nó bắt chước được văn
phong, nó nhại lại “style” của văn bản đó. Rất bí hiểm. 😊
-
Trường
hợp thứ hai là nét chữ viết tay. Phần tử của chuỗi, trong trường hợp này, là điểm
chấm bút khi chúng ta viết tay. Nghĩa là một tọa độ (x, y) trong không gian hai
chiều. Chuỗi chính là dãy các tọa độ như vậy. Anh/chị hãy chú ý đến chi tiết rất
thú vị: mô hình “handwriting synthesis” (trong bài báo) có thể “bắt chước
nét chữ viết tay”! Trong thế giới thực, đối với những người quen thân, khi họ
cho chúng ta xem bản viết tay, chúng ta có thể nhận biết người đó là ai. Tôi
đoán rằng rất ít trong số chúng ta (trên diễn đàn này) có thể bắt chước được
nét chữ viết tay của người khác. Thế mà máy có thể làm được điều đó. Thì đó
chính là trí tuệ nhân tạo (Artificial Intelligence) chứ còn gì nữa!
-
💡 Cái chung về dữ liệu của hai trường hợp trên là gì? Trong
tiếng Anh, người ta gọi loại dữ liệu này là autoregressive. Tôi dịch từ
này ra tiếng Việt là “tự động tiếp diễn”. Vì sao vậy?
Đối
với trường hợp văn bản thì muốn văn bản có nghĩa, “từ” tiếp theo phải là một
“tiếp diễn” có quy luật nào đó của dãy các từ trước đó.
Đối
với trường hợp viết tay, lấy ví dụ viết chữ “a”. Kể từ khi chúng ta đặt bút xuống
giấy thì nét sau phải “tiếp diễn” các nét trước, theo một quy tắc nhất định, để
“vẽ” được chữa “a”, chứ không phải nét bút di chuyển một cách bất kỳ. Tức là
“nét” tiếp theo tuân theo một quy luật nào đó của dãy các “nét” trước đó.
-
Trong
một lần diễn thuyết năm 2015, Alex Graves có đề cập đến việc ứng dụng
mô hình “handwriting synthesis” vào TTS. Chú ý sự tương đồng giữa chữ viết
tay và âm thanh giọng nói: chúng đều là dữ liệu autoregressive - dữ liệu
“tự động tiếp diễn”.
-
💡 “Nghiền ngẫm” sâu hơn một chút, chúng ta nhận thấy dữ liệu
“autoregressive” (tự động tiếp diễn) có những đặc tính rất thú vị và thực
tế nó có ảnh hưởng sâu sắc đến Machine Learning. Ở đây, tôi chỉ xin đàm
luận đến 2 đặc tính của nó.
1.
Dữ
liệu không cần dán nhãn – Unsupervised Learning. Chúng ta chú ý tính chất
phát sinh của loại dữ liệu autoregressive. Phần tử tiếp theo được tạo ra dựa
trên dãy các phần tử trước đó. “Nhãn” trong trường hợp này được lấy từ chính
chuỗi dữ liệu đầu vào. Tính chất này giúp máy “tự học” mà không cần giám sát,
đó chính là Unsupervised Learning. Do việc dán nhãn mất rất nhiều công sức,
đắt đỏ và thâm chí la bất khả thi nên giới nghiên cứu tập trung vào tìm các giải
pháp cho Unsupervised Learning. Dữ liệu autoregressive là một ứng
viên tuyệt vời.
2.
Tri
thức suy diễn từ dữ liệu. Vì mỗi một phần tử trong dữ liệu autoregressive
được tạo ra từ dãy các phần tử trước đó nên bản thân các dãy dữ liệu chứa một
quy tắc suy diễn nào đó. Từ đó suy ra, càng có nhiều đoạn dữ liệu, tức là dữ liệu
càng lớn thì càng có nhiều quy tắc suy diễn – nghĩa là số lượng “tri thức suy
diễn” càng nhiều. Trong đời sống thực tế, mỗi một kiến thức mới học được, rõ
ràng là phải dựa vào khối kiến thức chúng ta đã học trước đó. Nếu, bằng một
cách nào đó, có một mô hình có thể “thâu tóm” được hầu hết các “tri thức suy diễn”
từ xưa đến nay, thì mô hình đó rõ ràng là một cỗ máy trí tuệ nhân tạo khổng lồ,
tương tự như trí tuệ của một siêu nhân! 😊
Bên lề ▲
➡ Neural Vocoder
(vocoder trên nền mạng nơ-ron). Bàn về neural vocoder, theo quan
sát của riêng cá nhân, tôi thấy DeepMind đi tiên phong với đề xuất WaveNet vào năm 2016. Sau WaveNet có một số đề
xuất khác như SampleRNN, WaveGlow hoặc WaveGAN. Tuy nhiên, do WaveNet đi đầu và có nhiều
ý tưởng đột phá, nên tôi xin phép anh/chị chỉ đàm luận về mô hình này.
-
Trước khi đi
vào chi tiết bài báo, theo tôi, chúng ta nên nắm các ý tưởng chính của họ.
↓
·
Sóng
âm thanh là loại dữ liệu autoregressive (tự động tiếp diễn) – như đã được
đề cập ở phần “<Bên
lề>”.
·
Sóng
âm thanh được tạo ra theo hình thức “tự động phát sinh”, phần tử sau được “suy
diễn” ra từ chuỗi các phần tử trước. Hình thức “suy diễn” là áp dụng thuật toán
softmax. Nghĩa là trong P ứng viên (candidate) của kết quả “suy
diễn”, ứng viên nào có xác suất lớn nhất sẽ được chọn.
·
Người
ta huấn luyện mô hình WaveNet cho toàn bộ các phát âm của một ngôn ngữ với N “người
nói” (speaker), với rất nhiều đoạn văn bản thuộc ngôn ngữ đấy. Tập hợp “người
nói” được chọn sao họ có tính đại diện cao nhất: vùng, miền, phương ngữ. Sau
khi huấn luyện, mạng WaveNet coi như biết “tiếng nói” của ngôn ngữ đó với đầy đủ
đặc tính vùng, miền, phương ngữ.
-
💡 Như
vậy, WaveNet có thể “nói” được bất cứ ngôn ngữ nào miễn là nó được huấn luyện một
cách đầy đủ (số người nói và số giờ nói).
-
Anh/chị nào muốn
hiểu kỹ về mô hình này thì cách tốt nhất là nên đọc bài báo tôi đã dẫn đường
link (WaveNet).
Trong phần tiếp theo, chúng ta cùng khảo sát vài điểm đặc biệt của mô hình.
·
Mạng
được chọn không phải là RNN mà là CNN (Convolutional Neural Network). Vì
sao không chọn RNN là mạng thích hợp với dữ liệu tuần tự mà lại chọn CNN? Lý
do: khi huấn luyện CNN, có thể tính song song đầu ra, vì vào thời điểm huấn luyện,
tất cả dữ liệu mẫu đã được gán nhãn (tức là biết trước đầu ra). Lưu ý:
điều này chỉ đúng khi huấn luyện. Còn khi suy diễn (inference) thì mô
hình suy diễn tuần tự từng “điểm” sóng âm thanh một: đầu tiên là “tính” x1,
xong “tính” x2 dựa trên x1, …, “tính” xn dựa
trên x1, x2, …, xn-1, … Nếu trong 1 giây cần lấy
16,000 mẫu thì mô hình phải hoàn tất công việc tính toán 16,000 mẫu dưới 1 giây
để hệ thống đảm bảo có thể chạy theo thời gian thực (real-time). Đây là
nhược điểm trong phiên bản đầu tiên của WaveNet.
-
·
Đầu
ra của WaveNet: sóng âm thanh. Đương nhiên, sóng âm thanh có giá trị liên tục. Vì
máy tính không lưu được các giá trị liên tục nên cần phải lấy mẫu. Khi lấy mẫu
chúng ta chú ý đến 2 chi tiết: tần số lấy mẫu (frequency) và cường độ (intensity).
WaveNet lấy 16,000 mẫu/giây (tương đương với tần số 16kHz). Cường độ (intensity),
sau khi chuẩn hóa (normalization), thực chất là một số nguyên 16 bit.
Như vậy, dưới góc độ lập trình, đầu ra của WaveNet là mảng các số nguyên 16
bit. Mỗi một giây, WaveNet sản sinh ra 16,000 số nguyên như vậy. (Chú ý thêm:
cách họ biến đổi số 16 bit thành số 8 bit khi áp dụng thuật toán softmax
– xem mục 2.2 trang 3.)
-
·
WaveNet
dựng mô hình như thế nào? Đầu tiên, để xây dựng mô hình tổng thể ban đầu, người
ta cho mạng huấn luyện bằng cách “nghe” 109 người nói trong thời gian 44 giờ.
Sau khi “học” xong, mạng có khả năng nói giọng tổng hợp, “lơ lớ” gần giống với
tất cả 109 người này.
-
·
Sau
đó, mô hình có thể “đọc” một đoạn văn bản nào đó bằng giọng “tổng hợp” của 109
người nói trên. Bên cạnh đó, rất đáng chú ý, mạng cũng có thể đọc văn bản
bằng cách “lọc riêng” một giọng của một trong số 109 người nói đã tham gia huấn
luyện!
·
Bằng
cách nào mà họ có thể thực hiện được như vậy (lọc giọng từng người nói)? Đây là
một câu hỏi rất thú vị. Trong bài báo, họ có giải thích. Cách họ vận hành mạng
có tên gọi là “WaveNet có điều kiện” (Conditional WaveNet). Họ chia
thành 2 loại điều kiện: điều kiện tổng thể (global condition) và điều kiện
cục bộ (local condition).
o
💡 Thế nào gọi là điều kiện tổng thể? Là điều kiện làm thay đổi
toàn bộ quy trình phát sinh dữ liệu từ đầu đến cuối. Ví dụ về trường hợp này là
chọn giọng đọc của một người. Nhưng làm thế nào mà người ta “lọc” ra được giọng
của riêng một người? Chúng ta chú ý đến cách họ mã hóa “người nói” trong mô
hình, họ dùng kỹ thuật one-hot vector. Nghĩa là mỗi một “người nói” ứng
với một vector mà trong vector đó chỉ có một ô có giá trị bằng 1, còn lại tất cả
các ô khác có giá trị bằng 0. Chúng ta chú ý đến phương trình số 2 – ký hiệu là
Eq. (2) ở cuối trang 4 – trong tham số hàm kích hoạt (activation function),
người ta nhân h (h trong trường hợp này là one-hot vector)
với ma trận của các hệ số (weight). Chúng ta hình dung kết quả phép
nhân: hủy hết tất cả “người nói” khác với h (các ô có giá trị bằng 0 trong
one-hot vector thì nhân với bất cứ cái gì cũng bằng 0).
-
Một cách trực quan: ứng với mỗi một “người nói” (speaker) là một công-tắc
tắt/bật. Việc lọc ra một giọng đọc cũng giống như việc chúng ta chỉ bật một
công-tắc và tắt 108 công-tắc còn lại.
-
o
💡 Thế nào gọi là điều kiện cục bộ? Là điều kiện chỉ làm thay
đổi mô hình trong một khoảng thời gian nào đó. Ví dụ về trường hợp này là “đọc”
một đoạn văn bản. Cách họ làm: căn cứ vào đoạn văn bản để “phát sinh” một chuỗi
“sóng âm thanh”. Chuỗi sóng âm thanh của văn bản có tần số có thể không khớp với
tần số của WaveNet (thường là nhỏ hơn tần số của WaveNet). Do đó, họ phải khớp
2 tần số, bằng cách upsampling (tăng) tần số của “văn bản” cho bằng tần
số của WaveNet. Chuỗi dữ liệu được làm khớp này sau đó được trộn với dòng dữ liệu
chính của WaveNet. Cách trộn: sử dụng phép toán tích chập (convolution). Để dễ hình dung, chúng ta tưởng tượng
lúc này có 2 “sợi sóng”: một sợi là của hệ thống chính và một sợi được “chiết”
ra từ đoạn văn bản. Phép tích chập tức là chúng ta chập 2 “sợi sóng” đấy lại với
nhau. Kết quả là sợi “chập” nằm khoảng giữa 2 sợi: thấp hơn sợi cao và cao hơn
sợi thấp.
-
·
Để
khắc phục nhược điểm suy diễn (inference) chậm, phiên bản sau của WaveNet
được nâng cấp thành Parallel WaveNet – mời anh/chị tham khảo bài
báo. Phiên bản nâng cấp
của WaveNet sử dụng tần số 24kHz. Tần số cao hơn cho kết quả là sóng “mịn” hơn
nhưng đòi hỏi nhiều phép tính hơn.
-
Đến đây tôi xin
trả lời cho câu hỏi được đặt ra ở phần đầu của đàm luận về vocoder: với
WaveNet, chúng ta có thể dễ dàng thay giọng đọc “tổng hợp” bằng giọng đọc của một
người bất kỳ trong số những người tham gia huấn luyện mô hình.
-
🗎→🔈
ⓕ Cách tiếp cận theo tư duy Machine Learning.
Các mô hình
theo tư duy mạng nơ-ron chỉ xuất hiện sau khi WaveNet ra đời (năm 2016). Xin lược
kể một vài mô hình:
·
Đầu
tiên phải kể đến giải pháp Char2Wav của Viện Trí tuệ nhân tạo Mila (Mila
- Quebec AI Institute) vào đầu năm 2017. Vocoder của Char2Wav là SampleRNN (neural vocoder).
-
·
Tiếp
theo có giải pháp Tacotron của Google, sau đó họ nâng cấp lên
thành bản Tacontron2. Dĩ nhiên, họ sử dụng neural vocoder
là WaveNet vì DeepMind đã sát nhập vào Google từ năm 2014.
-
·
Cũng
trong năm 2017, Facebook cho ra đời giải pháp VoiceLoop. Họ sử dụng vocoder có tên là WORLD.
-
·
Năm
2019, nhóm nghiên cứu của Microsoft và Baidu đã đề xuất giải pháp FastSpeech. Trong kiến trúc mô hình họ không đề cập
đến vocoder. Tuy nhiên, trong thử nghiệm họ sử dụng vocoder là WORLD và WaveGlow.
-
➡
Các mô hình này có điểm gì chung không? Trả lời: Có – ngoại trừ FastSpeech, gần
như tất cả các mô hình đều theo cách tiếp cận “end-to-end” (E2E). Cách
tiếp cận E2E luôn luôn là lực hút đối với giới nghiên cứu trong thời gian gần
đây, đặc biệt kể từ sau năm 2014.
Giải pháp E2E
“cậy” vào 2 điểm tựa: dữ liệu nhiều (Big Data) và mạng nơ-ron (Neural
Network). Nghĩa là cứ có thật nhiều bản ghi [Văn bản → Sóng âm thanh], rồi
lấy tập hợp dữ liệu này huấn luyện cho một mô hình mạng nơ-ron nào đó. Sau đó,
khi có văn bản mới đưa vào, mô hình sẽ “suy diễn” ra “sóng âm thanh” (của tiếng
nói) tương ứng với văn bản đó. Cách tiếp cận này bỏ qua các bước “lằng nhằng
trung gian” ở giữa. Mà, như chúng ta biết đấy, thông thường các bước “lằng nhằng
trung gian” gây nhức đầu. 😊
-
🎗 Reminder: Trong mấy lần nhàn đàm trước, chúng ta
đã khá quen với giải pháp E2E. Nhân tiện đây tôi xin nhắc lại để làm tươi bộ nhớ:
Viết một cách vắn
tắt: E2E = encoder-attention-decoder (mã hóa-chú ý-giải mã).
E2E đối với trường
hợp “text-to-speech”:
[văn bản/âm vị]→mã
hóa→ [context]→giải mã→ [sóng âm thanh]→vocoder
-
🗎→🔈
ⓖ Một vài thách thức đối với text-to-speech.
·
Thách
thức đầu tiên là tìm ra thước đo khách quan về chất lượng mô hình. Thước đo MOS
vẫn chỉ là thước đo chủ quan, phụ thuộc vào việc chọn tập hợp người đánh giá. Hai
mô hình với hai tập hợp người đánh giá khác nhau, hai tập dữ liệu mẫu khác nhau
thì khó so sánh khách quan được. Chỉ có thước đo khách quan thì cộng đồng
nghiên cứu mới “tự tin” để so sánh giữa các mô hình. Như đàm luận ở phần trước,
cho đến hiện nay, chưa ai tìm được thước đo này.
_ Để khắc phục một phần, một số nhà khoa học thống nhất đo chất lượng mô hình
thông qua một tập dữ liệu chung và tổ chức việc đo chất lượng mô hình hàng năm
(kể từ năm 2005): "Blizzard Challenge".
-
·
Một
thách thức khác là việc chuẩn hóa văn bản (text normalization): chuyển đổi
số và chữ viết tắt thành lời.
_ Ví dụ về chuyển chữ viết tắt thành lời: NASA. Chuyển thành “na-xa” hay chuyển
thành “nờ-a-ét-xì-a”?
_ Ví dụ về chuyển đổi số: 135. Chuyển thành “một-ba-năm” hay chuyển thành “một
trăm ba lăm”? Nếu viết “Chương VI” thì sẽ thành “chương vi” hay “chương sáu”?
-
·
Một
thách thức nữa là việc “chuyển đổi văn bản thành phiên âm”: (text-to-phoneme).
Đối với tiếng Việt chúng ta ít có vấn đề nhưng đối với các ngôn ngữ khác như tiếng
Anh có một chút khác biệt. Thông thường mỗi một từ chỉ có một cách phát âm. Điều
này đúng với tiếng Việt. Nhưng đối với một số ngôn ngữ khác như tiếng Anh thì
có vấn đề về heteronym (cùng từ khác âm). Cùng một từ nhưng lại có nhiều
cách phát âm – tùy vào nghĩa của từ hoặc tùy vào “thì”. Ví dụ từ “tear”
trong tiếng Anh có 2 cách phát âm (/teə/ hoặc /tɪə/). Ví dụ khác là từ “read”
trong tiếng Anh. Thì hiện tại thì phiên âm là /riːd/ còn thì quá khứ thì phiên
âm là /red/.
-
Đấy là chúng ta
bàn cho “hết nhẽ” thế thôi, chứ nếu chúng ta xem “máy nói” như người nước ngoài
nói tiếng mẹ đẻ của mình thì chúng ta vẫn dễ dàng hiểu, dù có một vài chỗ phát
âm chưa thật “chuẩn”! 😊
(\_/)
(
•_•)
/
>☕