สร้าง มุกเสี่ยว โดยใช้ Python และ Deep Learning (Text Generation)
Introduction
Text Generation เป็นหนึ่งในงาน NLP ที่ใช้ในการสร้างประโยคใหม่ขึ้น จากชุดข้อมูลที่ถูกส่งไปให้โมเดลทำการเรียนรู้ โดยวันนี้เราจะสอนสร้างโมเดลอย่างง่ายโดยใช้ Python และ Tensorflow โดยบทความนี้จะพยายามเขียนให้เข้าใจได้ง่าย ลงรายละเอียดเท่าที่จำเป็น ถ้าใครสนใจในรายละเอียด ผมจะพยายามแนบลิ้งค์ไว้เพื่อให้เข้าไปอ่านทำความเข้าใจต่อได้
ข้อดีอย่างหนึ่งของงาน Text Generation นี้ก็คือ เราไม่จำเป็นต้องมีเฉลยเหมือน NLP tasks อื่นๆเช่น sentiment analysis ที่จำเป็นต้องมีเฉลยอย่าง positive, negative ซึ่งจำเป็นต้องใช้แรงคนในการทำเฉลย แต่เราสามารถใช้คำในประโยคตัวเองเป็นเฉลยได้เลย เช่น ประโยคว่า “ฉันกินข้าว” สามารถปิดคำถัดๆ ไปเพื่อเก็บไว้เป็นเฉลยได้ คือ “ฉันกิน” และเฉลยคือ “ข้าว”
ข้อมูลที่ใช้ในการทำโมเดล
เอามาจาก 2 แหล่งคือ
- 100 แคปชั่นเสี่ยว กวนๆ 2021–2022 มุกเสี่ยว ตลก ฮาๆ เอาไว้จีบหนุ่มจีบสาว
- คัดมาเน้นๆ 200 แคปชั่นอ่อย แคปชั่นโสด 2021–2022 รูปคู่ไม่มีโพสต์แบบนี้ก็ได้!
ที่เป็นภาษาไทยทั้งหมด โดยตัด punctuation เช่น “!”, “?”, “.” และ emoji ออกแล้ว โดยเก็บอยู่ในรูปของไฟล์ .txt

การตัดคำ
เนื่องจากงานนี้เราต้องการให้โมเดลคิดคำใหม่ออกมา สิ่งสำคัญอย่างแรกเลยคือ เราต้องแปลงประโยคของเราให้กลายเป็นคำก่อน ซึ่งการแบ่งคำในภาษาไทยไม่เหมือนกับภาษาอังกฤษ ที่สามารถแบ่งคำได้จากการเว้นวรรคได้เลย เช่น
“I need coffee” แบ่งคำได้เป็น “I”, “need”, “coffee” โดยใช้ spacebar ในการแบ่งคำออกมา
แต่ในภาษาไทย “ฉันต้องการกาแฟ” จะไม่ใช้ spacebar ในการแบ่งคำ ทำให้เป็นปัญหาอย่างหนึ่ง ซึ่งในบทความนี้จะใช้ตัวตัดคำภาษาไทยของ PyThaiNLP ในการตัดคำ

โมเดลที่ใช้
เนื่องจากงานนี้เป็น sequential data ที่การใช้คำและลำดับของคำมีผลกับการ predict ของโมเดล ทำให้เราเขียนกฎในการ generate คำได้ยาก ทำให้ต้องใช้ Deep learning เข้ามาช่วยในการทำนายคำ
เป็นการแปลงคำให้กลายเป็นตัวเลข เนื่องจากโมเดลไม่สามารถเข้าใจความหมายของคำได้ เราเลยต้องช่วยแปลงให้อยู่ในรูปแบบของ vector เพื่อให้โมเดลเข้าใจความหมายของคำมากขึ้น และลดขนาด features ในการคำนวนลง
- LSTM (Long Short-Term Memory)
LSTM มักใช้กับข้อมูลที่มีลักษณะเป็น sequence ซึ่งงาน text generation ก็ถือเป็น sequence อย่างหนึ่ง อธิบายคร่าวๆ ก็คือ ปกติเราอ่านหนังสือจากซ้ายไปขวา แล้วเราจะสามารถจำเนื้อหาก่อนหน้านี้ได้ด้วย ว่าใครทำอะไร ถ้าเราอ่านผ่านมันมาก่อน ซึ่ง LSTM จะทำตัวคล้ายๆ กันคือจำคำก่อนหน้านี้ได้ด้วย ซึ่งทั้งหมดทำได้ด้วยการคิดผ่านสมการตัวหนึ่ง ที่เราจะไม่พูดถึงในบทความนี้ ถ้าหากอยากอ่านเรื่อง LSTM ต่อ สามารถอ่านต่อได้ที่บทความนี้ครับ link (ผมไม่ได้เป็นคนเขียนนะ)
- Dropout
เป็นเทคนิคหนึ่งที่ใช้ลดการ overfit ของโมเดล เนื่องจากข้อมูลเรามีปริมาณน้อย เป็นไปได้ที่โมเดลจะตอบประโยคเดิมๆ จากในข้อมูลที่เราส่งไปให้มันเรียนรู้ ซึ่งเป็นสิ่งที่เราไม่ต้องการ เราต้องการประโยคใหม่ๆ การใช้ dropout จึงเข้ามาช่วยแก้ปัญหานี้ได้ในระดับหนึ่ง

หลังจากเตรียมข้อมูลและโมเดลเรียบร้อย เราจะเริ่ม train โมเดลเราของกันโดยผมกำหนดให้โมเดลเรียน 100 รอบ ใช้เวลาประมาณ 10 นาที บน Google Colab โดยใช้ GPU ครับ

ทดสอบโมเดล
ส่วนสุดท้ายคือการพิมพ์คำแรกเพื่อให้โมเดลทายคำต่อไปออกมาเรื่อยๆ จนกว่าจะเจอคำว่า END ที่เป็นสัญญาณบอกว่าจบประโยค แต่ในการทำนายคำเราจะต้องมีการ process นิดหน่อย เนื่องจากโมเดลของเราทำนายคำออกมาตามความน่าจะเป็น ถ้าเราเลือกหยิบคำที่มีความน่าจะเป็นสูงที่สุดมาใช้เป็นคำต่อไป อาจจะเกิดเหตุการที่โมเดลเลือกคำเดิมออกมาใช้เรื่อยๆ ไม่มีวันจบ หรือโมเดลพูดแค่ประโยคเดิมๆ ทำให้ไม่เกิดความหลากหลายของประโยค
เราเลยเลือกสุ่มคำออกมา แต่สุ่มตามความน่าจะเป็นด้วย คำไหนที่โอกาสออกเยอะ ก็จะสุ่มโดนง่ายขึ้น การใช้วิธีนี้จะช่วยแก้ปัญหาการ generate ประโยคซ้ำๆ ออกมา

จากตัวอย่างจะเห็นว่าโมเดลของเราค่อนไปทาง overfit กับประโยคที่เคยรู้จักใน training set ถ้าเจอประโยคแปลกๆ ประโยคก็จะเอ๋อๆ หน่อย เช่น

แนวทางในการพัฒนาโมเดลเพิ่มเติม
เนื่องจากโมเดลนี้เป็นโมเดลแบบที่ไม่ซับซ้อนมาก ใช้เวลาในการ train ไม่นานและข้อมูลก็มีน้อยมากๆ ทำให้คำที่ได้มีจำกัด ขาดความหลากหลายในการใช้ภาษาซึ่งมีช่องว่างให้พัฒนาเพิ่มได้
โดยสิ่งน่าจะเพิ่มเพื่อให้โมเดลเรียนรู้ได้ดีขึ้นคือ
- เพิ่มจำนวนประโยคสำหรับการ training
- เพิ่ม Pre-trained Language Model ให้โมเดลรู้จักคำมากขึ้น
จบแล้วครับ สำหรับโมเดลในการสร้างมุกเสี่ยว หวังว่าบทความนี้จะมีประโยชน์และช่วยเป็นแนวทางในการพัฒนาโมเดล NLP เบื้องต้น สามารถชี้แนะหรือติชมได้ตามอัธยาศัยเลยครับ ขอบคุณครับ
github: link
Colab for training: link
Colab for generate sentence: link