Theppitak's blog

My personal blog.

12 มิถุนายน 2555

ThaiLaTeX Hyphenation Super-tuning

จาก blog ที่แล้ว ที่ผมพูดถึงการ fine-tune hyphenation pattern สำหรับภาษาไทยใน TeX โดยลงท้ายไว้ว่า อีกไม่นานคง release มาให้ทดลองใช้กันนั้น ปรากฏว่ามันไม่ได้ตรงไปตรงมาอย่างที่คิด

ผมได้อัปโหลด snapshot svn20120423 ของ thailatex ไปไว้ที่ Debian experimental และทดลองใช้เตรียมเอกสารที่ใช้งานจริงแทนรุ่นใน sid ก็กลับพบการแทรกยัติภังค์ผิดหลายจุด ทั้ง ๆ ที่ patgen ก็ได้รายงานผลการทดลอง hyphenate ตัวพจนานุกรมต้นทางด้วย pattern ที่ได้ ว่าถูกต้อง 100% โดย error เป็น 0 แล้วก็ตาม การที่ยังพบ error ในเอกสารจริงจึงนับเป็นเรื่องที่ไม่คาดคิด ถ้าเป็นเช่นนี้ ผมก็ยังไม่สามารถ release ได้

แรกสุดนั้น ผมยังมืดแปดด้านว่าจะ debug pattern ยังไง เพราะยังมองระบบเป็น black box อยู่ สุดท้ายจึงได้แนวทาง ว่าต้อง dry run pattern ต่าง ๆ ด้วยอัลกอริทึมที่ TeX ใช้ จึงนับเป็นจุดเริ่มต้นของการล้วงเข้าไปในรหัสของตัว pattern แล้วก็ได้เข้าใจสภาพปัญหามากขึ้น

ไม่ว่าปัญหาของ patgen จะเป็นอะไร แต่การไล่ pattern ก็ทำให้รู้จุดโหว่ของ pattern ที่มันสร้างมา จึงคิดวิธีแก้ด้วยการเพิ่ม ข้อยกเว้น (exception) เข้าไปเอง โดยเพิ่ม level 6 และ 7 เข้ามาจากเดิมที่ให้ patgen สร้างมาแค่ 5 level พอได้วิธีแก้แล้วก็เริ่มแก้ error ที่พบในเอกสารของผม

จากนั้น ก็ทดลองเอาเอกสารเก่า ๆ มาคอมไพล์ใหม่เพิ่มเติม ก็พบ error ใหม่ ๆ อยู่เนือง ๆ ในช่วงแรกก็ได้แต่ไล่แก้ แล้วก็หาเอกสารมาคอมไพล์เพิ่มเติมไปเรื่อย ๆ

ทำไปได้สักพักก็รู้สึกว่าอัตราของ error มันไม่ได้ลดลงเลย พอเจอเอกสารใหม่ ก็ไปเจอ error ที่คำใหม่ แถมเป็น error ที่ไม่น่าให้อภัยด้วย สุดท้ายก็ได้แนวคิดที่จะทดสอบแบบทั่วถึง (thorough test) ไปเลย โดยเขียนสคริปต์ test-hyphen.sh (มีอยู่ใน SVN) เพื่อนำคำที่มีในพจนานุกรมทั้งหมดมาผ่านคำสั่ง \showhyphens{...} ของ TeX เพื่อแสดงจุดแทรกยัติภังค์ทั้งหมดของแต่ละคำ แล้วเปรียบเทียบกับพจนานุกรมต้นทางเพื่อหา error ทั้งหมดที่ยังเหลืออยู่

พอเจอตัวเลขของ error ทั้งหมดถึงกับผงะ คืออยู่ที่ 9,660 รายการ จากรายการคำทั้งหมด 23,785 รายการ คิดเป็น 40% ถือว่าเยอะมากทีเดียว แต่ภายหลังพบว่ามีข้อผิดพลาดของสคริปต์ในการเปรียบเทียบ ทำให้ตัวเลขสูงเกินจริง พอแก้แล้วก็เหลือ error อยู่ 2,574 รายการ คิดเป็นราว 10.8% ก็ยังถือว่าเยอะอยู่ดีสำหรับการไล่แก้แบบ manual

ก็ไม่มีทางเลือก ถ้าต้องการให้มัน release ได้โดยไม่ขายหน้าประชาชี ผมก็ต้องไล่แก้ error เหล่านี้ โดยได้รายงานความคืบหน้าเป็นระยะ ๆ ทาง Google+ และทาง Facebook โดยใช้เวลาร่วม 10 วัน (ไม่นับวันที่พักเพราะป่วย) ในการแก้ error จนเหลือ 0

ระหว่างที่แก้ ก็ได้พบว่าสาเหตุของ error มีได้หลายทาง เช่น

  • พจนานุกรมต้นทางผิดพลาด หรือแทรกยัติภังค์ไม่สอดคล้องกัน บางคำเมื่อเป็นคำโดดแทรกยัติภังค์อย่างหนึ่ง แต่พออยู่ในคำประสมกลับแทรกอีกอย่างหนึ่ง ทำให้ patgen ชั่งน้ำหนักไม่ถูกว่าจะเอาอย่างไหน เป็นต้น
  • กรณีตัวอย่างน้อยเกินไปสำหรับจุดแทรกบางจุด เพราะมีที่ใช้น้อย ทำให้คะแนนที่ได้ไม่ถึง threshold ที่กำหนด กฎจึงไม่ถูกสร้าง
  • จุดแทรกบางจุดมีความแปรปรวนสูง เช่น "-นี' มีทั้งจุดที่แทรก เช่น เส-นีย์, แก-นี-มีด, สถา-นี, ทัศ-นีย์ มีทั้งจุดที่ไม่แทรก เช่น สุ-หนี่, ถนัด-ถนี่, เหนียว, อนี-จะ, เสนียด, เฉนียน ทำให้ patgen ชั่งน้ำหนักไม่ถูก
  • พารามิเตอร์ที่กำหนดให้กับ patgen ในบาง level กำหนดช่วงความยาวที่ทำให้พลาดบาง pattern เช่น ใน level 5 ตั้งความยาวไว้ 4-11 ก็จะพลาด pattern ความยาว 3 ลงมา เป็นต้น ซึ่งตรงนี้ถือว่าจำเป็นต้องทำ เพราะได้ลองกำหนดความยาวต่ำลงแล้ว ปรากฏว่ากฎมัน aggressive ขึ้นมาก ทำให้เกิด error เพิ่มเติมเป็นผลข้างเคียงมากมาย

ก็ถือเป็น error ที่พอเข้าใจได้ แต่ที่ไม่เข้าใจคือ ทำไม patgen จึงไม่รายงาน error เหล่านี้ขณะทดลอง hyphenate พจนานุกรมต้นทาง ซึ่งผลของการไม่รายงาน error ก็ทำให้ patgen ไม่ยอมสร้าง pattern เพิ่มอีกแม้จะบังคับพารามิเตอร์หรือทดลองเพิ่มจำนวน level อีกก็ตาม เพราะมันเองก็เข้าใจว่า error เป็นศูนย์แล้ว ไม่จำเป็นต้องทำเพิ่มอีก

สำหรับ error ที่เกิดจากพจนานุกรม ก็ปรับที่พจนานุกรม ซึ่งในหลายกรณีทำให้ได้กฎเพิ่ม และไปลด error ในกรณีอื่น ๆ ที่เกี่ยวข้องทันทีด้วย ส่วนกรณีอื่น ๆ ก็จำเป็นต้องแก้โดยเพิ่มข้อยกเว้นเป็นรายกรณีไป

บทเรียนจากการทำงานครั้งนี้คือ การทดสอบที่ดีช่วยได้มากในการควบคุมคุณภาพ โดยตอนที่ได้สคริปต์ test-hyphen.sh นั้น ถือเป็นก้าวกระโดดทีเดียว แทนที่จะต้องไปหาเอกสารมาคอมไพล์เรื่อย ๆ ก็แค่สั่งสคริปต์ทดสอบก็รู้ทันทีว่าตอนนี้อัตรา error เป็นเท่าใด และสคริปต์ทดสอบนี้ก็สามารถนำมาใช้กลั่นกรองการเพิ่มคำในพจนานุกรมในอนาคตได้ด้วย ทำให้รู้ว่าจะต้องเพิ่มข้อยกเว้นกำกับอีกหรือไม่ ซึ่งผมก็นำมาใช้จริง โดยเขียนเป็นสคริปต์ diff-dicts.sh อีกตัวหนึ่ง (มีใน SVN อีกเช่นกัน) เพื่อใช้เปรียบเทียบพจนานุกรมเดิมกับพจนานุกรมของ libthai โดยทดลองแทรกยัติภังค์กับคำใหม่แล้วสร้างเป็น diff กับของเดิมเพื่อให้ตรวจสอบก่อนเพิ่มเข้าพจนานุกรมต่อไป ทำให้ work flow สำหรับการ sync พจนานุกรมข้ามโครงการราบรื่นขึ้น

ขั้นต่อไป เพื่อให้การทำงานได้ผลดีที่สุด swath ควรจะเปลี่ยนมาใช้พจนานุกรมชุดเดียวกับที่ใช้สร้าง hyphenation pattern ด้วย เพื่อให้จุดแบ่งคำพอดีกัน และสามารถใช้กฎที่ผ่านการทดสอบกับพจนานุกรมชุดนี้แล้วในการแทรกยัติภังค์อย่างถูกต้อง (สำหรับรุ่นปัจจุบัน ผู้ใช้สามารถใช้ตัวเลือก -d เพื่อใช้พจนานุกรมของ libthai แทนของ swath ไปพลางก่อนได้)

หลังจากปรับพจนานุกรมของ swath แล้ว จึงจะ release thailatex ตัวใหม่ต่อไป

อ้อ.. เกือบลืม.. ระหว่างนี้ ผู้ใช้ Debian สามารถทดลองใช้ thailatex ตัวล่าสุด (svn20120609) ที่แก้เสร็จแล้วได้จาก experimental นะครับ

ป้ายกำกับ: ,

0 ความเห็น:

แสดงความเห็น (มีการกลั่นกรองสำหรับ blog ที่เก่ากว่า 14 วัน)

<< กลับหน้าแรก

hacker emblem