ComBioLaw.De » Blog » เขียนโปรแกรม » โปรแกรมตัดคำภาษาไทย

โปรแกรมตัดคำภาษาไทย

imageคนที่ใช้ Linux โดยเฉพาะอย่างยิ่ง Ubuntu คงจะรู้สึกอึดอัดขัดใจกับโปรแกรมสำคัญอย่าง OpenOffice ที่เวอร์ชั่นล่าสุดมีปัญหากับการใช้ภาษาไทย พอเขียนภาษาไทยได้สักสองบรรทัด โปรแกรมก็จะตายไปเฉย ๆ ทีแรกผมไม่ได้สนใจกับปัญหานี้มากนัก เพราะไม่ค่อยได้เขียนเอกสารภาษาไทย อีกทั้งเครื่องของคุณเช ฯ ซึ่งใช้ Ubuntu เหมือนกัน ก็ยังใช้ภาษาไทยได้ ก็เลยนึกว่าปัญหานี้ได้รับการแก้ไขแล้ว แต่เพิ่งรู้ทีหลังว่าเครื่องคุณเช ฯ เป็น Ubuntu 7.04 ซึ่งไม่มีปัญหานี้

คุณ sugree ได้เขียนวิธีแก้ปัญหานี้ไว้ที่บล็อกตั้งนานแล้ว ทั้งวิธียาว ๆ และวิธีสั้น ๆ แต่เนื่องจากการคอมไพล์โปรแกรม OpenOffice ต้องใช้เวลานานมาก ก็เลยเกิดอาการขี้เกียจเสียงั้น (เป็นนิสัยที่แย่มาก) อีกทั้งนาน ๆ ครั้งผมจะเขียนเอกสารภาษาไทยสักครั้ง (อย่างมากปีละสองครั้ง) ก็เลยลองหาวิธีอื่นดู วิธีที่ผ่านหัวมาวิธีแรกคือใช้ AbiWord หรือไม่ก็ KOffice แทน ปรากฏว่า AbiWord นี่หนักสุด เพราะทั้งอ่านและเขียนภาษาไทยไม่ได้เลย ส่วน KOffice ตัดคำภาษาไทยได้ห่วยมาก เลยนึกถึง ThaiLatex ขึ้นมา คนใช้ Ubuntu และ Debian จะได้เปรียบเรื่องนี้มาก เพราะการติดตั้งและใช้ ThaiLatex ง่ายเหมือนหยิบกล้วยที่ปอกไว้แล้วเข้าปาก (ต้องขอขอบคุณทีมงาน ThaiLatex ไว้ ณ ที่นี้ด้วยครับ)

แต่ ThaiLatex ไม่ตัดคำภาษาไทย ต้องใช้โปรแกรม cttex ในการตัดคำต่างหาก ทีนี้แหละก็มาถึงปัญหาที่ต้องแก้ เพราะ cttex มันสร้างปัญหาให้เยอะพอสมควร อย่างแรกเลยคือ cttex ใช้คำสั่ง b ในการแยกคำแบบ zero space ซึ่งเป็นคำสั่งที่ Latex มันไม่รู้จัก ตอนคอมไพล์เลยเจอ error อื้อเลย ซึ่งแก้ได้โดยไปโพสต์ถามไว้ใน codenone โชคดีที่ช่วงนี้ codenone คึกคัก (กว่าแต่ก่อน) ก็เลยมีคนมาตอบเร็ว ...

เขียนโปรแกรม เขียนโปรแกรม

bow_der_kleine bow_der_kleine

คำสั่งตัดคำที่ถูกต้องคือ {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

read 2875

<<สภาลูกผสม/ชมรมอีลิท || Yes, we can !>>

wd

รบกวนฝากลองทดสอบประสิทธิภาพ PyICU ด้วยซิครับ

ผมว่าตัดได้ 100% เลยนะ แต่ไม่แน่ใจเรื่องความเร็ว

isThai and ThaiWarp function

debian: ติดตั้ง PyICU

15 Feb 08

bow_der_kleine

image กราฟฟิกที่เห็นคือผลการทดสอบครับ โค้ดการทดสอบดาวน์โหลดได้ที่นี่ครับ

ผมได้แก้โค้ดตัวอย่างของ PyICU นิดหน่อยโดยใช้ NumPy เข้ามาช่วยตรวจสอบว่าตัวอักษรตัวใดบ้างเป็นภาษาไทย แทนฟังก์ชั่น isThai()  เพิ่มความเร็วให้โปรแกรมอีกนิดนึง

ความเร็วที่เห็นไม่น่าแปลกใจนัก เพราะ ICU มีความสามารถสูงกว่า SilverBullet มาก แต่คำถามคือ SilverBullet มีความสามารถเพียงพอกับความต้องการในการใช้งานหรือไม่

15 Feb 08

wd

สุดยอดครับ :)

คงต้องเลือกใช้แบ่งตามประเภทงานน่ะครับ

ถ้าเป็นงานที่ไม่ต้องการความถูกต้องมาก แต่ต้องให้รวดเร็ว ก็ใช้ SilverBullet

แต่ถ้างานที่ต้องการความถูกต้อง แต่ไม่ต้องเร็วมากนัก ก็ใช้ PyICU

15 Feb 08

ความคิดเห็น (click here to comment)

Search

Navigation

รวมลิงก์น่าสนใจ

ความเคลื่อนไหว

Login

name password

ลืมรหัสผ่าน