01Overall Concept
ไอเดียหลัก — Multinomial Naive Bayes เหมาะกับข้อมูลจำนวนครั้ง เช่น แต่ละคำปรากฏในเอกสารกี่ครั้ง โมเดลเรียนรู้ว่าคำไหนพบบ่อยในแต่ละหมวด แล้วรวมหลักฐานจากทุกคำเพื่อเลือกหมวดของเอกสารใหม่ โดยไม่ต้องอ่านลำดับคำเหมือนคน
ลองนึกภาพว่า — เหมือนแยกข่าวจากร่องรอย ถ้าพบ goal และ team บ่อยก็เอนเอียงไปทางกีฬา ถ้าพบ chip และ code บ่อยก็เอนเอียงไปทางเทคโนโลยี
ตัวอย่างการนำไปใช้ — จัดหมวดข่าว กรองข้อความเบื้องต้น และทำ baseline ที่เร็วสำหรับข้อความหลายหมื่นหรือหลายแสนคำใน vocabulary
02อธิบายภาษาคนเข้าใจง่ายๆ
ลองทำตารางที่หนึ่งแถวคือหนึ่งข่าว และแต่ละคอลัมน์คือคำ เช่น goal กับ code ถ้าข่าวหนึ่งมี goal สามครั้งและ code หนึ่งครั้ง แถวนั้นจะเป็น [3,1]
ตอนฝึก เราบอกหมวดของข่าวเก่าไว้ด้วย โมเดลนับว่าข่าวกีฬาใช้แต่ละคำกี่ครั้ง และข่าวเทคโนโลยีใช้กี่ครั้ง แล้วเปลี่ยนจำนวนเหล่านั้นเป็นสัดส่วน
ตอนอ่านข่าวใหม่ มันตรวจทุกคำแล้วรวมหลักฐาน คำที่เจอซ้ำจะมีผลซ้ำตามจำนวนครั้ง จึงต่างจาก Bernoulli NB ที่สนใจเพียงมีหรือไม่มีคำ
ถ้าคำหนึ่งไม่เคยปรากฏในหมวดใดเลย เราไม่อยากสรุปว่าหมวดนั้นเป็นไปไม่ได้ตลอดกาล alpha จึงเติมจำนวนสมมติเล็กน้อยให้ทุกคำ วิธีนี้เรียกว่า smoothing
โมเดลนี้ไม่เข้าใจประโยคปฏิเสธหรือลำดับคำโดยตรง เช่น “ดี” กับ “ไม่ดี” อาจต้องสร้าง feature ที่เก็บคำคู่เพื่อช่วย และคำที่ใช้ฝึกต้องสร้างจากชุดฝึกเท่านั้น
ภาพจำ: นับร่องรอยจากคำแต่ละคำ แล้วรวมคะแนนว่าหมวดไหนมีหลักฐานมากที่สุด
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เปลี่ยนเอกสารเป็นตาราง
แบ่งข้อความและ label เป็น train/test ก่อน ใช้ CountVectorizer เรียนรู้ vocabulary เฉพาะชุดฝึก แล้วนับคำให้ได้ X ที่ทุกค่าไม่ติดลบ โค้ดสาธิตใช้ตาราง count สังเคราะห์โดยตรงเพื่อให้รันได้โดยไม่ดาวน์โหลดข้อมูล
นับคำภายในคลาส
ให้ N_cj เป็นจำนวนคำ j รวมในคลาส c และ V เป็นจำนวนคำใน vocabulary คำนวณ θ_cj=(N_cj+alpha)/(Σ_j N_cj+alpha×V) เช่นนับได้ [8,2] กับ alpha=1 จะได้ [9/12,3/12]
รวมหลักฐานโดยไม่คูณตัวเลขเล็กซ้ำ
ข่าว [2,0] ให้ score_c=log P(c)+2×log θ_c1 การใช้ log ป้องกันค่าความน่าจะเป็นที่คูณกันหลายครั้งเล็กจนคอมพิวเตอร์แทนไม่ได้ คลาสที่ score สูงสุดเป็นคำตอบ
ฝึกและทำนาย
ใช้ MultinomialNB(alpha=1.0).fit(X_train,y_train) แล้ว predict(X_test) ถ้ารับข้อความดิบควรวาง CountVectorizer กับโมเดลใน pipeline เดียวกัน ห้ามใช้ StandardScaler แบบลบค่าเฉลี่ยจน count ติดลบ
วัดผลแยกตามหมวด
ดู accuracy และ macro F1 รวมถึง confusion matrix ลอง alpha หลายค่าบน validation หากหมวดเล็กถูกกลบให้เทียบ Complement NB โค้ดและ Playground ใช้ 3 หมวดกับคำ 2 คำเพื่อเห็นขอบเขตง่าย จึงไม่ใช่ผลทดสอบเอกสารจริง
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
alphafit_priorclass_priorข้อมูลที่รับเข้ามา
X เป็นจำนวนคำที่ไม่ติดลบ และ y เป็นหมวดเอกสาร
คำรวมในคลาส [8,2] · alpha=1 · V=2พารามิเตอร์ที่ใช้
- alpha
- จำนวนสมมติที่เติมต่อคำเพื่อ smoothing
- fit_prior
- เรียนรู้โอกาสคลาสจากความถี่ในชุดฝึกหรือไม่
- class_prior
- ระบุ prior เองหากมีเหตุผลรองรับ
ผลลัพธ์ที่ได้
คลาสที่ได้คะแนนสูงที่สุด และ predict_proba ที่ควรตรวจ calibration ก่อนใช้เป็นความมั่นใจ
สัดส่วนคำหลัง smoothing = [0.75,0.25]คำนวณทีละขั้น
- 01
นับ N_cj ของแต่ละคำแยกคลาส
- 02
คำนวณ θ_cj=(N_cj+alpha)/(ΣN_cj+alpha×V)
- 03
เลือก argmax_c [log P(c)+Σx_j log θ_cj]
ควรรู้อีกนิด — CountVectorizer ต้อง fit จากข้อความฝึกเท่านั้น และถ้าใช้ภาษาไทยต้องเลือกวิธีตัดคำให้เหมาะกับงาน ตัวอย่างจำลองใช้ count โดยตรงจึงไม่ได้สาธิตการตัดคำไทย
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn# ดาวน์โหลด sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์import numpy as np data = np.genfromtxt("multinomial-naive-bayes-sample.csv", delimiter=",", skip_header=1)X = data[:, :2] from sklearn.naive_bayes import MultinomialNBfrom sklearn.metrics import accuracy_score, classification_report y = data[:, 2].astype(int)# กันทุกแถวที่ 5 ไว้ทดสอบ ตามข้อมูลสาธิตใน Playground# งานจริงควรเลือก split ให้เหมาะกับเวลา/บุคคล/กลุ่มของข้อมูลis_test = np.arange(len(X)) % 5 == 0X_train, X_test = X[~is_test], X[is_test]y_train, y_test = y[~is_test], y[is_test]model = MultinomialNB(alpha=1)model.fit(X_train, y_train)pred = model.predict(X_test)print("Test accuracy:", accuracy_score(y_test, pred))print(classification_report(y_test, pred, labels=[0, 1, 2], zero_division=0)) โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด
05Learn by playing
ปรับ alpha · smoothing แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง