1. เริ่มต้นง่ายๆ กับ ASR ภาษาไทย

โดย SpeeChy

สวัสดีครับ ก็เป็นบทความเชิง Tutorial บทความแรกสำหรับกลุ่มผู้สนใจใน ASR (Automatic speech recognition) นะครับ บทความแรกนี้มีจุดประสงค์ที่จะแนะนำให้ผู้ที่เริ่มต้นสำหรับ ASR ไม่ว่าสำหรับภาษาใด แต่เนื่องจากระบบสำหรับภาษาอื่นๆ ก็มีมามากแล้ว ผมจึงอยากใช้เวทีนี้ ค่อยๆ สร้างองค์ความรู้และแหล่งข้อมูลฟรีๆ สำหรับภาษาไทยโดยเฉพาะ เริ่มกันด้วยการสร้าง ASR ง่ายๆ สำหรับรู้จำเสียงพูดลำดับตัวเลข (Digit sequence) และแน่นอนเป็นภาษาไทย ศูนย์ ถึงเก้า ไม่ใช่ ซีโร่ ถึง นายน์ นะครับ ก่อนอื่น ผมอยากจะแยกเป็น Tutorial สำหรับคนสองกลุ่ม

  • กลุ่มที่ 1 (อย่างเร็ว) - อยากจะทดลองใช้ระบบรู้จำดูผลการใช้งาน โดยผมจะมีโมเดลที่ผ่านการเรียนรู้มาแล้วให้ครับ
  • กลุ่มที่ 2 (อย่างลึก) - อยากจะเรียนรู้ขั้นตอนวิธีการสร้างส่วน ประกอบต่างๆ ตั้งแต่เริ่มเลยครับ
บางท่านอาจจะทราบแล้วว่ามี ASR Toolkit ที่สร้างโดยศูนย์วิจัยต่างๆ ในโลกมากมาย อาทิเช่น Hidden Markov toolkit (HTK) โดย Cambridge University หรือ Sphinx โดย Canegie Mellon University เปิดให้ดาวน์โหลดมาใช้ในการทดลองวิจัยได้ครับ (แต่ขายไม่ได้) เราสามารถใช้ Toolkit ดังกล่าว มาสร้างระบบสำหรับภาษาไทยได้ไม่ยากครับ ตราบใดที่เรามี ฐานข้อมูลให้กับมัน ในบทความนี้ ผมก็ขอยึดเอา HTK เป็นหลักนะครับ ใน HTK เองก็มี Tutorial ให้เหมือนกัน อยากจะอ่านจากตรงนั้นหรือตรงนี้ก็แล้วแต่ความพอใจของแต่ละท่านละกันครับ


กลุ่มที่ 1 (อย่างเร็ว)

ขั้นตอนที่ 1

  • ดาวน์โหลด HTK จาก http://htk.eng.cam.ac.uk มา install ตามขั้นตอนที่สอนในเว็ป
  • ตั้ง Path ให้สามารถเรียกคำสั่ง Executable files ของ HTK หาก install ถูกต้อง เมื่อเรียกคำสั่งใดๆ ของ HTK โดยไม่ได้ใส่ Argument ใดๆ โปรแกรมจะแสดง Short help ของคำสั่งนั้นๆ
ขั้นตอนที่ 2
  • ดาวน์โหลด Tutorial thaispeech_1-1.tar.gz (819 kB)
  • Unzip ด้วยคำสั่ง

    prompt> tar -zxf thaispeech1-1.tar.gz

  • ในไดเรคทอรี thaispeech1-1/ จะประกอบด้วยไดเรคทอรีย่อยดังนี้

    config/เก็บไฟล์ที่กำหนดพารามิเตอร์ต่างๆ ในการรู้จำ
    am/เก็บไฟล์โมเดลเสียง (Acoustic model)
    lm/เก็บไฟล์โมเดลภาษา (Language model)
    mfc/สำหรับเก็บไฟล์ค่าสำคัญของเสียงที่จะรู้จำ (Speech feature) เริ่มต้นจะยังว่างเปล่า
    wav/เก็บไฟล์เสียงที่เป็นตัวอย่างในการทดลองรู้จำ เช่น 13579.wav เป็นเสียงพูดตัวเลข 13579 ลอง play ฟังดูได้ครับ เป็นไฟล์ wav ธรรมดา

  • นอกจากนี้ในไดเรคทอรี thaispeech1-1/ ยังมีไฟล์อีก 4 ไฟล์ได้แก่

    code.scpเก็บลิสต์ของไฟล์เสียง .wav คู่กับไฟล์ค่าสำคัญของเสียง .mfc ไฟล์นี้เป็นอินพุตของ code.sh ครับ เปิดดูได้ครับ เป็น ASCII text ธรรมดา
    test.scpเก็บลิสต์ไฟล์เสียงที่ต้องการจะรู้จำ แต่ในรูปแบบของไฟล์ .mfc แล้วนะครับ ไฟล์นี้ก็เป็น ASCII text ธรรมดา ลองเปิดดูครับ
    code.shเป็น Script file เพื่อแปลงไฟล์เสียง .wav เป็นไฟล์ .mfc ซึ่งเก็บค่าสำคัญของเสียง
    recog.shอันนี้เป็น Script file สั่งให้ระบบทำการรู้จำครับ

ขั้นตอนที่ 3
  • ในการรู้จำ ต้องแปลงไฟล์เสียง .wav เป็นไฟล์ค่าสำคัญ .mfc ก่อน โดยใช้คำสั่งในไดเรคทอรี thaispeech1-1/

    thaispeech1-1> code.sh

    คำสั่งนี้จะทำการแปลง .wav เป็น .mfc ตามที่ลิสต์ไว้ใน code.scp ครับ ลองดูในไดเรคทอรี thaispeech1-1/mfc/ จะพบว่ามีไฟล์ .mfc เกิดขึ้นมา

ขั้นตอนที่ 4
  • ในการรู้จำก็ง่ายๆ ครับ ในไดเรคทอรี thaispeech1-1/ ใช้คำสั่ง

    thaispeech1-1> recog.sh

    ระบบจะทำรับเอาไฟล์ .mfc ที่ลิสไว้ใน test.scp มาทำการรู้จำทีละไฟล์ละเก็บผลการรู้จำไว้ในไฟล์ output.mlf ที่สร้างขึ้นใหม่ในไดเรคทอรีเดียวกัน เปิดดู output.mlf ครับ เป็น text file ธรรมดา แสดงผลการรู้จำแต่ละไฟล์ น่าเสียดายที่ HTK ไม่สามารถแสดงผลเป็นภาษาไทยได้ ผมเลยสร้าง ระบบให้แสดงตัวเลขเป็นภาษาอังกฤษดังนี้ครับ

    ศูนย์ = suun4หนึ่ง = nvng1
    สอง = s@@ng4สาม = saam4
    สี่ = sii1ห้า = haa2
    หก = hok1เจ็ด = cet1
    แปด = pxxt1เก้า = kaw2

  • จะทดลองอัดเสียงตัวเองเป็นไฟล์ .wav แล้วมารู้จำดูก็ทำได้เช่นเดียวกันครับ เพียงแค่แก้ชื่อไฟล์ที่จะรู้จำใน code.scp และ test.scp แล้วก็ทำตามขั้นตอนที่ 3 และ 4 เท่านั้นเอง แต่มีข้อแม้นิดนึงนะครับ ไฟล์ .wav ที่อัดมา ต้องอัดด้วย 16 บิต 16 กิโลเฮิร์ต โมโน และเก็บไฟล์ในรูปแบบ ของ PCM wav ครับ สำหรับท่านที่ไม่ค่อยเข้าใจค่าต่างๆ เหล่านี้ ก็อดใจรอ Tutorial ต่อๆ ไปนะครับ จะค่อยๆ ลงลึกแบบเข้าใจง่ายๆ ครับ

  • แท้จริงแล้วคำสั่งของ HTK ก็สามารถใช้ในการรู้จำแบบพูดโดยตรงผ่านไมโครโฟนแล้วรู้จำทันทีได้เหมือนกันครับ เรียกว่า Live recognition หากท่านมั่นใจว่าได้เซตอัพไมโครโฟนของท่านให้รับเสียงได้แล้วล่ะก็ ลองดาวน์โหลดไฟล์คำสั่ง liverecog.sh และ liverecog.config ไปวางในไดเรคทอรี thaispeech1-1/ แล้วสั่งดูครับ

    thaispeech1-1> liverecog.sh

    ระบบจะทำการโหลดโมเดลเสียงและภาษามาเตรียมไว้ พร้อมกับรอรับเสียงพูดของท่าน

  • สุดท้ายก็มาเรียนรู้กันครับ ว่าคำสั่งต่างๆ ที่ทดลองไป ระบบทำงานอย่างไรใน หลักการรู้จำเสียง


กลุ่มที่ 2 (อย่างลึก)

ขั้นตอนที่ 1

  • ดาวน์โหลด HTK จาก http://htk.eng.cam.ac.uk มา install ตามขั้นตอนที่สอนในเว็ป
  • ตั้ง Path ให้สามารถเรียกคำสั่ง Executable files ของ HTK หาก install ถูกต้อง เมื่อเรียกคำสั่งใดๆ ของ HTK โดยไม่ได้ใส่ Argument ใดๆ โปรแกรมจะแสดง Short help ของคำสั่งนั้นๆ
ขั้นตอนที่ 2
  • ดาวน์โหลด Tutorial thaispeech_1-2.tar.gz (19.98 MB)
  • Unzip ด้วยคำสั่ง
    prompt> tar -zxf thaispeech1-2.tar.gz

  • ในไดเรคทอรี thaispeech1-2/ จะประกอบด้วยไดเรคทอรีย่อยดังนี้

    config/เก็บไฟล์ที่กำหนดพารามิเตอร์ต่างๆ ในการเรียนรู้และรู้จำ
    script/เก็บ Script file ที่ใช้สั่งเพื่อเรียนรู้
    am/สำหรับเก็บไฟล์โมเดลเสียง (Acoustic model) เริ่มต้นยังว่างเปล่าครับ เพราะยังไม่ได้สร้าง
    lm/สำหรับเก็บไฟล์โมเดลภาษา (Language model)
    mfc/สำหรับเก็บไฟล์ค่าสำคัญของเสียง (Speech feature) เริ่มต้นยังว่างเปล่าก่อนครับ
    wav/เก็บไฟล์เสียงที่เป็นตัวอย่างในการเรียนรู้และทดลองรู้จำ เช่น 13579.wav เป็นเสียงพูดตัวเลข 13579 ลอง play ฟังดูได้ครับ เป็นไฟล์ wav ธรรมดา

  • นอกจากนี้ในไดเรคทอรี thaispeech1-2/ ยังมีไฟล์ได้แก่

    code.scpเก็บลิสต์ของไฟล์เสียง .wav คู่กับไฟล์ค่าสำคัญของเสียง .mfc ไฟล์นี้เป็นอินพุตของ code.sh ครับ เปิดดูได้ครับ เป็น ASCII text ธรรมดา
    code.shเป็น Script file เพื่อแปลงไฟล์เสียง .wav เป็นไฟล์ .mfc ซึ่งเก็บค่าสำคัญของเสียง
    train.scpเก็บลิสต์ไฟล์เสียงที่ใช้ในการเรียนรู้ แต่อยู่ในรูปแบบของไฟล์ .mfc แล้วนะครับ ลองเปิดดู ครับ เป็น ASCII text ธรรมดา
    trainam.shเป็น Script file สั่งให้ระบบเริ่มเรียนรู้ สร้างโมเดลเสียงที่ใช้ในการรู้จำ
    trainlm.shเป็น Script file สั่งให้ระบบสร้างโมเดลภาษาที่ใช้ในการรู้จำ
    test.scpเก็บลิสต์ไฟล์เสียงที่ต้องการจะรู้จำ ในรูปแบบของไฟล์ .mfc ลองเปิดดูครับ
    recog.shอันนี้เป็น Script file สั่งให้ระบบทำการรู้จำครับ

ขั้นตอนที่ 3
  • เริ่มต้น ต้องแปลงไฟล์เสียง .wav เป็นไฟล์ค่าสำคัญ .mfc ก่อน โดยใช้คำสั่งในไดเรคทอรี thaispeech1-2/

    thaispeech1-2> code.sh

    คำสั่งนี้จะทำการแปลง .wav เป็น .mfc ตามที่ลิสต์ไว้ใน code.scp ครับ ลองดูในไดเรคทอรี thaispeech1-2/mfc/ จะพบว่ามีไฟล์ .mfc เกิดขึ้นมา

ขั้นตอนที่ 4
  • ทำการสร้างโมเดลเสียงที่ใช้ในการรู้จำ โดยใช้คำสั่ง

    thaispeech1-2> trainam.sh

    หลังจากสั่งคำสั่งนี้ ระบบจะนำไฟล์ .mfc ที่ใช้ในการเรียนรู้ (ลิสต์ไว้ใน train.scp) มาสร้างโมเดลเสียง ใช้เวลานาน พอสมควรขึ้นอยู่กับความเร็วของเครื่องนะครับ หลังจากจบการเรียนรู้ จะพบว่าใน thaispeech1-2/am/ เกิดไดเรคทอรี ย่อยขึ้นมากมาย แต่ละไดเรคทอรีเก็บโมเดลเสียงที่ซับซ้อนขึ้นเรื่อยๆ ไดเรคทอรีสุดท้ายคือ thaispeech1-2/am/tiehmm2m_3/ จะเก็บโมเดลเสียงอันสุดท้าย ใช้ในการรู้จำ

  • ภายใน trainam.sh มีคำสั่งย่อยมากมาย มาเรียนรู้กันครับ ว่าแต่ละคำสั่งทำอะไรใน หลักการสร้างโมเดลเสียง
ขั้นตอนที่ 5
  • ทำการสร้างโมเดลภาษาที่ใช้ในการเรียนรู้ โดยใช้คำสั่ง

    thaispeech1-2> trainlm.sh

    คำสั่งนี้ จะทำการแปลงไฟล์ grammar (ไฟล์ dgs.gram ใน thaispeech1-2/config/) ซึ่งเราเขียนขึ้นเพื่อกำหนด ว่าระบบจะรู้จำประโยคแบบใดได้บ้าง ไปเป็นไฟล์ .wdnet ซึ่งเป็นโมเดลภาษาที่ระบบใช้ในการรู้จำ เก็บไว้ใน thaispeech1-2/lm/

  • แล้วไฟล์ grammar นี้ แท้จริงเตรียมมาอย่างไร ดูใน หลักการสร้างโมเดลภาษา ครับ
ขั้นตอนที่ 6
  • ในการรู้จำก็ง่ายๆ ครับ ในไดเรคทอรี thaispeech1-2/ ใช้คำสั่ง

    thaispeech1-2> recog.sh

    ระบบจะทำรับเอาไฟล์ .mfc ที่ลิสไว้ใน test.scp มาทำการรู้จำทีละไฟล์ละเก็บผลการรู้จำไว้ในไฟล์ output.mlf ที่ สร้างขึ้นใหม่ในไดเรคทอรีเดียวกัน เปิดดู output.mlf ครับ เป็น ASCII text ธรรมดา แสดงผลการรู้จำแต่ละไฟล์ น่า เสียดายที่ HTK ไม่สามารถแสดงผลเป็นภาษาไทยได้ ผมเลยสร้างระบบให้แสดงตัวเลขเป็นภาษาอังกฤษดังนี้ครับ

    ศูนย์ = suun4หนึ่ง = nvng1
    สอง = s@@ng4สาม = saam4
    สี่ = sii1ห้า = haa2
    หก = hok1เจ็ด = cet1
    แปด = pxxt1เก้า = kaw2

  • จะทดลองอัดเสียงตัวเองเป็นไฟล์ .wav แล้วมารู้จำดูก็ทำได้เช่นเดียวกันครับ เพียงแค่แก้ชื่อไฟล์ใน code.scp และ test.scp แล้วก็ทำตามขั้นตอนที่ 3 และ 6 เท่านั้นเอง (ไม่ต้องเรียนรู้โมเดลแล้วนะครับ เรามีแล้ว) แต่มีข้อแม้นิดนึงนะครับ ไฟล์ .wav ที่อัดมา ต้องอัดด้วย 16 บิต 16 กิโลเฮิร์ต โมโน และเก็บไฟล์ในรูปแบบของ PCM wav ครับ สำหรับท่านที่ไม่ค่อยเข้าใจค่าต่างๆ เหล่านี้ ก็อดใจรอ Tutorial ต่อๆ ไปนะครับ จะค่อยๆ ลงลึกแบบเข้าใจง่ายๆ ครับ
  • แท้จริงแล้วคำสั่งของ HTK ก็สามารถใช้ในการรู้จำแบบพูดโดยตรงผ่านไมโครโฟนแล้วรู้จำทันทีได้เหมือนกันครับ เรียกว่า Live recognition หากท่านมั่นใจว่าได้เซตอัพไมโครโฟนของท่านให้รับเสียงได้แล้วล่ะก็ ลองดาวน์โหลดไฟล์คำสั่ง liverecog.sh และ liverecog.config ไปวางในไดเรคทอรี thaispeech1-2/ แล้วสั่งดูครับ

    thaispeech1-2> liverecog.sh

    ระบบจะทำการโหลดโมเดลเสียงและภาษามาเตรียมไว้ พร้อมกับรอรับเสียงพูดของท่าน

  • คราวนี้ก็มาเรียนรู้กันครับ ระบบทำการรู้จำอย่างไรใน หลักการรู้จำเสียง


หลักการรู้จำเสียง

ในการรู้จำ ระบบไม่ได้เอาสัญญาณเสียงเพียวๆ ไปเทียบนะครับ แต่จะดึงเฉพาะค่าสำคัญของเสียงออกมา เราเรียกค่าสำคัญนี้ว่า Speech feature ค่าสำคัญที่เป็นที่นิยมมากที่สุดในปัจจุบันคือ Mel-frequency cepstral coefficient (MFCC) มันคืออะไรคงต้องว่ากันยาวๆ ใน Tutorial ต่อๆ ไปครับ เอาเป็นว่ามันเป็นตัวแทนของเสียงในการรู้จำได้เป็นอย่างดี ขั้นตอนการแปลงนี้ เราทำในคำสั่ง code.sh ครับ ก็คือแปลงจาก .wav เป็น .mfc นั่นเอง ค่า MFCC นี้เก็บเป็นเวกเตอร์ครับ เวกเตอร์นึงแทนสัญญาณเสียงยาวประมาณ 20 มิลลิวินาที แต่ละเวกเตอร์ก็แทนสัญญาณเสียง ที่ค่อยๆ เลื่อนไปแบบ overlap เช่นเลื่อนไปทีละ 10 มิลลิวินาที ดังรูปที่ 1 ดังนั้นหากมีเสียงที่ยาวซัก 1 วินาทีเข้ามา ก็จะแทนด้วยเวกเตอร์จำนวน 100 อัน

รูปที่ 1 การดึง Speech feature

Sequence ของเวกเตอร์ที่แทนสัญญาณเสียงนี้มักจะเรียกกันว่า Observation sequence ขอแทนสั้นๆ ด้วยตัว O ละกันนะครับ และ เรียกเวกเตอร์ใดๆ ใน O ว่า Observation vector ก่อนที่จะมารู้ว่าระบบรู้จำได้อย่างไร เราต้องรู้จักคำว่า Phone คำว่า โมเดลการออกเสียง (Pronunciation model) คำว่า โมเดลเสียง (Acoustic model) และคำว่าโมเดลภาษา (Language model) ก่อน

Phone คืออะไรครับ Phone คือหน่วยย่อยสุดทางเสียง ตัวอย่างเช่น คำว่า "การ" อ่านออกเสียงด้วยเสียง "ก" ตามด้วยสระ "า" และลงท้ายด้วย เสียงตัวสะกด "น" พวกนี้แหละครับคือ Phone ในทางภาษาศาสตร์ จะมีสัญลักษณ์มาตรฐานแทนเสียง Phone แต่ละเสียง ตัวอย่างเช่น "k" แทน เสียง "ก" "aa" แทนสระ "า"

โมเดลการออกเสียงคืออะไรครับ หน้าที่ของมันคือ บอกว่า คำ (Word) ใดๆ ออกเสียงอย่างไร โดยจะบอกเป็น Sequence ของ Phone ครับ อาทิเช่น "การ" ออกเสียงว่า "k aa n^" "ขนม" ออกเสียงว่า "kh a n o m^" วิธีสร้างโมเดลการออกเสียงง่ายๆ ก็คือการสร้าง Pronunciation dictionary ที่เก็บ list ของคำคู่กับเสียงอ่านของมัน ตัวอย่างของ Pronunciation dictionary ก็คือไฟล์ dgs.dict ในไดเรคทอรี /config

โมเดลเสียงคืออะไร ผมอยากจะอธิบายง่ายๆ ดังรูปที่ 2 โดยปกติเราจะมีโมเดลเสียง 1 โมเดลต่อ 1 Phone เมื่อเราป้อน Observation sequence เข้าไปยังโมเดลเสียงใดๆ มันจะคำนวณค่าความน่าจะเป็นที่ Observation sequence นั้นจะเป็นเสียงของ Phone นั้นๆ ความน่าจะเป็นที่ว่านี่เขียน สั้นๆ ว่า P(O|p) โดยที่ p คือโมเดลเสียงของ Phone ใดๆ

รูปที่ 2 หน้าที่ของ Acoustic model

โมเดลภาษาคืออะไรครับ โมเดลภาษาจะบอกเราว่าคำ (Word) นี้ ตามด้วยคำนี้ได้หรือไม่ หรือในบางโมเดลจะบอกค่าความน่าจะเป็นที่คำใดๆ จะพูดต่อกัน อาทิเช่น โมเดลภาษาอาจจะบอกว่า "จะ ไป" เกิดได้ แต่ "ไป จะ" ไม่ได้ หรืออาจจะบอกเป็นค่าความน่าจะเป็นว่า "จะ ไป" มีโอกาสเกิดได้ 0.8 แต่ "ไป จะ" มีโอกาสเกิดได้แค่ 0.01 เป็นต้น โมเดลภาษาแท้จริงไม่เพียงบอกโอกาสที่คำสองคำจะเกิดคู่กันเท่านั้น มันยังสามารถบอกด้วยว่า ทั้งประโยคมีโอกาสเกิด ได้เท่าไหร่ สมมติว่าเรามีประโยค ซึ่งประกอบด้วยคำต่อๆ กันหลายๆ คำ ขอแทนด้วย W ละกันนะครับ W = (w1...wM) โดยที่ w แทนคำแต่ละคำ โมเดลภาษาจะบอกว่า W สามารถเกิดได้หรือไม่ หรือบอกเป็นค่าความน่าจะเป็นว่ามีโอกาสเกิดมากน้อยแค่ไหน ค่าความน่าจะเป็นที่ว่าขอแทนด้วย P(W) ละกัน รูปที่ 3 แสดงให้เห็นหน้าที่ของโมเดลภาษา

รูปที่ 3 หน้าที่ของ Language model

การรู้จำจะทำตามขั้นตอนต่อไปนี้ครับ

  1. ระบบรับ Observation sequence ที่ต้องการรู้จำเข้ามา
  2. มันจะเริ่มด้วยการเดาว่าเป็นคำใดต่อๆ กัน! จะเป็นประโยคว่า "ฉัน รัก เธอ" ประโยคว่า "ฉัน หิว ข้าว" หรือ "อาหาร อร่อย ดี" ฯลฯ.
  3. หลังจากเดาประโยคขึ้นมาแล้ว มันจะส่งประโยคนั้นเข้าไปยัง Language model ได้ค่าความน่าจะเป็น P(W) ที่จะเกิดประโยคดังกล่าว
  4. หลังจากนั้นมันจะทำการแปลงประโยคเป็นเสียงอ่านโดยอาศัย Pronunciation model อาทิเช่น จาก "ฉัน รัก เธอ" เป็น "ch a n^ r a k^ th vv"
  5. เมื่อได้ Sequence ของ Phone แล้ว ก็จะเอา Acoustic model ของแต่ละ Phone มาต่อกัน แล้วทำการป้อน Observation sequence เข้าไปยัง Acoustic model ของทั้งประโยค (ดังนั้น Acoustic model จะต้องสามารถต่อกันได้) ก็ได้จะค่าความน่าจะเป็น P(O|W) ซึ่งเกิดจาก P(O|p) ของแต่ละ Phone คูณกัน
  6. สุดท้ายมันก็จะเอา P(W) ในข้อ 3 มาคูณกับ P(O|W) ในข้อ 5 ได้เป็น P(O,W) ซึ่งหมายถึง โอกาสที่สัญญาณเสียงดังกล่าวจะเป็นเสียงประโยค W ครับ
  7. แล้วมันก็ทำอย่างนี้กับทุกๆ ประโยคที่เดาขึ้นมา และเทียบค่า P(O,W) ว่าประโยคไหนมีโอกาสสูงที่สุด ก็ตอบเป็นประโยคนั้น ง่ายไหมครับ :)
คราวนี้ปัญหาก็ตามมาสิครับ ว่าประโยคที่เป็นไปได้มีหลากหลายล้านล้านแบบ ยิ่งไม่กำหนดว่าประโยคยาวเท่าไหร่ด้วยแล้วล่ะก็ จะมีประโยคที่เป็นไป ได้จำนวนอินฟินิตี้เลย แล้วระบบที่ไหนมันจะไปทำงานได้ล่ะครับ วิธีการแก้ไขก็คือ การสร้าง Word network ครับ โดยเอาคำมาต่อๆ กันในลักษณะของ Network ดังรูปที่ 4 ระหว่างคำก็กำกับด้วยโอกาสที่แต่ละคำจะต่อกัน หรือ P(wi|wi-1) และในแต่ละคำก็ประกอบด้วย Acoustic model ของ Phone ที่ต่อกันเป็นเสียงอ่านของคำนั้นๆ แล้วเวลาทำงานก็จะผ่านสัญญาณเสียงเข้าไป ในขณะที่ผ่าน Node ของ Network แต่ละ Node ก็จะ มีการคูณค่าความน่าจะเป็น P(O,W) ต่อๆ ไปเรื่อยๆ หากในเส้นทางใดที่ค่าความน่าจะเป็นรวมขณะนั้น ตกต่ำกว่าค่า Threshold ที่กำหนด ก็ให้เลิก วิ่งไปเส้นทางนั้น เท่านี้ก็จะช่วยลดจำนวนประโยคที่จะต้องคำนวณลงได้มากมายมหาศาลครับ วิธีนี้เขาเรียกกันว่า Beam search ครับ หรือแปลง่ายๆ ก็คือ Search ภายใน Beam ที่กำหนดเท่านั้น จริงๆ ยังมีอีกวิธีในการกำหนด Beam ของการ Search โดยกำหนดให้ ณ ขณะใดๆ จะมีเส้นทางที่วิ่ง ไปได้ ไม่เกิน N เส้นทาง วิธีนี้ก็ช่วยลดจำนวนประโยคที่ต้องคำนวณลงมหาศาลเช่นกัน เราเรียกวิธีที่สองนี้ว่า N-best search

รูปที่ 4 Word network สำหรับการรู้จำ

ตัวรู้จำหรือ Recognition engine ที่แท้แล้วก็คือ ตัวที่ทำหน้าที่ Search ไปตาม Word network นี่แหละครับ บางทีเราเรียกส่วนที่ทำหน้าที่ตรง นี้ว่า Decoder ก็ได้ครับ เป็นอันว่าเข้าใจแล้วนะครับ เอาล่ะขอสรุปอีกที Speech recognizer ประกอบด้วย Decoder ที่ทำหน้าที่สร้าง Word network และ Search ไปตามเส้นทางบน Network โดยอาศัย Acoustic model และ Language model เป็นตัวคำนวณความน่าจะเป็นของ การเกิด Phone และ Word นั่นเอง

คราวนี้ลองนึกย้อนไปยังระบบที่เราทดลองสร้างไปนะครับ ระบบที่รู้จำ Digit sequence ระบบนี้ก็มีคำที่เกิดขึ้นได้แค่ 10 คำคือ ศูนย์ ถึง เก้า เราก็สร้าง Pronunciation dictionary ไว้ในไฟล์ /config/dgs.dict แล้วเราก็มี Acoustic model ก็คือไฟล์ /config/dgs.am และ Language model ในไฟล์ /config/dgs.wdnet ในการรู้จำ ตัว Decoder คือคำสั่ง HVite จะอ่าน Acoustic และ Language model พร้อมทั้ง Pronunciation dictionary มา แล้วค่อยเริ่มรับสัญญาณเสียงครับ


หลักการสร้างโมเดลเสียง (Acoustic model)

โมเดลเสียงคืออะไร ผมอยากจะอธิบายง่ายๆ โดยใช้ รูปที่ 2 ประกอบนะครับ ปกติเราจะมีโมเดลเสียง 1 โมเดลต่อ 1 Phone เมื่อเราป้อน Observation sequence เข้าไปยังโมเดลเสียงใดๆ มันจะคำนวณค่าความน่าจะเป็นที่ Observation sequence นั้นจะเป็นเสียงของ Phone นั้นๆ ความน่าจะเป็นที่ว่านี่เขียน สั้นๆ ว่า P(O|p) โดยที่ p คือโมเดลเสียงของ Phone ใดๆ

เอาล่ะครับ เมื่อรู้จัก Acoustic model ในแบบมุมกว้างแล้ว ก็มารู้จักมันในมุมที่ลึกลงไปอีกหน่อยนะครับ Acoustic model ยอดฮิตที่ไม่มีใครเอา ชนะได้จนปัจจุบันนี้ ใช้วิธีที่เรียกว่า Hidden Markov Model (HMM) ฟังดูน่ากลัวนะครับ ผมจะพยายามอธิบายให้เข้าใจง่ายๆ ที่สุดนะครับ HMM ในรูปแบบมาตรฐานสำหรับแทนเสียง Phone 1 Phone นั้นจะมีหน้าตาดังรูปที่ 5 ซึ่ง Observation sequence จะถูกป้อนเข้าทางซ้ายหรือ เข้าทาง Node ที่ 1 และออกทาง Node สุดท้าย ในระหว่างที่ Observation vector แต่ละตัว วิ่งอยู่ใน HMM นี้ จะวิ่งไปข้างหน้า หรือย่ำอยู่ที่ Node เดิม (ตาม Link ที่มีอยู่) เท่านั้น ไม่มีการย้อนกลับ เราจึงเรียก HMM แบบนี้ว่า Left-to-right model

รูปที่ 5 Left-to-right HMM

Link ที่เชื่อมระหว่าง Node เรียกว่า Transition และ Node แต่ละอันเรียกว่า State ในขณะที่ Observation vector หนึ่งๆ กระโดดจาก State i ไป State j จะมีความน่าจะเป็นของการกระโดดคือ aij เราเรียกความน่าจะเป็นของการกระโดดนี้ว่า Transition probability และเมื่อ Observation vector เช่น ot ไปตกที่ State i จะมีความน่าจะเป็นของการตกคือ bi(ot) ซึ่งเราเรียกว่า Emission probability ไฟล์ /config/proto5s เป็นหน้าตาของ HMM ของ Phone 1 ตัวครับ ลองเปิดดู

รูปที่ 6 proto5s

รูปที่ 6 เป็นไฟล์เริ่มต้นของ HMM 1 ตัวนะครับ ยังไม่ได้รับการ Train เลย ในการ Train HMM จะทำตามขั้นตอนดังนี้ครับ (สามารถดูคำสั่งที่เต็มๆ ประกอบไปด้วยในไฟล์ trainam.sh นะครับ)

  1. แปลงไฟล์เสียง .wav ที่จะใช้ Train Acoustic model เป็นไฟล์ค่าลักษณะเด่น .mfc ก่อนด้วยคำสั่ง HCopy

  2. เตรียมไฟล์ที่กำกับว่าไฟล์เสียงแต่ละไฟล์ประกอบด้วย Phone อะไรต่อกันบ้าง ไฟล์นี้อาจจะเรียกว่า Label file ก็ได้นะครับ ในที่นี้เราได้เตรียม ให้แล้ว ก็คือไฟล์ /config/monophn.mlf ตรงนี้หากอยากรู้ว่าเรานิยาม Phone ของภาษาไทยไว้อย่างไร แล้วแต่ละตัวแทนด้วยตัวอักษรอะไร ขอ ให้ดูใน Thai phoneme ครับ สังเกตนิดนึงนะครับว่า ในแต่ละไฟล์เสียงนั้นจะมี Phone "sil" ปิดหัวปิดท้ายอยู่เสมอ มันคือเสียงเงียบหรือ Silence ครับ เป็น Phone พิเศษตัวนึงที่จะต้อง Train จากสัญญาณเสียงด้วย

  3. มันมีสองทางในการเริ่มต้น Train HMM ครับ ทางแรกหากเรามี Label file ที่กำกับตำแหน่งเริ่มตำแหน่งจบของแต่ละ Phone ในสัญญาณ เสียงเลยล่ะก็ เราสามารถ Train ด้วยคำสั่ง HInit แต่ถ้าเราไม่มีปัญญาไปนั่ง Mark ตำแหน่งเริ่มตำแหน่งจบของ Phone มีเพียง Label file ที่บอก ว่ามี Phone อะไรอยู่บ้างเท่านั้น เราก็สามารถ Train HMM ด้วยวิธีการที่เรียกว่า Flat start ซึ่งใช้คำสั่ง HCompV ในที่นี่ผมใช้ Flat start นะครับ HCompV จะทำการแบ่ง Observation sequence ใน .mfc ทุกไฟล์เป็นส่วนๆ เท่ากับจำนวน Phone ที่กำกับทั้งหมดใน Label file แล้วทำการ คำนวณค่า Emission และ Transition probability ใส่ใน proto5s โดยมองว่าทุก Phone เป็น Phone เดียวกัน ผลก็จะได้ proto5s ตัวใหม่ ใน /am/hmm_0/proto5s เป็นเหมือน HMM ที่เฉลี่ยค่า Probability ให้เท่าๆ กันสำหรับทุก Phone ส่วนวิธีการคำนวณค่า Emission และ Transition probability นั้นผมยังไม่ขอพูดถึงตรงนี้นะครับ เพราะมันโคตร Math เอาไว้เริ่มเข้าใจคุ้นเคยกับ Speech recognition แล้วผมจะ ค่อยๆ เล่าให้ฟังเพิ่มเติม

  4. หลังจากได้ /am/hmm_0/proto5s แล้ว ก็ทำการ copy ไปเป็น Phone แต่ละตัว ที่ต้องใช้ในระบบของเราครับ อันนี้ผมก็สร้างไฟล์ /config/monophn.list ซึ่งประกอบตัว Phone ที่มีในเสียงตัวเลขศูนย์ถึงเก้า รวมทั้ง Phone พิเศษสำหรับเสียงเงียบ "sil" และใช้คำสั่ง /script/create_mono.sh ที่ผมเขียนขึ้นเอง คำสั่งนี้ทำการ copy proto5s ไปเป็นไฟล์ของแต่ละ Phone ที่มีอยู่ใน /config/monophn.list พร้อมทั้งแก้ไขชื่อ Phone ในบรรทัด ~h "proto5s" เป็น Phone นั้นๆ ด้วย

  5. ทำการ Re-estimate แต่ละ Phone HMM ด้วย .mfc ทั้งหมดใหม่ ด้วยคำสั่ง HERest ซึ่งผมเขียนไว้ในคำสั่ง /script/herest_mono.sh อีกที เราจะใช้คำสั่ง HERest ในการปรับค่า Emission และ Transition probability ในแต่ละ Phone หลายๆ รอบ (ในตัวอย่างของผม ทำการ Re-estimate 3 รอบ) จะได้ HMM ของ Phone ใหม่ที่มีค่าแตกต่างกันในแต่ละ Phone ไฟล์ Phone HMM ที่ได้ตรงนี้จะเก็บเป็นไฟล์เดียวแล้วนะครับ ไม่ใช่ไฟล์ละ Phone ชื่อไฟล์ว่า newMacros เก็บใน /am/hmm_1, hmm_2 และ hmm_3 คือการ Re-estimate รอบแรกรอบสอง และรอบสามนั่นเอง จะเห็นว่าวิธีนี้เริ่มต้นสร้าง HMM จาก proto5s ตัวเดียวกัน เราถึงได้เรียกว่า Flat start ไงครับ วิธีนี้ช่วยได้เยอะคือเราไม่ต้องนั่ง Mark ตำแหน่ง Phone เลย

  6. ตรงนี้เราจะได้ HMM model ของ Monophone เรียบร้อยแล้วครับเพียงแต่เก็บไว้ที่เดียวกันหมด คือไฟล์ newMacros มาถึงตรงนี้ผมต้อง ขออธิบายทฤษฎีเพิ่มเติมเพื่อให้เข้าใจคำสองคำครับคือ Monophone model และ Triphone model ใน Monophone model นั้น HMM 1 ตัวจะแทน Phone 1 Phone โดยไม่สนใจว่า Phone ข้างๆ เป็น Phone อะไร ดังนั้น สัญญาณเสียงของ Phone เดียวกันจะถูกเอามา Train HMM ของ Phone นั้นๆ ทั้งหมด ดังแสดงในรูปที่ 7a แต่นักวิจัยทางด้านนี้เขาบอกว่า เสียงของ Phone เดียวกัน อาจจะแตกต่างกันได้หากอยู่ในตำแหน่งต่างๆ กันไป ขึ้นกับว่า Phone ข้างๆ เป็น Phone อะไร เช่น เสียง "n^" ในคำว่า "k aa n^" (การ) กับเสียง "n^" ในคำว่า "k aa n^ m vva ng^" (การเมือง) จะแตกต่างกัน เพราะเสียง "n^" ในกรณีหลังจะเริ่มควบกับเสียง "m" ในพยางค์ถัดไป ดังนั้นจึงมีการ เสนอให้สร้าง Phone model แยกกันในทุกๆ กรณีที่ Phone รอบข้างต่างกัน เราเรียก Model แบบนี้ว่า Context-dependent phone model ตัวอย่าง Context-dependent phone model ที่เป็นที่นิยมคือ Triphone model ซึ่งแยกแยะ Phone แต่ละตัวตาม Phone ข้างหน้าและข้างหลัง ดังเช่นในรูป 7b เรามักแทน Triphone model ด้วยสัญลักษณ์เช่น "aa-n^+m" ซึ่งก็คือ Phone model ของ "n^" เฉพาะที่อยู่ระหว่าง "aa" กับ "m"

    รูปที่ 7 (a) Monophone model (b) Triphone model

    ในขั้นตอนต่อไปนี้ เราจะทำการแปลง Monophone model ที่สร้างไว้ใน /am/hmm_3/newMacros ไปเป็น Triphone model เริ่มต้นโดย ใช้คำสั่ง /script/mono2tri.sh คำสั่งนี้จะอาศัยคำสั่ง HLEd เพื่อแปลง Label file /config/monophn.mlf เป็นแบบ Triphone /config/triphn.mlf พร้อมกับสร้างลิสของ Triphone ที่มีทั้งหมดออกมาคือ /config/triphn.list

  7. หลังจากนั้น จะใช้คำสั่ง HHEd ใน /script/clonetri.sh เพื่อสร้าง Triphone HMM ใน /am/trihmm_0/newMacros คำสั่ง HHEd นี้ต้องการไฟล์อันนึงชื่อว่า mktri.hed ซึ่งสามารถสร้างได้ด้วยคำสั่ง /script/mktrihed.pl อันนี้ผมรวมขั้นตอนไว้ในคำสั่งเดียวคือ /script/clonetri.sh ครับ หลังจากใช้คำสั่งนี้แล้ว จะปรากฏไฟล์ /am/trihmm_0/newMacros ขึ้น ลองเปิดดูครับ แล้ว Search หาบรรทัดที่มี ~h จะเห็นว่าชื่อของ HMM จะกลายเป็นรูปแบบของ Triphone model แล้ว

  8. เราต้องทำการ Re-estimate Phone model ที่เป็น Triphone นี้ใหม่ครับ โดยทำเหมือนกับการ Re-estimate ในขั้นตอนที่ 5 ผมเขียน Script file ชื่อ /script/herest_tri.sh เพื่อทำการ Re-estimate Triphone HMM 3 รอบด้วยคำสั่งเดิมครับ HERest ผลลัพธ์สุดท้ายจะได้ /am/trihmm_3/newMacros

  9. ผมคิดว่าถึงตรงนี้ บางท่านอาจจะเริ่มตะหงิดๆ ว่า Triphone HMM จะดีเหรอ ในเมื่อจำนวน Triphone มีเยอะมากๆๆ ในขณะที่ Triphone บางตัว เกิดขึ้นเพียงครั้งเดียวใน Training set เท่ากับว่าบาง Triphone ได้รับการ Train ครั้งเดียว!!ท่านกำลังคิดถูกแล้วครับ Triphone HMM ตรงนี้ ถ้าเอาไปใช้ล่ะก็ ผลแย่แน่นอนครับ สาเหตุหลักคืออย่างว่าแหละครับ ข้อมูล Train มันไม่พอ และเป็นไปไม่ได้เลยหากเราจะมานั่งอัดเสียงเพิ่มให้มันพอ เพราะเราเองก็ไม่รู้ว่าเมื่อไหร่ถึงจะพอ นักวิจัยเขาก็ฉลาดคิดต่อครับ เขาคิดว่าถ้างั้น Triphone บางตัวน่าจะมีองค์ประกอบคล้ายๆ กันนะ อาทิเช่น "aa-n^+b" ใน "k aa n^ b aa n^" (การบ้าน) กับ "aa-n^+k" ใน "k aa n^ k i n" (การกิน) เสียงต้นๆ น่าจะคล้ายกัน แต่ต่างกันตรงท้ายๆ ที่เริ่มจะพูดคำว่าบ้าน หรือกิน และในเมื่อ HMM 1 ตัวนั้นเราแทนด้วย State 3 State ดังรูปที่ 8 งั้น State 1 กับ 2 ของมันน่าจะมีค่า Probability เหมือนกัน จากความคิดตรงนี้ ทำให้ HMM State จำนวน 6 State จาก 2 Triphone "aa-n^+b" และ "aa-n^+k" เหลือแค่ 4 State โดยที่มัน Share State 1 กับ 2 ร่วมกัน เรา เรียก วิธีนี้ว่า Tied-state model ดังรูปที่ 5

    รูปที่ 8 Tied-state model

    คราวนี้การสร้าง Tied-state model ก็เริ่มต้นด้วยการสร้างไฟล์ใหม่อันนึงที่เก็บลิสของ Triphone ทั้งหมด ไม่เพียงแค่ Triphone ที่เกิดใน Training set เท่านั้น แต่รวม Triphone ที่เกิดได้ใน Digit sequence ด้วย ผมได้เขียน Perl script ไว้ชื่อว่า /script/fulltri.pl ใช้ในการสร้าง ไฟล์ดังกล่าว ผมเรียกใช้คำสั่งนี้ใน /script/fulltri.sh อีกทีนึงครับ ผลการรันคำสั่งนี้ก็จะได้ไฟล์ /config/triphn-full.list

  10. ต่อมาคือขั้นตอนการ copy Triphone HMM ไปเป็น Tied-state HMM โดยก่อนอื่นเราจะต้องมีไฟล์ที่ชื่อว่า /config/tie.hed อันนี้เขียน โดยนักภาษาศาสตร์ครับ เป็นไฟล์ที่กำหนดว่า เสียง Phone ใดจัดอยู่ในกลุ่มเดียวกัน คำสั่ง HHEd อีกแหละครับ ที่อาศัยไฟล์ดังกล่าวในการ Tie State ของแต่ละ Triphone เข้าหากัน ผมเขียนคำสั่งนี้ไว้ใน script/tri2tied.sh ครับ ผลการ Tie จะได้เป็น HMM ใหม่ในไฟล์ /am/tiehmm_0/newMacros ส่วนหลักการเลือกว่าจะ Tie State ไหนเข้ากับ State ไหนนั้นเขาใช้ Decision tree ครับ ผมยังไม่ขออธิบายในที่นี้นะครับ เพราะยาวววว

  11. เมื่อได้ Tied-state HMM มาแล้ว ก็เหมือนเดิมครับ Re-estimate ใหม่ 3 รอบด้วยคำสั่ง HERest ซึ่งผมรวมไว้ในคำสั่ง script/herest_tied.sh เรียบร้อยแล้ว สุดท้ายได้ /am/tiehmm_3/newMacros ครับ

  12. HMM model ที่ได้ตรงนี้ถือได้ว่า Train มาดีแล้วครับ สามารถนำไปใช้งานได้เลย เพียงแต่ว่านักวิจัยเขายังมีวิธีพัฒนาให้ผลดีขึ้นอีกด้วยการเพิ่ม Mixture แต่ละ HMM state เอาสิครับ Mixture คืออะไรกัน ผมอยากจะขออธิบายง่ายๆ ตรงนี้

    ก่อนอื่นขอให้ระลึกก่อนว่า Emission probability คืออะไร มันคือค่าความน่าจะเป็นที่ Observation vector ตัวหนึ่ง ot จะมาตกที่ State ที่ i ใดๆ หรือเราแทนมันด้วย bi(ot) คราวนี้โดยปกติค่าความน่าจะเป็นตรงนี้มักจะกำหนดให้อยู่ในรูปแบบ Gaussian distribution (Normal distribution) ครับ! หน้าตาของมันก็ในรูปที่ 9a ครับ ไอ้เจ้า Gaussian distribution เนี่ย แทนด้วยค่าสองค่าคือ Mean กับ Variance ลองกลับไปดูในรูปที่ 3 ครับ จะเห็นว่า 1 State จะมี Mean ชุดนึง Variance ชุดนึง อย่างนี้เขาเรียกว่า 1 Mixture ครับ

    นักวิจัยเขาคิดว่ากำหนดให้มันคำนวณ Emission probability ด้วย 1 Mixture Gaussian distribution ไม่น่าจะดี เพราะในความเป็นจริง มันอาจจะมีการกระจายในรูปแบบอื่นก็ได้ วิธีการง่ายๆ ในการเปลี่ยนให้มันมี Distribution ในรูปแบบที่ซับซ้อนกว่านี้ ก็คือการเพิ่ม Mixture ครับ กล่าวคือให้ 1 State มีหลาย Gaussian distribution ดังในรูป 9b แล้วเวลามี ot ใดๆ มาตกที่ State นี้ ให้คำนวณค่า bi(ot) จากผลรวมของหลายๆ Gaussian เท่านี้แหละครับ

    รูปที่ 9 (a) 1-Mixture Gaussian (b) 2-Mixture Gaussian

    โดยปกติเราจะเพิ่ม Mixture ให้กับ HMM จาก 1 Mixture เป็น 2 จาก 2 เป็น 4 ไปเรื่อยๆ นะครับ ผมทำการเพิ่ม Mixture ใน /am/tiehmm_3/newMacros จาก 1 เป็น 2 Mixture โดยใช้คำสั่ง HHEd (อีกแล้ว) ซึ่งเขียนไว้ในคำสั่ง /script/mix1to2.sh นะครับ เมื่อเรียกคำสั่งนี้ มันจะทำการ Split Gaussian จาก 1 อันต่อ State (1 Mean 1 Variance) เป็น 2 อันต่อ State (2 Mean 2 Variance) เก็บไว้ใน /am/tiehmm2m_0/newMacros พร้อมทั้ง ทำการ Re-estimate ใหม่อีก 3 รอบด้วยคำสั่ง HERest เหมือนเดิม HMM สุดท้ายคือ /am/tiehmm2m_3/newMacros ครับ เป็นอันว่าจบการสร้าง Acoustic model


หลักการสร้างโมเดลภาษา (Language model)

โมเดลภาษาคืออะไรครับ โมเดลภาษาจะบอกเราว่าคำ (Word) นี้ ตามด้วยคำนี้ได้หรือไม่ หรือในบางโมเดลจะบอกค่าความน่าจะเป็นที่คำใดๆ จะพูดต่อกัน อาทิเช่น โมเดลภาษาอาจจะบอกว่า "จะ ไป" เกิดได้ แต่ "ไป จะ" ไม่ได้ หรืออาจจะบอกเป็นค่าความน่าจะเป็นว่า "จะ ไป" มีโอกาสเกิดได้ 0.8 แต่ "ไป จะ" มีโอกาสเกิดได้แค่ 0.01 เป็นต้น โมเดลภาษาแท้จริงไม่เพียงบอกโอกาสที่คำสองคำจะเกิดคู่กันเท่านั้น มันยังสามารถบอกด้วยว่า ทั้งประโยคมีโอกาสเกิด ได้เท่าไหร่ สมมติว่าเรามีประโยค ซึ่งประกอบด้วยคำต่อๆ กันหลายๆ คำ ขอแทนด้วย W ละกันนะครับ W = (w1 ? wM) โดยที่ w แทนคำแต่ละคำ โมเดลภาษาจะบอกว่า W สามารถเกิดได้หรือไม่ หรือบอกเป็นค่าความน่าจะเป็นว่ามีโอกาสเกิดมากน้อยแค่ไหน ค่าความน่าจะเป็นที่ว่าขอแทนด้วย P(W) ละกัน รูปที่ 3 แสดงให้เห็นหน้าที่ของโมเดลภาษา

การสร้าง Language model มีวิธีหลักๆ 2 วิธีครับ วิธีแรกเป็นการเขียนกฎ หรือ Rule-based model อีกวิธีคือการเรียนรู้จากฐานข้อมูลหรือบาง ทีเราเรียกว่า Statistical model สำหรับ Digit sequence recognition ที่ทดลองกันนี้ เป็นการรู้จำเสียงพูดตัวเลขต่อเนื่อง โดยมีคำที่พูดได้อยู่แค่ ศูนย์ ถึง เก้า และแต่ละคำสามารถต่อกับคำใดๆ ก็ได้ จึงสามารถเขียนด้วยกฎง่ายๆ ได้ ไม่จำเป็นต้องเรียนรู้จากฐานข้อมูล ใน HTK toolkit เราสามารถเขียน กฎของ Language model โดยสร้างไฟล์ /config/dgs.gram ก็เป็น Text file ง่ายๆ ลองเปิดดูครับ

รูปที่ 10 dgs.gram

ในส่วนบรรทัดแรกก็จะบอกว่ามีคำอะไรเกิดขึ้นได้บ้าง ในที่นี้ก็มีสิบคำคือศูนย์ ถึงเก้า (suun4 ถึง kaw2) ส่วนต่อมาก็เป็นการกำหนดไวยกรณ์ของประโยค ที่เกิดขึ้นได้ โดยเริ่มที่ SENT-START คือเริ่มประโยค และจบด้วย SENT-END คือสิ้นสุดประโยค ภายในประโยคประกอบด้วย $digit ก็คือตัวเลข ที่กำหนดในบรรทัดแรก คร่อมด้วย <> หมายถึงต่อกันกี่ตัวก็ได้

หลังจากสร้างไฟล์ dgs.gram แล้ว จะต้องทำการแปลงไฟล์นี้ให้อยู่ในรูปแบบของ Word network ที่ใช้ในการรู้จำใน HTK การแปลงทำได้โดยใช้คำสั่ง HParse (เปิดดูใน Script file /trainlm.sh) จะทำการแปลง dgs.gram เป็น dgs.wdnet ซึ่งใช้ในการรู้จำต่อไปครับ


Thai Phoneme

พยัญชนะต้น

 

สระ

 

ตัวสะกด

เดี่ยว

ตัวอย่าง

ผสม

ตัวอย่าง

 

เดี่ยว

ตัวอย่าง

ผสม

ตัวอย่าง

 

เดี่ยว

ตัวอย่าง

p

าก

pr

ประสาน

 

a

อะ

ia

เอียะ

 

p^

t

ต้, กุฏิ

phr

พราน

 

aa

อา

iia

เอีย

 

t^

เกร็

c

tr

ตรียม

 

i

อิ

va

เอือะ

 

k^

ปา

k

ก่อน

kr

กราบ

 

ii

อี

vva

เอือ

 

n^

หา

z

าน

khr

คร่

 

v

อึ

ua

อัวะ

 

m^

ph

, ภั, ผ่าน

pl

ปล

 

vv

อื

uua

อัว

 

ng^

ฟา

th

ทิ้, , ฒ่,

าน, มณโ

phl

พลาด

 

u

อุ

6 หน่วย

 

j^

ยา

 

uu

อู

 

 

 

w^

กา

ch

อบ,

thr

จันทร

 

e

เอะ

 

 

 

เสียงทับศัพท์

kh

, ขิ, ฆ่

kl

กล

 

ee

เอ

 

 

 

f^

กรา

b

อก

khl

คลื่อน

 

x

แอะ

 

 

 

l^

แอ

d

ด้าน,

kw

กวาง

 

xx

แอ

 

 

 

s^

เอ

m

ม่

khw

ขว

 

o

โอะ

 

 

 

ch^

คลั

n

าน,

เสียงทับศัพท์

 

oo

โอ

 

 

 

12 หน่วย

ng

งิ

br

บร

 

@

เอาะ

 

 

 

 

 

l

ล่, กี

bl

บลู

 

@@

ออ

 

 

 

 

 

r

, ทัย

fr

ฟราย

 

q

เออะ

 

 

 

 

 

f

, ฟั

fl

ฟล

 

qq

เออ

 

 

 

 

 

s

าย, ศิลา,

รัก, ซ่อน

dr

ดรากอน

 

18 หน่วย

 

 

 

 

 

 

 

 

 

 

 

 

 

h

, ฮา

17 หน่วย

 

 

 

 

 

 

 

 

w

ว่

 

 

 

 

 

 

 

 

 

 

j

้อน, ญิ

 

 

 

 

 

 

 

 

 

 

21 หน่วย

 

 

 

 

 

 

 

 

 

 


Copyright (c) 2004 Chai Wutiwiwatchai