AIResearch.in.th และ PyThaiNLP ปล่อยโมเดลถอดความจากเสียงพูดภาษาไทย (Speech-to-Text) ความแม่นยำทัดเทียมผู้นำตลาดอย่าง Microsoft, Google, Amazon ให้ใช้ฟรีภายใต้ลิขสิทธิ์ CC-BY-SA 4.0 (Open Source)

IWCDWAFI
AIResearch.in.th
Published in
11 min readSep 5, 2021

(English Below)

AIResearch.in.th ร่วมมือกับ PyThaiNLP ปล่อยโมเดลถอดความจากเสียงภาษาไทย (Automatic Speech Recognition; ASR) ที่ถูกเทรนบนข้อมูล Common Voice 7.0 ประมาณ 133 ชั่วโมง ประกอบด้วยโมเดลที่เทรนจากศูนย์ด้วย Kaldi และโมเดลที่ปรับแต่งจาก XLSR-Wav2Vec2 จาก Facebook ทุกโมเดลมีความแม่นยำทัดเทียมกับบริการของผู้นำตลาดอย่าง Microsoft, Google, Amazon สามารถเข้าถึงและใช้เพื่องานวิจัยและการค้าได้ภายใต้ลิขสิทธิ์ CC-BY-SA 4.0 (open source) ทั้งแบบ on-cloud และ on-premise เมื่อรันบน CPU แต่ละโมเดลใช้เวลาในการถอดเสียงประมาณ 1.09 วินาทีต่อหนึ่งคลิปสั้น โมเดลเหล่านี้เหมาะกับบทสนทนาทั่วไป เช่น การสั่งอาหาร บริการลูกค้า และจดประชุม เป็นต้น แต่อาจไม่สามารถถอดความชื่อเฉพาะได้ดีนัก

โมเดลของเรายังไม่ใกล้เคียงจุดที่ ASR ภาษาไทยควรจะเป็นในฐานะโมเดลที่ใช้งานได้ดีในทุกบริบท

การเปรียบเทียบกับโมเดลของ Microsoft, Google, Amazon นั้นทำโดยที่โมเดลเหล่านั้นไม่ได้รับการปรับแต่งกับ Common Voice 7.0) ปัญหาที่อาจพบ เช่น คำที่โมเดลไม่เคยเห็นในชุด train, ชื่อเฉพาะ (ชื่อแบรนด์, ศัพท์เทคนิค, แสลง, ฯลฯ) และคำทับศัพท์ภาษาอังกฤษ ยังเป็นความท้าทายที่รอให้นักพัฒนาหาทางแก้ไขต่อไป เราเชื่อว่านี่คือหนึ่งในก้าวแรกสู่การพัฒนาโมเดล ASR แบบ open source อย่างแข็งแรงของชุมชนต่อไป

ลองโมเดลได้ที่

วิธีเทรน

มันไม่ง่ายเลยที่จะเทรนโมเดล ASR บน Common Voice

เราใช้ข้อมูลคลิปเสียงภาษาไทยรวม 133 ชั่วโมง (ผู้พูด 7,212 คน) จาก Mozilla Common Voice 7.0 ในการเทรนโมเดลของเรา เพื่อการนี้ @tann9949 ได้สร้างกฎการทำความสะอาดข้อความสำหรับงานถอดเสียงขึ้นมา เริ่มจากการลบตัวอักษรที่ไม่ใช่ตัวอักษรภาษาไทย ภาษาอังกฤษ หรือตัวเลขออก แม้ตัวอักษรเหล่านี้อาจจะบอกถึงโทนเสียง เช่น ! อาจบอกถึงเสียงตกใจ หรือ ? อาจบอกถึงเสียงสงสัย แต่มีหลายตัวอักษรที่ไม่มีความหมายใดๆ เลยในภาษาไทย เช่น ", ., ;, หรือ :ต่อมา เราจัดการแก้คำที่มักสะกดผิด เช่น ที่สะกดด้วย สองอัน, ที่สะกดด้วย และ รวมถึงทำให้วรรณยุกต์ทุกอันถูกต้องตามไวยกรณ์อักษรสูง-กลาง-ต่ำ อีกขั้นคือการเปลี่ยน เป็นคำที่ซ้ำ เช่น ดีมากๆเป็น ดีมากมากและสุดท้าย เราเปลี่ยนประโยคที่หลุดกฎเหล่านี้ด้วยมือเท่าที่ทำได้

Mozilla ได้ทำการลบประโยคที่ซ้ำกันตรงๆ ออก และสุ่มประโยคแยกออกเป็นชุด train, validation และ test ปัญหาที่เราพบคือบางประโยคอาจจะดูไม่เหมือนกันก่อนการทำความสะอาด แต่หลังจากทำความสะอาดแล้วกลับกลายเป็นประโยคเดียวกัน

เพื่อแก้ปัญหานี้ @ekapolc และ @14mss ได้ทำการแบ่งชุดข้อมูลที่ถูกทำความสะอาดแล้วใหม่เป็น train (86,586 ประโยค), dev-unique(3,027 ประโยค), test-unique(2,502 ประโยค) ด้วยขั้นตอนดังต่อไปนี้:

การกระทำเช่นนี้ นอกจากจะแก้ปัญหาประโยคซ้ำในชุดเดียวกันแล้ว ยังป้องกัน data leakage ผ่านผู้พูดคนเดียวกันในหลายชุดข้อมูลอีกด้วย เราทำการ benchmark บนชุด test-unique

สร้างโมเดล Kaldi จากศูนย์

Kaldi เป็นเครื่องมือถอดเสียงอัตโนมัติที่ถูกออกแบบให้เทรนโมเดล ASR แบบคลาสสิคได้อย่างมีประสิทธิภาพ โมเดล Kaldi ประกอบด้วย 3 ส่วนคือ acoustic model, lexicon และ language model

Acoustic model ทำการทำนาย speech feature ในช่วงเวลาใดเวลาหนึ่งออกมาเป็นหน่วยเสียงหรือ phoneme พูดง่ายๆ คือการสะกด phoneme ด้วย speech feature บางอย่าง เช่น filterbank, MFCC, MFCC+pitch เป็นต้น โมเดลเป็นโมเดลประเภท generative ที่ถูกเทรนซ้ำๆ ด้วยวิธีเรียบง่ายอย่าง HMM-GMM หรือวิธีที่ซับซ้อนอย่าง HMM-DNN เพราะฉะนั้น เราจึงทดลองบนชุด validation ด้วย mono, tri1b, tri3b เป็นต้น acoustic model ที่ซับซ้อนที่สุดที่เราใช้คือ tdnn-chainหรือ Time-Delay Neural Networks

Lexicon คือการจับคู่ระหว่าง phoneme จาก acoustic model ไปยังตารางตัวอักษร โดยทั่วไปแล้วจำเป็นต้องใช้นักภาษาศาสตร์ในการสร้าง phoneme representation สำหรับคำแต่ละคำ แต่ด้วยข้อจำกัดทางทรัพยากร เราจึงใช้เพียงแค่ grapheme representation แทน (แทน phoneme ด้วยตัวอักษร เช่น ฉันฉ ั น)

Language model ทำหน้าที่แก้ประโยคให้ดูสมเหตุสมผล ที่ผ่านมาเราใช้ acoustic model เปลี่ยน speech เป็น phoneme และ lexicon เปลี่ยน phoneme เป็นคำ ทำให้เราได้ประโยคที่ถอดความมาระดับหนึ่งแล้ว แต่บางคำที่ออกเสียงคล้ายกันเดินไปสามารถทำให้ประโยคผิดได้ เช่น ค่าเงินบาทและ ฆ่าเงินบาท (ถ้าใช้จริงคงค่อนข้างมีปัญหา!) เราจึงจำเป็นต้องใช้ language model ให้แน่ใจว่าคำที่โมเดลเราปล่อยออกมานั้นตรงกับบริบทที่เราต้องการ ในงานนี้ เราใช้ n-gram language model ในการแก้ประโยค

เราทำการทดลองตามสูตรมาตรฐานของ commonvoice kaldi recipe โดยใช้ NVIDIA V100 GPU 4 อันเพื่อให้ได้ batch size ที่ใหญ่ที่สุดเท่าที่จะทำได้ ใช้เวลาประมาณ 1 วันในการเทรนโมเดลหนึ่งครั้ง เทียบได้เท่ากับ 12.44 kg CO2 eq. หรือการขับรถทั่วไป 50 กิโลเมตร

ปรับแต่ง XLSR-Wav3Vec2 สำหรับภาษาไทย-พลังบุญทำให้ Common Voice ใหญ่ขึ้น 16 เท่า

XLSR-Wav2Vec2 เป็นโมเดลที่ถูกเทรนจากรูปคลื่นดิบของเสียงจาก 53 ภาษาด้วยชุดข้อมูล Common Voice และ BABEL โมเดลเรียนรู้ตัวแทนของ quantized speech unit ด้วย contrastive loss การเทรนข้อมูลแบบนี้ได้รับการพิสูจน์แล้วว่าได้ผลดีกว่าเทรนด้วยข้อมูลจากเสียงในภาษาเดียว นี่เป็นนิมิตรหมายอันดีสำหรับภาษาทรัพยากรน้อยอย่างภาษาไทย ที่ก่อนหน้านี้ Common Voice 6.1 มีเพียง 8 ชั่วโมงเท่านั้น @tann9949 ปรับแต่งโมเดลด้วยชุดข้อมูลขนาดเล็กนี้ได้ผลดีพอประมาณ (chompk/wav2vec2-large-xlsr-thai-tokenized) แต่จุดเปลี่ยนที่แท้จริงคือการรณรงค์ “ทำบุญด้วยการบริจาคเสียง” บนโซเชียลมีเดียช่วงเดือนเมษายน 2021 ที่ทำให้ Common Voice 7.0 มีปริมาณข้อมูลเพิ่มขึ้นถึง 133 ชั่วโมง เป็นจุดที่การปรับแต่งโมเดลคุณภาพสูงกลายเป็นสิ่งที่ทำได้อย่างแท้จริง

เราปรับโน้ตบุ๊ค Fine-tuning Wav2Vec2 for English ASR notebook ของ HuggingFace สำหรับ Wa2Vec2 Fine-tuning Week มาใช้เพื่อปรับแต่งโมเดลของเราด้วย Connectionist Temporal Classification (CTC) loss โมเดลใช้ vocab ระดับตัวอักษร 62 tokens ประกอบด้วยตัวอักษรภาษาไทย อังกฤษ ตัวเลข และ token พิเศษ เช่น [PAD] สำหรับ CTC blank token, [UNK] สำหรับ token ที่โมเดลไม่เคยเห็น, และ |สำหรับช่องว่าง " "เราแบ่งคำในประโยคด้วยช่องว่าง และตัดคำด้วย PyThaiNLP 2.3.1 ตาม Wav2Vec ถึงแม่ว่า CTC loss จะถูกคำนวณในระดับตัวอักษรก็ตาม ไฟล์เสียง mp3ถูกเปลี่ยนให้ sampling rate เป็น 16 kHz เพื่อให้เหมาะกับโมเดล XLSR-Wav2Vec ที่ถูกเทรนมาก่อน

เราทำการปรับแต่งโมเดลบน NVIDIA V100 GPU เป็นจำนวน 100 epochs (ประมาณ 135k steps) ด้วย batch size ขนาด 32 ตัวอย่าง เราใช้ linear learning rate schedule ด้วย warm-up steps จำนวน 1,000 steps และ peak learning rate ที่ 1e-4 เราเลือกโมเดลที่ step ที่ validation loss ต่ำสุดในแต่ละ epoch ปรากฎว่านั่นคือ epoch สุดท้าย หมายความว่าเราอาจจะเทรนต่อได้อีกเล็กน้อย เราใช้เวลาในการเทรนประมาณ 5 วัน เทียบเท่ากับ 15.55 kg of CO2 eq. หรือการขับรถทั่วไปประมาณ 62.8 กิโลเมตร

การประเมินผลและเทียบกับโมเดลในตลาด

เราวัดผลโมเดลบนชุด test-uniqueโดยใช้ Word Error Rate (WER) ด้วยคำที่ตัดด้วย PyThaiNLP 2.3.1 หรือ deepcut และ Character Error Rate (CER) เพื่อป้องกันความแตกต่างที่เกิดจากการทำนายของแต่ละโมเดล เราลบช่องว่างและตัวอักษรพิเศษทั้งหมด (เช่น .ด้วย AWS Transcribe) แล้วจึงตัดคำด้วย PyThaiNLP 2.3.1 หรือ deepcut

โมเดลของเราได้ผลลัพธ์ดีพอๆ กับโมเดล ASR ชั้นนำอื่นๆ ที่ใช้ในระดับอุตสาหกรรม เช่น Microsoft, Google และ Amazon อนึ่ง โมเดลที่นำมาเทียบเหล่านี้ไม่ได้รับการปรับแต่งกับ Common Voice ดังนั้นจึงอาจจะมีผลดีกว่าหากถูกปรับแต่ง เป็นเรื่องน่าสนใจที่ผลการทดลองแย่ลงเมื่อเราทำการแก้ตัวสะกดผิดด้วย n-gram language model จาก Thai National Corpus (TNC) ที่ทำโดย @wannaphong นี่อาจจะเป็นเพราะ TNC เต็มไปด้วยคำภาษาเขียน เราจึงอาจจะต้องสร้างชุดข้อมูลภาษาพูดเพื่อทำให้การแก้คำผิดได้ผลดีขึ้น

WER เป็นตัวชี้วัดที่ขึ้นอยู่กับการตัดคำเป็นอย่างมาก CER จึงอาจจะเป็นตัวชี้วัดที่ดีกว่าสำหรับประโยคสั้นๆ อย่างใน Common Voice อีกสิ่งหนึ่งที่เราควรจะสร้างคือตัวชี้วัดที่เหมาะกับ ASR ภาษาไทย

การใช้งานโมเดลและโมเดล Speech-to-Text สำหรับทุกคนอย่างแท้จริง

สามารถอ่านวิธีการเทรนโมเดล Kaldi ได้ใน vistec-ai/commonvoice-th คุณสามารถเริ่มเทรนโมเดลบน Common Voice 7.0 ได้อย่างง่ายดาย แต่คุณจำเป็นต้องสร้าง webrtc front-end สำหรับติดต่อกับ Kaldi server เพื่อใช้โมเดลแบบ online ก่อน สามารถอ่านรายละเอียดต่อได้ใน danijel3/KaldiWebrtcServer

อีกโมเดลหนึ่งคือ airesearch/wav2vec2-large-xlsr-53-th ที่คุณสามารถใช้ได้ฟรีภายใต้ CC-BY-SA 4.0 เช่นกัน โดยลองเล่นได้ทันทีผ่าน HuggingFace Model Hub บนเครื่อง ml.t3.2xlarge ของเรา การถอดความ 1 คลิปสั้นใช้เวลาโดยเฉลี่ย 1.09 วินาที (45 นาที 31 วินาทีสำหรับ 2,502 ประโยคหรือประมาณ 2 ชั่วโมงบนชุด test) โมเดลสามารถ deploy บน AWS SageMaker ด้วย official support หรือ cloud ยี่ห้ออื่น หรือบนเซิร์ฟเวอร์ของคุณเอง

AIResearch.in.th and PyThaiNLP Release High-Performance, Open-source Automatic Speech Recognition (ASR) Models for Thai

AIResearch.in.th and PyThaiNLP release open-source, high-performance ASR models trained on Common Voice 7.0. These include Kaldi models trained from scratch and a fine-tuned XLSR-Wav2Vec2 model. Our models have comparable performance to zero-shot APIs offered by market leaders such as Microsoft, Google and Amazon on our test set. Our models are under the CC-BY-SA 4.0 license and can be easily and freely deployed for both research and commercial purposes on cloud and on premise, with inference time of about 1 second on average on CPU. We recommend trying these models for general conversations such as ordering food, customer service, and transcribing meetings; however, they may have troubles recognizing named entities.

Our models are still far from a robust Thai ASR model that is applicable to all contexts.

Performance comparison with Microsoft, Google and Amazon APIs are done without fine-tuning these APIs on Common Voice 7.0 thus their performance after fine-tuning is expected to be much closer or better than ours. Problems such as unknown words in the training set, named entities such as brand names, technical terms, slangs, etc., and English words in mostly Thai sentences are still open challenge for researchers and developers. We hope our models will help serve as one of the first steps towards a strong community effort on open-source Thai ASR.

Try our models at

How to train at

One Does Not Simply Train An ASR Model on Common Voice

We used the Mozilla Common Voice Corpus 7.0 which contains 133 validated hours in Thai, crowdsourced from 7,212 speakers. @tann9949 created cleaning rules designed for Thai speech recognition tasks. First, we removed non-alphanumeric characters, mostly punctuations, since whereas some may be indicative of tones such as `!` (excited tone) or `?` (questioning tone), others are not as relevant to speech in Thai such as `“`, `.`, `;`, or `:`. Second, we normalize misspellings such as `แ` spelled as double `เ`s, `ำ` spelled as `ํ` and `า`, and make sure all tonal marks follow vowels.Third, we replace all `ๆ`, which marks repeated words, with actual repeated words; for instance `ดีมากๆ` will become `ดีมากมาก`. Lastly, we hard-coded some sentences that fall through the cracks of these rules.

Mozilla deduplicated the dataset by exact match, then randomly sampled into train, validation and test splits. The problem is that at face value these splits may appear to be unique sentences, but after we clean the crowdsource texts that serve as labels for our models, they become duplicates.

In order to solve this, @ekapolc and @14mss re-split the cleaned dataset into `train` (86,586 sentences), `dev-unique` (3,027 sentences) and `test-unique` (2,502 sentences) using the following procedure:

There is also the `dev` and `test` splits where we do not take into account duplication of sentences within the same splits.

This procedure not only solves the problem of duplicated sentences after cleaning, it also prevents data leakage by having the same speakers in different splits. We benchmark on the unique version of the test split.

Train Kaldi Models from Scratch

Kaldi is an automatic speech recognition toolkit that is designed specifically to efficiently train a classical ASR model. The model is composed of 3 parts: acoustic model, lexicon, and language model.

An acoustic model aims to model a probability of a speech feature in each time frame given labeled phonemes. Simply put, its job is to learn to spell a phoneme from a given input speech feature (filterbank, MFCC, MFCC+pitch, etc.). The model is generative and is trained iteratively, from a simple method (HMM-GMM) up to a more complex method such as HMM-DNN. Therefore, we will see the validation split results containing `mono`, `tri1b`, `tri3b`, etc. This indicates an iterative acoustic model training. The most sophisticated acoustic model we used is called `tdnn-chain` which refers to Time-Delay Neural Networks.

Lexicon is just a mapping between a phoneme from an acoustic model to a specific word in a look-up table. Normally, linguists are required to obtain a phoneme representation of words, but due to our limited resource, we just used a grapheme representation (representing phonemes as characters `ฉัน` -> `ฉ ั น`) instead.

Finally, a language model tries to correct the sentence that doesn’t feel quite likely. We knew that acoustics models pronounce phonemes from speech, lexicon maps phonemes to words. Thus, we should obtain a brief transcription sentence. However, some similar word pronunciation can ruin a sentence (`ค่าเงินบาท` and `ฆ่าเงินบาท` sounds the same but totally different meaning!). Therefore, we need final proof that our sentence sounds just right considering the context, and that job is for the language model. In this work, we use a n-gram language model to rescore the final transcription.

We conduct our experiment following standard commonvoice kaldi recipe using 4 NVIDIA V100 GPUs to obtain the highest batch size possible. The training takes around a single day to complete a full training pipeline. This results in the carbon footprint of 12.44 kg of CO2 eq., equivalent to driving an average car for 50 km.

Fine-tune XLSR-Wav2Vec2 for Thai and How Merit-Making Grows Thai Common Voice by 16 Times

XLSR-Wav2Vec2 is a cross-lingual pretrained model for ASR using raw waveforms of 53 languages using Common Voice and BABEL datasets. The model learns the representation of multilingual quantized speech units using contrastive loss. It has been shown that this multilingual pretraining yields better results than monolingual pretraining. This is promising for low-resource languages in terms of speech datasets such as Thai. Previously, Thai Common Voice 6.1 stagnated around 8 validated hours. @tann9949 fine-tuned chompk/wav2vec2-large-xlsr-thai-tokenized on this very small dataset with some success. But, it was only after an extremely successful make-merit-through-voice-donation campaign on social media in April 2021, where we saw Common Voice 7.0 grew to 133 validated hours, that fine-tuning a high-performance model became truly feasible.

We adapted HuggingFace’s Fine-tuning Wav2Vec2 for English ASR notebook for Wav2Vec2 Fine-tuning Week. Wav2Vec2 model fine-tunes using Connectionist Temporal Classification (CTC) loss using character tokens. We use 62 tokens in total with Thai and English characters, as well as special tokens namely `[PAD]` as the CTC blank token, `[UNK]` for any unknown character, and `|` as the space token. We decided to word-tokenize our texts with space using PyThaiNLP 2.3.1 to follow the convention of pretrained Wav2Vec even though CTC loss is calculated at character level. The `mp3` audio files are resampled to the sampling rate of 16 kHz to match the pretrained model.

We conduct fine-tuning on a single V100 GPU for 100 epochs (around 135k steps) with the batch size of 32 examples. We use a linear learning rate schedule with 1,000 warm-up steps and peak learning rate of 1e-4. We chose the model with the lowest validation loss at the end of each epoch; this turns out to be the last epoch which could mean we can further train the model for lower validation loss. The total training time is roughly 5 days. This results in the carbon footprint of 15.55 kg of CO2 eq., equivalent to driving an average car for 62.8 km.

Evaluation and Benchmarking

We evaluate the performance on the test set (`test-unique`) using Word Error Rate (WER) where words are defined by PyThaiNLP 2.3.1 and deepcut, and Character Error Rate (CER). To avoid discrepancies due to model output variations (some models output words with spaces; others output texts without spaces), we remove all spaces and special characters (such as `.` by AWS Transcribe) and re-tokenize with PyThaiNLP 2.3.1 and deepcut.

We have comparable performance with industry-grade ASR models from Microsoft, Google and Amazon. Nonetheless, since we did not fine-tune these models with Common Voice data before testing, their performance could have been better if fine-tuning was done. Interestingly, spell-correcting the output from our model makes the performance worse. This could be due to the fact that our spell correction algorithm devised by @wannaphong relies on n-grams from Thai National Corpus, which contains mostly written language. We might need a corpus for spoken language for better performance.

WER is highly dependent on the applied word tokenization algorithm, while CER might be sufficient for short sentences but misleadingly low for longer ones. Therefore, we see a gap where more suitable performance metrics can be created for Thai ASR.

Inference, Deployment, and Truly Open-source ASR Models for All

For Kaldi models, we provide a vistec-AI/commonvoice-th kaldi recipe which automates training on Common Voice 7.0 starting with minimal effort. To perform an online decoding, a webrtc front-end is required to communicate with kaldi’s server. For more information, we encourage users to read more at danijel3/KaldiWebrtcServer for an example of webrtc decoding.

airesearch/wav2vec2-large-xlsr-53-th is an open-source model under CC-BY-SA 4.0 license. You can try the demo directly on HuggingFace. On our `ml.t3.2xlarge` instance, CPU inference takes on average 1.09 seconds per a short clip (45 minutes 31 seconds over 2,502 examples equivalent to about 2 hours in the test set). The model can be deployed directly on AWS SageMaker with official support as well as other cloud or on-premise platforms.

--

--