News classification #2: รู้จักกับ Word embedding และ Word2Vec
Text classification with Word embedding and Word2Vec
มาต่อกันกับตอนที่ 2 หลังจากที่ตอนก่อนหน้า ได้ทำความรู้จักกับ Deep learning ประเภท NLP กันแล้ว พร้อมทั้งเตรียม Dataset เกี่ยวกับหัวข้อข่าว เพื่อที่เตรียมทำ News classification model สามารถอ่านย้อนหลังได้ตาม Link ด้านล่าง
Word embedding and Word2Vec
ที่ต้องยกเรื่องนี้ขึ้นมาพูดก่อน เพราะวันนี้ต้องการใช้ทั้ง 2 เทคนิคนี้ ในการพัฒนาโมเดล ดังนั้นจึงควรทำความรู้จักก่อนว่าคืออะไร
Word embedding ความหมายอย่างง่ายที่สุดคือ การแปลงคำเป็นตัวเลข โดยที่ผลลัพธ์ที่ได้จะออกมาในรูปแบบของ Vector หมายความว่า คำหนึ่งคำสามารถแทนค่าได้ตัวเลขชุดนี้ ซึ่งวิธีการนี้แตกต่างและถือเป็นข้อดี (หรือเปล่า?) เมื่อเทียบกับการทำ Vector ประเภท TF-IDF เนื่องจากการทำ TF-IDF คำจะถูกแปลงเป็น Vector ที่แทนด้วยความถี่ ดังนั้นจึงเกิด Sparse matrix (Matrix ที่ประกอบไปด้วยเลข 0 จำนวนมาก) ได้ง่ายเวลานำไปใช้งาน Word embedding จึงสามารถมาทดแทนช่องว่างตรงนี้ได้ ซึ่งรายละเอียดเกี่ยวกับ TF-IDF ข้อติดไว้ก่อน ถ้ามีโอกาสไว้มาเขียนให้อ่านอีกที

Word2Vec คือการสร้างโมเดลจาก Word embedding โดยการนำ Word embedding หลาย ๆ ชั้นมาสร้างเป็นโมเดล ซึ่งทำการ Training โดยการคำนวณตัวเลขจากบริเวณใกล้เคียง (Context หรือ Corpus) หมายความว่าการคำนวณเลขออกมาได้ ต้องอาศัยบริบทรอบ ๆ พิจารณาประกอบ ซึ่งโมเดลประเภทนี้สามารถ Train เก็บไว้ใช้เองส่วนตัวได้ ถ้ามีโอกาสเดี๋ยวมาลอง Train โมเดลขึ้นมาเอง เพื่อดูลักษณะการทำงาน แต่วันนี้ขอใช้โมเดลที่เทรนเสร็จแล้ว เพื่อความง่ายและแม่นยำ

Model

อย่างที่บอกไปว่าวันนี้ไม่ได้ทำ Word2Vec model เอง แต่ไปหยิบโมเดลที่ทำเสร็จแล้ว เพื่อนำมาทำ Classification model ต่อไป ซึ่ง Word2Vec model มีหลากหลายมาก สามารถเลือกใช้ให้เหมาะกับประเภทงานที่ต้องการทำได้เลย
โจทย์ในวันนี้คือการสร้างโมเดลแยกประเภทข่าว โดยที่ Input เป็นเนื้อหาข่าว อาจเป็น Full article หรือแค่ Summary แล้วให้โมเดลวิเคราะห์ว่าเนื้อหาที่ Input เข้าไป ควรถูกจัดให้อยู่ในประเภทไหน เพื่อให้เกิดความแม่นยำและสมเหตุสมผลมากที่สุด จึงควรเลือกโมเดลที่ Train ขึ้นมาจากข้อมูลที่เป็นข่าว โดยที่เราสามารถหาโมเดลได้จากลิงค์ด้านล่าง
ขอเลือกโมเดล word2vec-google-news-300 เพราะ Train ขึ้นมาด้วยข่าวจำนวนมาก แต่ดูเหมือนว่าจะเยอะเกินความจำเป็นสำหรับแบบฝึกหัดไปเสียหน่อย เพราะโมเดลมีขนาดค่อนข้างใหญ่ ประกอบไปด้วย 100 Billion คำ เลยขอใช้เป็นโมเดลจาก Google เหมือนเดิม แต่เป็นเวอร์ชั่น Slim แทน โดยโมเดลประกอบไปด้วยคำจำนวน 3 แสนคำเท่านั้น แต่เพียงพอแล้วสำหรับแบบฝึกหัดนี้
สามารถโหลดโมเดลมาไว้เพื่อรอการทำ Process ต่อไป
Code
แม้ว่าเลือกโมเดลที่มีขนาดเล็กแล้ว แต่จำนวนคำก็ยังเยอะไปอยู่ดี ดังนั้นขอทำการสกัดคำออกมาจากโมเดล โดยที่เลือกทั้งหมด 8 หมื่นคำ (ตรงนี้สามารถเพิ่มหรือลดลงได้ตามความเหมาะสม) โดยเริ่มจากการสร้าง list
ของ Vector คำศัพท์ทั้งหมดที่อยู่ในโมเดล ซึ่งสามารถใช้ .vocab.keys()
เพื่อดังค่าทั้งหมดออกมาเก็บไว้ใน list
จากนั้นทำการวนลูป เพื่อดึงคำศัพท์ออกมาทีละคำเก็บไว้เป็น Array ผลลัพธ์สุดท้ายจากในตัวแปร V
คือ Vector ของคำศัพท์ทั้งหมด 8 หมื่นคำ โดยแต่ละคำแทนด้วยตัวเลขทั้งหมด 300 ตัวเลข (80000, 300)
word processing... 0
word processing... 5000
word processing... 10000
word processing... 15000
word processing... 20000
word processing... 25000
word processing... 30000
word processing... 35000
word processing... 40000
word processing... 45000
word processing... 50000
word processing... 55000
word processing... 60000
word processing... 65000
word processing... 70000
word processing... 75000
word processing... 80000
80000
(80000, 300)
ต่อมาเป็นการจัดการกับ Dataset ก่อนเริ่ม Training model ขอ Recap จากตอนก่อนหน้านี้ ที่มีเรื่องติดเอาไว้หนึ่งเรื่องคือ การโหลด NLTK มาไว้ตั้งแต่ตอนแรก แบบไม่มีเหตุผล ซึ่งต้องนำมาใช้ในส่วนนี้ ข้อมูลที่โหลดมาคือ “คลัง” คำศัพท์และสัญลักษณ์ จริง ๆ แล้วขั้นตอนนี้เปรียบเหมือนการทำ Cleansing data ให้กับข้อมูลที่เป็น Text โดยโมเดลไม่ต้องการพิจารณา Text ที่เป็นสัญลักษณ์ และ Text ที่เป็น Stop words และใน NLTK ได้มีการเก็บข้อมูลประเภทนี้ไว้
Stop word หมายถึงคำที่พบเจอบ่อย ๆ แต่ไม่มีผลต่อรูปหรือความหมายของประโยค เช่น a, an, the, also, just, quite, unless, etc. ซึ่งคำเหล่านี้ไม่ควรถูกนำมาพัฒนาโมเดล เพราะอาจเกิด Bias ขึ้นได้ ดังนั้นจึงควรทำการลบออกจาก Input data เช่นเดียวกันกับ Text ที่เป็นสัญลักษณ์ เช่น !, ., “”, ,, etc. ควรทำการลบออกก่อนเริ่ม Train model เช่นกัน
เริ่มต้นด้วยการ set
ว่าคำไหนเป็น Stop word บ้าง โดยสามารถใช้งาน Dataset ที่โหลดมาจาก NLTK ได้โดยตรง ซึ่งข้อมูลสำหรับโมเดลนี้เป็นภาษาอังกฤษ สามารถใช้ stopwords.words(‘english’)
และใส่ set()
ไว้ข้างหน้าเพื่อให้ Word ทั้งหมดเป็น Unique
เขียนเป็นฟังก์ชั่นเพื่อใช้งาน โดยตั้งใจให้รับข้อมูลเป็น Pandas series ที่เก็บ String เรียงเป็นบรรทัด จากนั้นสร้าง list
ว่างเพื่อไว้เก็บค่าที่ได้จากการวนลูป ผ่าน Pandas series เข้าสู่ word_tokenize()
และให้ตัวแปร heading
มารับ เพื่อทำการตัดคำ โดยการทำงานของการตัดคำหรือ Tokenizer มีการทำงานเหมือน ๆ กันแทบทุกภาษาคือรับ Input เข้าเป็น String และ Output ออกมาเป็น List of string หรือ List ที่ประกอบไปด้วยคำในประโยคนั้น ๆ

เมื่อได้ heading
ที่เป็น List ของคำศัพท์แล้ว ต่อไปเป็นการลบ Stop word และ Syntax ออกจาก List

ต่อมาเป็นการเก็บค่า Index ของ heading
จาก Word vector ที่สร้างเอาไว้ด้านบน (8 หมื่นคำ) โดยทำการวนลูปใน heading
เพื่อดูว่าคำศัพท์แต่ละคำมีอยู่ในตัวแปร V
ที่สร้างเอาไว้แล้วหรือไม่ ถ้ามีให้เก็บค่า Index ของคำนั้น ๆ ไว้เป็น Array เพื่อนำไปใช้ปรับค่า Weight ในชั้น Embedding layer ใน Neural network ต่อไป
มาถึงตรงนี้ Material ในการทำโมเดล “เกือบ” พร้อมทั้งหมดแล้ว แต่ยังขาดสิ่งจำเป็นอยู่นิดหน่อย ซึ่งเป็นการทำ Zero padding และการออกแบบ LSTM ให้สามารถปรับ Weight ในชั้น Embedding layer ได้
ไม่คิดเหมือนกันว่าต้องเขียนยาวถึง 3 ตอน แต่เพื่อความเข้าใจง่าย และเพื่อไม่ให้เนื้อหาตอนนี้ยาวจนเกินไป ขอย้าย Details ทั้งสองไปไว้ตอนหน้า หวังว่าโมเดลจะเสร็จที่ตอนต่อไป