Mục lục
- Mục tiêu bài học
- Class imbalance là gì
- Vì sao imbalance là vấn đề
- Diagnose — kiểm tra distribution
- 3 hướng xử lý chính
- Random Oversampling và Undersampling
- SMOTE — synthetic minority
- SMOTE variants
- imbalanced-learn — API
- ImbPipeline — tránh leak qua CV
- class_weight — cân lại loss
- Threshold tuning
- Khi nào KHÔNG resample
- Đánh giá model imbalanced
- Pitfall thường gặp
- Code — so sánh 4 chiến lược
- Bài tập thực hành
- Tổng kết Series 2
- Bài tiếp theo
Mục tiêu bài học
Sau bài này, bạn sẽ:
- Hiểu vì sao class imbalance làm accuracy misleading và lệch gradient về majority.
- Phân biệt 3 hướng xử lý: resampling,
class_weight, threshold tuning. - Dùng SMOTE qua
imblearnvà biết tại sao chỉ apply trên train. - Bọc SMOTE trong
ImbPipelineđể tránh leak khi chạy cross-validation. - Chọn metric phù hợp: F1, ROC-AUC, PR-AUC thay vì accuracy.
Class imbalance là gì
Class imbalance là tình trạng distribution các class trong dataset chênh lệch lớn. Ví dụ trong bài toán phân loại nhị phân:
- 95% negative, 5% positive — imbalance nhẹ.
- 99% negative, 1% positive — imbalance nặng.
- 99.9% negative, 0.1% positive — extreme imbalance (fraud, rare disease).
Các bài toán thực tế phổ biến có imbalance:
- Fraud detection: giao dịch gian lận chỉ chiếm 0.1-0.5% tổng giao dịch.
- Medical screening: tỷ lệ mắc bệnh hiếm trong dân số thường < 1%.
- Churn prediction: 5-15% khách hàng rời dịch vụ.
- Click-through prediction: tỷ lệ click ~1-3% trên hiển thị quảng cáo.
- Equipment failure: lỗi thiết bị xảy ra rất hiếm so với hoạt động bình thường.
Multi-class cũng có thể imbalanced (vd phân loại 10 loại bệnh, 1 loại chiếm 70%, 9 loại còn lại chia 30%). Cách xử lý tương tự, chỉ phức tạp hơn về metric.
Vì sao imbalance là vấn đề
Có 3 hệ quả chính:
- Accuracy misleading: với dataset 99% negative, model luôn dự đoán "negative" đã đạt 99% accuracy nhưng không phát hiện positive nào. Đây là baseline mặc định mà nhiều người vô tình "tự lừa".
- Gradient bias về majority: loss function (vd cross-entropy) tổng hợp lỗi trên mọi sample. 99 sample negative đóng góp 99 lần lỗi vào loss tổng, 1 sample positive chỉ 1 lần. Gradient descent kéo tham số tối ưu cho majority, bỏ qua minority.
- Model "lười" predict majority: vì cách an toàn nhất để giảm loss là predict toàn majority. Decision boundary bị kéo về phía minority đến mức gần như không phân được.
Một số model bị ảnh hưởng nặng hơn: Logistic Regression và NN dùng loss tổng hợp, dễ thiên về majority. Tree-based (RF, XGBoost) ít nhạy hơn vì split dựa trên impurity, nhưng vẫn cần can thiệp ở imbalance nặng.
Diagnose — kiểm tra distribution
Trước khi xử lý, luôn kiểm tra tỷ lệ class:
import pandas as pd
import matplotlib.pyplot as plt
# Đếm số lượng và tỷ lệ
print(df["y"].value_counts())
print(df["y"].value_counts(normalize=True))
# Vẽ bar chart
df["y"].value_counts().plot(kind="bar")
plt.title("Class distribution")
plt.show()
Một số mốc tham khảo (không phải ngưỡng cứng):
- Tỷ lệ minority > 40%: gần balanced, không cần can thiệp.
- Minority 20-40%: nhẹ, thử model trước, nếu recall thấp mới can thiệp.
- Minority 5-20%: vừa, dùng
class_weight="balanced"hoặc threshold tuning. - Minority < 5%: nặng, kết hợp resampling (SMOTE) hoặc
scale_pos_weight, đánh giá bằng PR-AUC.
Cũng kiểm tra distribution trong train, val, test riêng — đảm bảo train_test_split(..., stratify=y) giữ tỷ lệ class qua các split.
3 hướng xử lý chính
- Resampling (thay đổi data): oversample minority, undersample majority, hoặc tạo synthetic sample (SMOTE). Sửa imbalance ở mức dataset.
- class_weight (thay đổi loss): giữ nguyên data, nhân trọng số lớn hơn cho lỗi trên minority. Sửa imbalance ở mức loss function.
- Threshold tuning (thay đổi quyết định): giữ nguyên data và loss, chỉ hạ ngưỡng quyết định (vd từ 0.5 xuống 0.3) để tăng recall cho minority. Sửa imbalance ở mức inference.
Ba hướng không loại trừ nhau — có thể kết hợp. Trong thực tế thường thử theo thứ tự: class_weight trước (rẻ, không thay data), threshold tuning nếu cần kéo recall, SMOTE khi 2 cách trên chưa đủ.
Random Oversampling và Undersampling
Random Oversampling: copy ngẫu nhiên sample của minority cho đến khi số lượng bằng majority. Đơn giản, không cần thuật toán phức tạp.
- Ưu: triển khai 1 dòng code; giữ nguyên thông tin majority.
- Nhược: bản copy không thêm thông tin mới — model dễ overfit pattern minority (vì nhìn cùng 1 sample nhiều lần).
Random Undersampling: drop ngẫu nhiên sample của majority cho đến khi số lượng bằng minority.
- Ưu: train nhanh hơn (dataset nhỏ đi); cân nhanh phân bố.
- Nhược: vứt đi thông tin có thể quan trọng của majority; nếu dataset nhỏ, mất nhiều sample dẫn đến underfit.
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
ros = RandomOverSampler(random_state=42)
X_over, y_over = ros.fit_resample(X_train, y_train)
rus = RandomUnderSampler(random_state=42)
X_under, y_under = rus.fit_resample(X_train, y_train)
Cả 2 chỉ apply trên train. Test giữ nguyên distribution thật để metric phản ánh hiệu năng production.
SMOTE — synthetic minority
SMOTE (Synthetic Minority Over-sampling Technique) do Chawla et al. (2002, JAIR) đề xuất. Thay vì copy sample minority, SMOTE tạo sample mới bằng cách interpolate giữa 1 sample minority và 1 trong K láng giềng (mặc định K=5) cũng thuộc minority.
Quy trình tạo 1 synthetic sample:
- Chọn 1 sample minority
x. - Tìm K láng giềng gần nhất của
xtrong cùng class (dùng KNN). - Chọn ngẫu nhiên 1 láng giềng
x_nn. - Tạo sample mới:
x_new = x + λ × (x_nn - x), vớiλ ~ Uniform(0, 1).
x_new nằm trên đoạn thẳng nối x và x_nn — là điểm "ở giữa" 2 sample minority có sẵn. Vì không duplicate, model không overfit theo cách như Random Oversampling.
Lưu ý quan trọng:
- SMOTE chỉ hoạt động với feature liên tục. Với categorical, cần variant SMOTE-NC.
- SMOTE nhạy với outlier — nếu sample minority là outlier, synthetic sample sinh ra cũng "loằng ngoằng" theo.
- Khi feature space high-dim, KNN trong SMOTE đắt và kém ổn định (curse of dimensionality). PCA trước SMOTE đôi khi cải thiện.
- SMOTE giả định vùng giữa 2 sample minority cũng thuộc minority — không phải lúc nào cũng đúng (vd minority chia thành nhiều cluster tách rời).
SMOTE variants
Có nhiều biến thể giải các vấn đề SMOTE gốc:
- BorderlineSMOTE: chỉ generate synthetic từ những sample minority nằm gần decision boundary (xác định qua KNN xen lẫn majority). Tập trung vào vùng khó phân biệt thay vì vùng minority "an toàn".
- ADASYN (Adaptive Synthetic): generate nhiều synthetic hơn cho minority sample mà láng giềng đa số thuộc majority — tức là vùng khó. Tỷ lệ synthetic mỗi sample tỷ lệ thuận với độ "khó" của vùng.
- SMOTE-NC (Nominal Continuous): hỗ trợ feature categorical. Với feature categorical, value của synthetic sample được chọn theo majority vote của K láng giềng thay vì interpolate.
- SMOTE-ENN: kết hợp SMOTE (oversample) và Edited Nearest Neighbours (loại sample nhiễu sau khi resample). Cleaner dataset hơn.
- SMOTE-Tomek: kết hợp SMOTE và Tomek links (loại cặp sample gần nhau khác class). Tương tự SMOTE-ENN.
Tất cả có sẵn trong imblearn.over_sampling và imblearn.combine. Trong phần lớn dự án, SMOTE gốc đủ; chỉ cần variant khi gặp pattern cụ thể (nhiều categorical → SMOTE-NC; boundary phức tạp → BorderlineSMOTE).
imbalanced-learn — API
imbalanced-learn (import: imblearn) là package mở rộng của sklearn cung cấp tất cả thuật toán resampling. Cài đặt: pip install imbalanced-learn.
from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state=42, k_neighbors=5)
X_res, y_res = sm.fit_resample(X_train, y_train)
print("Trước:", y_train.value_counts().to_dict())
print("Sau: ", pd.Series(y_res).value_counts().to_dict())
Các tham số chính của SMOTE:
sampling_strategy: tỷ lệ minority/majority sau resample. Default"auto"cân về 1:1. Có thể đặt số (vd0.5nghĩa là minority bằng 50% majority) hoặc dict.k_neighbors: số láng giềng để interpolate. Default 5. Tăng nếu minority quá ít.random_state: bắt buộc set để reproducible.
Quy tắc bất biến: SMOTE và mọi kỹ thuật resampling khác CHỈ apply trên train. Nếu resample test:
- Distribution test khác production — metric đo được không phản ánh hiệu năng thực.
- Synthetic sample trong test = data leak nếu được tạo từ thông tin train.
- Tệ nhất: vô tình "make test easier", model trông tốt giả tạo.
ImbPipeline — tránh leak qua CV
Cross-validation chia train thành nhiều fold. Mỗi fold đóng vai validation 1 lần. Nếu bạn resample trước CV, sample synthetic ở fold validation có thể được tạo từ sample ở fold train (vì SMOTE chạy trên toàn bộ X_train trước khi chia fold). Đây là leak — synthetic test sample "biết" thông tin train.
sklearn Pipeline không hỗ trợ resampler vì các step trong Pipeline phải implement transform, còn resampler có method khác là fit_resample. Vì vậy imblearn cung cấp Pipeline riêng tương thích — drop-in replacement, gọi fit_resample chỉ ở step train của mỗi fold:
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.over_sampling import SMOTE
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score
pipe = ImbPipeline([
("scaler", StandardScaler()),
("smote", SMOTE(random_state=42)),
("clf", LogisticRegression(max_iter=1000)),
])
scores = cross_val_score(pipe, X_train, y_train, cv=5, scoring="f1")
print("F1 mean:", scores.mean())
Trong mỗi fold của CV: scaler fit trên train fold → SMOTE fit_resample trên train fold (đã scale) → LogisticRegression fit. Validation fold đi qua scaler (transform only), bỏ qua SMOTE, rồi predict. Không leak.
Cú pháp tham số trong Pipeline giống sklearn — step__param (vd "smote__k_neighbors": 3) để tune SMOTE qua GridSearchCV/RandomizedSearchCV.
class_weight — cân lại loss
Thay vì can thiệp data, class_weight can thiệp loss: nhân loss của sample minority với hệ số lớn hơn để chúng "nặng" hơn trong tổng loss. Không tạo data mới, không drop data — đơn giản và rẻ.
sklearn hỗ trợ class_weight trên nhiều estimator: LogisticRegression, SVC, DecisionTreeClassifier, RandomForestClassifier, SGDClassifier, RidgeClassifier...
from sklearn.linear_model import LogisticRegression
# Cách 1: balanced — auto inverse frequency
model = LogisticRegression(class_weight="balanced", max_iter=1000)
# Cách 2: dict — weight thủ công
model = LogisticRegression(class_weight={0: 1, 1: 10}, max_iter=1000)
"balanced" tự tính weight theo công thức: weight_c = n_samples / (n_classes × n_samples_c). Class hiếm hơn → weight lớn hơn. Đây là baseline tốt — thử trước khi tinh chỉnh dict.
Với XGBoost/LightGBM, tham số tương đương là scale_pos_weight — tỷ số negative / positive trong train (chỉ cho binary):
import xgboost as xgb
ratio = (y_train == 0).sum() / (y_train == 1).sum()
model = xgb.XGBClassifier(scale_pos_weight=ratio)
So sánh với resampling:
class_weightnhanh hơn (không thay data, không tốn RAM).- Không thêm noise như SMOTE.
- Hỗ trợ trực tiếp trong nhiều estimator — không cần thêm library.
- Nhược: với extreme imbalance (< 1%),
class_weightđôi khi không đủ — kết hợp SMOTE.
Threshold tuning
Mặc định predict() dùng threshold 0.5: predict_proba > 0.5 → class 1. Với imbalanced data, ngưỡng này thường khiến model bỏ sót positive (vì model "không tự tin" về minority).
Threshold tuning: dùng predict_proba rồi tự chọn threshold theo metric mục tiêu.
import numpy as np
from sklearn.metrics import precision_recall_curve, f1_score
probs = model.predict_proba(X_val)[:, 1]
precisions, recalls, thresholds = precision_recall_curve(y_val, probs)
# F1 ở mỗi threshold
f1s = 2 * precisions * recalls / (precisions + recalls + 1e-9)
best_idx = np.argmax(f1s[:-1]) # thresholds ngắn hơn 1
best_threshold = thresholds[best_idx]
print(f"Best threshold: {best_threshold:.3f}")
print(f"Best F1: {f1s[best_idx]:.4f}")
# Predict với threshold mới
y_pred = (probs > best_threshold).astype(int)
Một số lưu ý:
- Threshold tuning phải làm trên validation set, không phải test. Apply threshold tìm được lên test để báo metric.
- Threshold tối ưu phụ thuộc metric mục tiêu: maximize F1 ≠ maximize recall ≠ maximize precision. Chọn metric dựa trên cost của FP vs FN trong bài toán.
- Trong fraud detection, FN (bỏ sót gian lận) tốn hơn FP nhiều — ưu tiên recall cao, hạ threshold mạnh.
- Threshold tuning không thay model — luôn có thể áp dụng sau khi đã train xong (kể cả model đã class_weight hay SMOTE).
Khi nào KHÔNG resample
Resampling không phải lúc nào cũng cần — đôi khi gây hại:
- Tree-based model (Decision Tree, Random Forest, XGBoost, LightGBM): native support tham số
class_weighthoặcscale_pos_weight. Khuyến nghị dùng trước. SMOTE đôi khi vẫn giúp nếu imbalance rất nặng, nhưng không cần làm bước đầu tiên. - Imbalance nhẹ (minority > 20%): dùng
class_weight="balanced"hoặc threshold tuning đủ. SMOTE thêm noise không cần thiết. - Dataset đã rất lớn: oversample làm chậm training; undersample chỉ là vứt data — thử
class_weighttrước. - Feature high-dim (vd embeddings > 100 chiều): KNN trong SMOTE kém ổn định. Synthetic sample dễ trở thành noise.
- Bài toán cần calibrated probability: SMOTE và undersampling thay distribution → output probability bị lệch. Cần calibration (Platt scaling, isotonic regression) sau đó nếu downstream dùng probability thật.
Quy tắc thực dụng: thử baseline + class_weight trước. Nếu PR-AUC chưa đạt yêu cầu, thêm threshold tuning. Cuối cùng mới thử SMOTE qua ImbPipeline.
Đánh giá model imbalanced
Accuracy hỏng với imbalanced data (Bài 23 đã chỉ ra). Các metric phù hợp:
- Confusion matrix: luôn in ra để thấy số TP, FP, TN, FN. Đây là ground truth — mọi metric đều derive từ đây.
- Precision, Recall riêng cho minority:
classification_reportin luôn cả 2. - F1: harmonic mean của precision và recall. Tốt khi cần cân bằng 2 loại lỗi.
- ROC-AUC: ổn định khi imbalance nhẹ-vừa. Tuy nhiên ở extreme imbalance, ROC curve "lạc quan giả" — TPR và FPR đều dễ cao vì negative quá nhiều.
- PR-AUC (Average Precision): tốt nhất cho extreme imbalance. Vì PR curve không bị "loãng" bởi TN — chỉ tính positive thật và predicted positive.
from sklearn.metrics import (
confusion_matrix, classification_report,
roc_auc_score, average_precision_score,
)
probs = model.predict_proba(X_test)[:, 1]
y_pred = (probs > 0.5).astype(int)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred, digits=4))
print(f"ROC-AUC: {roc_auc_score(y_test, probs):.4f}")
print(f"PR-AUC: {average_precision_score(y_test, probs):.4f}")
Lưu ý: ROC-AUC và PR-AUC dùng predict_proba (continuous), không phụ thuộc threshold — phản ánh chất lượng ranking của model. F1 và confusion matrix phụ thuộc threshold.
Pitfall thường gặp
- SMOTE trên test: data leak nặng. Test phải giữ nguyên distribution thật. Đây là lỗi phổ biến nhất khi mới học imbalance handling.
- Resample trước CV thay vì trong Pipeline: nếu dùng sklearn Pipeline (không phải ImbPipeline), không bọc SMOTE được. Hoặc resample ngoài CV → synthetic sample lọt vào validation fold. Luôn dùng
imblearn.pipeline.Pipeline. - Đo accuracy → predict majority: optimize sai metric, model lười. Đổi sang F1 hoặc PR-AUC.
- Quên
stratify=ytrongtrain_test_split: với imbalance nặng, không stratify có thể khiến test fold không có sample positive nào → metric không tính được hoặc bằng 0. - So sánh model với baseline accuracy: với 99% negative, baseline luôn-predict-majority đã 99%. So sánh với baseline F1 hoặc PR-AUC mới có ý nghĩa.
- Tin SMOTE giải mọi vấn đề: SMOTE giả định vùng minority "lồi" — không đúng khi minority phân thành nhiều cluster tách rời. Thử BorderlineSMOTE/ADASYN hoặc
class_weight. - Output probability không calibrated sau SMOTE: nếu downstream (decision system) dùng raw probability, cần calibration sau khi train.
CalibratedClassifierCVcủa sklearn. - Optimize threshold trên test: dùng val cho threshold, test chỉ để báo cáo cuối cùng.
Code — so sánh 4 chiến lược
Dataset giả imbalanced 95/5 bằng make_classification, so sánh baseline, SMOTE, class_weight, threshold tuning:
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import (
confusion_matrix, f1_score, average_precision_score,
precision_recall_curve,
)
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline as ImbPipeline
from sklearn.pipeline import Pipeline
# Tạo dataset 95/5
X, y = make_classification(
n_samples=10000, n_features=20, n_informative=5,
weights=[0.95, 0.05], random_state=42,
)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, stratify=y, random_state=42,
)
print("Train distribution:", np.bincount(y_train))
def evaluate(name, model, X_test, y_test, threshold=0.5):
probs = model.predict_proba(X_test)[:, 1]
y_pred = (probs > threshold).astype(int)
f1 = f1_score(y_test, y_pred)
pr_auc = average_precision_score(y_test, probs)
cm = confusion_matrix(y_test, y_pred)
print(f"\n=== {name} (threshold={threshold:.2f}) ===")
print("Confusion matrix:\n", cm)
print(f"F1: {f1:.4f}")
print(f"PR-AUC: {pr_auc:.4f}")
return probs
# 1. Baseline
base = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000)),
])
base.fit(X_train, y_train)
evaluate("Baseline", base, X_test, y_test)
# 2. SMOTE qua ImbPipeline
smote_pipe = ImbPipeline([
("scaler", StandardScaler()),
("smote", SMOTE(random_state=42)),
("clf", LogisticRegression(max_iter=1000)),
])
smote_pipe.fit(X_train, y_train)
evaluate("SMOTE", smote_pipe, X_test, y_test)
# 3. class_weight
cw = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(
class_weight="balanced", max_iter=1000)),
])
cw.fit(X_train, y_train)
probs_cw = evaluate("class_weight=balanced", cw, X_test, y_test)
# 4. Threshold tuning từ baseline
probs_base = base.predict_proba(X_test)[:, 1]
precisions, recalls, thresholds = precision_recall_curve(
y_test, probs_base)
f1s = 2 * precisions * recalls / (precisions + recalls + 1e-9)
best_t = thresholds[np.argmax(f1s[:-1])]
evaluate("Baseline + threshold tuning",
base, X_test, y_test, threshold=best_t)
Mẫu output điển hình (số có thể đổi theo seed):
- Baseline F1 ~0.55, PR-AUC ~0.70 — bỏ sót khá nhiều positive.
- SMOTE F1 ~0.65, PR-AUC ~0.72 — recall lên rõ, precision giảm chút.
- class_weight F1 ~0.63, PR-AUC ~0.71 — tương đương SMOTE, rẻ hơn.
- Threshold tuning F1 ~0.68 (cao nhất) — vì optimize trực tiếp F1.
Ghi chú: threshold tuning trên test ở ví dụ là minh hoạ — production phải dùng validation set riêng.
Bài tập thực hành
Bài 1. Train LogisticRegression trên dataset fraud-like:
X, y = make_classification(
n_samples=20000, n_features=30, n_informative=8,
weights=[0.99, 0.01], random_state=42,
)
Chia train/test stratified 70/30. Báo confusion matrix, F1 minority, PR-AUC của baseline LogReg. So sánh với baseline "always predict majority" (F1 = 0, PR-AUC ≈ tỷ lệ positive).
Bài 2. Apply SMOTE qua ImbPipeline + 5-fold cross-validation với cross_val_score scoring "f1". So sánh F1 trung bình với baseline. Sau đó fit pipeline trên toàn train, đánh giá test. Cải thiện thực tế trên test bao nhiêu?
Bài 3. Thay SMOTE bằng class_weight="balanced". So sánh F1, PR-AUC, và wall-clock time với SMOTE. Cách nào nhanh hơn? Cách nào F1 cao hơn? Thử thêm class_weight={0: 1, 1: 50} — kết quả khác gì?
Bài 4. Tune threshold để maximize F1 trên validation (chia train thành train + val 80/20). Apply threshold tốt nhất lên test. So sánh với threshold default 0.5 ở các metric: precision, recall, F1. Nhận xét tradeoff recall vs precision khi hạ threshold.
Bài 5 (thử thách). Lặp lại Bài 1 với XGBoost (scale_pos_weight = neg/pos). So sánh F1 và PR-AUC với LogisticRegression + class_weight. XGBoost vẫn cần SMOTE không?
Tổng kết Series 2
Series 2 (Machine Learning cổ điển) gồm 42 bài qua 6 module:
- Module 1 — Giới thiệu ML: 3 loại ML (supervised, unsupervised, RL), quy trình build ML, scikit-learn cơ bản, dataset Iris.
- Module 2 — Tiền xử lý dữ liệu: feature engineering, scaling (Min-Max, Standardization), encoding (Label, One-Hot, Ordinal), outlier (IQR, Z-score), Pipeline.
- Module 3 — Regression: linear, multiple linear, polynomial, Ridge, Lasso; metric MSE, RMSE, R².
- Module 4 — Classification: Logistic Regression, KNN, Decision Tree, Random Forest, SVM, Gradient Boosting/XGBoost; metric accuracy, precision, recall, F1, confusion matrix, ROC-AUC.
- Module 5 — Unsupervised: K-Means, Hierarchical, DBSCAN, PCA; metric clustering (silhouette, Davies-Bouldin).
- Module 6 — Tối ưu và Đánh giá: train/val/test split, cross-validation, bias-variance, overfitting/underfitting, Grid Search, Random Search, Bayesian Optimization, class imbalance.
Sau Series 2, bạn train được ML model end-to-end với sklearn, biết chọn metric và resampling phù hợp với từng bài toán, biết tune hyperparameter và đánh giá generalization. Đó là toolkit đủ để giải phần lớn bài toán ML cổ điển (tabular data, dưới vài triệu sample).
Series 3 (Deep Learning) tiếp tục từ điểm này: chuyển từ model shallow (LogReg, RF) sang neural network nhiều tầng. Các khái niệm Series 1 (vector, ma trận, đạo hàm, gradient) và Series 2 (loss function, gradient descent, train/val split, overfitting, regularization, metric) tiếp tục dùng — Deep Learning thay đổi mô hình, không thay đổi nền tảng.
Bài tiếp theo
Series 3: Deep Learning — neural network từ perceptron đến Transformer: forward/backward, activation function, optimizer (SGD, Adam), CNN cho ảnh, RNN/LSTM cho sequence, attention, Transformer, framework PyTorch và TensorFlow. Series mở rộng trực tiếp từ nền tảng Series 1 (toán) và Series 2 (ML).
Tài liệu tham khảo
- imbalanced-learn — Documentation
- imbalanced-learn — SMOTE API reference
- imbalanced-learn — Common pitfalls and recommended practices
- imbalanced-learn — Pipeline
- Chawla, Bowyer, Hall & Kegelmeyer (2002) — SMOTE: Synthetic Minority Over-sampling Technique, JAIR
- scikit-learn — Unbalanced problems (class_weight)
- scikit-learn — LogisticRegression (class_weight parameter)
- scikit-learn — Precision-Recall curve example
- XGBoost — Parameters (scale_pos_weight)
- imbalanced-learn — Comparison of over-sampling methods
