การทำ Text Classification ภาษาไทยด้วย Stacking model

Atipat Daowraeng
Super AI Engineer
Published in
3 min readMar 28, 2021

สวัสดีครับ ในบทความนี้ผมจะมาสอนวิธีการทำ Text Classification ภาษาไทยด้วย Stacking Model (Machine Learning) กันนะครับ โดยบทความนี้เหมาะสมกับนักพัฒนา AI ในสาขาอื่นที่อยากเริ่มต้นศึกษาเกี่ยวกับเรื่อง NLP

ก่อนลงมือทำเรามารู้จัก Text Classification กันก่อนดีกว่า

Text Classification หรือ Document Classification คือการที่คอมพิวเตอร์สามารถแยกแยะข้อความหรือประโยคต่างๆ ได้ว่าควรที่จะอยู่ในหมวดหมู่ใด ซึ่งเป็นการเรียนรู้แบบ Supervise Learning หรือก็คือ ต้องมีผู้เชี่ยวชาญทำการกำหนดหมวดหมู่ต่างๆให้กับข้อมูล ขึ้นมาก่อนเพื่อใช้สำหรับการ Train Model

โดยการทำ Text Classification ในครั้งนี้ได้นำข้อมูลมาจาก True Voice Intent ซึ่ง เป็น Data set เสียงของลูกค้า True

โจทย์

วิเคราะห์ข้อความที่เป็นตัวหนังสือภาษาไทย (texts) ที่ได้มา ว่าควรที่จะอยู่ในประเภทไหน (destination) โดยที่มีการเตรียมชุดข้อมูล Train และ Test ไว้ให้แล

1. Explore the Data

— สำรวจข้อมูลเพื่อหา insights

ขั้นตอนนี้เราจะทำการสำรวจข้อมูลที่ได้มาว่ามีความสมบูรณ์มากน้อยแค่ไหนก็ที่เราจะทำการแก้ไขเพิ่มเติมในขั้นตอนต่อไป อย่างเช่นโปรเจกต์นี้เราต้องการเพียงแค่ 2 Columns ก็คือ — “texts” และ “destination”

Data frame ของชุดข้อมูล Train
  • Input: texts
    ตัวอย่าง: “ internet ยังความเร็วอยุ่เท่าไหร ครับ ”
  • Output: destination
    ตัวอย่าง: “promotion”

เพราะฉะนั้นเราจะต้องทำการสร้าง Data frame ใหม่และ ทำการ encoding destination ให้อยู่ในรูปแบบของตัวเลข(integers)เพื่อให้อยู่ในรูปแบบของข้อมูลที่ algorithm สามารถเข้าใจได้ง่ายโดยใช้ from sklearn.preprocessing import LabelEncoder

from sklearn.preprocessing import LabelEncoderdf_train = df_train[['texts','destination']]
labelencoder = LabelEncoder()
df_train["labels"] = labelencoder.fit_transform(df_train["destination"])
df_test["labels"] = labelencoder.fit_transform(df_test["destination"])
df_train.head()

Imbalanced Classes

เราจะเห็นว่า ข้อความที่มีอยู่ในแต่ละประเภทมีจำนวนที่ไม่เท่ากัน โดยส่วนใหญ่จะไปกองรวมกันอยู่ที่ billing and payment กับ promotions

import matplotlib.pyplot as pltfig = plt.figure(figsize=(5,5))
train_df_count = train_df.groupby(['destination']).texts.count().reset_index(name ='Total Texts')
train_df_count.sort_values('Total Texts').plot.bar(x='destination')
plt.show()

ซึ่งปัญหาดังกล่าวในกรณีที่แย่ที่สุดจะทำให้ Model ของเรามีความเอนเอียงไปยังประเภทที่เป็นกลุ่มใหญ่และเพิกเฉยต่อประเภทที่มีข้อมูลตัวอย่างน้อย เราจึงต้องทำการปรับสมดุลของชุดข้อมูลลด้วยวิธีการ Oversampling หรือ Undersampling

แต่ในกรณีนี้ Classes ที่มีข้อมูลส่วนใหญ่เป็นที่สนใจของเรา และอาจทำให้มีความแม่นยำที่สูงกับชุดข้อมูล ในขณะที่ประเภทที่มีข้อมูลจำนวนน้อยก็ยังมีความถูกต้องอยู่พอสมควร ดังนั้นเราจึงยังไม่สนใจในส่วนนี้

Text Representation

การทำ Text Classification นั้นเราไม่สามารถที่จะนำข้อความไปใส่ใน algorithm ได้โดยตรง ส่วนใหญ่ต้องทำให้ข้อความเหล่านั้นกลายเป็น เวกเตอร์ที่ประกอบไปด้วยตัวเลขที่แทนลักษณะ(features)ของข้อความก่อน หลังจากนั้นจึงจะสามารถนำเข้า algorithm เพื่อคำนวนต่อได้

ซึ่งส่วนใหญ่ของการสร้าง features สำหรับข้อความนั้นมักจะใช้วิธีการที่เรียกว่า bag of words หรือ การสร้างคลังคำศัพท์ที่แทนคำศัพท์นั้นด้วยตัวเลขหรือความถี่

โดยข้อมูลชุดนี้ผมจะคำนวนด้วยวิธีการ TF-IDF(Term Frequency, Inverse Document Frequency) โดยใช้ from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn.feature_extraction.text import TfidfVectorizer
from pythainlp.tokenize import word_tokenize
ws_tfidf = TfidfVectorizer(tokenizer=word_tokenize, ngram_range=(1, 2), sublinear_tf=True)
ws_vec = ws_tfidf.fit_transform(df_train['texts'])
ws_vec_test = ws_tfidf.transform(df_test['texts'])

ซึ่งถ้าเราทำการ print(ws_vec_tests) ออกมาก็จะได้ผลลัพธ์แบบ นี้
(12939,32541)
โดยที่ตัวแรกจะบ่งบอกถึงจำนวนข้อความทั้งหมดที่มีในชุดข้อมูล และตัวที่สองแสดงถึงจำนวนคำที่มีในชุดข้อมูลทั้งหมด (features)

2. Stacking Model

หลังจากที่เราทำการเตรียมข้อมูลเสร็จเรียบร้อยแล้วก็ถึงเวลาของการ Train Model ซึ่งครั้งนี้ผมเลือกที่จะใช้หลักการ Ensemble Method ซึ่งเป็นหนึ่งในเทคนิคของ Machine learning ที่นำ Model หลายๆ Model มารวมกันเพื่อที่จะทำให้ผลลัพธ์ออกมาดีที่สุด ซึ่ง Model ที่นำมาใช้ สามารถใช้ Algorithm ของ Machine learning อะไรก็ได้

Stacking คือการนำผลลัพธ์จากหลายๆ โมเดลในที่นี้ คือ Random Forest, Linear SVC, Logistic Regression, KNN มาเข้าโมเดลอีกตัวหนึ่งซึ่งในที่นี้คือ Logistic Regression เพื่อคำนวนให้ได้ Class ที่มีความน่าจะเป็นมากที่สุดออกมา

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import StackingClassifier
from sklearn.neighbors import KNeighborsClassifier
estimators = [
('rf', RandomForestClassifier(n_estimators=10, random_state=42)),('svc',LinearSVC(random_state=42)),('knn',KNeighborsClassifier(n_neighbors=15)),('lgr',LogisticRegression(random_state=42))
]
clf = StackingClassifier(
estimators=estimators,
final_estimator=LogisticRegression(random_state=42),
n_jobs=-1,
verbose=2,
cv=5
)
clf.fit(ws_vec, df_train['labels'])

3. Model Evaluation

จาก Model ดังกล่าวได้ความถูกต้องจากการ predict ชุดข้อมูล Test เป็น ดังนี้

ซึ่ง Model นี้ยังไม่ได้เป็น Model ที่ดีที่สุดนะครับ ต่อไปเราลองมาดูกันดีกว่าว่า Model ทำนายผิดอย่างไรบ้าง?

import seaborn as snscategory_id_df = df_train[['destination','labels']].drop_duplicates().sort_values('labels')conf_mat = confusion_matrix(test_df['labels'],pred)
fig, ax = plt.subplots(figsize=(5,5))
sns.heatmap(conf_mat,annot=True, fmt='d', xticklabels=category_id_df.destination.values,yticklabels=category_id_df.destination.values)
plt.show()

บทสรุป

บทความนี้ได้สอนการทำ Text Classification ตั้งแต่การจัดการกับข้อมูลให้อยู่ในรูปแบบที่สามารถนำเข้า algorithm และได้ Model ออกมาสำเร็จ
Source code: Google Colab

--

--