ใช้ CoreNLP ผ่าน Clojure

ผมเริ่มหัดเขียน Java มาตั้งแต่ราว ๆ พ.ศ. ๒๕๔๐ แต่ว่าจนกระทั่งเดี๋ยวนี้ก็ยังรู้สึกว่ายังเขียนไม่เป็น แต่ CoreNLP ที่เอามาใช้ตัดคำก็ได้ บอกชนิดของคำก็ได้ วิเคราะห์ความสัมพันธ์ของคำในประโยคก็ได้ ดันเขียนด้วย Java

การไปเรียกใช้หลัก ๆ มี 2 วิธีคือเรียกตรง ๆ กับเรียกผ่าน HTTP server ผมไม่อยากเรียกผ่าน HTTP server เพราะขี้เกียจไป start server ก่อน ทางออกก็เลยเป็นการเรียกใช้ผ่าน Clojure

API แบบเรียกตรง ๆ ของ CoreNLP มี  2 แบบคือ Simple กับอีกแบบคือ Advance (มั้ง) แน่นอนผมเลือก Simple

;; Copyright (c) 2016, Vee Satayamas
;; All rights reserved.
;;
;; License: GPLv3 http://www.gnu.org/licenses/gpl-3.0.html

'{:dependencies [[org.clojure/clojure "1.8.0"]
                 [edu.stanford.nlp/stanford-corenlp "3.6.0"]
                 [edu.stanford.nlp/stanford-corenlp "3.6.0" :classifier "models"]
                 [com.google.protobuf/protobuf-java "2.6.1"]
                 [org.slf4j/slf4j-log4j12 "1.7.21"]]}

(require '[clojure.pprint :refer [pprint]])
(import edu.stanford.nlp.simple.Document)

(let [doc (Document. "I saw her. She met me.")]
  (pprint (.sentences doc)))

อันนี้เรียกด้วย inlein นะครับ เพราะว่าผมยัด dependencies มาไว้ใน source code เลย ส่วนที่วุ่นวายที่สุดก็คือ dependencies นี่ล่ะครับ ที่เหลือก็แค่สร้าง object ของ Document ขึ้นมา แล้วเรียก method .sentences มันก็คืน instance ของ “ประโยค” ออกมาให้เลย

Apertium ภาษาไทย

Apertium เป็นระบบแปลภาษาแบบใช้กฎการถ่ายโอน (โดยเฉพาะแบบตื้น) ที่สำคัญมันเป็นซอฟต์แวร์เสรี (Free software; ~ Open source software)

Apertium กับภาษาไทยอยู่ในระยะเริ่มต้น แต่ก็เอาลงติดตั้งเพื่อช่วยกันพัฒนาได้ เอาไปใช้คงยังไม่ไหว

  1. เบื้องต้นดูตามนี้ได้เลย
  2. ใน svn ที่ sf.net/projects/apertium ใน trunk ลง lttoolbox apertium apertium-lex-tools
  3. ลง vislcg3
  4. ใน incubator ใน svn ที่ sf.net/projects/apertium ลง apertium-tha
  5. ใน incubator ใน svn ที่ sf.net/projects/apertium ลง apertium-tha-eng อันนี้จะท่ายากหน่อยเพราะต้องสั่งทำนอง ./autogen.sh –with-lang1=(ชี้ไปที่ path ของ apertium-tha) ที่ลงไปก่อนหน้านี

เสร็จแล้ว ใน folder ของ apertium-tha-eng ลองสั่ง apertium -d . eng-tha ก็จะเริ่มแปลได้นิดหน่อย

ตอนนี้มันก็จะออกมาฮาฮาประมาณนี้

$ apertium -d . eng-tha
I am a cat.
#ฉัน #คือ *a #แมว.

ป.ล. ไม่เข้าใจถามไดใน IRC ที่ irc.freenode.org ห้อง #apertium

wordcut 0.7.0 เรียกใช้จาก command line ได้แล้วครับ

wordcut คือโปรแกรมตัดคำ (word segmentation)

วิธีติดตั้ง

npm install -g wordcut

เวลาใช้ก็จะประมาณนี้อะครับ

$ wordcut
กากากา
กา กา กา

คือพิมพ์ กากากา เข้าไปมันก็ตัดได้ กา กา กา ออกมา

More info: http://github.com/veer66/wordcut

โปรแกรมตัดคำ แบบใช้ PHP ล้วน ๆ

ที่ผ่านมามีหลายท่านสนใจถามเข้าหลังจากที่แสดงตัวอย่างเรียก Swath จาก PHP ให้ดู แต่ส่วนมากพอใช้บน Windows หลายคน ก็งง ๆ ผมก็งง ก็เลยจัดอันนี้ไป โปรแกรมตัดคำมันบน PHP ล้วน ๆ เสียเวลาเขียนไปหลายชั่วโมงอยู่ครับ น่าจะมี bug อะไรเต็มไปหมดถ้าท่านใดพบกรุณาแจ้งไปที่ https://github.com/veer66/PhlongTaIam/issue เดี๋ยวนี้ใช้ github แล้วครับ เพื่อท่านใดจะช่วยแก้จะได้ fork แล้ว pull request กลับมาได้เลย ไม่ต้องเสียเวลาย้ายไปย้ายมาให้ลำบากเหมือนโครงการก่อน

เข้าไป download ที่ https://github.com/veer66/PhlongTaIam ได้เลยครับ ถ้าเอาง่าย ๆ ก็ click ที่ปุ่มที่เขียนว่า zip และมีรูปเมฆมีลูกศรชี้ลงครับ ก็ได้ code ไปทั้งหมด เอาไปวางใน htdocs ก็น่าจะใช้ได้เลย

แต่ก็อาจจะเจ๊งบน Windows หรือสิ่งแวดล้อมที่ต่างจากที่ผมใช้อยู่อยู่ดี ถ้าปัญหาอะไรก็ถามไว้ที่นี่ได้ครับ แต่ว่าส่วนมากผมมักจะตอบไม่ได้  แต่ก็เผื่อมีท่านอื่นตอบได้ครับ

KUCut Web API

KU Cut Web API ผมอยากจะเรียกใช้ KU Cut จาก Java จึงสร้าง web api ง่ายๆ ขึ้นมาบน CherryPy สามารถดู code ได้จาก https://bitbucket.org/veer66/kucut/src/a54de79d39f9/kucut/webapi.py วางไฟล์นี้ไว้ใน folder เดียวกับ simple_kucut_wrapper.py หรือว่าจริงๆ แล้วก็ใช้ kucut ล่าสุดจาก Hg repository เลยก็ได้

จากนั้นก็ลง CherryPy ผมใช้รุ่น 3.2

จากนั้น run server ตรงๆ ได้เลย ใช้ตำสั่ง python webapi.py

เวลาเรียกใจงานก็เข้า URL ประมาณ http://localhost:8089/index?text=%E0%B8%81%E0%B8%B2%E0%B8%81%E0%B8%B2%E0%B8%81%E0%B8%B2%E0%B8%81%E0%B8%B2 (มันคือ กินกินกิน แบบ UTF8 แล้วเปลี่ยนมาเป็น URL)

ก็ได้ผลลัพธ์คืนมาเป็น [[[“\u0e01\u0e32”, “\u0e01\u0e32”, “\u0e01\u0e32”, “\u0e01\u0e32”]]] เป็น JSON ครับ เอาไป decode ได้เลย

ใช้ Swath จาก PHP

Update: โปรแกรมตัดคำแบบใช้ PHP เลยก็มีนะครับ: https://github.com/veer66/PhlongTaIam

ทางบ้านถามเข้ามาหลายท่าน ผมจึงเขียนออกมาได้แบบนี้ครับ

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Swath Web</title>
	<meta name="generator" content="TextMate http://macromates.com/">
	<meta name="author" content="Vee Satayamas">
	
</head>
<body>
<form method="post">
<textarea name="input_text" cols="80" rows="10"></textarea>
<input type="submit" value="submit">
</form>
<?php

    function swath($input_text) 
    {
        $input_filename= tempnam("/tmp", "swath_");
        $output_filename= tempnam("/tmp", "swath_");
        $input_text_tis620 = iconv("UTF-8", "TIS-620", $input_text);
        file_put_contents($input_filename, $input_text_tis620);
        system("/usr/bin/swath < $input_filename > $output_filename");
        $raw = file_get_contents($output_filename);
        $raw_utf8 = iconv("TIS-620", "UTF-8", $raw);
        unlink($input_filename);
        unlink($output_filename);
        return preg_split('/\|/', $raw_utf8);
    }

    if($_REQUEST['input_text']) {
        $output = swath($_REQUEST['input_text']);
        print implode(" ", $output);
    }
?>
</body>
</html>

แต่ว่าแบบนี้เราต้องลง swath ไว้ใน /usr/bin นะครับ ฯ​ ลงไว้ที่อื่นก็ไม่น่าเป็นไรนะครับ เปลี่ยนใน code เอาเลยก็ได้ ฯ อีกอย่างคือต้องการใช้ iconv ด้วย ฯ แต่ถ้าไม่ใช้ iconv ก็น่าจะได้อีกเหมือนกัน ฯ​ เปลี่ยนหน้าเว็บเป็น TIS-620 ให้หมดก็น่าจะใช้ได้เลย ฯ

Vauquois’s triangle

Vauquois’s triangle หรือ Translation triangle เอาไว้แสดง architecture ของ Machine translation system ต่างๆ จะใช้สถิติใช้กฎก็ใช้สามเหลี่ยมนี้ได้ ประมาณว่ามองคนละมิติกัน

สามเหลี่ยมที่ว่า [click]

ใช้ Tubsub API ผ่าน PHP

ก็เขียน code แบบนี้เลยครับ

<?php
  function tubsub($txt) {
    $txt = urlencode($txt);
    $data = "input=$txt";
    $ch = curl_init("http://vivaldi.cpe.ku.ac.th/~vee/tubsube2t.php");
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);      
    curl_close($ch);
    $ans = json_decode($output);
    return $ans[0];
  }

  print tubsub("toto") . "\n";
?>

เขียนแบบข้างบนโปรแกรมก็จะพิมพ์ออกมาว่าเขียน toto ภาษาไทยเขียนอย่างไร ถ้าจะใช้กับอย่างอื่นก็ copy function tubsub ไปใช้ได้เลยครับ

GIZA++ 1.0.3 บน Ubuntu 9.10

ผมพยายามจะลง Giza++ 1.0.3 บน Ubuntu 9.10 จริงๆ มี .deb ให้ใช้แต่ว่า ผมไม่ได้ใช้เพราะอยากจะ code ของ Giza++ ด้วย

แต่ว่าก็มีปัญหานิดหน่อย เพราะว่า string ที่จองมาเก็บปี จองมาน้อยไปหน่อย คล้ายๆ ปัญหา y2k ก็เลย patch ไปแบบนี้

diff -Nur giza-pp/GIZA++-v2/file_spec.h giza-pp.orig/GIZA++-v2/file_spec.h
--- giza-pp/GIZA++-v2/file_spec.h	2010-02-06 19:05:55.000000000 +0000
+++ giza-pp.orig/GIZA++-v2/file_spec.h	2009-03-20 11:41:12.000000000 +0000
@@ -37,13 +37,13 @@
   struct tm *local;
   time_t t;
   char *user;
-  char time_stmp[18];
+  char time_stmp[17];
   char *file_spec = 0;
   
   t = time(NULL);
   local = localtime(&t);
   
-  sprintf(time_stmp, "%03d-%02d-%02d.%02d%02d%02d.", local->tm_year, 
+  sprintf(time_stmp, "%02d-%02d-%02d.%02d%02d%02d.", local->tm_year, 
 	  (local->tm_mon + 1), local->tm_mday, local->tm_hour, 
 	  local->tm_min, local->tm_sec);
   user = getenv("USER");

รายงานบักไปแล้วเหมือนจะซ้ำด้วย http://code.google.com/p/giza-pp/issues/detail?id=20 บรรยากาศก็เงียบๆ