Cross-validation và siêu tham số
Bạn sẽ học được
- Chọn kiểu cross-validation phù hợp với dữ liệu.
- Chạy
GridSearchCVtrên pipeline. - Hiểu vì sao điểm tìm được bằng grid search bị lạc quan.
- Dùng nested cross-validation để ước lượng khách quan.
- Đọc kết quả và tránh tối ưu quá mức.
Khái niệm cốt lõi
Cross-validation chia train thành K fold, huấn luyện trên K−1 fold và đánh giá trên fold còn lại, lặp K lần rồi lấy trung bình.
Fold 1: [val] [train] [train] [train] [train]
Fold 2: [train] [val] [train] [train] [train]
...Lợi ích: mọi dòng dữ liệu đều được dùng để đánh giá đúng một lần, và ta thấy được độ dao động giữa các fold.
Chọn kiểu chia
| Kiểu | Dùng khi |
|---|---|
KFold | Dữ liệu độc lập, lớp cân bằng |
StratifiedKFold | Phân loại, đặc biệt khi mất cân bằng |
GroupKFold | Nhiều dòng cho mỗi đối tượng |
TimeSeriesSplit | Dữ liệu chuỗi thời gian |
Với phân loại mất cân bằng, luôn dùng StratifiedKFold. Nếu không, có fold chỉ có vài ca dương và điểm dao động rất mạnh.
Cross-validation cơ bản
from sklearn.model_selection import StratifiedKFold, cross_val_score
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(
model,
X_train,
y_train,
cv=cv,
scoring="roc_auc",
)
print(scores)
print(f"{scores.mean():.3f} ± {scores.std():.3f}")Truyền pipeline, không truyền dữ liệu đã tiền xử lý. Mỗi fold phải tự fit lại toàn bộ tiền xử lý.
Độ lệch chuẩn quan trọng: 0,86 ± 0,01 ổn định hơn 0,86 ± 0,06 rất nhiều, dù trung bình bằng nhau.
Tìm siêu tham số
from sklearn.model_selection import GridSearchCV
param_grid = {
"clf__C": [0.01, 0.1, 1, 10],
"clf__class_weight": [None, "balanced"],
}
search = GridSearchCV(
model,
param_grid,
cv=cv,
scoring="roc_auc",
n_jobs=-1,
refit=True,
)
search.fit(X_train, y_train)
print(search.best_params_)
print(search.best_score_)Lưu ý cú pháp: tham số của bước trong pipeline cần tiền tố clf__. Viết C thay vì clf__C sẽ báo lỗi.
Số lần huấn luyện: 4 × 2 = 8 tổ hợp, mỗi tổ hợp 5 fold → 40 lần fit. Với dữ liệu lớn, cân nhắc RandomizedSearchCV hoặc giảm lưới.
Vì sao best_score_ bị lạc quan
best_score_ là giá trị cao nhất trong 8 tổ hợp. Chọn cao nhất trong nhiều lần thử luôn thiên lên — kể cả khi mọi tổ hợp tương đương, tổ hợp may mắn nhất sẽ thắng.
Với lưới lớn và tập nhỏ, chênh lệch có thể 2–5 điểm AUC. Đó là lý do không được báo cáo best_score_ như hiệu năng thật.
Cách đúng: dùng validation riêng, hoặc nested CV.
Nested cross-validation
from sklearn.model_selection import cross_val_score
inner = GridSearchCV(model, param_grid, cv=cv, scoring="roc_auc")
outer = cross_val_score(
inner,
X_train,
y_train,
cv=cv,
scoring="roc_auc",
)
print(f"{outer.mean():.3f} ± {outer.std():.3f}")Vòng ngoài đánh giá quy trình "tìm siêu tham số rồi huấn luyện", vòng trong tìm siêu tham số. Điểm vòng ngoài là ước lượng khách quan.
Chi phí: 5 fold ngoài × 5 fold trong × 8 tổ hợp = 200 lần fit. Chấp nhận được với dữ liệu vừa; với dữ liệu lớn cần giảm lưới.
Sau khi tìm được siêu tham số
- Huấn luyện lại trên toàn bộ train với tham số tốt nhất (
refit=Truelàm việc này). - Đánh giá một lần trên test.
- Ghi lại cả điểm validation và test.
Nếu test thấp hơn validation nhiều, quay lại kiểm tra rò rỉ và kích thước mẫu — đừng chỉnh tham số cho đến khi test đẹp.
Lỗi thường gặp
- Cross-validate dữ liệu đã tiền xử lý: rò rỉ.
- Dùng
KFoldcho dữ liệu mất cân bằng: fold thiếu ca dương. - Dùng
KFoldcho dữ liệu thời gian: rò rỉ tương lai. - Báo cáo
best_score_: lạc quan. - Lưới quá lớn: tốn thời gian, tăng nguy cơ chọn may mắn.
- Chỉnh tham số theo test: test mất giá trị.
- Bỏ qua độ lệch chuẩn: chọn mô hình không ổn định.
Thực hành
- Chạy
StratifiedKFold5 fold trên pipeline. - Chạy
GridSearchCVvới lướiCbốn giá trị. - So sánh
best_score_với điểm validation riêng. - Chạy nested CV và so sánh.
- Thử
TimeSeriesSplittrên dữ liệu có cột ngày.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Điểm CV dao động mạnh | Fold quá nhỏ hoặc không stratify | StratifiedKFold, tăng K |
| Lỗi "invalid parameter" | Thiếu tiền tố bước | clf__C |
best_score_ cao hơn test | Chọn cực trị | Dùng nested CV |
| CV cao bất thường | Tiền xử lý ngoài pipeline | Đưa vào pipeline |
| Chạy quá lâu | Lưới quá lớn | Giảm lưới hoặc randomized |
Tóm tắt
- Chọn kiểu CV theo cấu trúc dữ liệu.
- Luôn cross-validate trên pipeline.
best_score_là cực trị, không phải ước lượng khách quan.- Nested CV cho ước lượng đáng tin, đổi lại chi phí tính toán.
- Chỉ chạm test một lần sau khi đã chốt mọi thứ.
Dùng ← → để chuyển bài