Quy trình huấn luyện với scikit-learn
Bạn sẽ học được
- Đóng gói tiền xử lý và mô hình vào một
Pipeline. - Xử lý cột số và cột phân loại khác nhau bằng
ColumnTransformer. - Tránh rò rỉ khi chuẩn hoá và điền thiếu.
- Chạy cross-validation trên toàn pipeline.
- Lưu và tái sử dụng pipeline khi triển khai.
Khái niệm cốt lõi
Một mô hình thực tế gồm nhiều bước: điền giá trị thiếu, mã hoá biến phân loại, chuẩn hoá, rồi mới đến mô hình.
Nếu làm thủ công từng bước, rất dễ fit scaler trên toàn bộ dữ liệu — một dạng rò rỉ. Pipeline buộc mọi bước phải fit trên đúng tập train.
Pipeline = tiền xử lý → mô hìnhKhi gọi pipeline.fit(X_train, y_train), mọi bước chỉ thấy train. Khi gọi predict, chúng dùng tham số đã học từ train.
Ví dụ đầy đủ
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
numeric = ["tenure_months", "monthly_spend", "support_tickets"]
categorical = ["plan", "country", "channel"]
preprocess = ColumnTransformer(
transformers=[
(
"num",
Pipeline([
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler()),
]),
numeric,
),
(
"cat",
Pipeline([
("impute", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore")),
]),
categorical,
),
]
)
model = Pipeline([
("preprocess", preprocess),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(X_train, y_train)Ba chi tiết quan trọng:
handle_unknown="ignore"để dữ liệu mới có giá trị phân loại chưa từng thấy không làm lỗi.class_weight="balanced"giúp mô hình không bỏ qua lớp thiểu số.SimpleImputerđặt trong pipeline, không chạy trước khi chia dữ liệu.
Vì sao thứ tự quan trọng
Sai:
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # fit trên toàn bộ dữ liệu
X_train, X_test = train_test_split(X_scaled, ...)scaler đã học trung bình và độ lệch chuẩn của cả tập test. Thông tin test rò rỉ vào train, điểm đánh giá cao hơn thực tế.
Đúng:
model.fit(X_train, y_train) # scaler chỉ thấy X_train
score = model.score(X_test, y_test)Với dữ liệu lớn, chênh lệch có thể nhỏ và khó phát hiện — nhưng nguyên tắc vẫn phải giữ.
Cross-validation trên pipeline
from sklearn.model_selection import cross_val_score
scores = cross_val_score(
model,
X_train,
y_train,
cv=5,
scoring="roc_auc",
)
print(scores.mean().round(3), scores.std().round(3))Điểm quan trọng: truyền pipeline, không truyền dữ liệu đã tiền xử lý. Mỗi fold tự fit lại toàn bộ tiền xử lý trên phần train của fold đó.
Nếu tiền xử lý trước rồi mới cross-validate, mỗi fold đã thấy thông tin của fold khác.
Thiếu giá trị và giá trị ngoài miền
print(X.isna().mean().sort_values(ascending=False).head())Nếu một cột thiếu hơn 40–50%, cân nhắc bỏ thay vì điền. Điền quá nhiều tạo ra tín hiệu giả.
Với cột số, median bền hơn mean khi có ngoại lai. Với cột phân loại, most_frequent là mặc định hợp lý; có thể thêm nhãn "missing" như một phạm trù riêng nếu việc thiếu dữ liệu mang thông tin.
Lưu và triển khai
import joblib
joblib.dump(model, "churn_pipeline.joblib")
loaded = joblib.load("churn_pipeline.joblib")
loaded.predict(new_customers)Lưu cả pipeline, không lưu riêng mô hình. Nếu chỉ lưu mô hình, lúc dự đoán phải tự nhớ thứ tự và tham số tiền xử lý — gần như chắc chắn sẽ lệch.
Phiên bản thư viện cũng phải khớp khi tải lại. Ghi phiên bản scikit-learn vào tài liệu triển khai.
Kiểm tra pipeline trước khi báo cáo
- Fit trên train, dự đoán trên validation: điểm phải hợp lý, không sát 1,0.
- Kiểm tra
model.named_stepsđể chắc các bước có mặt. - Đếm số đặc trưng sau
ColumnTransformerbằngpreprocess.get_feature_names_out(). - Chạy một dòng dữ liệu mới chưa từng thấy để chắc không lỗi.
Lỗi thường gặp
- Fit scaler trên toàn bộ dữ liệu: rò rỉ.
- Điền thiếu trước khi chia: rò rỉ.
- One-hot không có
handle_unknown: lỗi khi gặp phạm trù mới. - Chỉ lưu mô hình, không lưu pipeline: dự đoán sai lệch.
- Cross-validate dữ liệu đã tiền xử lý: điểm lạc quan.
- Quên
class_weight: mô hình bỏ qua lớp thiểu số. - Đổi thứ tự cột khi dự đoán: kết quả sai nhưng không báo lỗi.
Thực hành
- Dựng
ColumnTransformercho ba cột số và ba cột phân loại. - Bọc trong
Pipelinevới logistic regression. - Chạy
cross_val_scorevới 5 fold. - So sánh điểm khi tiền xử lý sai thứ tự.
- Lưu pipeline bằng
joblibvà dự đoán một dòng mới.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Điểm CV cao hơn test nhiều | Tiền xử lý ngoài pipeline | Đưa vào pipeline |
| Lỗi khi dự đoán dữ liệu mới | Phạm trù chưa thấy | handle_unknown="ignore" |
| Kết quả khác sau khi tải lại | Chỉ lưu mô hình | Lưu cả pipeline |
| Cột phân loại bị bỏ qua | Sai tên cột | Kiểm tra get_feature_names_out |
| Mô hình đoán toàn lớp đa số | Không cân bằng trọng số | class_weight="balanced" |
Tóm tắt
Pipelinegiữ tiền xử lý và mô hình thành một khối.ColumnTransformerxử lý cột số và phân loại riêng.- Fit mọi thứ trên train, không bao giờ trên toàn bộ dữ liệu.
- Cross-validate trên pipeline, không trên dữ liệu đã xử lý.
- Lưu cả pipeline khi triển khai.
Dùng ← → để chuyển bài