แยกภาพจากโทนสีด้วย Time Series Mining

ผมมีโอกาสได้เรียนวิชา Time Series Mining and Knowledge Discovery ซึ่งอันที่จริงก็คือ Data Mining มัน Domain ของข้อมูลอีกแบบนึงที่เรียกว่า “Time Series”

สิ่งที่เรียกว่า Time Series เราก็อาจจะเรียกว่า ข้อมูลที่เราพลอตได้คล้าย ๆ กราฟ X-Y ซึ่งมีแกน X เป็น “เวลา” และแกน Y เป็นค่าอื่น คุณสมบัติที่เรารู้ตอนนี้ของ Time Series ก็คือ เนื่องจากเวลามีความสำคัญเชิงลำดับ นั่นคือมีความสำคัญบอกว่าใครมาก่อนมาหลังและจะสลับกันไม่ได้ คุณสมบัตินี้สำคัญมาก เพราะว่า Algorithm ต่าง ๆ ในวิชานี้จะมี assumption นี้เสมอในชุดข้อมูล

และเนื่องจากอาจารย์ต้องการให้ทำ mid-term project โจทย์ก็คือ “หาวิธีแปลงข้อมูลที่ไม่ใช่ Time Series มาเป็น Time Series ที” ผมกับเพื่อนอีกคน ก็ต้องพยายามลองเอาความรู้และ background ที่มีมาสร้างเป็น project ทาง Time Series mining ดูบ้าง

ซึ่งสุดท้ายแล้วเราเลือกว่าหาวิธีแปลง รูปภาพเป็น Time Series เพื่อเอาไปแจกแจงว่าภาพนี้มีสีโทนอะไร ?

ตัวอย่าง Application ที่มีใช้จริงในชีวิตประจำวันก็เช่น

ภาพจาก google.com เวลาที่เราต้องการค้นหาภาพจากโทนสีของมัน

คำถามที่เราถามกับตัวเองก็คือ หากต้องการทำแบบนี้บ้างต้องทำไง ?

คำตอบก็คือ ไม่น่ายาก ถ้าเราทำเป็น Time Series ได้ แล้วเราก็น่าจะ cluster หรือ classify ต่อไปได้ไม่ยาก เพียงแต่ว่าเราต้องแปลงภาพเป็น Time Series ที่ make sense กล่าวคือ มันต้องเป็น Time Series ที่แสดงออกถึงคุณสมบัติที่เราต้องการใช้สำหรับแต่ละรูปที่มันถูกแปลงมา

วิธีการแปลง

  1. เรามีรูป
  2. แปลงรูปนั้นเป็น bitmap นั่นก็คือ array 2 มิติของ pixels ต่าง ๆ ในรูปภาพ (แต่ละช่องของ pixel จะประกอบไปด้วย 3 ข้อมูล ก็คือ RGB)
  3. แปลง bitmap นั้นให้เป็น bitmap ของ HSV (โดยทั่วไปมีคำสั่งเราไม่ต้องเขียนเอง)
  4. เราจะหยิบเฉพาะค่า hue (เฉดสี) ของแต่ละช่องของ array เท่านั้น
ทำไมต้อง HSV ?
ปกตินั้นภาพต่าง ๆ จะอยู่ใน color space RGB ซึ่งจะแสดงเป็นค่าของความเข้มแสงสีต่าง ๆ แต่ว่าเราไม่ต้องค่าความเข้มของแสงสีจริง ๆ เราต้องการว่า หลังจากมันผสมกันแล้วมันได้สีอะไร และอีกอย่างเราไม่ต้องการด้วยว่ามันสว่างขนาดไหน เราต้องการว่าหากมันอยู่ภายใต้สภาพแสงเดียวกันแล้วมันน่าจะมีสีอะไร นั่นก็คือค่า hue ใน color space HSV นั่นเอง

5. ตอนี้เราได้ค่า hue แล้ว เราเตรียมถังสีไว้ 256 ถังสี

6. เราจะนำค่า hue ของแต่ละ pixel มาโยนใส่ถังสีที่มันใกล้เคียงที่สุด เนื่องจากเรามีเพียง 256 ถัง แน่นอนว่าบางสีมันอาจจะไม่มีถังของตัวเองเป๊ะ ๆ

เราโยน pixel แต่ละอันลงในแต่ละถังสีที่ตรง (ใกล้เคียง) กับสีของตัวเอง ทำเช่นนี้กับทุก ๆ pixel ในรูปภาพ

7. หลังจากทุก ๆ pixel ถูกโยนเข้าไปในถังสีแล้ว เราต้อง Normalize เพราะเราต้องไม่ลืมว่าแต่ละภาพมันมีจำนวน pixel ไม่เท่ากัน แปลว่าสำหรับแต่ละภาพจะมีชุดถังสีที่มีของอยู่ในนั้นไม่เท่ากัน เราต้องทำให้เท่ากันด้วยการปรับให้มันมีผลรวมของในถังสีเท่ากับ 1 สำหรับ ๆ ทุกๆ ภาพ

8. เอาถังสีมาต่อ ๆ กันแล้วเราก็จะได้ histogram ซึ่งใช้แทนภาพนี้ในการแยกแยะโทนสีของภาพได้แล้ว !

ถึงตรงนี้เราจะได้วิธีในการแปลง แต่เราขาดสิ่งที่สำคัญกว่านั้น “มันดีจริง ๆ หรือ?” โดยผมจะแสดงให้ดูด้วยการลอง classify จริง ๆ ให้ดูว่ามันทำงานได้จริง ๆ และแม่นทีเดียว !

สมมติว่าเรามีชุดข้อมูล 2 ชุด คือ สำหรับฝึกฝนตัวแบ่งแยกเรา (Training data) และสำหรับการทดสอบ (Testing data)

โดยเราจะใช้ตัวแบ่งแยกที่เรียกว่า kNN (k-nearest neighbors) และแน่นอนว่า kNN ต้องใช้ distance measure ซึ่งเราจะใช้ Euclidean distance ในที่นี้

ทำไมต้อง Euclidean distance ?
ในทาง Time Series เรามีอีก (หลาย) วิธีในการวัดระยะทาง ยกตัวอย่างเช่น DTW (Dynamic time warpping) ซึ่งจะมีความสามารถในการวัดความต่างที่ค่อนข้างยืดหยุ่นกว่า คือข้อมูลไม่จำเป็นต้องตรงกันเป๊ะ ๆ ก็จะบอกได้ว่ามันเหมือน ๆ กัน
แต่มันใช้ไม่ได้สำหรับกรณีนี้ เราไม่ต้องการให้มัน warp เหมือน DTW เพราะค่าว่าทางแกน X คือค่าเฉดสีและเราไม่ต้องจับคู่สีที่ไม่เหมือนกันไว้ด้วยกัน อีกอย่างหนึ่งหากค่าเฉดสีต่างกันไม่มาก Euclidean distance ก็จะบอกว่ามันไม่ต่างกันมากอย่างที่เราต้องการอยู่ดี

ผลลัพธ์เราได้ดังนี้ (ภาพด้านล่าง) จาก 150 samples ใน training data และ 25 samples ใน testing dataโดยไม่มีภาพซ้ำกันเลย 1-NN หรือ 1-nearest neighbor เดาได้ถูกต้อง 100% ซึ่งน่าพอใจมากทีเดียว :D

สุดท้ายนี้สำหรับใครที่ต้องการดูตัวอย่างโค้ดที่ใช้ในการทดสอบจริง ๆ เข้าไปชมที่ github repo ได้นะ