Thay vì tin vào một mô hình duy nhất, ensemble kết hợp nhiều mô hình "yếu" (weak learner) thành một mô hình "mạnh". Tùy cách kết hợp, ta có thể chủ yếu giảm variance (Bagging) hoặc chủ yếu giảm bias (Boosting) — đây là nhóm thuật toán cho kết quả thực chiến tốt nhất trên dữ liệu bảng.
Một weak learner là mô hình chỉ nhỉnh hơn đoán mò một chút — thường là một cây quyết định nông (decision tree). Một cây đơn lẻ dễ thiên lệch hoặc quá nhạy với dữ liệu. Nhưng nếu ta huấn luyện rất nhiều cây rồi tổng hợp ý kiến của chúng, các lỗi ngẫu nhiên có xu hướng triệt tiêu lẫn nhau, còn tín hiệu chung thì được khuếch đại. Đó chính là ensemble learning.
Có hai chiến lược tổng hợp nền tảng, khác nhau căn bản ở chỗ các mô hình được huấn luyện song song hay tuần tự, và do đó tấn công vào thành phần lỗi nào trong phân rã bias–variance:
| Tiêu chí | Bagging (Bootstrap Aggregating) | Boosting |
|---|---|---|
| Cách huấn luyện | Song song — các mô hình độc lập, có thể train cùng lúc | Tuần tự — mô hình sau phụ thuộc kết quả mô hình trước |
| Dữ liệu cho mỗi mô hình | Mỗi mô hình học trên một mẫu bootstrap (lấy mẫu có hoàn lại từ tập gốc) | Cùng tập dữ liệu, nhưng trọng số mẫu/residual được điều chỉnh dần |
| Cách kết hợp | Bỏ phiếu đa số (phân loại) / trung bình (hồi quy) | Tổng có trọng số của các mô hình |
| Mục tiêu chính | Giảm VARIANCE (chống overfit) | Giảm BIAS (sửa dần các lỗi) |
| Rủi ro | Khó giảm bias nếu mô hình cơ sở quá đơn giản | Dễ overfit hơn nếu nhiễu nhiều / quá nhiều vòng |
| Đại diện | Random Forest | AdaBoost, Gradient Boosting (XGBoost…) |
Random Forest là ứng dụng kinh điển của Bagging cho cây quyết định. Nó huấn luyện một "khu rừng" gồm nhiều cây quyết định, với hai nguồn ngẫu nhiên để các cây khác nhau và ít tương quan với nhau:
Khi dự đoán, kết quả của rừng là sự tổng hợp của tất cả cây: bỏ phiếu đa số cho bài toán phân loại, và trung bình cho bài toán hồi quy. Vì variance của trung bình \(B\) biến ngẫu nhiên (gần) độc lập giảm theo số lượng, càng nhiều cây ít tương quan thì dự đoán càng ổn định.
Hai "đặc sản" miễn phí của Random Forest:
| Tính năng | Ý nghĩa |
|---|---|
| OOB error (Out-of-Bag) | Với mỗi cây, các mẫu không rơi vào bootstrap của nó (~37%) đóng vai trò tập kiểm tra "ẩn". Gộp lại cho ta ước lượng lỗi nội bộ mà không cần tách riêng validation set. |
| Feature importance | Đo mức độ một đặc trưng giúp giảm impurity (hoặc qua permutation) trên toàn rừng — biết đặc trưng nào quan trọng. |
| Ưu điểm | Nhược điểm |
|---|---|
| Mạnh và chính xác ngay với cấu hình mặc định | Khó diễn giải — một rừng hàng trăm cây gần như "hộp đen" |
| Ít overfit nhờ trung bình hóa nhiều cây | Mô hình lớn, tốn bộ nhớ và chậm khi dự đoán hàng loạt |
| Ít cần tinh chỉnh siêu tham số, chịu được nhiễu & đặc trưng thừa | Có thể thiên lệch với đặc trưng phân loại nhiều mức |
Boosting xây dựng ensemble theo kiểu tuần tự: mỗi mô hình mới được thêm vào với nhiệm vụ sửa lỗi của tổ hợp các mô hình trước đó. Nhờ "vá" dần các sai sót, boosting biến một chuỗi weak learner bias cao thành một mô hình tổng bias thấp.
AdaBoost (Adaptive Boosting) là phiên bản nền tảng. Ý tưởng: gán cho mỗi mẫu huấn luyện một trọng số. Ban đầu mọi mẫu có trọng số bằng nhau. Sau mỗi vòng, ta tăng trọng số những mẫu bị phân loại sai và giảm trọng số những mẫu đã đúng — buộc weak learner kế tiếp phải tập trung vào những ca khó.
Mỗi weak learner \(h_t\) tại vòng \(t\) được gán một trọng số (mức độ tin cậy) dựa trên lỗi có trọng số \(\epsilon_t\) của nó:
$$\alpha_t=\frac12\ln\frac{1-\epsilon_t}{\epsilon_t}$$Trực giác: nếu \(\epsilon_t\) nhỏ (learner tốt) thì \(\alpha_t\) lớn — tiếng nói của nó có trọng lượng cao; nếu \(\epsilon_t\) tiến tới \(0.5\) (đoán mò) thì \(\alpha_t \to 0\). Khi \(\epsilon_t \lt 0.5\) ta luôn có \(\alpha_t \gt 0\).
Trọng số của từng mẫu được cập nhật theo việc nó đúng hay sai (\(y_i\) là nhãn thật, \(h_t(x_i)\) là dự đoán):
$$w_i \leftarrow w_i \, e^{-\alpha_t \, y_i \, h_t(x_i)}$$Với mẫu đúng (\(y_i h_t(x_i) \gt 0\)) trọng số giảm; với mẫu sai (\(y_i h_t(x_i) \lt 0\)) trọng số tăng. Sau đó chuẩn hóa lại để \(\sum_i w_i = 1\).
Dự đoán cuối cùng là tổng có trọng số các weak learner, lấy dấu để ra nhãn \(\{-1, +1\}\):
$$H(x)=\text{sign}\Big(\sum_t \alpha_t \, h_t(x)\Big)$$Gradient Boosting tổng quát hóa ý tưởng boosting cho mọi hàm mất mát khả vi. Thay vì điều chỉnh trọng số mẫu như AdaBoost, mỗi mô hình mới được khớp vào gradient âm của loss tính trên dự đoán hiện tại — với loss bình phương, gradient âm chính là phần dư (residual = giá trị thật − giá trị dự đoán). Nói cách khác, từng cây mới học cách "đẩy" dự đoán đi đúng hướng làm loss giảm nhanh nhất.
Đây thực chất là gradient descent trong không gian hàm: mỗi cây là một bước đi theo hướng dốc nhất của loss, với learning rate \(\eta\) điều tiết độ lớn mỗi bước. Xem lại nền tảng tối ưu hóa ở bài Gradient Descent.
Ba thư viện gradient boosting được dùng nhiều nhất trong thực tế (và thường thắng trên dữ liệu bảng):
| Thư viện | Điểm mạnh nổi bật |
|---|---|
| XGBoost | Chuẩn mực thực chiến; có regularization, xử lý missing value, song song hóa tốt |
| LightGBM | Rất nhanh và nhẹ bộ nhớ; mọc cây theo leaf-wise, hợp dữ liệu lớn |
| CatBoost | Xử lý đặc trưng phân loại (categorical) cực tốt, ít cần tiền xử lý |
So sánh ba thuật toán ensemble tiêu biểu:
| Tiêu chí | Random Forest | AdaBoost | Gradient Boosting |
|---|---|---|---|
| Họ | Bagging | Boosting | Boosting |
| Huấn luyện | Song song | Tuần tự | Tuần tự |
| Giảm chủ yếu | Variance | Bias | Bias |
| Cơ chế sửa lỗi | Bỏ phiếu / trung bình | Tăng trọng số mẫu sai | Khớp gradient / residual của loss |
| Nhạy với nhiễu | Thấp | Cao | Trung bình (cần regularization) |
| Tinh chỉnh | Ít | Vừa | Nhiều (η, depth, số cây…) |
Cả ba đều có sẵn trong scikit-learn với cùng API fit / predict:
from sklearn.ensemble import ( RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier, ) from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42) # Random Forest — baseline mạnh, dùng OOB để ước lượng nội bộ rf = RandomForestClassifier(n_estimators=300, oob_score=True, max_features="sqrt", random_state=42) rf.fit(X_tr, y_tr) print("OOB:", rf.oob_score_) print("Importance:", rf.feature_importances_) # AdaBoost — tuần tự, tăng trọng số mẫu bị sai ada = AdaBoostClassifier(n_estimators=200, learning_rate=0.5, random_state=42) ada.fit(X_tr, y_tr) # Gradient Boosting — khớp residual của loss gb = GradientBoostingClassifier(n_estimators=300, learning_rate=0.05, max_depth=3, random_state=42) gb.fit(X_tr, y_tr) for name, model in [("RF", rf), ("Ada", ada), ("GB", gb)]: acc = accuracy_score(y_te, model.predict(X_te)) print(name, round(acc, 4))