ย้ายบล็อกไปที่ bact.cc แล้วนะครับ

พ.ร.บ.คอมพิวเตอร์
หยุด ร่างพ.ร.บ.คอมพิวเตอร์
พื้นที่เก็บข้อมูลออนไลน์ ฟรี 2GB จาก Dropbox (sync กับ Windows, Linux, Mac, iPhone, Android ฯลฯ ได้)
Showing posts with label Opendream. Show all posts
Showing posts with label Opendream. Show all posts

2009-12-23

Writerly Web: Writing as an Open Web Interface #drumbeat #openweb

เมื่อสองอาทิตย์ที่แล้ว เป็นทีม Opendream ไปเสนอไอเดียสั้น ๆ 5 นาที (ซึ่งทำได้ไม่ทันเวลา) ที่งาน Mozilla Drumbeat @ Neoteny Camp

(โพสต์ครั้งแรกที่ Opendream blog / twitter list @opendream/ers เปิดแล้ว)

technorati tags: , , , ,

2009-12-07

Web Character Simplification Chart 0.1 #opendream

ก่อนจะประมวลผลข้อความ เราจำเป็นต้องทำความสะอาดข้อความเสียหน่อย ทั่ว ๆ ไปที่จำเป็นต้องทำ ก็เช่น แปลง new line (\r\n หรือ \n), หรือแปลงให้อยู่ในชุดอักขระ (character set) ที่โปรแกรมใน processing pipeline จะทำงานได้ เช่นแปลง ä เป็น ae หรือแปลง “ ” เป็น " ", หรือการ normalize ลำดับอักขระ เช่น น.หนู+สระอำ+ไม้โท → น.หนู+ไม้โท+สระอำ, หรือไปถึงขั้นซับซ้อน อย่างแก้ตัวสะกด

(กรณีเป็นงานลักษณะจดหมายเหตุ หรือ archival ก็อาจจำเป็นต้องเก็บตัว raw text ก่อนแปลงเอาไว้ด้วย เพราะการแปลงอาจจะ(และมักจะ)เป็น lossy คือแปลงไปแล้วแปลงกลับมาได้ไม่เหมือนเดิม เช่นตัวอย่างข้างบน ที่แปลง “ ” เป็น " ")

การทำความสะอาดข้อความ หรือ text cleansing นี้ มีจุดประสงค์หลายอย่าง อย่างหนึ่งก็เพื่อเพิ่มความต้องตรงกัน (integrity) ภายในเนื้อข้อความ ซึ่งกรณีถ้าจะเอาข้อความนี้ไปประมวลผลทางสถิติ เช่นเอาไปฝึกเครื่อง (machine learning) ความต้องตรงกันภายในข้อความนี้ ก็มีผลต่อความแม่นยำของตัวแบบที่จะฝึกได้

จุดประสงค์อีกอย่างของการทำความสะอาดข้อความ ก็เพื่อลดความซับซ้อนของการประมวลผลด้วย ไม่ว่าจะเป็นการลดความซับซ้อนของตัวแบบ หรือการลดความซับซ้อนของเงื่อนไขในโปรแกรม เช่น ทำให้เขียน regular expression ได้สะดวกขึ้น

สำหรับแอปพลิเคชั่นการค้นหาและการทำดัชนี การทำความสะอาดข้อความ รวมไปถึงการทำให้ข้อความมันซับซ้อนน้อยลง (ไม่ว่าจะในทางลำดับอักษร ซึ่งจะมีผลต่อขนาดของ word set หรือการลดขนาดของ character set ด้วยการยุบตัวอักษรบางตัวเข้าด้วยกัน) จะช่วยให้ดัชนีมีขนาดเล็กลงด้วย และถ้าใช้ประกอบกับตารางการแทนอักษร/คำ (replacement table) ก็จะช่วยให้โอกาสการเจอคำที่ค้นหา มีมากขึ้น เนื่องจากลดผลกระทบจากการสะกดไม่ตรงกัน (spelling variations) (จริง ๆ จะใช้ replacement table อย่างเดียวก็ได้ แต่กรณีนั้น search space ก็จะใหญ่ขึ้น มีผลต่อประสิทธิภาพ)

ในตอนที่เขียน JavaScript สำหรับใช้กับ Roti ก็คิดไว้าว่าจะเจอปัญหาลักษณะนี้ ซึ่งจะมีผลต่อการคำนวณหาบล็อกโพสต์ที่ใกล้เคียง (ดูตัวอย่างได้ที่ท้ายโพสต์นี้ ตรงที่เขียนว่า 'roti thinks you may like these posts...') เลยให้จาวาสคริปต์ทำความสะอาดข้อความนิดหน่อย ก่อนจะส่งไปเซิร์ฟเวอร์

เนื่องจาก Roti ทำงานกับเอกสารเว็บ ซึ่งมี 'ปัญหา' อีกอย่าง คือการใช้ HTML/XML entities แทนตัวอักษร เช่นใช้ & เพื่อแทนอักษร & ดังนั้นก่อนจะทำอะไรกับข้อความ จึงควร decode entities พวกนี้ออกมาก่อน

กรณีของ HTML entities ถ้าใช้ PHP สามารถใช้ฟังก์ชั่น html_entity_decode($text) ได้เลย แต่ในจาวาสคริปต์มันไม่มี (หรือผมไม่รู้ว่ามันมี) ก็เลยใช้แทนที่สตริงแบบบ้าน ๆ ไป

ตารางข้างล่างปรับแก้มาจากตัวจาวาสคริปต์ roticlient.js และใส่รายละเอียดเพิ่มเติมนิดหน่อย ยินดีรับคำแนะนำครับ

possible replacements ในตารางนั้น เป็นเพียงคำแนะนำตั้งต้น การจะเลือกใช้อะไร ขึ้นอยู่กับแอปพลิเคชั่นด้วย เช่น ตัวเลือกที่เหมาะกับการเอาไปทำดัชนี ก็อาจจะไม่เหมือนกับตัวเลือกที่เหมาะกับการเอาไปแสดงผล เช่น zero-width space ถ้าทำดัชนี การแทนด้วย space น่าจะเหมาะ แต่ถ้าจะเอาไปแสดงผล การลบมันทิ้งไปเลย น่าจะเหมาะกว่า

Web Character Simplification Chart 0.1

Throw away extra semantics for a simpler text processing. This is only a suggestion. Apply to your needs accordingly.

Character NameCharacterUnicodeASCII range?HTML EntitiesPossible Replacements
Space  yes  
Non-breaking space U+00A0yes (space)
Zerowidth space U+200B  (space), <delete>
 
Soft hyphen U+00ADyes&shy;<delete>
 
Hyphen-Minus-U+002Dyes  
Hyphen-U+2010  - (hyphen-minus)
Minus signU+2212 &minus;-
Figure dashU+2012  -
En dashU+2013 &ndash;-, --
Em dashU+2014 &mdash;-, ---
Horizontal barU+2015  -
Armenian hyphen֊U+058A  -
Hebrew magaf־U+05BE  -
Mongolian todo hyphenU+1806  -
Japanese chōonpuU+30FC  -
 
Hyphen bulletU+2043  * (star), -, <delete>
Small bulletU+2022  *, -, <delete>
 
Tilde~U+007Eyes&tilde; 
Swung dash˜U+2053  ~ (tilde)
Wave dashU+301C  ~
Wavy dashU+3030  ~

ด้านล่างนี้ เป็นตัวอย่างโค้ดที่แทนที่ตัวอักษรต่าง ๆ จาก roticlient.js

return str.replace(/(&nbsp;|&#8208;|&#8210;|&ndash;|&#8211;|&mdash;|&#8212;|&#8213;|&#8275)/g, ' ') .replace(/(&shy;|&#xAD;|&#173;|&#x200B;|&#8203)/g,'') .replace(/[\u200b\u200d\u00ad]/g, '') .replace(/[!\?;:"'`“”^\*\+\-_\(\)\[\]\{\}#@&~\.,\\\/\|]/g, ' ') .replace(/\s+/g, ' ');

ติดตามการพัฒนา Roti ได้จาก Opendream's blog

(โพสต์นี้ให้ @pittaya เนื่องจากเคยถามเอาไว้เมื่อนานเมือกแล้ว)

technorati tags: , ,

2009-12-03

[12 Dec] Grails Meeting Day @ Opendream HQ

มนุษย์หุ่นยนต์ @roofimon แจ้งข่าวที่ Narisa.com:
Grails Meeting Day 1.0, มาคุยกันเรื่อง Grails

เสาร์ที่ 12 ธันวานี้ ที่รังรัก Opendream (แผนที่)
MRT สุทธิสาร + ต่อมอไซต์ บอกว่าไป อารียา แมนดารีนา (20 บาท)
โอเพ่นดรีมคือบ้านเลขที่ 299/92

12 Dec 2009 at Opendream
MRT Suttisarn + motobike taxi to Areeya Mandarina (20 baht)
Opendream office is house number 299/92

technorati tags: , ,

2009-06-02

on various things, digital this and information that

[ปรับปรุง 12:46: เพิ่ม Greenstone และลิงก์ libraryhub.in.th ขอบคุณ @markpeak]

[ปรับปรุง 2009.07.17: แก้ไขข้อมูลเกี่ยวกับระบบบรรณารักษ์ที่คลาดเคลื่อน ขอบคุณ อ.บุญเลิศ]

สี่ห้าวันที่ผ่านมา บุกตะลุยเก็บข้อมูลเกี่ยวกับห้องสมุดและระบบสารสนเทศดิจิทัลให้ :=3

ไม่ได้เน้นไปที่พวก Library 2.0 มากนัก อยากรู้เรื่องระบบข้างใต้เพิ่มเติมมากกว่า การประยุกต์ข้างบนคิดว่าพอเข้าใจไอเดียบ้างแล้วส่วนหนึ่ง (ลองดู นำเสนอโดย @iteau และ @projectlib เกี่ยวกับเรื่องนี้และ TCDC Resource Center - @iteau เขียนควันหลงนิดนึง) เดี๋ยวลองเอามาประกอบกัน

เว็บ DegreeTutor แนะนำโอเพ่นซอร์ส ILS (integrated library system) 3 ตัว ได้แก่ Koha, Evergreen ILS, และ VuFind ทุกตัวทำงานกับ OPAC (open public access catalog) ได้หมด :

  • Koha เป็น ILS ที่ติดตั้งง่าย มีหลายที่ในเมืองไทยใช้แล้ว เช่น ห้องสมุดดิจิทัลของ STKS (โชว์ในงาน LibCamp), ห้องสมุดวุฒิสภา, ม.อุบลก็กำลังเตรียมใช้, บล็อก STKS สวทช. เขียนถึงเยอะเหมือนกัน
  • Evergreen ILS เขาว่าเป็นระบบ fault-tolerance เลยทีเดียว มั่นใจได้
  • VuFind เป็น Library Resource Portal ที่มาครอบ ILS เพื่อขยายความสามารถของ OPAC ให้เป็น OPAC 2.0 [อ.บุญเลิศ] ยังอยู่ในช่วงพัฒนา (RC) อาจจะยังไม่เรียบร้อยนัก แต่มีความสามารถเยอะ ใช้ระบบค้นหาของ Apache Solr หายห่วง โครงการห้องสมุดดิจิทัลคิดดี กำลังเล็งว่าอาจจะเอามาเป็นหน้ากากครอบฐานข้อมูลย่อย ๆ ต่าง เพื่อให้ผู้ใช้ใช้งานง่ายขึ้น

เสริมจากความเห็นโดย อ.บุญเลิศ คือ ทั้ง Koha และ Evergreen นั้น เป็น ILS ที่มีความสามารถเทียบเท่ากับ ILS ที่ขายกัน ระดับ VTLS, InnoPAC/Millenium ILS, และ Horizon/SirsiDynix

ส่วน ILS รุ่นเล็กลงไป คือ OpenBiblio และ PHPMyLibrary

งานหลักอันนึงของห้องสมุดก็คือ การทำ catalog หนังสือ หรือป้อนข้อมูลหนังสือเข้าไปในระบบ เพื่อให้สืบค้นและยืมคืนได้ ซึ่งก็ใช้แรงงานไม่น้อย ถ้ามีเครื่องทุ่นแรงก็คงจะดี นึกไอเดียประมาณ CDDB หรือ freeDB.org ที่เราเสียบซีดีเพลงเข้าเครื่อง แล้วโปรแกรมเล่นเพลงก็จะไปค้นฐานข้อมูลที่คนอื่นเขาใส่ข้อมูลชื่อเพลงชื่อนักร้องไว้เราแล้ว เราไม่ต้องใส่เองหมด เว้นว่าหาไม่เจอ เราก็ใส่เข้าไปหน่อย แล้วคนอื่นจะได้ใช้ด้วย เอาแบบนั้น สำหรับเมตาดาต้าหนังสือ ก็จะได้ ‡biblios.net โครงการเพิ่งเริ่มได้ไม่นาน แต่ดูดีทีเดียว มาจาก LibLime ผู้ร่วมพัฒนา Koha

นอกจากสารสนเทศที่เป็นหนังสือเล่มแล้ว ก็ยังมีเอกสารที่ไม่ใช่หนังสือ ซึงตอนนี้ก็เป็นดิจิทัลได้จำนวนมากแล้ว วิธีหนึ่งที่นิยมและมีประสิทธิภาพก็คือ self-archiving คือเก็บของใครของมัน ใครผลิตคนนั้นก็เก็บ เป็น institutional repository แต่แชร์ข้อมูลค้นหากันได้ ระบบจัดเก็บสารสนเทศองค์กรที่เป็นโอเพ่นซอร์สและใช้โปรโตคอล OAI-PMH สำหรับแลกเปลี่ยนเมตาดาต้าเพื่อการค้นหา มีสองตัว :

  • DSpace เมืองไทยมีใช้หลายที่ เช่น คลังปัญญาจุฬาฯ โดย สถาบันวิทยบริการ จุฬาลงกรณ์มหาวิทยาลัย, ห้องสมุดดิจิทัลคิดดี โดย เอไอที, สำนักงานคณะกรรมการการศึกษาขั้นพื้นฐาน และ มศว., NSTDA Knowledge Repository (สวทช.) โดย ศูนย์บริการความรู้ทางวิทยาศาสตร์และเทคโนโลยี
  • EPrints เมืองไทยเท่าที่ทราบ ไม่มีใครใช้ ผมดูแล้วมันน่าจะลงง่ายกว่าแฮะ (จากประสบการณ์ส่วนตัว ระหว่าง UIMA กับ GATE พบว่า GATE ปวดหัวน้อยกว่า ผมเลยคิดว่า จะลอง EPrints ก่อนละกัน เหตุผลแถ ๆ :p)

@markpeak แนะนำอีกตัว (thx!) คือ Greenstone เท่าที่ค้น ๆ ดูคร่าว ๆ อันนี้ ไม่ได้เป็น institutional repository software เหมือนกับ DSpace หรือ EPrints เสียทีเดียว แต่เป็น digital library software (ดูจากบล็อกนี้ ผมเองก็ยังตอบไม่ได้ว่า แต่ละอย่างมันต่างกันชัด ๆ อย่างไร คิดว่ามันก็ทับ ๆ กันอยู่เยอะ แต่กรณีของ IR นี่ เรื่อง self-archiving น่าจะเป็นลักษณะสำคัญอันนึง) Greenstone นี่น่าสนใจมาก เขาบอกว่าสนับสนุนหลายภาษา มีภาษาไทยด้วย (ยังไม่ได้ค้นต่อว่าที่ว่า สนับสนุนภาษา เนี่ย แปลว่าอะไร) มี UNESCO หนุน โอเพ่นซอร์ส และสนับสนุนโปรโตคอล OAI-PMH ร่วมพัฒนาโดยมหาลัยที่สร้าง WEKA data mining workbench/toolkit ดูดีนะเนี่ย

open archives, collections, repositories, libraries พวกนี้ นอกจากจะเปิดให้ดูเฉย ๆ แล้ว ถ้าจะให้มีประโยชน์จริง ๆ มันก็ควรจะค้นหาได้แบบ programmable หน่อย หรืออย่างน้อยก็มีวิธีในการค้นหาเหมือน ๆ กันนิดนึง ผู้ใช้จะได้ไม่ต้องเรียนรู้เยอะ ก็เลยเป็นที่มาของมาตรฐานในการค้นหา รวมไปถึงการแลกเปลี่ยนเมตาดาต้าแบบอัตโนมัติด้วย

เอาง่ายที่สุด ก็น่าจะใช้ OpenSearch สืบค้นได้ (ถ้านึกไม่ออกว่า OpenSearch คืออะไร ตัวช่องค้นหาบนแถบเครื่องมือใน Internet Explorer 7+ และ Mozilla Firefox 3+ ต่างก็สืบค้นจากบริการที่เราระบุ ผ่าน OpenSearch ... อืม ยังไม่ชัด แต่ก็ดูใกล้ตัวหน่อยนึง) แล้วส่งผลลัพธ์ออกมาเป็น RSS/Atom รูปแบบข้อมูลยอดนิยม, ถ้ามี JSON ล่ะก็แจ๋ว ในแง่การเขียนโปรแกรมโดยเฉพาะฝั่ง browser-side

ชุดต่อมา มาจากกลุ่ม Open Archives Initiative มีตัวชูโรงคือ OAI-PMH ที่พูดถึงก่อนหน้านี้ เอาไว้แลกเปลี่ยนเมตาดาต้า :

สำหรับการสืบค้นสารสนเทศ ดูมาตรฐาน Z39.50 (ISO 23950: Information Retrieval (Z39.50): Application Service Definition and Protocol Specification) และ SRU (Search/Retrieve via URL) คู่กับ CQL (Contextual Query Language). ‡biblios.net ที่พูดถึงก่อนหน้านี้ รองรับ SRU/CQL ด้วย

ข้อกำหนดเมตาดาต้าที่ได้รับนิยมนำไปปรับใช้มากที่สุดในเว็บนั้น คือ Dublin Core Metadata Initiative (DMCI) ซึ่งคนที่ใช้งานเอกสาร XML ต่าง ๆ อาจจะพอคุ้นเคย ใน namespace dc: ซึ่งถูกนำไปใช้กับรูปแบบเอกสาร XML หลายชนิด OAI เองก็ใช้ Dublin Core

ความเห็นเพิ่มเติมจาก อ.บุญเลิศ ขณะนี้ DCMI ก็ยอมรับแล้วว่า DC ไม่ใช่มาตรฐานเดียวที่ใช้ได้ มีการทำ Cross กับเมทาดาทาอื่นแล้ว ลองหาอ่านได้จาก DC conference ต่างๆ ได้ครับ

สำหรับรูปแบบข้อมูลผลลัพธ์จากการสืบค้นสารสนเทศอื่น ๆ ก็เช่น MARCXML ซึ่งพัฒนาต่อมาจากปู่ MARC มีช่องข้อมูลมากมาย เรียกได้ว่าครบถ้วน แต่ก็ซับซ้อนปวดหัว, ต่อมาจึงมี Metadata Object Description Schema (MODS) ซึ่งอยู่ระหว่างกลาง MARC กับ Dublin Core (ซึ่งมีช่องข้อมูลน้อยมาก ๆ ประมาณว่าใช้ได้กับงานอย่าง RSS Feed จะให้ใช้กับห้องสมุดก็ขาดตกไปหลายอย่าง) เรียกว่า MODS มีช่องข้อมูลที่จำเป็นต้องใช้บ่อย ๆ ในงานห้องสมุด ในขณะเดียวกันก็ไม่ซับซ้อนจนเกินไป, Metadata Authority Description Schema (MADS) เป็นมาตรฐานที่ออกมาใช้คู่กับ MODS

acronyms ที่พ่นออกมามากมายข้างบน เกินครึ่งกำหนดโดยห้องสมุดรัฐสภาสหรัฐ (Library of Congress) ที่เหลือก็โดยห้องสมุดของมหาวิทยาลัยหรือศูนย์วิจัยต่าง ๆ

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

  • oss4lib - Open Source Systems for Libraries
  • code4lib - coders for libraries, libraries for coders กลุ่มเป้าหมายจะเน้นนักพัฒนามากกว่า oss4lib
  • บล็อก STKS - ภาษาไทย มีเรื่องการจัดการความรู้ เรื่องห้องสมุดดิจิทัลอยู่เรื่อย ๆ โดยเฉพาะซอฟต์แวร์ที่เป็นโอเพ่นซอร์ส
  • LibraryHub - โดย @projectlib เรื่องห้องสมุดในแง่มุมต่าง ๆ (ไม่ได้เน้นเฉพาะเรื่องซอฟต์แวร์)

นอกจากเรื่อง digital repositories แล้วถ้ามีเรื่องการอนุรักษ์ preservation, digitization ควรดู TEI ไว้ด้วย Text Encoding Initiative เป็นชุดข้อแนะนำในการบันทึกข้อความมาอยู่ในระบบดิจิทัล พร้อม ๆ กับคำแนะนำในการบันทึกคำอธิบายข้อมูลต่าง ๆ (annotation) ด้วย การทำ archiving, preservation ในลักษณะนี้ ถือเป็นคีย์สำคัญสำหรับ สาขา ที่เรียกว่า digital humanities (มนุษยศาสตร์ดิจิทัล) ซึ่งส่วนหนึ่งเป็นการใช้เครื่องมือดิจิทัลศึกษาเอกสาร (และบันทึกผลการวิเคราะห์ไปเป็น annotation อีกชั้น layer นึงบนเอกสาร)

เอ้อ ถ้าอยากทำ OCR มีทูลคิตโอเพ่นซอร์สชื่อ OCRopus ลองแล้ว ใช้ได้เลย มันเชื่อมชิ้นส่วนที่จำเป็นในงาน OCR เข้าด้วยกัน ทั้งส่วนแปลงไฟล์ฟอร์แมต หมุนรูป ทำ layout analysis ทำตัวแบบภาษา และการแปลงภาพเป็นตัวอักษร ตัว engine ที่ใช้แปลงภาพเป็นตัวอักษร ตอนนี้ใช้ tesseract อยู่ โอเพ่นซอร์สเช่นกัน ทั้งหมดนี้เขียนด้วย C แต่มี Python binding ถ้าต้องการ ชุด OCRopus และ tesseract นี้มี Google สนับสนุนการวิจัยและพัฒนา คาดว่าน่าจะเป็นตัวเดียวกับที่ใช้เป็นส่วนหนึ่งของระบบ Google Book Search ผมลองคอมไพล์แล้วรันเล่นดู เจ๋งดี ถ้าใช้ tesseract เฉย ๆ ผลลัพธ์จะเป็น plain text แต่ถ้าใช้ OCRopus tool chain มันได้มาเป็น HTML เลย (hOCR microformat) ซึ่งแปลว่าเราจะได้ layout และ style มาด้วย ตัวหนา ตัวเอียง มาหมด

แสกนเข้ามาแล้ว มันก็ต้องมีที่ผิดบ้างแหละ มากน้อยแล้วแต่ จะช่วยกันแก้ไขได้ยังไง ? ลองดูตัวแบบจากโครงการ Distribute Proofreaders (DP) (แนะนำโดย @thai101 ขอบคุณมาก ๆ ครับ) ซึ่งเป็นการเปิดให้อาสาสมัครบนอินเทอร์เน็ตมาช่วยกันพิสูจน์อักษร แก้ตัวสะกดผิด โดยโครงการนี้เจาะจงไปที่การแสกนหนังสือที่ไม่มีหรือพ้นการคุ้มครองลิขสิทธิ์ไปแล้ว (เป็นสมบัติสาธารณะหรืออยู่ใน Public Domain) พิสูจน์อักษร แล้วก็ส่งต่อหนังสือที่เสร็จสมบูรณ์แล้ว ให้กับ Project Gutenberg ต่อไป ตัวแบบของ DP นี้อาจจะเอามาปรับใช้กับโครงการอื่น ๆ ก็ได้

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

งงกันมาพอสมควรแล้ว โพสต์นี้ไม่ได้ช่วยให้ใครเข้าใจอะไรขึ้นมาได้แน่ ผมเองก็ไม่เข้าใจ แต่มันพอจะทำให้เห็นความเชื่อมโยง อย่างน้อยก็ของตัวย่อมหาศาลที่จะบุกรุกเข้ามาในชีวิตคุณ ถ้าอยากจะเข้าไปสนุกในสนามห้องสมุดิจิทัล โปรดสังเกตว่าผมใช้คำว่า เข้าไป ไม่ใช่ เข้ามา เพราะผมเองก็ยังไม่ได้อยู่ในสนามนั้น :p ถ้าพัฒนาโปรแกรมอินเทอร์เน็ตได้ สนใจงานพวกนี้ อาจจะเฉี่ยวไปเฉี่ยวมาหน่อย ลองดู Jobs @Opendream

ถ้าอยากอ่านอีก โดดไป ProjectLib LibraryHub เลย หรือแจม LibCamp (ภาพงาน) ที่เดี๋ยวจะมีอีก ผมไม่รับผิดชอบแล้ว! มึน!

อยากมึนหนัก? เผ่นไปบล็อก iTeau โลด จริง ๆ ก็อาจจะไม่มึนนะ เขาเขียนอธิบายดีน่ะ ยกจอก :)

follow @projectlib @iteau @markpeak @kengggg และ @klaikong

อยากมีร้านสำหรับนั่งอ่านหนังสือ

technorati tags: , , , , , , ,

2009-04-28

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: , , ,

2009-04-24

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: , , ,