Học có giám sát (supervised learning) là nhóm thuật toán học từ dữ liệu đã có nhãn — mỗi mẫu gồm đặc trưng đầu vào X và đáp án đúng y. Bài này đi qua các thuật toán nền tảng: Linear/Logistic Regression, k-NN, Decision Tree, Random Forest, Boosting, SVM và Naive Bayes — kèm trực giác, khi nào dùng, các hyperparameter quan trọng và code sklearn thực chiến.
Học có giám sát: ta có tập huấn luyện gồm nhiều cặp (X, y) — X là ma trận đặc trưng (features, mỗi dòng một mẫu, mỗi cột một biến), y là nhãn/đáp án. Mô hình học một hàm f(X) ≈ y để khi gặp X mới (chưa từng thấy) có thể dự đoán y. "Có giám sát" nghĩa là quá trình học được "chấm điểm" bằng đáp án đúng đã biết.
Hai bài toán chính, phân biệt bởi kiểu của y:
| Loại | y là gì | Ví dụ | Ví dụ thuật toán |
|---|---|---|---|
| Regression (hồi quy) | Số thực liên tục | Dự đoán giá nhà, doanh thu, nhiệt độ | Linear Regression, Random Forest Regressor, XGBoost |
| Classification (phân loại) | Nhãn rời rạc (2 lớp hoặc nhiều lớp) | Spam/không spam, chẩn đoán bệnh, nhận dạng chữ số | Logistic Regression, k-NN, SVM, Random Forest |
Mọi mô hình sklearn đều theo một API thống nhất: model.fit(X_train, y_train) để học, rồi model.predict(X_test) để dự đoán. Điều then chốt là đánh giá trên dữ liệu chưa từng thấy (test set) — mô hình học thuộc lòng train nhưng dự đoán tệ trên dữ liệu mới gọi là overfitting.
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y) model.fit(X_train, y_train) y_pred = model.predict(X_test)
DummyClassifier(strategy="most_frequent"), với regression so với dự đoán trung bình. Một mô hình phức tạp không thắng nổi baseline là dấu hiệu có gì đó sai (leak, feature yếu, hoặc bài toán khó hơn tưởng).Trực giác: giả sử y phụ thuộc tuyến tính vào các đặc trưng — vẽ một đường/mặt phẳng khớp nhất với đám điểm dữ liệu. Mô hình: ŷ = w₀ + w₁x₁ + w₂x₂ + … + wₙxₙ, trong đó w₀ là intercept (hệ số chặn) và wᵢ là trọng số của từng đặc trưng.
Hàm mất mát (cost) — MSE: trung bình bình phương sai số MSE = (1/m) Σ (yᵢ − ŷᵢ)². Ta tìm bộ w tối thiểu hoá MSE. Nghiệm có công thức đóng (Normal Equation): w = (XᵀX)⁻¹ Xᵀy; với dữ liệu lớn sklearn dùng phân rã ma trận / gradient descent thay vì nghịch đảo trực tiếp.
Giả định quan trọng: quan hệ tuyến tính; phần dư (residual) độc lập, phương sai đồng nhất (homoscedasticity) và xấp xỉ phân phối chuẩn; ít đa cộng tuyến.
Đa cộng tuyến (multicollinearity): khi hai đặc trưng tương quan mạnh, XᵀX gần suy biến → hệ số w trở nên bất ổn, dấu và độ lớn vô nghĩa (khó diễn giải). Kiểm tra bằng VIF; xử lý bằng bỏ bớt biến hoặc dùng regularization (mục sau).
from sklearn.linear_model import LinearRegression lr = LinearRegression().fit(X_train, y_train) # lr.coef_ = trọng số wᵢ, lr.intercept_ = w₀ from sklearn.metrics import mean_squared_error, r2_score print(r2_score(y_test, lr.predict(X_test))) # R² càng gần 1 càng tốt
Ý tưởng: thêm một "hình phạt" vào cost để giữ trọng số w nhỏ → mô hình đơn giản hơn, bớt overfit, ổn định hơn khi có đa cộng tuyến. Tham số alpha (hay λ) điều khiển mức phạt: alpha lớn = phạt mạnh = mô hình đơn giản hơn (bias tăng, variance giảm).
| Phương pháp | Hình phạt | Đặc điểm |
|---|---|---|
| Ridge (L2) | + α Σ wᵢ² | Co nhỏ các hệ số nhưng hiếm khi về đúng 0. Rất tốt khi có đa cộng tuyến; giữ lại toàn bộ đặc trưng. |
| Lasso (L1) | + α Σ |wᵢ| | Đẩy một số hệ số về đúng 0 → tự động feature selection. Hữu ích khi nghi ngờ nhiều đặc trưng vô dụng. |
| Elastic Net | trộn L1 + L2 | Kết hợp cả hai (l1_ratio). Tốt khi nhiều đặc trưng tương quan theo nhóm. |
from sklearn.linear_model import Ridge, Lasso, ElasticNet Ridge(alpha=1.0).fit(X_train, y_train) Lasso(alpha=0.1).fit(X_train, y_train) # hệ số =0 bị loại ElasticNet(alpha=0.1, l1_ratio=0.5).fit(X_train, y_train)
StandardScaler trong một Pipeline để tránh phạt thiên lệch.Bất chấp cái tên "regression", đây là thuật toán phân loại. Nó tính tổ hợp tuyến tính z = w·x + b rồi bóp qua hàm sigmoid σ(z) = 1 / (1 + e⁻ᶻ) để ra một xác suất trong khoảng [0, 1].
Hàm mất mát — log-loss (cross-entropy): −(1/m) Σ [ y·log(p) + (1−y)·log(1−p) ]. Phạt rất nặng khi mô hình tự tin nhưng sai.
Ngưỡng (threshold): mặc định dự đoán lớp 1 nếu p ≥ 0.5. Có thể chỉnh ngưỡng để đánh đổi precision/recall (vd bài toán y tế hạ ngưỡng để bắt nhiều ca dương tính hơn).
Đọc hệ số / odds: mỗi hệ số wᵢ là log-odds. exp(wᵢ) là odds ratio: nếu exp(w)=1.5 thì tăng 1 đơn vị đặc trưng làm odds thuộc lớp 1 tăng 50% (giữ nguyên các biến khác). Đây là lý do Logistic Regression được ưa dùng khi cần giải thích (tín dụng, y tế). Có tham số C (nghịch đảo mức regularization) và penalty.
from sklearn.linear_model import LogisticRegression clf = LogisticRegression(C=1.0, max_iter=1000).fit(X_train, y_train) proba = clf.predict_proba(X_test)[:, 1] # xác suất lớp 1 pred = (proba >= 0.5).astype(int) # tự chỉnh ngưỡng
Trực giác: không "học" gì cả (lazy learning) — lưu toàn bộ dữ liệu train. Khi dự đoán một điểm mới, tìm k điểm gần nhất (theo khoảng cách Euclid) rồi lấy nhãn đa số (classification) hoặc trung bình (regression).
Chọn k: k nhỏ (vd 1) → bám nhiễu, variance cao, dễ overfit; k lớn → mượt hơn nhưng có thể bỏ qua cấu trúc cục bộ (underfit). Thường thử k lẻ (tránh hòa) bằng cross-validation.
Cần scaling: vì dựa trên khoảng cách, đặc trưng có thang đo lớn sẽ áp đảo → bắt buộc chuẩn hoá. Chi phí: train gần như miễn phí nhưng dự đoán chậm (phải so với mọi điểm) và tốn bộ nhớ; kém với dữ liệu nhiều chiều (curse of dimensionality).
from sklearn.neighbors import KNeighborsClassifier from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler knn = make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5)) knn.fit(X_train, y_train)
Trực giác: chia dữ liệu bằng một loạt câu hỏi ngưỡng ("tuổi > 30?", "thu nhập > 50tr?"), tạo cây nhị phân; mỗi lá là một dự đoán. Rất trực quan, không cần scaling, xử lý được cả biến số và biến hạng.
Chia theo tiêu chí nào: tại mỗi nút, chọn đặc trưng + ngưỡng làm "trong sạch" nhất các nhánh con. Đo độ vẩn đục bằng Gini impurity 1 − Σ pᵢ² hoặc entropy −Σ pᵢ log pᵢ (information gain). Hai tiêu chí thường cho kết quả tương tự.
Vấn đề overfit: cây để mọc tự do sẽ nhớ từng mẫu train (lá thuần khiết) → dự đoán tệ trên dữ liệu mới. Kiểm soát bằng các tham số:
from sklearn.tree import DecisionTreeClassifier dt = DecisionTreeClassifier(max_depth=5, min_samples_leaf=20, criterion="gini").fit(X_train, y_train) # dt.feature_importances_ cho biết biến nào quan trọng
Ý tưởng chung: kết hợp nhiều mô hình để thắng một mô hình đơn. Có hai trường phái đối lập về cách kết hợp:
| Bagging (Random Forest) | Boosting (XGBoost…) | |
|---|---|---|
| Cách học | Song song, độc lập | Tuần tự, cây sau sửa lỗi cây trước |
| Mục tiêu chính | Giảm variance | Giảm bias (và variance) |
| Cây thành phần | Cây sâu (khác nhau nhờ bootstrap + random features) | Cây nông (weak learners) |
| Rủi ro | Khó overfit, an toàn | Dễ overfit nếu chỉnh sai, cần tinh chỉnh |
Bagging & Random Forest: huấn luyện nhiều cây, mỗi cây trên một mẫu bootstrap (lấy có hoàn lại) của dữ liệu; Random Forest bổ sung: mỗi lần chia chỉ xét một tập con ngẫu nhiên các đặc trưng → các cây ít tương quan → gộp (vote/trung bình) cho kết quả ổn định. Tham số chính: n_estimators (số cây, càng nhiều càng ổn), max_depth, max_features. Là lựa chọn "mặc định mạnh" cho dữ liệu bảng.
Boosting: xây cây tuần tự, mỗi cây tập trung vào lỗi còn lại của cả đội trước đó.
Tham số chính của boosting: n_estimators (số cây), learning_rate (bước học — nhỏ thì cần nhiều cây hơn nhưng ổn định hơn; đánh đổi với n_estimators), max_depth (thường nông 3–8). Tinh chỉnh cặp learning_rate ↔ n_estimators là quan trọng nhất.
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier rf = RandomForestClassifier(n_estimators=300, max_depth=None, n_jobs=-1).fit(X_train, y_train) # XGBoost (thư viện riêng: pip install xgboost) from xgboost import XGBClassifier xgb = XGBClassifier(n_estimators=400, learning_rate=0.05, max_depth=4, subsample=0.8).fit(X_train, y_train)
Trực giác: tìm siêu phẳng (hyperplane) phân tách hai lớp sao cho margin (khoảng cách tới điểm gần nhất của mỗi lớp) là lớn nhất. Các điểm nằm sát lề gọi là support vectors — chỉ chúng quyết định ranh giới.
Kernel giúp phân tách dữ liệu không tuyến tính bằng cách ánh xạ lên không gian cao chiều mà không tính tường minh (kernel trick): linear (dữ liệu tách tuyến tính, nhiều đặc trưng như text), rbf (mặc định, biên cong linh hoạt).
Hai tham số cốt lõi: C (đánh đổi lề rộng ↔ ít lỗi train: C lớn = phạt lỗi nặng = lề hẹp, dễ overfit), gamma (với RBF: tầm ảnh hưởng của một điểm — gamma lớn = biên uốn sát từng điểm = overfit). SVM cần scaling và chậm trên dữ liệu rất lớn.
from sklearn.svm import SVC svm = make_pipeline(StandardScaler(), SVC(kernel="rbf", C=1.0, gamma="scale")) svm.fit(X_train, y_train)
Dựa trên định lý Bayes với giả định "ngây thơ" (naive): các đặc trưng độc lập với nhau khi biết lớp. Dù giả định hiếm khi đúng, nó chạy cực nhanh, cần ít dữ liệu và mạnh bất ngờ cho phân loại văn bản / lọc spam. Biến thể: MultinomialNB (đếm từ), GaussianNB (đặc trưng liên tục), BernoulliNB (nhị phân).
from sklearn.naive_bayes import MultinomialNB nb = MultinomialNB().fit(X_train, y_train)
| Thuật toán | Ưu điểm | Nhược điểm | Khi nào dùng |
|---|---|---|---|
| Linear/Logistic Regression | Nhanh, dễ diễn giải hệ số, baseline tốt | Chỉ bắt quan hệ tuyến tính | Baseline; khi cần giải thích; dữ liệu tuyến tính |
| Ridge/Lasso | Chống overfit, Lasso chọn đặc trưng | Vẫn tuyến tính, cần scale | Nhiều đặc trưng / đa cộng tuyến |
| k-NN | Đơn giản, không giả định, phi tuyến | Dự đoán chậm, cần scale, kém khi nhiều chiều | Dữ liệu nhỏ, biên phức tạp |
| Decision Tree | Trực quan, không cần scale, đọc được luật | Overfit, variance cao | Cần giải thích luật; làm nền cho ensemble |
| Random Forest | Mạnh, ít chỉnh, chống overfit, đo importance | Nặng bộ nhớ, kém diễn giải, không extrapolate | Lựa chọn "mặc định" cho dữ liệu bảng |
| Gradient Boosting / XGBoost / LightGBM | Độ chính xác cao nhất trên dữ liệu bảng | Nhạy hyperparameter, dễ overfit, huấn luyện tuần tự | Khi cần accuracy tối đa và chịu tinh chỉnh |
| SVM | Hiệu quả khi nhiều chiều, biên rõ ràng | Chậm với dữ liệu lớn, khó chỉnh, cần scale | Dữ liệu vừa, nhiều đặc trưng (text) |
| Naive Bayes | Cực nhanh, ít dữ liệu vẫn chạy | Giả định độc lập phi thực tế | Phân loại văn bản, lọc spam |