Notes: Part Of Speech and Co-Occurrence Analysis (Thai)

Part Of Speech and Co Occurrence Analysis

บทเรียนนี้สรุปแนวคิดหลักเกี่ยวกับส่วนของคำ (Part Of Speech, POS) และการวิเคราะห์การเกิดร่วมกันของคำ (Co-occurrence) พร้อมการประยุกต์ใช้งานในงานประมวลผลข้อความ เน้นการทำความเข้าใจถึงการแปลงข้อความเป็นเวกเตอร์ การทำ Tokenization และการสร้างฟีเจอร์ต่างๆ ตั้งแต่การ Stemming, Lemmatization ไปจนถึงการหาคำศัพท์รูปแบบต่างๆ เช่น N-grams และ Skip-N-grams รวมถึงการทำ Named Entity Recognition (NER) ด้วยเครื่องมือต่างๆ ทั้ง spaCy, NLTK และ PyThaiNLP และการประยุกต์ใช้งานจริงที่เกี่ยวข้องกับภาษาอังกฤษและภาษาไทย

Text Vectorization และ Tokenization เบื้องต้น

ข้อความจะถูกแปลงออกมาเป็นโทเคน (token) หรือคำโดด (word) ก่อน แล้วจึงเปลี่ยนเป็นตัวเลขสำหรับการวิเคราะห์ต่อไป วิธีการเวกเตอร์มีหลายรูปแบบ เช่น One-Hot, Bag of Words (BoW) และ TF-IDF แต่ละรูปแบบมีจุดมุ่งหมายและการใช้งานที่ต่างกัน โดยทั่วไปนำเวกเตอร์ไปส่งต่อให้โมเดลทางคณิตศาสตร์เพื่อการจ าแนกประเภทหรือการจัดกลุ่ม Text Vectorization Tokenization Numerical and structured format

เนื้อหาการเรียน Text processing (week 1 - 5)

เนื้อหาครอบคลุมการ Tokenization, Frequency-based Text Vectorization, Mini project presentation, POS & Co-occurrence Analysis และ Embedding-based Text Vectorization เพื่อให้เห็นภาพการประมวลผลข้อความตั้งแต่ขั้นพื้นฐานจนถึงเทคนิคขั้นสูงกว่าในการแทนเวกเตอร์ด้วยวิธีต่างๆ

Outline ของวิชา

หัวข้อสำคัญประกอบด้วย Stem & Lemma, Part Of Speech (POS), N Gram & Co-occurrence, Named Entity Recognition (NER) ซึ่งนำไปใช้งานร่วมกับการสร้างเวกเตอร์และการวิเคราะห์ข้อมูลข้อความได้จริง

Stemming และ Lemmatization

รากศัพท์หรือรากคำ (Root word) เป็นแนวคิดสำคัญเมื่อเราทำ Tokenization โดยโทเคนที่ได้จากการทา tokenization ด้วยเครื่องมืออย่าง NLTK, spaCy และ PythaiNLP สามารถแยกโทเคนที่เกิดจากการย่อคำได้ เช่นข้อความ “isn’t” แยกเป็น “is” และ “n’t” ซึ่งช่วยให้ทราบว่าคำว่า “is” มาจากคำว่า “be” และ “n’t” มาจากคำว่า “not” สิ่งนี้เรียกว่ารากศัพท์ของโทเคน และแนวคิดนี้นำไปสู่การหารากศัพท์ (Stemming) และการหาคำพื้นฐานที่ควรเป็น (Lemmatization) เพื่อให้การวิเคราะห์มีความหมายมากขึ้น

Stemming: การตัดส่วนประกอบของโทเคน

Stemming คือการแปลงโทเคนให้เป็นรากศัพท์โดยการตัด prefix และ suffix ของโทเคน ตัวอย่าง prefix เช่น un- หรือ re- เข้ากับคำว่า “happy” ทำให้ได้ unhappy หรือ replay; suffix เช่น -ing, -ed, -ful ทำให้ได้ running, walked, hopeful, happiness เป็นต้น แนวทางนี้มักใช้กฎ (rule-based) ในการตรวจสอบว่าต้องตัดอะไรบ้าง การใช้งานสามารถทำได้ด้วย nltk โดยมีชุดเงื่อนไขที่หลากหลาย เช่น Porter และ Snowball แต่ spaCy และ pythainlp ไม่มีคำสั่งสำหรับ stemming โดยตรง

Stemming: ปัญหาและข้อจำกัด

การตั้งกฎตัด prefix และ suffix อาจไม่ครอบคลุมทุกกรณี ทำให้เกิดผลลัพธ์ที่ไม่ตรงกับความหมาย เช่น “unhappy” บางครั้งถูกตัดจนให้ผลลัพธ์ที่ไม่เหมาะสม หรือกรณีคำที่ผันรูปที่มีการเปลี่ยนรูปตัวอักษร เช่น “aaing” เหลือเพียง “aa” ที่ไม่มีความหมาย หรือคำเช่น “yes” ที่โดนตัด suffix จนไม่น่าเป็นคำเดิม สิ่งเหล่านี้ชี้ให้เห็นว่า rule-based stemming อาจไม่เหมาะสมในทุกกรณี

Lemmatization: ตราบาปของภาษาอังกฤษกับคลังศัพท์

Lemmatization แตกต่างจาก stemming ตรงที่ไม่เพียงตัด suffix/prefix แต่พยายามเปลี่ยนโทเคนให้เป็นคำพื้นฐานที่เหมาะสมตามหน้าที่ของคำจริงๆ โดยอ้างอิงคลังศัพท์ (dictionary-based) เช่น คำโทเคน “running” ที่ทำหน้าที่เป็นกริยา จะถูกแปลงเป็น “run” ในขณะที่ในประโยคที่มีการใช้งานเป็นนามก็ยังอาจเกิดการแปรต่างๆ ขึ้น ดังนั้น Lemmatization มักใช้งานด้วยพจนานุกรมและการพิจารณาหน้าที่คำ (POS tagging) เพื่อหาความหมายที่ถูกต้อง

Lemmatization: spaCy vs NLTK และ PyThaiNLP

  • spaCy: การทา Doc จะสร้าง Token object ซึ่งมี attribute lemma_ ที่ให้ค่า lemma ของโทเคน; ตัวอย่างเช่น “is” เปลี่ยนเป็น “be” และ “running” เปลี่ยนเป็น “run” โดยระบบจะพิจารณาหน้าที่คำอัตโนมัติ (POS) เพื่อกำหนดการ lemmatize อย่างถูกต้อง
  • NLTK: ใช้ WordNetLemmatizer ที่ต้องระบหน้าที่ของคำ (POS) เพื่อให้ lemmatize ทำงานได้ถูกต้อง ค่าเริ่มต้นของ WordNetLemmatizer จะคิดว่าโทเคนเริ่มต้นเป็นคำนาม หากไม่มีการกำหนด POS ที่สอดคล้อง ก็อาจคืนค่าเดิม
  • PyThaiNLP: สำหรับภาษาไทย เนื่องจากภาษาไทยมีลักษณะคำโดด ไม่มีการผันรูปเหมือนภาษาอังกฤษ จึงไม่มีขั้นตอน lemmatization แบบตรงๆ แต่มีฟีเจอร์ที่ช่วย normalize และ spell-check เพื่อช่วยให้ประมวลผลได้ราบรื่นขึ้น

Lemmatization ใน spaCy: ตัวอย่างและข้อสังเกต

เมื่อทา Doc ด้วย spaCy ข้อมูลในแต่ละโทเคนจะถูกเก็บไว้ในคลาส Token และแอตทริบิวต์ lemma_ จะถูกแสดงร่วมกับค่าของ token เพื่อดูการเปลี่ยนแปลง เช่น ประโยค “Silpakorn University was originally established as the School of Fine Arts under Thailand's Fine Arts Department in 1933.” จะได้ Lemma ที่แสดงออกมาเป็นคำพื้นฐานของแต่ละคำ เช่น Silpakorn, University, be, originally, establish, as, the, School, of, Fine, Arts, under, Thailand, 's, Fine, Arts, Department, in, 1933

Lemmatization: ประโยคยาวกับปัญหาของ POS

กรณีประโยคอย่าง “Running is fun” เรื่องการเก็บโทเคนที่เป็นนามหลังจาก lemmatize อาจทำให้ได้ผลลัพธ์ที่ไม่ตรงตามที่ต้องการ เนื่องจาก POS tagging ในบางกรณีอธิบายรวมถึงกรณีที่คำทั่วไปในรูปแบบต่างๆ ทำให้การ lemmatize ใน spaCy กับบางประโยคอาจมีความผิดพลาดได้ ขณะที่ NLTK อาจให้ผลลัพธ์ที่ต่างไป เพราะ WordNetLemmatizer จะตีความหน้าที่ของโทเคนแตกต่างกันไปตามการระบุ POS

Lemmatization: ปัญหาใน NLTK และทางออก

สาเหตุที่ spaCy ทำงานแตกต่างจาก NLTK คือใน spaCy เมื่อสร้าง Doc ระบบจะทำ POS tagging อัตโนมัติและกำหนดวิธี lemma ตามหน้าที่คำ ในขณะที่ NLTK ต้องระบุก่อนใน WordNetLemmatizer ค่าของ POS จึงถูกตีความในเชิงนาม (noun) เป็นหลัก ซึ่งอาจทำให้คำบางคำเช่น “is” ถูกตีความเป็นนามและไม่มีคำใน WordNet คอยรองรับ จึงคืนค่าเดิม ปัญหานี้สามารถแก้ได้ด้วยการระบุ POS ที่ถูกต้องหรือการผสาน POS กับการ lemmatize

POS tag และการใช้งานร่วมกับ Lemmatization

การติดแท็ก POS มีบทบาทสำคัญในการทำ lemmatize ให้ถูกต้อง โดยใน spaCy จะมีการคาดเดาหน้าที่คำอัตโนมัติ ส่วน NLTK ต้องมีการกำหนด POS และ map ไปสู่คำจำแนกประเภทที่สอดคล้องใน WordNet เพื่อให้ได้ lemma ที่ถูกต้อง สำหรับภาษาไทย POS tagging มีความแตกต่างมากจึงต้องอาศัยเครื่องมืออย่าง PyThaiNLP ซึ่งให้ Universal POS และ ORCHID/LST20 พร้อมตัวเลือก corpus เพื่อเลือกคลังศัพท์ที่เหมาะกับภาษาไทย

การรวม POS กับ Lemmatization เพื่อปรับปรุงการวิเคราะห์

เมื่อได้ stemming/lemmatization และ POS แล้ว เราสามารถนำไปใช้งานร่วมกับการทาเวกเตอร์ด้วย TF-IDF หรือวิธีการที่เรียนมาก่อนเพื่อให้โมเดลไม่ต้องทําความเข้าใจเวกเตอร์ที่ต่างกันระหว่างโทเคนที่ดูเหมือนกัน เช่น “is”, “am”, และ “are” ถูกแปลงเป็นคำพื้นฐานเดียวเป็น “be” เพื่อช่วยลดความซับซ้อนในการเรียนรู้ของโมเดล

Thai POS Tagging ด้วย PyThaiNLP

สำหรับภาษาไทย ไฟล์ POS tag อยู่ใน PyThaiNLP โดยใช้คำสั่ง pos_tag เพื่อแท็กโทเคน โดยผลลัพธ์จะมีแท็กที่ต่างจากภาษาอังกฤษ เช่น “PPRS”, “XVMB” ซึ่งจริงๆ แล้ว POS tag ของภาษาไทยมีรูปแบบ Universal POS ร่วมกับ ORCHID และ LST20 ให้เลือกใช้งานผ่านอาร์กิวเมนต์ corpus (ค่าเริ่มต้น ORCHID) เพื่อให้การติดแท็กตรงกับคลังศัพท์ภาษาไทยมากที่สุด

แอปพลิเคชัน Lemmatization + POS กับการเวกเตอร์ TF-IDF

หลังจากทำ Stemming, Lemmatization และ POS แล้ว ผู้ใช้งานสามารถนำข้อมูลไปปรับปรุงประโยคก่อนการทำเวกเตอร์ด้วย TF-IDF หรือวิธีที่เรียนมาก่อน เพื่อช่วยลดภาระของโมเดลในการทำความเข้าใจเวกเตอร์ที่มีลักษณะคล้ายคลึงกันของโทเคน (เช่น “is”, “am” และ “are” ที่แปลงเป็น “be”) และทำให้โมเดลมีประสิทธิภาพมากขึ้นในงานการจำแนกข้อความ

N-grams และ Co-occurrence (การปรากฏร่วมของโทเคน)

N-grams คือการจับคู่โทเคนตามลำดับกัน โดย n เป็นจำนวนโทเคนที่ต้องการติดกัน เช่น 2-grams (bigram) ประกอบด้วยคู่กี่คู่เช่นกัน 3-grams (trigram) และ 4-grams (quadgram) การจับคู่นี้ช่วยให้เห็นความหมายที่ชัดเจนมากขึ้นเมื่อโทเคนบางตัวปรากฏร่วมกัน เช่น ในประโยค “I love you” จะได้โทเคน [“I”, “love”, “you”] และเมื่อสร้าง 2-gram จะได้ [(“I”, “love”), (“love”, “you”)] และ 3-gram [(“I”, “love”, “you”)] ซึ่งเราสามารถสร้างเวกเตอร์จาก N-grams ได้ด้วย CountVectorizer หรือ TfidfVectorizer

N-grams ในการใช้งานจริงกับไลบรารีต่างๆ

  • N-grams สามารถสร้างได้ด้วย NLTK ผ่านฟังก์ชัน ngrams() โดยระบุค่า n ตามที่ต้องการ รวมถึงพารามิเตอร์ panleft และ padright สำหรับการเลื่อนซ้าย/ขวาของข้อความ เพื่อให้ครบจำนวน n
  • ใน PyThaiNLP สามารถใช้ calculatengramcounts() เพื่อสร้าง n-gram ในช่วง nmin ถึง nmax โดยกำหนด nmin และ nmax เช่น nmin = 2, nmax = 4
  • Skip-N-grams คือการสร้าง N-gram แบบข้ามโทเคน (k) โดยไม่จำเป็นต้องติดกันเสมอไป เช่น ในข้อความ “I love data science and NLP and computer.” ถ้า n = 2 และ k = 2 จะได้ชุดตัวอย่างเช่น [“I love” , “I data” , “I science”] ข้ามโทเคน 2 ตำแหน่ง

Skip-N-grams: ตัวอย่างและการใช้งาน

การทำ skip-n-gram สามารถทำได้ด้วย nltk ผ่านฟังก์ชัน skipgrams() โดยระบุขนาด n-gram (n) และขนาดการข้ามโทเคน (k) ผลลัพธ์สามารถนำไปเวกเตอร์ด้วยการใช้งาน CountVectorizer หรือ TfidfVectorizer โดยตั้งค่า ngram_range เพื่อกำหนดช่วงของ n ที่ต้องการ

N-grams Application: ผลลัพธ์ทางประสิทธิภาพ

ผลลัพธ์จากการทดลองมีดังนี้ เลขความถูกต้อง (accuracy) สำหรับ TF-IDF แบบ baseline อยู่ที่ประมาณ

  • Actual TF-IDF: 0.62 (N = 7532)
  • N-grams + TF-IDF: ประมาณ 0.67 ซึ่งแสดงให้เห็นว่าการใช้ N-grams ช่วยเพิ่มประสิทธิภาพได้
  • N-grams + TF-IDF (รายละเอียด macro/weighted averages): ค่า macro avg อยู่ที่ประมาณ 0.73–0.65 และ weighted avg ประมาณ 0.73–0.66 ตามการนำเสนอในตารางที่สลับตำแหน่งข้อมูล
  • Skip-N-grams Application (TF-IDF): ประมาณ 0.62 และ Skip-N-gram + TF-IDF: ประมาณ 0.43 ซึ่งแสดงให้เห็นว่า Skip-N-grams บางกรณีไม่ให้ประโยชน์เท่ากับ N-grams ปกติ

Named Entity Recognition (NER)

การรู้จำชื่อเฉพาะเป็นการจับกลุ่มคำที่เป็นชื่อบุคคล สถานที่ องค์กร หรือหน่วยเวลา โดยมีทั้งการใช้งานแบบ Rule-based และโมเดลสถิติ(NER) เพื่อช่วยจำแนกและติดแท็ก

  • spaCy: สามารถทำ NER ได้ด้วย doc.ents ซึ่งแสดงผลเป็นข้อความที่มีแท็กชนิดต่างๆ เช่น ORG (องค์กร), GPE (สถานที่ เช่น เมือง/ประเทศ), MONEY (จำนวนเงิน), DATE (วันเวลา) และมีอธิบายแท็กด้วย spacy.explain(ent.label_)
  • NLTK: มี ne_chunk() สำหรับ NER โดยต้องทำ POS tagging ก่อน แล้วค่อยทำ NER
  • PyThaiNLP: รองรับ NER ภาษาไทยผ่าน NER(engine) ด้วย thainer-v2 หรือ thainer และมีตัวอย่างแท็กเช่น PERSON, ORGANIZATION, DATE, LOCATION, MONEY ฯลฯ พร้อมทั้งตัวอย่างการใช้งาน

ตัวอย่างการใช้งานจริง (สรุปจากตัวอย่างในสไลด์)

  • ตัวอย่าง spaCy NER: ข้อความ “Apple is looking to buy a startup in Bangkok for $1 billion by 2025.” ได้ ent.text และ ent.label_ เช่น Apple => ORG, Bangkok => GPE, $1 billion => MONEY, 2025 => DATE
  • ตัวอย่าง NER ในภาษาไทยด้วย PyThaiNLP: การใช้งาน ner_obj.tag(text) ได้ผลลัพธ์เป็นชุดแท็ก เช่น ('นาย', 'B-PERSON'), ('มหาวิทยาลัยศิลปากร', 'B-ORGANIZATION') เป็นต้น และมีรายการแท็กอื่นๆ เช่น DATE, LOCATION, PERSON, ORGANIZATION ตามตารางการแท็กที่ระบุไว้

สรุปประเด็นสำคัญและเชื่อมโยงกับโลกจริง

  • การทำ Tokenization → Stemming/Lemmatization → POS tagging เป็นขั้นตอนหลักในการเตรียมข้อมูลสำหรับการเวกเตอร์และการเรียนรู้ของโมเดล เพื่อให้ได้ representation ที่สื่อความหมายได้ดีขึ้น และลดความซ้ำซ้อนของคำที่มีรากศัพท์เหมือนกันแต่ใช้งานต่างกันในบริบทต่างๆ
  • การใช้ TF-IDF เป็นวิธีหนึ่งในการแปลงคำเป็นเว็กเตอร์ โดย TF-IDF มุ่งเน้นคำที่มีความสำคัญในเอกสารหนึ่งๆ โดยปรับน้ำหนักคำที่มีความถี่สูงทั่วทั้งชุดข้อมูลออกไป
  • N-grams ช่วยให้เห็นความหมายร่วมระหว่างคำที่ปรากฏติดกันมากขึ้น ในขณะที่ Skip-N-grams สามารถจับความสัมพันธ์ที่ห่างกันได้ แต่ผลลัพธ์ขึ้นกับบริบทและข้อมูลจริง บางครั้งไม่ให้ประสิทธิภาพมากไปกว่าการใช้งาน N-grams ปกติ
  • NER เป็นส่วนสำคัญในการตีความความหมายของข้อความ โดยการระบุชื่อเฉพาะช่วยให้โมเดลเข้าใจบริบทของข้อมูลมากขึ้น และช่วยในการกรองข้อมูลที่มีความสำคัญในงานประเภทต่างๆ
  • ภาษาไทยมีลักษณะเฉพาะในเรื่อง POS tagging และไม่จำเป็นต้อง lemmatization เหมือนภาษาอังกฤษ ดังนั้นเครื่องมืออย่าง PyThaiNLP จึงมีแนวทางเฉพาะเพื่อรองรับภาษาไทย เช่น Universal POS, ORCHID, และ LST20 พร้อมตัวเลือก corpus เพื่อให้เหมาะสมกับงาน

สมุดจดสรุป (แนวทางสำหรับสอบ)

  • รากศัพท์ (root word) และการทำ Tokenization มีผลต่อการวิเคราะห์ของโมเดลอย่างมาก โดยการทำ stemming หรือ lemmatization ช่วยลดความแตกต่างของรูปแบบคำที่มีความหมายเดียวกัน
  • Stemming เป็นวิธีการตัดส่วนประกอบของคำเพื่อให้ได้รากศัพท์ แต่มีข้อจำกัดด้านความถูกต้องและความหมายของคำที่เกิดขึ้น ในขณะที่ Lemmatization อ้างอิงคลังศัพท์และ POS เพื่อให้ได้คำพื้นฐานที่ถูกต้องในบริบท
  • spaCy และ NLTK มีความแตกต่างในวิธีการ lemmatize และ POS tagging ดังนั้นการเลือกเครื่องมือขึ้นกับภาษาและลักษณะข้อมูลที่ใช้งาน
  • N-grams และ Skip-N-grams เป็นวิธีการสร้าง feature ที่ช่วยให้โมเดลเห็นความหมายร่วมระหว่างโทเคน แต่ประสิทธิภาพขึ้นกับข้อมูลและการตั้งค่า parameter เช่น ngram_range และ k
  • TF-IDF เป็นวิธีการเปลี่ยนข้อความเป็นเวกเตอร์ที่ให้ความสำคัญกับคำที่มีความหมายเชิงบริบทสูง และการรวมกับ POS และ Lemmatization สามารถเพิ่มประสิทธิภาพในการจำแนกข้อความได้
  • NER เป็นส่วนสำคัญในการทำความเข้าใจข้อมูล โดย spaCy, NLTK และ PyThaiNLP มีแนวทางที่ต่างกันในการระบุชื่อเฉพาะและแท็กที่เกี่ยวข้อง

รายการอ้างอิงที่สำคัญจากสไลด์

  • TF-IDF formula: TF ext{-}IDF(t,d) = tf(t,d) imes ext{log} rac{N}{df(t)} โดยที่ N คือจำนวนเอกสารทั้งหมด และ df(t) คือจำนวนเอกสารที่มีคำทำนั้น
  • ชนิดของ N-grams: 2-grams (bigram), 3-grams (trigram), 4-grams (quadgram)
  • ความแตกต่างระหว่าง Stemming และ Lemmatization และการใช้งานร่วมกับ POS tagging
  • strumenti และตัวอย่างการใช้งาน spaCy, NLTK และ PyThaiNLP ในการทำ NER และ POS tagging
  • ตัวอย่างผลลัพธ์การทดลองต่างๆ เช่น Accuracy ของ TF-IDF และ N-grams ที่แสดงถึงประสิทธิภาพที่สูงกว่ากรณี baseline เมื่อใช้ N-grams ร่วมกับ TF-IDF