เตรียม parallel corpus สำหรับ word alignment จาก .po

วิธีที่ก็ใช้ polib อ่าน .po ของ GNOME มาแล้วก็พยายาม ตัดเครื่องหมายทิ้ง. แม้แต่ string ที่มีหลายบรรทัดก็ตัดทิ้ง.

ขั้นแรกเลยคือเข้าไปที่ web L10N ของ GNOME http://l10n.gnome.org/languages/th/gnome-2-22 หลังจาก copy & paste และแก้ด้วยความถึกนิดหน่อย ผมก็ได้รายการของ .po มา.

Download po file pessulus       100% (30/0/0)
Download po file Sabayon        100% (230/0/0)
GNOME developer platform (66% translated)
Download po file atk    95% (117/0/6)
Download po file gail   100% (103/0/0)

พอได้แบบนี้มาแล้วก็เขียนโปรแกรมมาตัดๆ หน่อย

get_pkg.rb

while gets
    if $_ =~ /Download po file ([^s]+)/
        print "wget  http://l10n.gnome.org/POT/#{$1}.HEAD/#{$1}.HEAD.th.pon"
    end
end

ก็ได้ script ที่ load .po ออกมา

$ ruby get_pkg.rb > download.sh && sh download.sh

พอได้แบบนี้มาแล้วผมก็เขียนโปรแกรมมา extract ของใน .po มาชื่อ ext_po.py


#-*- coding: UTF-8 -*-
import sys
import polib
import getopt
import re

class Params:
    def __init__(self, o_eng_path, o_tha_path, i_po_paths):
        self.o_eng_path = o_eng_path
        self.o_tha_path = o_tha_path
        self.i_po_paths = i_po_paths

    def __str__(self):
        return str(self.__dict__)

def usage():
    print "Usage: " + sys.argv[0] + " -e  -t   ..."

def usage_and_exit():
    usage()
    sys.exit(2)

def get_params():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "e:t:")
        keys = [o[0] for o in opts]
        if not "-e" in keys:
            print "Require English output filename"
            usage_and_exit()
        if not "-e" in keys:
            print "Require Thai output filename"
            usage_and_exit()
        if len(args) < 1:
            print "Require po filename"
            usage_and_exit()
        return Params(o_eng_path = filter(lambda o: o[0] == "-e", opts)[0][1],
                      o_tha_path = filter(lambda o: o[0] == "-t", opts)[0][1],
                      i_po_paths = args)
    except getopt.GetoptError, err:
        print str(err)
        usage_and_exit()

def entry_constraints(entry):
    return not entry.translated() and entry.msgstr != ""
        and entry.msgid != ""

def remove(txt, sym):
    return re.sub(sym, " ", txt)

def convert_text(txt):
    syms = ["_", "...", ":", "|", "-+", "/+", "%w", "",
            """, "©", "~", "(", ")"]
    return reduce(remove, syms, txt)

def split_line(txt):
    return filter(lambda tok: not re.match("^ *$", tok),
                  re.split("n", txt))

def split_line_in_entry(ans, entry):
    e_lines = split_line(entry[0])
    t_lines = split_line(entry[1])
    if len(e_lines) == 1 and len(t_lines) == 1:
        return ans + [(e_lines[i], t_lines[i]) for i in range(len(e_lines))]
    else:
        return ans

def ext_po_file(o_eng_file, o_tha_file, po):
    entries = filter(entry_constraints, list(po))
    entries = [(entry.msgid, entry.msgstr) for entry in entries]
    entries = [(convert_text(e[0]), convert_text(e[1])) for e in entries]
    entries = reduce(split_line_in_entry, entries, [])
    for entry in entries:
        o_eng_file.write(entry[0] + "n")
        o_tha_file.write(entry[1] + "n")

def ext_with_ofiles(o_eng_file, o_tha_file, i_po_paths):
    for i_po_path in i_po_paths:
        po = polib.pofile(i_po_path)
        ext_po_file(o_eng_file, o_tha_file, po)

def ext(o_eng_path, o_tha_path, i_po_paths):
    o_tha_file = open(o_tha_path, 'w')
    o_eng_file = open(o_eng_path, 'w')
    ext_with_ofiles(o_eng_file, o_tha_file, i_po_paths)
    o_eng_file.close()
    o_tha_file.close()

def init_charset():
    reload(sys)
    sys.setdefaultencoding('utf-8')

def main():
    init_charset()
    params = get_params()
    ext(params.o_eng_path, params.o_tha_path, params.i_po_paths)

if __name__ == '__main__':
	main()

จากนั้นก็สั่ง (โดยสมมุติว่า .po ทั้งหมดอยู่ใน folder เดียวกัน)

$ python ext_po.py -e e -t t  *.po

cut.sh เอาไว้ตัดคำโดยใช้  kucut อีกที

#!/bin/sh
iconv -f UTF-8 -t TIS-620 < $1 > $1.tis
kucut –line=” ” $1.tis
iconv -f TIS-620 -t UTF-8 < $1.tis.cut > $1.cut

แล้วก็ใช้ cut.sh โดยเรียก

$ ./cut.sh t && mv t.cut t

จากนั้นก็ไปเรียก GIZA++ แบบที่แก้ๆไปแล้ว ได้เลย

$ plain2snt e t

$ train-giza++ e.vcb t.vcb e_t.snt

เป็นอันเรียบร้อย

ได้ผลออกมาแบบนี้

# Sentence pair (1) source length 6 target length 6 alignment score : 0.000163118
รายการ เมนู ใหม่ ต้อง มี ชื่อ
NULL ({ }) New ({ 3 }) menu ({ 2 }) items ({ 1 }) need ({ 4 5 }) a ({ }) name ({ 6 })
# Sentence pair (2) source length 5 target length 5 alignment score : 0.00022357
เมนู ใหม่ ต้อง มี ชื่อ 

ผลอ่ายากนิดนึงแบบ New ({3}) หมายถึงว่า new ตรงกับคำภาษาไทยตัวที่ 3 ใน “รายการ เมนู ใหม่ ต้อง มี ชื่อ” ก็คือใหม่นั่นเอง.

One thought on “เตรียม parallel corpus สำหรับ word alignment จาก .po

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s