JTCC: library ตัดกลุ่มของตัวอักษรไทย

Mar 19 2010 Published by admin under Uncategorized

TCC คือกลุ่มของตัวอักษรไทยที่ไม่สามารถแยกจากกันได้ตามหลักการเขียนของภาษาไทย เสนอครั้งแรกใน paper Character Cluster Based Thai Information Retrieval TCC หนึ่งอาจจะไม่เป็นคำหรือไม่เป็นพยางค์ด้วยซ้ำ ตัวอย่างต่อไปนี้เป็น TCC ทั้งสิ้น

จะ, กับ, เข้, เพราะ, อื้อ, รู้, ใส่

เป็นต้น จะเห็นว่าแต่ละ TCC ที่ยกตัวอย่างไปไม่สามารถแยกตัวอักษรใดออกมาได้เลย เพราะถ้าแยกแล้วจะไม่สามารถอ่านได้ เช่น “ใส่” มี 3 ตัวอักษรแยก “ใ” ออกมาก็ไม่มีความหมายเพราะ “ใ” ต้องตามด้วยพยัญชนะบางอย่าง แยกไม้เอกยิ่งไม่ได้ใหญ่เพราะไม้เอกอยู่ตัวเดียวโดดๆ ไม่ได้ แบบนี้เป็นต้น มาดูตัวอย่างการแบ่ง TCC ที่ยาวขึ้นบ้าง

สังเกตตรงคำว่า “ฝาก” เราไม่แยก TCC เป็น “ฝาก|” แต่แยกเป็น “ฝา|ก|” เพราะเราไม่สามารถบอกได้ว่า “ก” จะเป็นตัวสะกดหรือจะเป็นพยัญชนะต้นให้กับ TCC ตัวถัดไป จึงต้องแบ่งย่อยไว้ก่อน คำว่า “ขวด” ที่แบ่งแบบนั้นก็ด้วยเหตุผลเดียวกัน สำหรับผู้ที่ทำงานด้านการประมวลผลภาษาธรรมชาติคงรู้จัก TCC ดีอยู่แล้ว แล้วอาจจะเขียนโปรแกรมตัดได้ไม่ยากเย็นนัก เช่นใช้ regular expression

เร็วๆนี้ เพิ่งนำตัวตัด TCC ที่พัฒนาขึ้นมาปล่อยเป็น library (open-source) ชื่อ JTCC พัฒนาด้วยภาษา Java โดยใช้ parser generator ที่ชื่อ ANTLR ช่วยเพื่อสร้าง parser จาก grammar ของ TCC ที่เขียนไว้  หากสนใจก็เชิญนำไปใช้ได้ด้วย license GPLv3 ตัว library ยังไม่สมบูรณ์มากนัก แน่นอนยังมีจุดบกพร่อง (ดูได้ที่หน้า issue ในเว็บของ JTCC) หากมีข้อเสนอแนะหรือคำถามก็เชิญได้เลยครับ :)

เว็บหลักของ JTCC :  http://jtcc.googlecode.com

4 responses so far

การเอาคำที่ตัดได้จาก Lucene Analyzer

Sep 26 2009 Published by admin under Uncategorized

มีผู้อ่านท่านหนึ่งถามมาว่าจะเอาคำที่ตัดได้จาก Analyzer ของ Lucene ไปใช้ได้อย่างไร จากการลองซักพักหนึ่งทำให้ได้วิธีมาดังนี้ครับ


import java.io.IOException;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.th.ThaiAnalyzer;

/**
 * Demonstrate how to obtain a list of Lucene tokens.
 * @author Wittawat Jitkrittum (Sep 26, 2009)
 */
public class TestLuceneAnalyzer {

public static void tokenize(Analyzer analyzer, String text) throws IOException{
// เรียก method ชื่อ tokenStream เพื่อให้ได้สายของ token มา argument แรกเป็นชื่อ field ใน
// document ของ Lucene ในที่นี้เราไม่ได้ใช้ ก็ไม่ต้องสนใจ
TokenStream ts = analyzer.tokenStream(null, new StringReader(text));
// สร้าง Token ไว้เก็บผลลัพธ์ของคำที่ได้มา
Token token  = new Token();
// วน loop เพื่อเอา token ทีละอันจาก TokenStream เหตุที่ใส่ token เป็น argument ไปให้ด้วย
// เข้าใจว่าอยากให้เร็วจะได้ไม่ต้องสร้างอันใหม่
while((token = ts.next(token)) != null){
String term = token.term(); //เรียก method term() บน token เพื่อเอาคำเป็น String
System.out.print(term);
System.out.print(" | ");
}
System.out.println();
}
public static void main(String[] args) throws Exception{
Analyzer thaiAnalyzer = new ThaiAnalyzer();
String text = "นี่คือประโยคเอาไว้ทดสอบการตัดคำของ Lucene Analyzer";
tokenize(thaiAnalyzer, text);
}
}

พอรัน main ด้านบนก็จะได้ประมาณนี้ครับ

นี่ | คือ | ประโยค | เอา | ไว้ | ทดสอบ | การ | ตัด | คำ | ของ | lucene | analyzer |

สำหรับคนที่อยากรู้เรื่องการทำ index โดยใช้ Lucene ขอเชิญคลิกอ่าน post อันเก่านี้ เขียนจบแล้วเพิ่งนึกได้ว่าผู้ที่ถามมาอาจจะอยากเข้าถึงคำที่อยู่ใน index รึป่าว.. ไม่ใช่เอา Analyzer มาใช้เฉยๆแบบนี้ ถ้ากรณีนั้นเอาไว้มีเวลาจะเขียนทีหลังครับ

3 responses so far

ความถี่ของคำ

Mar 22 2009 Published by admin under Uncategorized

ช่วงนี้ในโปรเจคระบบคำถามคำตอบที่ทำอยู่ต้องมีการให้น้ำหนักความหายากของคำ ยิ่งหายากยิ่งให้น้ำหนักมาก จึงจำเป็นต้องมีการหาความถี่ของคำเสียก่อน แล้วนำมาหาส่วนกลับของความน่าจะเป็น (1/ความน่าจะเป็นของคำที่สนใจ) ก็จะได้ค่าประมาณความหายากของคำ

การหาความถี่ของคำที่ได้ทำไปนั้นมีขั้นตอนดังนี้

  1. เตรียมรายการหัวเรื่องของวิกิพีเดียภาษาไทยทั้งหมดก่อน (ประมาณ 40,000 กว่าคำ ณ เวลาที่เขียนบทความนี้)
  2. นำคำที่เป็นหัวเรื่องแต่ละคำส่งไปเป็นคำค้นของ Yahoo search engine ผ่าน Yahoo Search API
  3. เก็บเนื้อหาของหน้าผลลัพธ์ (ไม่ได้เก็บทั้งเว็บ เก็บเฉพาะหน้าที่ขึ้นมาเป็นผลลัพธ์) 300 อันดับแรก (อาจจะเก็บน้อยกว่า 300 ถ้าผลลัพธ์มีไม่ถึง) หลังจากที่ขจัดแท็ก HTML ทิ้งหมดแล้ว
  4. หาความถี่ของคำโดยการนับจำนวนครั้งการเกิดในคลังเอกสารที่เก็บมาได้ โดยจะนับเฉพาะคำที่มีในดิก Lexitron และคำที่เป็นหัวเรื่องของวิกิพีเดียภาษาไทย

ข้อมูลทั้งหมดน่าจะมีประมาณ 2 ล้านหน้า แน่นอนแต่ละหน้ามีความยาวไม่เท่ากัน การใช้ภาษาก็อาจจะไม่เหมือนกัน และในขั้นตอนขจัดแท็ก ไม่ได้มีการตัดข้อความที่เป็นโฆษณาหรือเมนูต่างๆออก (เพราะไม่รู้ว่าตรงไหนเป็นโฆษณา)

ใครอยากได้ข้อมูลความถี่ของคำเหล่านี้สามารถโหลดไปใช้ได้เลย ที่นี่

One response so far