SMOTE สร้างตัวอย่างสังเคราะห์ด้วยการ interpolate ระหว่างจุดคลาสส่วนน้อยกับเพื่อนบ้าน k-NN ไม่ใช่แค่การทำสำเนาซ้ำแบบ RandomOverSampler
ต้องใช้ SMOTE เฉพาะบนชุดฝึก (train set) หลังการแบ่งข้อมูล ห้ามใช้กับชุดทดสอบเด็ดขาด เพราะจะทำให้ metric สูงเกินจริง (data leakage)
imbalanced-learn มี Pipeline คลาสของตัวเอง (imblearn.pipeline.Pipeline) เพราะ Pipeline ของ scikit-learn ไม่รองรับขั้นตอน resampling
SMOTENC จัดการฟีเจอร์ประเภทแบบ categorical ได้โดยตรง ส่วน SMOTEN สำหรับข้อมูล categorical ล้วน
สำหรับข้อมูลที่ไม่สมดุลไม่มาก (น้อยกว่า 1:10) การใช้ class_weight='balanced' ในโมเดลมักได้ผลดีกว่าและรวดเร็วกว่า SMOTE
วัดผลด้วย PR-AUC (Average Precision) และ F1 ของคลาสส่วนน้อย ไม่ใช่ accuracy ซึ่งหลอกลวงในข้อมูลไม่สมดุล
สารบัญ
SMOTE คืออะไร และทำงานอย่างไร?
การติดตั้งและตั้งค่า imbalanced-learn 0.13
ใช้งาน SMOTE พื้นฐานพร้อมโค้ดตัวอย่าง
SMOTE variants: ADASYN, BorderlineSMOTE, SMOTENC และ SMOTEN
รวม SMOTE เข้ากับ scikit-learn Pipeline อย่างถูกวิธี
SMOTE กับ class_weight: อันไหนดีกว่ากัน?
การประเมินโมเดลข้อมูลไม่สมดุลที่ถูกต้อง
ข้อผิดพลาดที่ควรหลีกเลี่ยงเมื่อใช้ SMOTE
SMOTE คืออะไร และทำงานอย่างไร?
เอาล่ะ ก่อนจะไปดูโค้ด มาปูพื้นให้ชัดก่อน SMOTE ย่อมาจาก Synthetic Minority Over-sampling Technique ถูกนำเสนอครั้งแรกโดย Chawla และคณะในปี 2002 อัลกอริทึมทำงานตามขั้นตอนดังนี้: (1) เลือกจุดหนึ่งจากคลาสส่วนน้อยแบบสุ่ม (2) หาเพื่อนบ้านที่ใกล้ที่สุด k จุด (ค่าดีฟอลต์ k=5) ในคลาสเดียวกัน (3) สุ่มเลือกหนึ่งในเพื่อนบ้านนั้น (4) สร้างจุดสังเคราะห์ใหม่บนเส้นตรงระหว่างสองจุดโดยใช้ค่าสุ่ม α ∈ [0, 1] เป็นตัวถ่วงน้ำหนัก คือ x_new = x + α · (x_neighbor − x)
ในการทำงานจริงกับปัญหาการตรวจจับการทุจริตของธนาคารที่ผมช่วยสร้างระบบให้ (อัตราส่วนคลาสประมาณ 1:850) ผมพบว่าความเข้าใจกลไกนี้สำคัญมาก เพราะ SMOTE ไม่ใช่ของวิเศษ มันสร้างจุดในบริเวณที่มีคลาสส่วนน้อยอยู่แล้วเท่านั้น หากคลาสส่วนน้อยของคุณเป็น outlier กระจัดกระจาย SMOTE จะสร้าง noise มากกว่าสัญญาณ ดูรายละเอียดใน SMOTE original paper (Chawla et al., 2002) และ เอกสาร imbalanced-learn ทางการ ที่อธิบายพารามิเตอร์ครบถ้วน
ข้อแตกต่างสำคัญระหว่าง SMOTE กับ RandomOverSampler คือ RandomOverSampler ทำสำเนาจุดที่มีอยู่ซ้ำ ๆ (over-fit เสี่ยงสูง) ส่วน SMOTE จะสร้างจุดใหม่ที่ไม่เคยมีอยู่ ทำให้ decision boundary ของโมเดลนุ่มนวลกว่า แต่ก็แลกกับความเสี่ยงในการสร้างจุดในบริเวณที่ทับซ้อนกับคลาสส่วนใหญ่
การติดตั้งและตั้งค่า imbalanced-learn 0.13
เวอร์ชันล่าสุด (0.13.x, มิถุนายน 2026) รองรับ Python 3.10+ และ scikit-learn 1.5+ ติดตั้งได้ผ่าน pip หรือ conda:
# ผ่าน pip
pip install imbalanced-learn==0.13.0
# ผ่าน conda (channel: conda-forge)
conda install -c conda-forge imbalanced-learn=0.13.0
# ตรวจสอบเวอร์ชัน
python -c "import imblearn; print(imblearn.__version__)"
# 0.13.0
ถ้าคุณใช้ scikit-learn เวอร์ชันเก่า (< 1.3) ควรอัปเกรดก่อน เพราะ imbalanced-learn 0.13 ใช้ estimator tags แบบใหม่ที่ต้องการ sklearn 1.3+ และหลาย metadata routing feature (เช่น set_config(enable_metadata_routing="enabled")) จะทำงานได้ก็ต่อเมื่อคู่กับ sklearn 1.5+ เท่านั้น
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
from collections import Counter
# สร้างชุดข้อมูลไม่สมดุลตัวอย่าง (อัตราส่วนคลาส 1:19)
X, y = make_classification(
n_samples=10000,
n_features=20,
n_informative=10,
n_redundant=5,
n_classes=2,
weights=[0.95, 0.05],
random_state=42,
)
print("การกระจายคลาสเดิม:", Counter(y))
# การกระจายคลาสเดิม: Counter({0: 9500, 1: 500})
โค้ดข้างต้นจำลองสถานการณ์ที่พบบ่อยในระบบตรวจจับความผิดปกติ ตัวเลข weights=[0.95, 0.05] คือสัดส่วนที่ตั้งใจให้เกิดความไม่สมดุล 95:5 ซึ่งเป็นระดับที่ SMOTE เริ่มมีผลชัดเจน
ใช้งาน SMOTE พื้นฐานพร้อมโค้ดตัวอย่าง
ก่อนใช้ SMOTE ต้องแบ่งข้อมูล train/test ก่อนเสมอ กฎเหล็กคือ SMOTE ใช้กับชุดฝึกเท่านั้น ห้ามใช้กับชุดทดสอบเด็ดขาด มิฉะนั้นจะเกิด data leakage และตัวชี้วัดจะสวยเกินจริง (ผมเคยเจอเคสที่ทีมส่งโมเดลขึ้นโปรดักชันโดยทำ SMOTE ก่อน split ผลคือ ROC-AUC 0.98 ตอนทดสอบ แต่บนข้อมูลจริงเหลือ 0.72)
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, average_precision_score
# 1) แบ่งข้อมูลด้วย stratify เพื่อรักษาสัดส่วนคลาสในทั้งสองชุด
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
print("ก่อน SMOTE (train):", Counter(y_train))
# 2) ใช้ SMOTE บนชุดฝึกเท่านั้น
smote = SMOTE(
sampling_strategy="auto", # oversample คลาสส่วนน้อยให้เท่าคลาสส่วนใหญ่
k_neighbors=5,
random_state=42,
)
X_train_res, y_train_res = smote.fit_resample(X_train, y_train)
print("หลัง SMOTE (train):", Counter(y_train_res))
# 3) ฝึกโมเดลบนข้อมูลที่ resample แล้ว
model = LogisticRegression(max_iter=1000, random_state=42)
model.fit(X_train_res, y_train_res)
# 4) ประเมินบนชุดทดสอบเดิม (ไม่ถูก resample)
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:, 1]
print(classification_report(y_test, y_pred, digits=3))
print("PR-AUC:", round(average_precision_score(y_test, y_proba), 3))
พารามิเตอร์ที่สำคัญที่สุดคือ sampling_strategy ค่า "auto" จะ oversample คลาสส่วนน้อยให้เท่ากับคลาสส่วนใหญ่ แต่ในทางปฏิบัติมักไม่เหมาะที่สุด ส่วนตัวผมมักตั้งเป็นค่า float เช่น 0.5 ซึ่งหมายถึงต้องการอัตราส่วน 1:2 หลัง resample ตัวอย่าง: SMOTE(sampling_strategy=0.5) จะให้ผลที่นุ่มนวลกว่า และลดความเสี่ยงในการ over-generate จุดสังเคราะห์
คำเตือน: ห้าม fit_resample บนข้อมูลทั้งหมดก่อนแบ่ง train/test เพราะจุดสังเคราะห์ที่สร้างจากจุดในชุดทดสอบจะรั่วเข้าสู่ชุดฝึกและทำให้ metric สูงหลอก อาการที่พบบ่อยคือ ROC-AUC 0.99+ ในการฝึกและทดสอบ แต่ประสิทธิภาพจริงในโปรดักชันตกฮวบ
SMOTE variants: ADASYN, BorderlineSMOTE, SMOTENC และ SMOTEN
SMOTE พื้นฐานอาจไม่เหมาะกับทุกสถานการณ์ imbalanced-learn จึงมี variant หลายตัวที่ควรรู้จัก:
ADASYN: Adaptive Synthetic Sampling
ADASYN คล้าย SMOTE แต่ให้ความสำคัญกับจุดที่ "ยาก" ก่อน โดยดูจากอัตราส่วนของคลาสส่วนใหญ่ในบริเวณเพื่อนบ้าน ยิ่งพื้นที่หนาแน่นด้วยคลาสส่วนใหญ่ ADASYN ก็จะสร้างจุดใหม่ที่บริเวณนั้นมากกว่า เหมาะกับปัญหาที่มี decision boundary ซับซ้อน
from imblearn.over_sampling import ADASYN
adasyn = ADASYN(sampling_strategy=0.5, n_neighbors=5, random_state=42)
X_res, y_res = adasyn.fit_resample(X_train, y_train)
BorderlineSMOTE: สร้างจุดใกล้ boundary
BorderlineSMOTE จะจำแนกจุดคลาสส่วนน้อยเป็น "safe", "danger", และ "noise" แล้วสร้างจุดสังเคราะห์เฉพาะจุดในกลุ่ม "danger" (จุดที่มีเพื่อนบ้านครึ่งหนึ่งเป็นคลาสส่วนใหญ่) ตัวเลือกนี้ทำงานดีกับ dataset ที่คลาสส่วนน้อยมีทั้งจุดที่ชัดเจนและจุดคลุมเครือ
from imblearn.over_sampling import BorderlineSMOTE
# kind="borderline-1" (ดีฟอลต์) หรือ "borderline-2"
bsm = BorderlineSMOTE(sampling_strategy=0.5, kind="borderline-1", random_state=42)
X_res, y_res = bsm.fit_resample(X_train, y_train)
SMOTENC และ SMOTEN สำหรับข้อมูล categorical
SMOTE ใช้กับฟีเจอร์เชิงตัวเลขเท่านั้น ถ้าข้อมูลของคุณมีฟีเจอร์ประเภทแบบ (categorical) ต้องใช้ SMOTENC (Nominal + Continuous) หรือ SMOTEN (Nominal only) ซึ่งเป็นเรื่องปกติมากในข้อมูลของแวร์เฮาส์การวิเคราะห์ (analytics warehouse) ที่มีทั้ง numeric metric และมิติ dimensional หากคุณต้องเตรียมข้อมูลก่อน อ่าน คู่มือจัดการ Missing Data ใน pandas 3.0 ก่อนน่าจะช่วยได้เยอะ
from imblearn.over_sampling import SMOTENC
# ระบุ index ของคอลัมน์ categorical
cat_features = [3, 5, 7] # คอลัมน์ 3, 5, 7 เป็น categorical
smotenc = SMOTENC(
categorical_features=cat_features,
sampling_strategy=0.5,
random_state=42,
)
X_res, y_res = smotenc.fit_resample(X_train_df, y_train)
ในเวอร์ชัน 0.13 SMOTENC รองรับการรับ boolean mask หรือชื่อคอลัมน์ (เมื่อ input เป็น DataFrame) แทน index ตัวเลขได้แล้ว ซึ่งช่วยลดข้อผิดพลาดในโปรเจกต์ที่คอลัมน์เปลี่ยนแปลงบ่อย
รวม SMOTE เข้ากับ scikit-learn Pipeline อย่างถูกวิธี
เหตุผลที่ Pipeline ของ scikit-learn ธรรมดารวม SMOTE ไม่ได้คือ SMOTE เป็น resampler ไม่ใช่ transformer มันเปลี่ยนทั้ง X และ y ในขณะที่ transformer ของ sklearn เปลี่ยนเฉพาะ X ทางแก้คือใช้ imblearn.pipeline.Pipeline ซึ่งมี API เหมือน sklearn ทุกประการแต่รองรับ resampler เพิ่มเติม หากคุณเคยอ่านบทความ คู่มือ scikit-learn Pipeline ฉบับสมบูรณ์ มาก่อน แนวคิดจะเหมือนเดิม เพียงเปลี่ยน import
from imblearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
pipeline = Pipeline([
("scaler", StandardScaler()),
("smote", SMOTE(sampling_strategy=0.5, random_state=42)),
("clf", RandomForestClassifier(n_estimators=200, random_state=42)),
])
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
จุดสำคัญ: SMOTE จะทำงานเฉพาะเมื่อเรียก fit เท่านั้น เมื่อเรียก predict หรือ transform ขั้นตอน SMOTE จะถูกข้ามอัตโนมัติ นี่คือพฤติกรรมที่ต้องการ เพราะเราไม่อยาก resample ข้อมูลทดสอบหรือข้อมูลโปรดักชัน
เมื่อจับคู่ Pipeline นี้กับ Cross-Validation, GridSearchCV จะ resample ในแต่ละ fold แยกกันโดยอัตโนมัติ ซึ่งเป็นวิธีที่ถูกต้อง ป้องกัน leakage อีกชั้น (ผมเคยเสียเวลาไปสองวันไล่แก้ metric ที่ดูดีเกินจริง สุดท้ายเจอว่าลืมย้ายจาก sklearn.pipeline ไป imblearn.pipeline นั่นเอง) หากต้องการเจาะลึกเรื่องการปรับพารามิเตอร์ ผมแนะนำอ่านต่อที่ คู่มือ Hyperparameter Tuning ด้วย GridSearchCV, RandomizedSearchCV และ Optuna
from sklearn.model_selection import GridSearchCV
param_grid = {
"smote__sampling_strategy": [0.3, 0.5, 0.7, 1.0],
"smote__k_neighbors": [3, 5, 7],
"clf__n_estimators": [100, 200, 400],
}
grid = GridSearchCV(
pipeline,
param_grid,
scoring="average_precision", # PR-AUC เหมาะกับข้อมูลไม่สมดุล
cv=5,
n_jobs=-1,
)
grid.fit(X_train, y_train)
print("พารามิเตอร์ที่ดีที่สุด:", grid.best_params_)
SMOTE กับ class_weight: อันไหนดีกว่ากัน?
คำถามที่พบบ่อยที่สุดในทีมของผมคือควรใช้ SMOTE หรือแค่ตั้ง class_weight='balanced' ในโมเดล? คำตอบขึ้นอยู่กับ (1) ระดับความไม่สมดุล (2) ขนาดข้อมูล (3) ชนิดโมเดล ดูตารางเปรียบเทียบด้านล่าง
ประเด็น SMOTE / ADASYN class_weight='balanced'
วิธีทำงาน สร้างตัวอย่างสังเคราะห์เพิ่มในชุดฝึก เพิ่มน้ำหนัก loss ของคลาสส่วนน้อยขณะฝึก
เวลาฝึก ช้า (dataset ใหญ่ขึ้น 2–20 เท่า) เร็ว (dataset เดิม)
ใช้ RAM สูง โดยเฉพาะเมื่อ oversample 1:1 ต่ำ ไม่เพิ่มขนาดข้อมูล
ปรับ hyperparameter ปรับได้มาก (k_neighbors, sampling_strategy, variant) ปรับได้น้อย (บาลานซ์ vs custom weights)
โมเดลที่รองรับ ทุกโมเดล (เพราะเปลี่ยนข้อมูล) เฉพาะโมเดลที่รองรับ (LogReg, SVM, RF, XGBoost บางเวอร์ชัน)
ข้อมูล categorical ต้องใช้ SMOTENC / SMOTEN ไม่มีข้อจำกัด
เหมาะกับ ไม่สมดุลปานกลาง (1:20 ถึง 1:100), มี pattern ชัดเจน ไม่สมดุลไม่มาก (< 1:10), ข้อมูลใหญ่
ความเสี่ยงหลัก สร้าง noise หากคลาสส่วนน้อยกระจัดกระจาย โมเดลอาจไม่ปรับ decision boundary พอ
ในประสบการณ์ของผมกับ dataset การตรวจจับการทุจริตขนาด 40 ล้านแถว การใช้ class_weight='balanced' ใน XGBoost (ผ่านพารามิเตอร์ scale_pos_weight) ให้ผล PR-AUC สูงกว่า SMOTE อยู่เล็กน้อยและใช้เวลาฝึกน้อยกว่า 8 เท่า แต่ในโปรเจกต์ทางการแพทย์ที่มีข้อมูลเพียง 3,000 แถวและอัตราส่วน 1:50 การใช้ BorderlineSMOTE + LightGBM ให้ผลดีกว่าเห็นได้ชัด ดูรายละเอียดใน เอกสาร scikit-learn เรื่อง class_weight
เคล็ดลับ: ทดลองทั้งสองแนวทางแบบ A/B พร้อมกันด้วย GridSearchCV บนแซมเปิลเล็ก ก่อนตัดสินใจใช้แนวทางใดกับข้อมูลชุดเต็ม การเดาโดยไม่วัดผลมักผิด
การประเมินโมเดลข้อมูลไม่สมดุลที่ถูกต้อง
Accuracy เป็นตัวชี้วัดที่ห้ามใช้กับข้อมูลไม่สมดุลอย่างเด็ดขาด ในชุดข้อมูลที่คลาสบวกมีเพียง 1% โมเดลที่ทำนายเป็นคลาสลบเสมอจะได้ accuracy 99% ทันที ซึ่งไร้ความหมายในการนำไปใช้จริง
ตัวชี้วัดที่ควรใช้แทนคือ:
Precision-Recall AUC (Average Precision): ทนต่อความไม่สมดุลดีที่สุด สนใจเฉพาะประสิทธิภาพบนคลาสบวก
F1-score ของคลาสส่วนน้อย: สมดุลระหว่าง precision และ recall
ROC-AUC: ใช้ได้แต่มีข้อจำกัด เพราะไม่ไวต่อการเปลี่ยนแปลงในกลุ่ม false positive ที่มากกว่ามาก
Matthews Correlation Coefficient (MCC): ให้ตัวเลขเดียวที่คำนึงถึงทั้ง 4 ช่องของ confusion matrix
from sklearn.metrics import (
average_precision_score,
f1_score,
roc_auc_score,
matthews_corrcoef,
precision_recall_curve,
)
import matplotlib.pyplot as plt
y_proba = pipeline.predict_proba(X_test)[:, 1]
y_pred = pipeline.predict(X_test)
print(f"PR-AUC: {average_precision_score(y_test, y_proba):.3f}")
print(f"F1 (คลาส 1): {f1_score(y_test, y_pred):.3f}")
print(f"ROC-AUC: {roc_auc_score(y_test, y_proba):.3f}")
print(f"MCC: {matthews_corrcoef(y_test, y_pred):.3f}")
# วาดกราฟ Precision-Recall
precision, recall, _ = precision_recall_curve(y_test, y_proba)
plt.plot(recall, precision, label="SMOTE + RF")
plt.xlabel("Recall")
plt.ylabel("Precision")
plt.title("Precision-Recall Curve")
plt.legend()
plt.show()
อีกเรื่องที่สำคัญมากคือการปรับ threshold การจำแนก ค่าดีฟอลต์ 0.5 ไม่ใช่ค่าที่ดีเสมอไป ในบางกรณีการเลื่อน threshold ลงเป็น 0.2 อาจให้ recall สูงขึ้นในระดับที่ธุรกิจต้องการ โดยแลกกับ precision ที่ลดลง การตัดสินใจนี้ควรอิงกับต้นทุนของ false positive และ false negative ในบริบทจริง ไม่ใช่ตัวเลข F1 เพียงอย่างเดียว
ข้อผิดพลาดที่ควรหลีกเลี่ยงเมื่อใช้ SMOTE
จากประสบการณ์รีวิวโค้ด ML กว่าร้อยโปรเจกต์ในช่วง 9 ปีที่ผ่านมา นี่คือข้อผิดพลาดที่พบซ้ำที่สุด ซึ่งควรจะหลีกเลี่ยงตั้งแต่เริ่มโปรเจกต์:
ทำ SMOTE ก่อนแบ่ง train/test: ทำให้เกิด leakage อย่างชัดเจน แก้โดยแบ่งข้อมูลก่อนเสมอ หรือใช้ imblearn.pipeline.Pipeline
ใช้ SMOTE บน dataset ขนาดเล็กมาก (< 200 ตัวอย่างของคลาสส่วนน้อย) จุดสังเคราะห์จะซ้ำ pattern ของจุดต้นแบบเดิม ๆ ไม่เพิ่มความหลากหลาย
ลืมทำ scaling ก่อน SMOTE เนื่องจาก SMOTE ใช้ระยะทาง Euclidean การไม่ scale ทำให้ฟีเจอร์ที่มี scale ใหญ่ครองการคำนวณเพื่อนบ้าน
oversample ให้เป็น 1:1 เสมอ โมเดลอาจ over-fit จุดสังเคราะห์ ลองเริ่มที่ 1:3 หรือ 1:2 ก่อน
ใช้ SMOTE กับ time-series data โดยตรง จุดสังเคราะห์จะละเมิดลำดับเวลา ต้องใช้เทคนิคเฉพาะเช่น time-aware oversampling หรือ TimeGAN
ไม่ตรวจสอบ distribution ของจุดสังเคราะห์ ใช้ t-SNE หรือ UMAP วาดจุดใหม่เทียบกับจุดเดิม ถ้าจุดใหม่กระจายไปยังบริเวณคลาสส่วนใหญ่แสดงว่า SMOTE กำลังสร้าง noise
สำหรับการรับประกันคุณภาพข้อมูลก่อนเข้าไปยังกระบวนการ resampling ผมแนะนำให้ใช้ Pandera หรือ Great Expectations เพื่อ validate schema และ constraint ก่อน ไม่งั้น SMOTE อาจสร้างจุดสังเคราะห์บน missing value หรือ outlier ที่ควรถูกจัดการก่อน
หมายเหตุ: ในเวอร์ชัน 0.13 มีการ deprecate พารามิเตอร์ n_jobs ใน SMOTE (เดิมใช้เร่งการค้นหาเพื่อนบ้าน) เพราะปัจจุบัน scikit-learn ใช้ NearestNeighbors ที่ขนานได้อยู่แล้ว หากโค้ดเก่ามี warning ให้ลบพารามิเตอร์นี้ออก
คำถามที่พบบ่อย
SMOTE ปรับปรุงประสิทธิภาพโมเดลเสมอหรือไม่?
ไม่ SMOTE ช่วยได้เมื่อคลาสส่วนน้อยมี pattern ที่ชัดเจนและกระจุกตัว หากคลาสส่วนน้อยเป็น outlier กระจัดกระจาย SMOTE จะเพิ่ม noise และทำให้ประสิทธิภาพแย่ลง ในหลายกรณี class_weight='balanced' ให้ผลดีกว่าและเร็วกว่า ควรทดสอบทั้งสองวิธีก่อนตัดสินใจ
ควรใช้ SMOTE บนชุดทดสอบด้วยไหม?
ไม่ควรอย่างเด็ดขาด ใช้ SMOTE เฉพาะกับชุดฝึกเท่านั้น การใช้กับชุดทดสอบทำให้เกิด data leakage และ metric สูงเกินจริง ประสิทธิภาพในโปรดักชันจะแตกต่างจากที่วัดได้ทันที การใช้ imblearn.pipeline.Pipeline ร่วมกับ cross-validation จะป้องกันปัญหานี้อัตโนมัติ
SMOTE ใช้กับข้อมูล categorical ได้ไหม?
SMOTE พื้นฐานใช้ไม่ได้ ต้องใช้ SMOTENC สำหรับข้อมูลผสม (numeric + categorical) หรือ SMOTEN สำหรับ categorical ล้วน โดยระบุ index หรือชื่อของคอลัมน์ categorical ผ่านพารามิเตอร์ categorical_features ทั้งสอง variant จัดการการสร้างค่า categorical ให้ถูกต้องโดยไม่สร้างค่าเฉลี่ยที่ไม่มีความหมาย
SMOTE ทำงานกับ deep learning ได้ไหม?
ได้ แต่ในทางปฏิบัติ deep learning มีเทคนิคอื่นที่ดีกว่า เช่น focal loss, weighted BCE loss, หรือการปรับ batch sampling ให้บาลานซ์ SMOTE เหมาะกับ tabular data และโมเดล classic ML มากกว่า สำหรับข้อมูลภาพหรือข้อความ ควรใช้ data augmentation เฉพาะโดเมนแทน
ข้อเสียของ SMOTE คืออะไร?
ข้อเสียหลัก 3 ประการคือ (1) สามารถสร้างจุดในบริเวณที่ทับซ้อนกับคลาสส่วนใหญ่ ทำให้ decision boundary สับสน (2) เพิ่มขนาดข้อมูลอย่างมาก ทำให้ใช้ RAM และเวลาฝึกเพิ่ม (3) ไม่ทำงานกับข้อมูล time-series หรือข้อมูลที่มี dependency ระหว่างแถว จำเป็นต้องเลือก variant ที่เหมาะกับปัญหาและตรวจสอบผลด้วย visualization เสมอ