ComBioLaw.De » Blog » เขียนโปรแกรม » โปรแกรมตัดคำภาษาไทย
โปรแกรมตัดคำภาษาไทย
คุณ sugree ได้เขียนวิธีแก้ปัญหานี้ไว้ที่บล็อกตั้งนานแล้ว ทั้งวิธียาว ๆ และวิธีสั้น ๆ แต่เนื่องจากการคอมไพล์โปรแกรม OpenOffice ต้องใช้เวลานานมาก ก็เลยเกิดอาการขี้เกียจเสียงั้น (เป็นนิสัยที่แย่มาก) อีกทั้งนาน ๆ ครั้งผมจะเขียนเอกสารภาษาไทยสักครั้ง (อย่างมากปีละสองครั้ง) ก็เลยลองหาวิธีอื่นดู วิธีที่ผ่านหัวมาวิธีแรกคือใช้ AbiWord หรือไม่ก็ KOffice แทน ปรากฏว่า AbiWord นี่หนักสุด เพราะทั้งอ่านและเขียนภาษาไทยไม่ได้เลย ส่วน KOffice ตัดคำภาษาไทยได้ห่วยมาก เลยนึกถึง ThaiLatex ขึ้นมา คนใช้ Ubuntu และ Debian จะได้เปรียบเรื่องนี้มาก เพราะการติดตั้งและใช้ ThaiLatex ง่ายเหมือนหยิบกล้วยที่ปอกไว้แล้วเข้าปาก (ต้องขอขอบคุณทีมงาน ThaiLatex ไว้ ณ ที่นี้ด้วยครับ) แต่ ThaiLatex ไม่ตัดคำภาษาไทย ต้องใช้โปรแกรม cttex ในการตัดคำต่างหาก ทีนี้แหละก็มาถึงปัญหาที่ต้องแก้ เพราะ cttex มันสร้างปัญหาให้เยอะพอสมควร อย่างแรกเลยคือ cttex ใช้คำสั่ง b ในการแยกคำแบบ zero space ซึ่งเป็นคำสั่งที่ Latex มันไม่รู้จัก ตอนคอมไพล์เลยเจอ error อื้อเลย ซึ่งแก้ได้โดยไปโพสต์ถามไว้ใน codenone โชคดีที่ช่วงนี้ codenone คึกคัก (กว่าแต่ก่อน) ก็เลยมีคนมาตอบเร็ว ... |
|
|
คำสั่งตัดคำที่ถูกต้องคือ {wbr} ไม่ใช่ b ต้องขอขอบคุณคุณ jittat ไว้ ณ ที่นี้ด้วยครับ (เดาว่าคุณ jittat คือ อ.มะนาว) ทำให้ปัญหาแรกได้รับการแก้ไขอย่างรวดเร็ว ปัญหาต่อมาคือ cttex มันตัดคำไม่ถูก ที่เป็นปัญหาหนัก ๆ คือ cttex ตัดคำระหว่างพยัญชนะ และสระ อันนี้งงมาก เหมือนใน KOffice เลย รับไม่ได้ และอ่านไม่ออกเป็นอย่างยิ่ง ก็เลยเริ่มค้นหาคนพัฒนาโปรแกรม เพื่อจะแจ้งปัญหาให้ทราบ แต่หาไม่เจอครับ ใครรู้จักช่วยฝากไปบอกด้วยแล้วกันครับ ในระหว่างที่ค้นหาอยู่นั้น Silver Bullet ของ lew ก็ผ่านเข้ามาในหัว ผมชอบวิธีการนี้ของ lew มากครับ นั่นก็คือตัดเฉพาะคำที่พบบ่อยที่สุดในภาษาไทยร้อยคำแรก ซึ่งจากที่ทดลองแค่ตัดคำร้อยคำนี้ ก็ตัดคำได้กว่า 70% ของคำทั้งหมดแล้วครับ เป็นวิธีที่ง่าย และได้ผลดีมากครับ ผมนำ Silver Bullet มาตัดแปลงใช้กับโปรแกรมที่เขียนด้วย PHP หน้าตาออกมาประมาณนี้ครับ
function SilverBulletWrap($dataIn){ //Thai-Wrap by LewCPE (http://lewcpe.com/blog/archives/313/silver-bullet/) $dataIn = preg_replace("/(มา(?:ก|ย|ตรการ|ตรา|ตุภูมิ|ชิก))/","$1<wbr />",$dataIn); $dataIn = preg_replace("/(ม(?:ี|ัน|ือ))/","$1<wbr />",$dataIn); $dataIn = preg_replace("/(([กขคงจชซดตถทนบปผพมยรลวสหอเแโใไ])(?:ท(?:ำ(?:ให้)?|ี่|(?:า|ั้)ง|่าน)|เ(?:ร(?:ื่อง|า)|ข้?า|พ(?:ราะ|ื่อ)|(?:ป็|ห็|ช่)น|มื่อ|กิด|ด็ก|วลา)|ก(?:ัน|ับ|าร|็|ลุ่ม|ว่า)|ใ(?:ห(?:้|ม่)|น|ช้)|ข(?:อง|ึ้น)|จ(?:ะ|น|าก|(?:ึ|ริ)ง)|แ(?:ล(?:ะ|้ว)|ต่|ห่ง|บบ)|ไ(?:ด้|ว้|ม่|ป|ทย)|ว(?:่าง|่า|ัน)|ค(?:วาม|น|ือ)|น(?:ี้|ั้น|าย)|ห(?:รือ|นึ่ง|ลาย)|อ(?:ย(?:ู่|่าง)|[ีอ]ก|าจ|(?:ื่|ั)น|ะไร)|ต(?:่(?:าง|อ)|้อง|าม|ัว)|ด(?:้(?:วย|าน)|ี)|ถ(?:ึง|้า|ูก)|ผ(?:ู้|ม|ล)|ป(?:ระเทศ|ี|ัญหา)|ส(?:ังคม|ามารถ|่วน|ิ่ง|ำคัญ)|(?:ซึ่|ยั|บา|ล)ง|โดย|รับ|ชีวิต|งาน|พรรค))/","$1<wbr />",$dataIn); return $dataIn; }plain code ตัวฟังก์ชั่นใช้งานได้ผลดีมากครับ ผมเคยนำมาใช้กับเวบไซท์ BioLawCom แต่ lew เตือนเรื่อง Performance เอาไว้ เพราะ Regular Express ที่ใช้ในโปรแกรมกินพลัง Server มาก ผมแก้ปัญหาด้วยการทำระบบ Cache รองรับเอาไว้ แต่ปัญหาก็ยังไม่หมดไป เพราะ HTML ที่ได้ประกอบด้วย Tag-wbr จำนวนมหาศาล ทำให้ Web-Browser ที่เปิดหน้าที่ถูกตัดคำด้วยโปรแกรมนี้อาจดื้อและยอมแพ้ ปิดตัวเองไปได้ง่าย ๆ สุดท้ายเลยต้องเอาฟังก์ชั่นนี้ออก เนื่องจากโปรแกรมที่เขียนด้วย PHP ไม่เหมาะกับโปรแกรมที่ใช้งานบน Desktop สักเท่าไร ผมก็เลยอยากได้ Silver Bullet ที่เป็น Python ก็เลยคัดลอก Regular Express ที่เขียนด้วย PHP ซึ่งลอกมาจาก Regular Express ที่ lew เขียนเอาไว้มาอีกที เอามาแปะไว้บนโปรแกรมภาษา Python แบบหน้าด้าน ๆ เฮ้ย !!! ใช้ได้เฉยเลย โดยแทบไม่ต้องเปลี่ยนอะไรเลย เนียนครับงานนี้ ผมเลยใช้โปรแกรมนี้เป็นโปรแกรมตัดคำสำหรับ ThaiLatex แทน cttex ไป ใช้ไปใช้มา มีการปรับแต่งนิด ๆ หน่อย ๆ โปรแกรมที่ได้เลยมีหน้าตาออกมาแบบนี้ครับ
#!/usr/bin/env python # -*- coding: tis-620 -*- import re import sys import os def SilverBullet(text, wordbreak): flick = lambda x,y : x+wordbreak+y text = reduce(flick, re.split('(มา(?:ก|ย|ตรการ|ตรา|ตุภูมิ|ชิก))', text)) text = reduce(flick, re.split('(ม(?:ี|ัน|ือ))', text)) text = reduce(flick, re.split('(เท่า|ศาสตร์)', text)) text = reduce(flick, re.split('(เ(?:ก|ข|ค|ป|พ)ลง)', text)) text = reduce(flick, re.split('(แ(?:ก|ข|ค|ป|พ)ลง)', text)) text = reduce(flick, re.split('(โ(?:ก|ข|ค|ป|พ)ลง)', text)) text = reduce(flick, re.split('((?:ท(?:ำ(?:ให้)?|ี่|(?:า|ั้)ง|่าน|รัพยากร|าง|ดลอง)|เ(?:ร(?:ื่อง|า|ียก)|ข้?า|พ(?:ราะ|ื่อ)|(?:ป็|ห็|ช่)น|มื่อ|กิด|ด็ก|วลา|ขียน)|ก(?:ัน|ับ|าร|็|ลุ่ม|ว่า)|ใ(?:ห(?:้|ม่)|น|ช้)|ข(?:อง|ึ้น|้าง)|จ(?:ะ|น|าก|(?:ึ|ริ)ง)|แ(?:ล(?:ะ|้ว)|ต่|ห่ง|บบ)|ไ(?:ด้|ว้|ม่|ป|ทย)|ว(?:่าง|่า|ัน)|ค(?:วาม|น|ือ)|น(?:ี้|ั้น|าย)|ห(?:รือ|นึ่ง|ลาย)|อ(?:ย(?:ู่|่าง)|[ีอ]ก|าจ|(?:ื่|ั)น|ะไร)|ต(?:่(?:าง|อ)|้อง|าม|ัว)|ด(?:้(?:วย|าน)|ี)|ถ(?:ึง|้า|ูก)|ผ(?:ู้|ม|ล)|ป(?:ระเทศ|ี|ัญหา|ระมาณ)|ส(?:ังคม|ามารถ|่วน|ิ่ง|ำคัญ|ัญญาณ)|(?:ซึ่|ยั|บา)ง|โดย|รับ|ชีวิต|งาน|พรรค|ร(?:ัก|ะบบ)))', text)) text = text.replace('ห'+wordbreak+'มาย', 'หมาย') text = text.replace('กัน'+wordbreak+'ยายน', 'กันยายน') text = text.replace(wordbreak+wordbreak, wordbreak) return text def wrap_all(): for fname in os.listdir('./'): if fname[-4:] == '.tex' and fname[-8:-4] != 'wrap' and fname != 'index.tex': open(fname[:-4]+'_wrap.tex','w').write(SilverBullet(open(fname).read(), '{wbr}')) if __name__ == '__main__' : wrap_all() os.system('pdflatex index.tex index.pdf')plain code ใครที่อยากนำไปใช้ ต้องแก้ไขฟังก์ชัน wrap_all() อีกหน่อยครับ เพราะในโปรแกรมที่ผมเขียน มันไม่ตัดคำในไฟล์ index.tex เนื่องจากผมใช้ไฟล์ index.tex เป็น configuation file และคอย include ไฟล์ต่าง ๆ และที่สำคัญ ต้องเซพไฟล์ทั้งไฟล์เอกสาร และไฟล์โปรแกรม (ตัว Python-Script ที่มีโค้ดข้างบน) เป็น TIS-620 ครับ เพราะ ThaiLatex สามารถใช้งานได้เฉพาะ TIS-620 เท่านั้น |
|
14 Feb 08 | by | tags เขียนโปรแกรม Python ภาษาไทย Latex
bow_der_kleine
ผมได้แก้โค้ดตัวอย่างของ PyICU นิดหน่อยโดยใช้ NumPy เข้ามาช่วยตรวจสอบว่าตัวอักษรตัวใดบ้างเป็นภาษาไทย แทนฟังก์ชั่น isThai() เพิ่มความเร็วให้โปรแกรมอีกนิดนึง ความเร็วที่เห็นไม่น่าแปลกใจนัก เพราะ ICU มีความสามารถสูงกว่า SilverBullet มาก แต่คำถามคือ SilverBullet มีความสามารถเพียงพอกับความต้องการในการใช้งานหรือไม่ |
wd
สุดยอดครับ :) คงต้องเลือกใช้แบ่งตามประเภทงานน่ะครับ ถ้าเป็นงานที่ไม่ต้องการความถูกต้องมาก แต่ต้องให้รวดเร็ว ก็ใช้ SilverBullet แต่ถ้างานที่ต้องการความถูกต้อง แต่ไม่ต้องเร็วมากนัก ก็ใช้ PyICU |
คนที่ใช้ Linux โดยเฉพาะอย่างยิ่ง Ubuntu คงจะรู้สึกอึดอัดขัดใจกับโปรแกรมสำคัญอย่าง OpenOffice ที่เวอร์ชั่นล่าสุดมีปัญหากับการใช้ภาษาไทย พอเขียนภาษาไทยได้สักสองบรรทัด โปรแกรมก็จะตายไปเฉย ๆ ทีแรกผมไม่ได้สนใจกับปัญหานี้มากนัก เพราะไม่ค่อยได้เขียนเอกสารภาษาไทย อีกทั้งเครื่องของคุณเช ฯ ซึ่งใช้ Ubuntu เหมือนกัน ก็ยังใช้ภาษาไทยได้ ก็เลยนึกว่าปัญหานี้ได้รับการแก้ไขแล้ว แต่เพิ่งรู้ทีหลังว่าเครื่องคุณเช ฯ เป็น Ubuntu 7.04 ซึ่งไม่มีปัญหานี้
กราฟฟิกที่เห็นคือผลการทดสอบครับ
wd
รบกวนฝากลองทดสอบประสิทธิภาพ PyICU ด้วยซิครับ
ผมว่าตัดได้ 100% เลยนะ แต่ไม่แน่ใจเรื่องความเร็ว
isThai and ThaiWarp function
debian: ติดตั้ง PyICU
15 Feb 08