2 กันยายน 2561

Published กันยายน 02, 2561 by with 0 comment

ทดลองทำ Thai Romanization ด้วย keras ใน Python


สวัสดีครับทุกท่าน บทความนี้เราจะไปทดลองทำ Thai Romanization ด้วย keras ใน Python กันครับ

Romanization คืออะไร ?

Romanization เป็นการถอดเสียงมาเป็นอักษรโรมัน ตัวอย่างการนำ Romanization มาใช้ เช่น  โปรแกรมร้องคาราโอเกะ เป็นต้น

สำหรับการถอดเสียงภาษาไทยมาเป็นอักษรโรมัน แม้มีเอกสารของราชบัณฑิตยสถาน กำกับแนวทางไว้ แต่ก็ไม่ใช่เรื่องง่าย เพราะภาษาไทยไม่มีการแบ่งคำ , มีพยางค์กับกฎการออกเสียงที่ซับซ้อน และคำหลาย ๆ คำออกเสียงไม่ตรงกับรูป จึงทำให้การพัฒนากฎการถอดเสียงภาษาไทยมาเป็นอักษรโรมันเป็นเรื่องที่ซับซ้อนอย่างมาก

ทางออกของเรานั้นคือ Deep learning โดยใช้ seq2seq ระดับตัวอักษร

เนื่องจากบทความนี้เป็นบทความที่บอกรายละเอียดในการทำเท่านั้น ไม่ขออธิบายทฤษฎีหรือกระบวนการทำงาน

เตรียมข้อมูล

ให้ทำการโหลดรายการคำภาษาไทยจากอะไรก็ได้มาประมาณเท่าที่ต้องการ บรรทัดละ 1 คำ แล้วบันทึกเป็นไฟล์ txt
แล้วทำการติดตั้งโปรแกรม Thai Romanization จาก http://pioneer.chula.ac.th/~awirote/resources/thai-romanization.html
ทำการเปิดโปรแกรมขึ้นมาแล้วไปเมนู Create > Romanized File เลือกไฟล์ที่บันทึกไว้แล้วรอสักครู่ (ขึ้นอยู่กับขนาดไฟล์) เสร็จแล้วจะได้ไฟล์นามสกุล .rom เป็นไฟล์ Romanization

จากนั้นให้ทำรวมไฟล์ txt กับ .rom เข้าเป็นไฟล์เดียวกัน โดยข้อมูลกับ Romanization คู่กันแล้วแยกกันด้วย \t ตัวอย่างเช่น
แมว mano
คน khon
เนื่องจากผมทำหลายไฟล์ทำให้ได้ไฟล์ข้อมูลข้อมูลหลายไฟล์ ผมจึงสร้าง database ด้วย SQLite ขึ้นมา ตั้งชื่อว่า dataset.db และสร้างตาราง data ตามโค้ดดังนี้

เสร็จแล้วเขียนโค้ดดึงข้อมูลจากไฟล์ txt และ rom เข้าไปเก็บใน Database ด้วยโค้ดดังนี้

ดึงข้อมูลจาก Databse กลับมาเขียนเป็น csv ไฟล์ตามรูปแบบไฟล์ดังนี้
กองพันทหารปืนใหญ่    kongphanthahanpuenyai
วิฑูรย์    withun
เมตาบอลิสม    metabolisom
บ้านหนองเลา    bannonglao
อายุษ    ayut
แทมปา    thaempa

ใช้โค้ด
เราจะได้ data.csv เป็นข้อมูลสำหรับนำไป Train สำหรับทำ Thai Romanization ด้วย keras

Train ข้อมูล

เราจะโค้ดตามเอกสาร A ten-minute introduction to sequence-to-sequence learning in Keras (https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html) ซึ่งทำงานด้วย Sequence-to-sequence learning (Seq2Seq) ในระดับตัวอักษร (character) โดยเป็น LSTM

ทำการโหลดโค้ดมาจาก https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq.py
แล้วดัดแปลงโค้ดตรงตัวแปร data_path , num_samples และ epochs
  • data_path เปลี่ยน path เป็น ''data.csv"
  • num_samples เปลี่ยนเป็นจำนวนบรรทัดทั้งหมดในไฟล์ ''data.csv"
  • epochs จำนวนการ Train เปลี่ยนตามความต้องการ
ตัวอย่างเช่น
ไฟล์ data.csv ของผม คือ https://github.com/wannaphong/thai-romanization/blob/master/dataset/data.csv มีทั้งหมด 648,241 บรรทัด ผมเปลี่ยนได้ดังนี้

เมื่อรัน
Number of samples: 648240
Number of unique input tokens: 91
Number of unique output tokens: 39
Max sequence length for inputs: 76
Max sequence length for outputs: 90
Train on 518592 samples, validate on 129648 samples
Epoch 1/20

    64/518592 [..............................] - ETA: 2:20:15 - loss: 0.7373
   128/518592 [..............................] - ETA: 1:16:17 - loss: 0.7081
   192/518592 [..............................] - ETA: 54:47 - loss: 0.7065 
   256/518592 [..............................] - ETA: 44:45 - loss: 0.6996
   320/518592 [..............................] - ETA: 38:45 - loss: 0.7010
รันโค้ด train หาก train เสร็จไม่มีปัญหาอะไรจะได้ไฟล์ s2s.h5 เป็นไฟล์ model ของ Thai Romanization ที่เราทำขึ้นมา

ใช้งาน Model

โหลดโค้ดจาก https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq_restore.py มาดัดแปลงตามโค้ดข้างบน แล้วรัน
Number of samples: 648240
Number of unique input tokens: 91
Number of unique output tokens: 39
Max sequence length for inputs: 76
Max sequence length for outputs: 90
-
Input sentence: คน
Decoded sentence: khon
เสร็จแล้วเขียนโค้ดเพิ่มเติมเข้าไปใน lstm_seq2seq_restore.py เพื่อให้สามารถรับ ข้อความภายนอก ที่ต้องการแปลงไปเป็น Romanization ได้

เวลานำไปใช้งาน เพียงแค่ใช้คำสั่ง rom(ข้อความ) เท่านี้เราก็ได้ Thai Romanization สำหรับใช้งานแล้ว
rom("แมว")

ผลลัพธ์
แมว\n

ปัญหาที่อาจจะพบในการทำ Thai Romanization ด้วย keras
1. ปัญหา MemoryError เช่น
Traceback (most recent call last):
  File "using.py", line 68, in <module>
    dtype='float32')
MemoryError
เพราะในการ train เป็น train ระดับตัวอักษร ทำให้เกิดการจอง array ในหน่วยความจำขนาดใหญ่มากเกินกว่าที่หน่วยความจำในเครื่องที่ train หรือเครื่องที่เรียกใช้งานจะรับข้อมูลเข้าหน่วยความจำไหว
มีทางแก้ 2 วิธี
  • เพิ่มแรม
  • ลดความยาวสตริงที่ใช้ในการ train
สำหรับผม ผมเลือกวิธีที่ 2 คือ ลดความยาวสตริงที่ใช้ในการ train ตามโค้ดใน https://github.com/wannaphong/thai-romanization/blob/master/train.py โดยจำกัดไม่ให้ถึ
 30 ตัวอักษรในฝั่งภาษาไทย ส่วน Romanization ไม่ให้ถึง 90 ตัวอักษร
สำหรับใช้งานได้สำหรับเครื่องแรมขั้นต่ำ 6 GB
2. อยากปรับ % validate
ให้ทำการแก้ไขโค้ด
model.fit([encoder_input_data, decoder_input_data], decoder_target_data,
          batch_size=batch_size,
          epochs=epochs,
          validation_split=0.2)
ตรง  validation_split โดยพารามิเตอร์นี้เป็นพารามิเตอร์สำหรับแบ่งข้อมูลมา validate จำนวน 0.2 หรือ 20 % ให้ปรับแก้ตรงนี้ตามความต้องการ
3. ปรับจาก  LSTM เป็น GRU layer ทำตาม https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html

โค้ดทั้งหมดอยู่ที่ https://github.com/wannaphong/thai-romanization
หากไม่ต้องการ Train ข้อมูลเอง สามารถใช้งาน thai2rom ได้ ผ่าน PyThaiNLP ดังนี้ https://github.com/PyThaiNLP/pythainlp_notebook/blob/master/thai2rom.ipynb
อ่านรายละเอียดเพิ่มเติมเกี่ยวกับ A ten-minute introduction to sequence-to-sequence learning in Keras ได้ที่ https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html

0 ความคิดเห็น:

แสดงความคิดเห็น

แสดงความคิดเห็นได้ครับ :)