ทดลอง Tesseract 4.0alpha กับภาษาไทย

Tesseract เป็นซอฟต์แวร์และไลบรารีแปลงภาพข้อความ (ที่คนอ่านเข้าใจ) ให้เป็นข้อความ (ที่คอมพิวเตอร์อ่านเข้าใจ) หรือที่เรียกกันว่า OCR

สาเหตุที่ Tesseract ได้รับความนิยม เพราะมันเป็นซอฟต์แวร์เสรี (free software ไม่ต้องจ่ายเงิน มีซอร์สโค้ดให้ดูและแก้ไขเผยแพร่ต่อได้ และประสิทธิภาพมันก็ดี จะเรียกใช้ตรงๆ ทาง command line ก็ได้ หรือจะเขียนโปรแกรมเชื่อมกับ API มันก็ได้ — ดู wrapper และ GUI อื่นๆ ได้ที่หน้า Add Ons ของโครงการ

ภาพที่จะส่งมา Tesseract ต้องเป็นภาพที่ปรับแต่งมาให้เหมาะกับการอ่านข้อความแล้ว คือหมุนมาค่อนข้างตรง และปรับแสงและสีให้อ่านง่าน พื้นหลังสีขาวหรือสีอ่อน ตัวอักษรสีดำ ใน StackOverflow มีคนอธิบายการใช้ OpenCV ปรับภาพเพื่อ OCR เอาไว้

Tesseract รองรับภาษาไทย (น่าจะตั้งแต่รุ่น 3) ตอนนี้รุ่น 4 กำลังจะออก เพิ่มเอนจินที่ใช้โมเดล Deep Learning แบบ LSTM เข้ามา เท่าที่ทีมพัฒนาทดสอบกันเอง มีข้อผิดพลาดน้อยกว่าเอนจินของรุ่นก่อน

โพสต์นี้จะพูดถึงการทดสอบรุ่น 4.0alpha บน macOS และทดลองเพิ่ม/ลดคำในรายคำศัพท์ที่ตัวเอนจิน LSTM จะเอาไปใช้

ส่วนใครจะใช้รุ่นที่ released แล้ว ติดตั้งด้วยวิธีปกติของแต่ละระบบปฏิบัติการได้นะครับ วิธีตามเอกสาร

ติดตั้งไลบรารีที่จำเป็น

brew install autoconf-archive leptonica icu4c pango

ไลบรารี icu4c (เอาไว้จัดการ Unicode) กับ pango (จัดการการวาดตัวอักษร) ติดตั้งเฉพาะถ้าเราต้องการฝึกโมเดลใหม่

อาจจะมีไลบรารีอื่นที่ต้องใช้เพิ่มเติม ลองอ่านที่ configure มันแจ้ง และติดตั้งตามที่มันบอกครับ

ICU ที่มากับ macOS ไม่มีไฟล์ header มาด้วย ดังนั้นใช้คอมไพล์ไม่ได้ ต้องลงใหม่ครับ

ตั้งค่า environment

ในไฟล์ ~/.bash_profile

export PATH="/usr/local/opt/icu4c/bin:$PATH"
export PATH="/usr/local/opt/icu4c/sbin:$PATH"
export LDFLAGS="-L/usr/local/opt/icu4c/lib"
export CPPFLAGS="-I/usr/local/opt/icu4c/include"

อันนี้ผมใช้ brew ปกติของมันจะเอาไลบรารีและเฮดเดอร์ต่างๆ ไปไว้ที่ไดเรกทอรี /usr/local/opt/ ถ้าใครติดตั้งไว้ที่อื่นก็เปลี่ยนตามนั้นครับ

ดาวน์โหลดโค้ดและเตรียมคอมไพล์

โค้ด Tesseract ตัวล่าสุดอยู่ที่ https://github.com/tesseract-ocr/tesseract ก็ไปโคลนหรือฟอร์กมาได้เลย

จากนั้นในไดเรกทอรีของ tesseract เราก็สร้างไฟล์คอนฟิกเพื่อเตรียมคอมไพล์

./autogen.h

และ

./configure

จากนั้นก็คอมไพล์และติดตั้งตัว tesseract

make
make install

และคอมไพล์และติดตั้งตัวโปรแกรมสำหรับฝึกและแก้ไขรายการคำ

make training
make training-install

ถ้าคอนฟิกไม่ผ่านหรือคอมไพล์ไม่ผ่าน ส่วนใหญ่สาเหตุมาจากการที่ tesseract หาไลบรารีที่มันต้องการไม่เจอ ซึ่งอาจจะเกิดจากการที่เครื่องเรายังไม่มี (ก็ติดตั้งซะ) หรือมีแล้วแต่หาไม่เจอ (ก็ลองตั้งค่า environment ดู)

ใช้งาน Tesseract

การจะใช้งาน Tesseract ได้ ต้องมีไฟล์ข้อมูลภาษาให้มันด้วย ซึ่งดาวน์โหลดได้จาก https://github.com/tesseract-ocr/tessdata_best และ https://github.com/tesseract-ocr/tessdata_fast ตัวแรกจะแม่นกว่า ตัวหลังจะเร็วกว่า

โมเดลภาษาไทยชื่อ tha.traineddata
โมเดลภาษาอังกฤษชื่อ eng.traineddata

ตัวอย่างการเรียกใช้งานจาก command line:

tesseract input.png output --oem 1 -l tha -c preserve_interword_spaces=1 --tessdata-dir ./tessdata_best/

  • tesseract — เป็นชื่อโปรแกรมที่เราใช้จาก command line
  • input.png — ตรงนี้จะเป็นชื่อภาพอะไรก็ได้ ได้ทั้งฟอร์แมต TIFF, PNG, JPG
  • output — ชื่อไฟล์ text ใส่ไปแบบนี้ ไฟล์ที่ออกมาจะใช้ชื่อ output.txt (เติม .txt ให้อัตโนมัติ)
  • –oem 1 — เลือก OCR Engine mode เป็น LSTM
  • -l tha — เลือกภาษาไทย ถ้าเอกสารเรามีทั้งไทยและอังกฤษ ก็ใช้ -l tha+eng
  • -c preserve_interword_spaces=1 — บอกเอนจินว่าไม่ต้องแทรกช่องว่างระหว่างตัวอักษรให้ เนื่องจากภาษาไทยเขียนติดกันโดยไม่มีช่องว่าง ถ้าแทรกมาจะอ่านลำบาก
  • –tessdata-dir ./tessdata_best/ — บอกไดเรกทอรีที่เก็บข้อมูลโมเดล

เท่าที่ลองให้อ่านภาพตัวอักษรที่ใช้ฟอนต์ Tahoma กับฟอนต์ Sukhumvit Set ก็อ่านได้แม่นอยู่นะครับ ยกเว้นพวกวรรณยุกต์เล็กๆ บางๆ อย่างไม้เอก บางทีจะหายไป เอนจินมันอาจจะไม่เห็น ตรงนี้ถ้าจะแก้ไขทำได้ด้วยการประมวลผลภาพก่อนส่งเข้า Tesseract เช่นทำให้เส้นหนาขึ้น

แก้ไขไฟล์ wordlist

ไฟล์ tha.traineddata จริงๆ ข้างในมีข้อมูลอยู่หลายประเภท เราสามารถแตกมันออกมาเป็นไฟล์ย่อยๆ ได้

combine_tessdata -u ./tessdata_best/tha.traineddata ./tessdata_TEST/tha.

จะได้ไฟล์ unicharset และไฟล์ dawg (Directed Acyclic Word Graphs) ออกมา ซึ่งจากไฟล์เหล่านี้ เราใช้สร้างรายการคำศัพท์ได้

dawg2wordlist ./tessdata_TEST/tha.lstm-unicharset ./tessdata_TEST/tha.lstm-word-dawg ./tessdata_TEST/tha.lstm-word-list

พอได้รายการคำศัพท์มาแล้ว เราแก้มันได้ด้วย text editor ทั่วไปเลย — 1 บรรทัด 1 คำ

พอแก้ไขเสร็จแล้ว ก็ทำกลับกัน คือแปลงรายการคำศัพท์ให้เป็น unicharset และ dawg

wordlist2dawg ./tessdata_TEST/tha.lstm-word-list ./tessdata_TEST/tha.lstm-word-dawg ./tessdata_TEST/tha.lstm-unicharset

และรวมทั้งหมดเข้าด้วยกันเป็นไฟล์ traineddata เพื่อเอาไปใช้งานกับ tesseract

combine_tessdata ./tessdata_TEST/tha.

เราสามารถลองใช้โมเดลใหม่นี้ได้โดยบอก tesseract ผ่านพารามิเตอร์ –tessdata-dir ให้มาใช้ข้อมูลในไดเรกทอรีนี้

(วิธีการจัดการกับไฟล์คำศัพท์นี้ ขอบคุณ Shreeshrii ที่ช่วยอธิบายอย่างละเอียด)

ผลการทดสอบ

เท่าที่ทดสอบเร็วๆ การ preprocess ประมวลภาพก่อนจะส่งให้ Tesseract มีผลมาก แค่ปรับภาพจากสีเป็นขาวดำ ก็ทำให้อ่านข้อความได้เพิ่มขึ้น และยิ่งเราตัด (crop) ภาพมาเฉพาะส่วนที่มีข้อความ มันก็จะแม่นขึ้นอีก อย่างไรก็ตามการ postprocess อย่างการทำ spellcheck แก้คำผิด ก็ยังจำเป็นอยู่ ถ้าต้องการความแม่นยำที่เพิ่มขึ้นครับ

ด้านล่างเป็นผลทดสอบด้วยโมเดลจาก tessdata_best โดยไม่ได้ปรับแต่งอะไรเพิ่ม

Pantip on Facebook Color - read with Tesseract
ภาพจากสื่อสังคม (ไม่ได้ preprocess เลย) เมื่อทดสอบอ่านด้วย Tesseract
Pantip on Facebook Black and White - read with Tesseract
ภาพจากสื่อสังคม (ปรับสีเป็นขาวดำ) เมื่อทดสอบอ่านด้วย Tesseract
Pantip on Facebook Black and White, Cropped - read with Tesseract
ภาพจากสื่อสังคม (ปรับสีเป็นขาวดำและตัดมาเฉพาะส่วนที่เป็นข้อความ) เมื่อทดสอบอ่านด้วย Tesseract

ใครลองเล่นแล้วได้ผลอย่างไรบอกกันได้ครับ

Punctual translation with punctuation marks

ความแตกต่างของคำแปลโดย Google Translate ที่เกิดจากการมีและไม่มีเครื่องหมายวรรคตอน วันนี้พบโดยบังเอิญ (2011.02.18):

  • “ถ่ายในห้อง (มีเครื่องหมายคำพูด) → “shot in the room.
  • ถ่ายในห้อง (ไม่มีเครื่องหมายคำพูด) → Taken in the room.

นี่อาจจะบอกได้ว่า Google Translate ใช้เครื่องหมายวรรคตอนในการคำนวณสถิติเพื่อใช้ในการแปลด้วย

เท่าที่เคยพบ งานทางด้านการประมวลผลภาษาธรรมชาติจำนวนมาก ไม่ค่อยสนใจเครื่องหมายวรรคตอนเท่าไหร่ (เว้นสาขา natural language generation และ discourse analysis) บางทีกรองทิ้งไปเลยก็มี

Say, Bilge and Akman, Varol (1997). Current Approaches to Punctuation in Computational Linguistics

Jones, Bernard (1996). What’s The Point? A (Computational) Theory of Punctuation

Jones, Bernard (1994). Exploring the role of punctuation in parsing natural language text

technorati tags:
,
,

ช่วงช่วง หลินฮุ่ย เคอิโงะ เสื้อแดง เอ็นจีวี นักศึกษา แพนด้า SEO OCR

OCRopus โอเพ่นซอร์สทูลคิตสำหรับงาน OCR รุ่น 0.4 ออกแล้วครับ น่าจะคอมไพล์อะไรต่าง ๆ ได้ง่ายขึ้นบนแพลตฟอร์มที่ไม่ใช่ GNU/Linux ครับ

ดาวน์โหลดได้ทันทีที่เว็บไซต์ OCRopus (โอเพ่นซอร์ส Apache License 2.0)

ที่หน้าเว็บ Course: OCRopus สอนการใช้งานและปรับแต่ง OCRopus มีวิธีเขียน Lua และ C++ เพื่อเรียกใช้ OCRopus ด้วย

แม้ OCRopus จะรองรับการเพิ่มเติมภาษาใหม่ ๆ เข้าไปได้ แต่ก็ต้องลงแรงหน่อย ตอนนี้ยังใช้ไทยไม่ได้โดยทันที

สำหรับคนที่มองหาตัวที่อ่านภาษาไทยได้ และไม่แพงนัก ลองหา ArnThai (อ่านไทย) มาทดสอบดู มีทั้งบนวินโดวส์และลีนุกซ์ (รุ่นบนลีนุกซ์เก่ากว่าหน่อย) ติดต่อเนคเทคได้ ถ้าสนใจนำไปใช้ ที่เคยถาม สามารถตกลงสัญญาอนุญาตได้หลายแบบ

สำหรับตัวที่มีประสิทธิภาพดีกว่านั้นและมีความสามารถเพิ่มเติมอื่น ๆ ที่อ่านไทยได้ คือ ABBYY FindReader อ่าน PDF ได้ ใช้ได้หลายภาษา (ทายอัตโนมัติ) คง document logical structure, formatting, style, ฟอนต์, และตาราง อู้ฟู่หรูหรามาก (ขอบคุณ @sarasinb และ @thai101 สำหรับข้อมูล)

รีวิวซอฟต์แวร์ OCR ต่าง ๆ บนลีนุกซ์ : โดย groundstate, โดย Peter Selinger. บทความ optical cahracter recogntion ที่วิกิพีเดียภาษาอังกฤษ มีลิงก์ไปหาซอฟต์แวร์ต่าง ๆ ด้านล่างสุด.

technorati tags: , , , ,

NLTK corpus readers for NECTEC BEST and ORCHID corpora

ความเดิมจากตอนที่แล้ว ทดลองสร้าง corpus reader ใน NLTK

ตอนนี้แก้การ encode ให้ใช้ได้กับ nltk.Text() แล้ว (แทนที่จะเก็บเป็น unicode ก็เก็บเป็น utf-8 encoded str แทน)

พร้อมกับเพิ่มตัวอ่านสำหรับคลังข้อความ BEST และ ORCHID ด้วย

ตัวอ่านคลัง BEST ในรุ่น 0.3 นี้ เรียกดูเป็นหมวดได้ (ข่าว วรรณกรรม สารานุกรม บทความ) เรียกดูข้อมูลกำกับขอบเขตคำ (word boundaries) ได้ แต่ยังไม่รองรับ <NE>named-entities</NE> กับ <AB>คำย่อ</AB> เนื่องจาก BEST ไม่มีข้อมูลขอบเขตประโยค ตัวอ่านคลังจะสร้างขึ้นเอง โดยสมมติ \n เป็นขอบเขตประโยค

ส่วนตัวอ่านคลัง ORCHID ในรุ่น 0.3 นี้ เรียกดูข้อมูลกำกับขอบเขตคำและชนิดคำ (Part-of-Speech) ได้ แต่ยังไม่รองรับขอบเขตย่อหน้า และยังเรียกดูเป็นรายเอกสารไม่ได้ (รุ่นนี้ทำงานกับคลัง ORCHID แบบที่ถูกเอา document-related metadata ออกไป)

ดาวน์โหลด & ติดตั้ง

แพ็คเกจ rotic รุ่น 0.3 ซอร์สโค้ดเผยแพร่ด้วยสัญญาอนุญาต GNU GPLv2 ตาม NLTK – ดาวน์โหลด rotic-0.3.tar.gz

วิธีติดตั้ง อ่าน README.TXT และ INSTALL.TXT – อย่าลืมดาวน์โหลดคลังข้อความมาติดตั้งด้วย รายละเอียดและสัญญาอนุญาตของข้อมูลแต่ละชุด อยู่ใน CORPORA.TXT

มีคำแนะนำอะไร เขียนมาบอกกันได้ครับ อยากจะลองทำให้มันเอาไปใช้ในการเรียนการสอนได้ – ไม่เฉพาะสำหรับนักเรียนคอมพิวเตอร์เท่านั้น แต่สำหรับนักเรียนภาษาศาสตร์ ฯลฯ ด้วย

ตอนนี้ความเร็วไม่ค่อยดีเท่าไหร่ โดยเฉพาะการโหลดตัว ORCHID ซึ่งใหญ่มาก ส่วนหนึ่งเป็นเพราะโค้ดยังซ้ำซ้อนอยู่หลายจุด เช่นตรงการแปลง utf-8 ที่น่าจะทำได้ตั้งแต่ระดับแรก ๆ ที่อ่านเข้ามาเลย ไม่ใช่มาแปลงเอาตอนหลัง-ต้องวนลูปอีกหนึ่งครั้งแบบขณะนี้ โค้ดยัง refactor ได้อีกเยอะ ใครคล่อง Python ก็ช่วยดูหน่อยนะครับ ผมแค่พอเขียนไถ ๆ ได้ ขอบคุณครับ 🙂

ตัวอย่างจาก example.py

1. พิมพ์ข้อความมั่ว ๆ ขึ้นมาจากตัวแบบ n-gram ที่สร้างจากคำในคลัง foosci :


foosci_text = nltk.Text(foosci.words())
foosci_text.generate()

ผลลัพธ์ :

… ซึ่ง ทฤษฎี สรุป ความรู้ ของ เรา เอา ไส้เดือน ไป ปล่อย ใน พื้นที่ ๆ มี ความ สงสัย ระหว่าง ความ เชื่อ เรื่อง มิติ ใหม่ นี้ …

2. พิมพ์ คำ/ชนิดคำ จาก 5 ประโยค แรกของคลัง ORCHID
โปรดสังเกตว่า เราใช้ชุดชนิดคำ (POS/tagset) แบบง่าย สามารถสลับชุดชนิดคำได้โดยสลับค่า simplify_tags :


for sent in orchid.tagged_sents(simplify_tags=True)[0:5]:
    print "[",
    for (word, tag) in sent:
        print word + "/" + tag,
    print "]"

ผลลัพธ์ :

[ การ/FIX ประชุม/V ทาง/N วิชาการ/N /PUNC ครั้ง/C ที่_1/DETN ]
[ โครงการวิจัยและพัฒนา/N อิเล็กทรอนิกส์/N และ/CONJ คอมพิวเตอร์/N ]
[ ปีงบประมาณ/N /PUNC 2531/N ]
[ เล่ม/C /PUNC 1/DETN ]
[ ศูนย์เทคโนโลยีอิเล็กทรอนิกส์และคอมพิวเตอร์แห่งชาติ/N ]

3. หาค่าการกระจายของสองคำ การ และ ความ ใน 4 หมวดของคลัง BEST
โปรดสังเกตว่า ตรงคำที่เราจะป้อนเข้าไปให้ฟังก์ชั่นต่าง ๆ ของ NLTK เราจะแปลงมันเป็น utf-8 encoded str ก่อน :


cfd = nltk.ConditionalFreqDist(
        (genre, word)
        for genre in best.categories()
        for word in best.words(categories=genre))

genres = ['news', 'encyclopedia', 'novel', 'article']
prefixs = [w.encode("utf-8") for w in [u'การ', u'ความ']]
cfd.tabulate(conditions=genres, samples=prefixs)

ผลลัพธ์ :

             การ ความ
        news 29567 11186
encyclopedia 25477 8541
       novel 4258 9097
     article 33200 16651

เล่นต่อเอง จากตัวอย่างในหนังสือ NLTK

เดี๋ยวอาจจะให้น้องฝึกงานที่โอเพ่นดรีมเอาไปทำต่อ เช่นทำให้มันใช้ AB, NE หรือขอบเขตประโยค/ย่อหน้าได้ .. เห็นนั่งเล่นเกมมาหลายวันละ :p

technorati tags:,,,

playing around Thai blog corpus with NLTK

อยากจะลองเล่น NLTK กับข้อมูลภาษาไทยดู คิดไปคิดมา เอาข้อมูลจาก foosci.com มาลองดูละกัน เขาเปิดให้ใช้ เป็น ครีเอทีฟคอมมอนส์ แสดงที่มา-อนุญาตแบบเดียวกัน (CC by-sa)

แต่ไม่อยากไปดึงมาเอง ขี้เกียจ เห็นว่าโครงการโรตี (อัลฟ่า) โดย Opendream ดูดบล็อกไทยจำนวนหนึ่งมาเก็บไว้ได้ระยะหนึ่งแล้ว เพื่อใช้ในการแนะนำลิงก์ (ดูตัวอย่างที่ keng.ws ที่ท้ายแต่ละโพสต์) ก็เลยเอาจากตรงนั้นมาใช้ละกัน

ข้อมูลที่มีเป็น XML ที่ dump มาจาก MySQL เราก็เขียนสคริปต์ก๊อก ๆ แก๊ก ๆ ดึงเฉพาะที่อยากได้ออกมา ด้วย xml.etree.cElementTree (ตอนแรกใช้ ElementTree แตน ๆ แต่อืดเกิน เนื่องจากแฟ้มมันใหญ่)
เอา HTML tags ออกด้วย Beautiful Soup แล้วตัดคำด้วย python-libthai ตัดประโยคแบบถึก ๆ ด้วย .split(‘\n’) จะได้ข้อมูลออกมาหน้าตาประมาณนี้ (จะเห็นว่าข้อมูลมันไม่ได้สมบูรณ์มาก มีแท็ก HTML โผล่มาด้วย-อันนี้เป็นที่ข้อมูลป้อนเข้าที่ dump มา) :


<?xml version="1.0" encoding="utf-8"?>
<roti>
  <entry id="4947" url="http://www.foosci.com/node/401" ...>
    <tags> <tag>LHC</tag> <tag>quantum physics</tag> ... </tags>
    <title> <w>บิดา</w> <w>ของ</w> <w>อนุภาค</w> ... </title>
    <content>
      <s> <w>p</w> <w>นัก</w> <w>วิทยาศาสตร์</w> ... </s>
      <s> <w>pcenter</w> <w space="1"> </w> <w>ภาพ</w> ... </s>
      ...
    </content>
  </entry>
  <entry>
    ...
</roti>

ใน w คือ คำ, ใน s คือ ประโยค

ดาวน์โหลดข้อมูล : foosci-20090424.tar.bz2 (สัญญาอนุญาต CC by-sa เช่นเดียวกับเนื้อหาใน foosci.com)
ข้างในจะมีสองแฟ้ม foosci00.xml และ foosci01.xml ให้ก๊อปปี้ไปใส่ในไดเรกทอรีข้อมูลของ NLTK (NLTK_DATA) $NLTK_DATA/corpora/rotibc ตัวโมดูลที่จะพูดถึงต่อจากนี้จะวิ่งมาหาที่ตำแหน่งนี้

ได้ข้อมูลมาแล้ว จะเอาเข้าไปใช้ใน NLTK ยังไง ? ก็ต้องเขียนตัว corpus reader ขึ้นมาก่อน ซึ่งกรณนี้ เราจะทำต่อมาจาก XMLCorpusReader (เรียกว่า inherit ไหม?) โดยไอเดียไม่มีอะไรมาก ก็ implement ตัวฟังก์ชั่น .words() เพื่อส่งกลับรายการคำ และฟังก์ชั่น .sents() เพื่อส่งกลับรายการประโยค โดยดูตัวอย่างจาก BNCCorpusReader

ที่ต้องทำเพิ่มเติมก็คือ สร้างแฟ้ม __init__.py ใส่ไว้ใน package เพื่อที่ว่าตอนโหลด มันจะได้โหลดเอาตัวข้อมูลขึ้นมาให้เราอัตโนมัติเลย (ซึ่งไม่ต้องกลัวอึด เพราะว่าโหลดแบบ lazy คือยังไม่ได้โหลดข้อมูลจริง ๆ จนกว่าจะใช้)

ตอนทำ __init__.py นี้ ทำให้รู้ว่า ทุกไดเรกทอรีที่เราจะใส่โมดูลอะไรลงไป จะต้องมีแฟ้มนี้ ไม่งั้นตอน build มันจะไม่นับไดเรกทอรีนั้นเป็น package จะข้ามไป เพราะงั้นถึงไม่ได้จะโหลดจะทำอะไร ก็ต้องใส่แฟ้มว่าง ๆ ไว้ (ดูเอกสาร Python Tutorial – Modules)

ใน __init__.py ไม่มีอะไรมาก แค่โหลดข้อมูลเฉย ๆ :
foosci = LazyCorpusLoader('rotibc', RotiCorpusReader, r'foosci\d+\.xml')

ดาวน์โหลดแพคเกจ roti.corpus : rotibc-0.1.tar.gz
แตกออกมาแล้ว ก็ลงด้วยคำสั่ง :
sudo python setup.py install
(ดูวิธีสร้าง setup.py มาจากเอกสาร Distutils – Creating a Source Distribution)

โอเค ครบละ ข้อมูล โปรแกรมอ่าน คราวนี้มาเล่นกัน ลองใน interpreter shell ของ Python ก็ได้


>>> from roti.corpus import foosci
>>> foosci.fileids() #แสดงรายชื่อแฟ้มในคลังข้อความ
['foosci00.xml', 'foosci01.xml']
>>> foosci.words() #แสดงรายการคำ
['p', u'\u0e19\u0e31\u0e01', ...]
>>> for w in foosci.words()[0:5]: #พิมพ์คำจากรายการ ตำแหน่ง 0-5
...     print w,
...
p นัก วิทยาศาสตร์ อังกฤษ ที่
>>>
>>> foosci.sents() #แสดงรายการประโยค
[['p', u'\u0e19\u0e31\u0e01', ...],
['pcenterimg', ' ', 'src=http://', ...], ...]
>>>

จะเห็นว่า เราพอจะเล่นอะไรกับมันได้ละ ถ้าจะเล่นมากกว่านี้ ลองดูตัวอย่างที่ Getting Started (NLTK)

ตัวอย่างหนึ่งจาก NLTK Book บทที่ 2 Accessing Text Corpora and Lexical Resources เขาลองเล่นกับ conditional frequency distribution เอามาสร้างประโยคมั่ว ๆ เล่น จากโมเดลไบแกรม ด้วยโค้ดด้านล่างนี้ :


def generate_model(cfdist, word, num=15):
    for i in range(num):
        print word,
        word = cfdist[word].max()

words = foosci.words()
bigrams = nltk.bigrams(words)
cfd = nltk.ConditionalFreqDist(bigrams)

ลองใส่คำอะไรสักคำให้มันดู มันจะสร้างประโยคมาให้


>>> generate_model(cfd, u'คอมพิวเตอร์')
คอมพิวเตอร์ ที่ มี ความ เสี่ยง มะเร็ง เต้า นม   href=http:// www. physorg. com/ ~r/ foosci/

การสร้างประโยคนั้น generate_model() ใช้วิธีเลือกเอาคำที่น่าจะเกิดต่อจากคำข้างหน้ามากที่สุด มาเรียงต่อกัน

ลองเล่นต่ออีกนิดหน่อยกับติวอันนี้ Working with corpora: Character Ngrams

ถ้ามีคลังข้อความที่น่ารัก ๆ กว่านี้ ก็น่าจะใช้ NLTK นี้ไปใช้เรียนสอน NLP หรือภาษาศาสตร์คลังข้อมูลง่าย ๆ ได้

ปัญหาอย่างนึงที่เจอตอนนี้คือ nltk.text.Text() ใช้กับ unicode ไม่ได้ คือมันจะพยายามแปลงข้อความไปเป็น ascii ซึ่งแปลงไม่ได้ แล้วก็จะตาย nltk.text.Text() นี่มีฟังก์ชั่นน่าใช้สำหรับการเรียนรู้เรื่องภาษาศาสตร์เยอะพอดู เช่น .concordance() .collocations() .similar()

<อัปเดต 2009.04.25> ใช้กับ nltk.Text() ได้แล้ว (แก้ตามคำแนะนำจากเมลกลุ่ม nltk-users) โดยต้องให้คำใน list เป็น str (“”) ที่ encode ด้วย utf-8 แทนที่จะใส่เป็นสตริงแบบ unicode (u””) ทำได้โดยแก้สองฟังก์ชั่น _elt_to_words() และ _elt_to_sents() ในแฟ้ม roti/corpus/rotibc.py ตรง .append(w.text) ให้เป็น.append(w.text.encode("utf-8", "replace")) เดี๋ยวจะปรับตัวแพคเกจใหม่ </อัปเดต>

ลองเล่นดูครับ เอาไปโมต่อตามสบาย โค้ดทั้งหมดเป็น public domain

ใช้ NLTK แล้วพบปัญหา คุยกับผู้ใช้รายอื่น ๆ ได้ที่เมลกลุ่ม nltk-users หรือถ้าอยากคุยกับคนไทย ลองกลุ่ม THLTA


แถม : Open License และคลังข้อมูลภาษา

ในงาน NAC 2009 โดยสวทช.ที่ผ่านมา ได้มีโอกาสแลกเปลี่ยนประเด็น open content, open license และ คลังข้อมูลภาษา กับคนในวงการ NLP จำนวนหนึ่ง ซึ่งก็มีความคิดเห็นหลาย ๆ อย่าง หลาย ๆ มุมก้นไป

เกือบทุกคนเห็นด้วยว่า เป็นเรื่องสำคัญที่ควรจะมีอะไรที่มันแชร์กันได้ ที่มัน open แต่ความหมายของคำว่า open สำหรับแต่ละคนก็ดูจะไม่เท่ากัน บางคนบอกว่า คลังอันนั้นอันนี้ฟรี ตัวนั้นตัวนี้โอเพ่นซอร์ส แต่พอไปดูเอาจริง ๆ ในรายละเอียด ก็พบว่า จำเป็นต้องลงทะเบียนก่อนบ้างหรือไม่ได้อัปเดตนานแล้วบ้าง (พจนานุกรม Lexitron) หรือลิงก์ดาวน์โหลดหายไปบ้าง (ORCHID Corpus – ดาวน์โหลดได้ที่ backup site) หรือก่อนหน้านี้เรื่องของฟอนต์หลาย ๆ ตัว ที่เอามาใช้ได้ฟรี แต่ไม่รู้ว่าจะโมได้ไหม redistribute ได้ไหม

ความเห็นของผมก็คือ จะเปิดหรือจะปิด อย่างไรก็ได้ เป็นสิทธิของเจ้าของข้อมูลที่เขาลงแรงลงเวลาไป
แต่ถ้าจะบอกว่าเปิด ก็ขอให้บอกให้ชัดเจนหน่อย ว่าในเงื่อนไขอะไร แล้วจะเอามาใช้จริง ๆ ได้ยังไง การบอกว่า เปิด เฉย ๆ โดยไม่ได้ให้รายละเอียดอะไรเลย ในทางปฏิบัติก็แทบจะเหมือนการไม่เปิด หน้า การแลกเปลี่ยนทรัพยากรและเครื่องมือ ที่ THLTA ก็อาจจะเป็นความพยายามหนึ่งที่จะทำให้เรื่องพวกนี้เคลียร์

สิ่งที่ผมคิดว่าน่าสนใจ และเป็นคุณสมบัติสำคัญของ open licenses ทั้งหลาย ไม่ว่าจะเป็น copyleft, GNU หรือ Creative Commons ก็คือ การไม่ต้องขออนุญาต ผมคิดว่าการไม่ต้องขออนุญาตนี้ทำให้ ข้อมูล โค้ด ไอเดีย ต่าง ๆ มันไหลเวียนได้อย่างอิสระ-ทันที ใครอยากจะเล่นอะไรก็เอา เต็มที่ ตามเงื่อนไขที่ประกาศไว้ชัดเจนล่วงหน้า ไม่ต้องรอไปรอมา ไม่ต้องตกอยู่ในภาวะไม่แน่ใจ

ซึ่งจริง ๆ แล้วเรื่องของความชัดเจนนี้ แม้จะเป็น closed content, closed source หรืออะไรก็ตาม ก็สามารถจะชัดเจนเรื่องนี้ได้ เพียงประกาศให้ชัดเจน — ไม่ใช่แค่บอกเฉย ๆ ว่า เปิด แล้วก็ทิ้งให้งง ให้เดาใจกันเล่น ๆ ว่า ตกลงจะเปิดแบบไหน เปิดยังไง

technorati tags:,,,

encode("UTF-8", "ignore") ข้าม ๆ เรื่องที่ทำไม่ได้ใน Python

หลังจากเอา python-libthai ของวีร์มาใช้กับข้อมูลที่ได้มาจากเว็บ ก็พบปัญหาเรื่อง character encoding นิดหน่อย

libthai นั้นปัจจุบันทำงานกับข้อมูลที่เป็นภาษาไทย 8 บิตอยู่ (น่าจะเป็น TIS-620) ตัว python-libthai เลยมีขั้นตอนการแปลงจากยูนิโค้ดไปเป็น 8 บิตก่อน
ทีนี้ ปรากฏว่า encoder “CP874”, “TIS_620” และ “ISO8859_11” ของ Python มันดันแปลงตัวอักษรบางตัวไม่ได้ (เนื่องจากใน charset พวกนั้น มันไม่มีตัวอักษรดังกล่าว) โปรแกรมก็เลยจะตาย ถ้าไปเจออักษรพวกนั้น

ก่อนตายมันจะโวยทำนองว่า :

UnicodeEncodeError: 'charmap' codec can't encode character
u'\u200b' in position 3560: character maps to <undefined>

วิธีแก้แบบถึก ๆ คือ เอาหูไปนาเอาตาไปไร่ซะ ignore มัน ด้วยการไปแก้ แฟ้มชื่อ libthai.c ของ python-libthai (แฟ้มนี้เป็น wrapper ที่ไปเรียก libthai ให้)

หาบรรทัดที่เรียกฟังก์ชั่น PyUnicode_Encode/Decode แล้วแก้พารามิเตอร์ตัวที่สี่เป็น “ignore” ซะ

เช่น จาก


PyObject *txt_cp874 =
    PyUnicode_Encode(s1, s1_len, "CP874", NULL);
tok =
    PyUnicode_Decode(buffer, tok_len, "CP874", NULL);

เป็น


PyObject *txt_cp874 =
    PyUnicode_Encode(s1, s1_len, "CP874", "ignore");
tok =
    PyUnicode_Decode(buffer, tok_len, "CP874", "ignore");

แล้ว sudo python setup.py install ใหม่อีกรอบ (อย่าลืมล้าง build เก่าทิ้งก่อน) ก็น่าจะใช้ได้แล้วครับ

ลิงก์ : Python Unicode How-to

technorati tags: 

MSDN blogs on Nat Lang and Search

ทีมวิจัยพัฒนาของไมโครซอฟท์ ที่ทำด้านภาษาธรรมชาติในโปรแกรมออฟฟิศ และเครื่องมือค้นหาระดับองค์กร

Microsoft Office Natural Language Team Blog
คุณสมบัติที่เกี่ยวข้องในชุดออฟฟิศ ก็จะเป็นพวก ตัดคำ ใส่ยัติภังค์ (hyphenation) ตรวจและแนะนำตัวสะกด ตรวจและแนะนำไวยากรณ์ แปลภาษาอัตโนมัติ ย่อความอัตโนมัติ ค้นหาคำ

Microsoft Enterprise Search Blog
จะเป็นพวกคุณสมบัติการค้นหา ในโปรแกรมฝั่งเซิร์ฟเวอร์ เช่น Search Server, Office SharePoint, Windows SharePoint, Exchange Server, SQL Server รวมไปถึงการทำงานร่วมกับโปรแกรมของบริษัทอื่นด้วย เช่น Lotus Notes
หรือการนำคอมโพเนนท์ที่เกี่ยวข้องของไมโครซอฟท์เอง มาให้บริการในสภาพการทำงานแบบองค์กร เช่น การนำเอา
Virtual Earth Interactive Maps มาใช้

ใครสนใจก็ตามอ่านกันได้ครับ บานเลย – -“

โพสต์ที่น่าสนใจ เช่น สร้างคลังข้อความจากเว็บ ด้วย Live Search API

technorati tags:
,
,
,
,

swath 0.3.4 Released

โปรแกรมตัดคำ swath ออกรุ่น 0.3.4 แล้ว

Swath 0.3.4 released. Swath (Smart Word Analysis for THai) is a word segmentation for Thai. Swath offers 3 algorithms: Longest Matching, Maximal Matching and Part-of-Speech Bigram. The program supports various file input format such as html, rtf, LaTeX as well as plain text.

Changes from 0.3.1 (the most recent version in Ubuntu repo is 0.3.1)

  • More secure temporary file handling.
  • Fix regression introduced during portability fix in 0.3.2. (Bug report by Pisut Tempatarachoke)
  • Fix bug that prevent ‘-u u,u’ from working. (Bug report by Neutron Soutmun)
  • Minor code and doc improvements.
  • Fix char signedness portability issues.
  • Improved messages and documentation.

Get the latest version from ftp://linux.thai.net/pub/thailinux/software/swath/

More info at http://linux.thai.net/node/117 (posted by thep)

(สะกด swath ยังไงครับ ? swath, Swath, SWATH ?)

technorati tags: , ,

Papers Written by Googlers

Research papers by people at Google

including ones by Peter Norvig, Dominic Widdows, Marius Pasca … and of course Sergey Brin and Lawrence Page themselves !

ผลงานวิจัยตีพิมพ์จากกูเกิล คนพวกนี้เขาขยันคิดอะไรกันออกมาทุกวัน ?

Peter Norvig นั่นเป็นเจ้าพ่อ AI เขียนหนังสือ Artificial Intelligence: A Modern Approach (ร่วมกับ Stuart Russell) น่าจะเป็นหนังสือ AI ที่ใช้ในชั้นเรียนมากที่สุด

Dominic Widdows เขียนหนังสือที่ผมชอบมากเล่มนึง คือ Geometry and Meaning เราจะแทน/วัด “ความหมาย” ด้วยเรขาคณิตได้ไหม ? เป็นหนังสือที่ให้ไอเดียอะไรใหม่ ๆ เยอะมาก ที่สำคัญคือ อ่านง่าย ตัวอย่างประกอบเยอะ รูปประกอบก็ทำดี

ส่วนใครสนใจเรื่อง open-domain question answering system และเรื่องที่เกี่ยวข้อง เช่นพวก named entity ก็ตามงานของ Marius Pasca นี่ไว้ เขาเขียนหนังสือด้านนี้ไว้เล่มนึงด้วย คือ Open-Domain Question Answering from Large Text Collections ผมไม่เคยอ่าน แต่หนังสือของ สำนักพิมพ์ CSLI ส่วนใหญ่จะไม่น่าผิดหวัง

… สองคนหลังนั่น ? ก็คนก่อตั้งกูเกิลไง … เขาเคยเป็นนักวิจัยมาก่อนนะ 😛

technorati tags:
,
,

The 3rd ADD Summer School

The 3rd Asian Applied Natural Language Processing for Linguistics Diversity and Language Resource Development (ADD 3) Lectures + Workshops
Feb 25 – Mar 3, 2008
@ Sirindhorn International Institute of Technology, Bangkadi Campus, Pathumthani, Thailand

ปีนี้เน้นเรื่องการประมวลผลภาพ (ข้อความ) และการประมวลผลเสียงพูด

พรุ่งนี้ว่าจะไปเข้าชั้นเรียน เรื่อง Semantic Web โดย อ.วิลาศ วูวงศ์

technorati tags: