Một model chỉ có ý nghĩa khi input của nó có sẵn lúc cần dự đoán, và output trả lời đúng câu hỏi đề đặt ra. Ba ví dụ dưới đây đi từ một bảng nhỏ, tới một baseline, rồi tới bước ghép dự đoán với đúng mã buổi.
Ví dụ 1: Chọn thông tin để chuẩn bị ghế
Mỗi hàng là một buổi sinh hoạt của câu lạc bộ. Chiều thứ Sáu, ta đã biết số người đăng ký và dự báo mưa. Số người thật sự đến thì phải sau buổi mới biết. Việc cần làm là dự đoán số người đến, còn mã buổi chỉ dùng để ghép kết quả.
import pandas as pd
sessions = pd.DataFrame({
"session_id": ["S01", "S02", "S03"],
"registered": [20, 30, 40],
"rain_forecast": [0.0, 0.5, 1.0],
"attendance": [18, 23, 28],
})
features = ["registered", "rain_forecast"]
X = sessions[features] # Bảng hai chiều: mỗi hàng là một buổi, mỗi cột là một feature.
y = sessions["attendance"] # Target là vector một chiều, và không được nằm trong X.
print("X/y shape:", X.shape, y.shape)
print("Feature:", X.columns.tolist())
print("Nhãn nếu hỏi có ít nhất 25 người:", (y >= 25).astype(int).tolist())
assert "attendance" not in X.columns
assert "session_id" not in X.columns
X/y shape: (3, 2) (3,)
Feature: ['registered', 'rain_forecast']
Nhãn nếu hỏi có ít nhất 25 người: [0, 0, 1]
Shape (3, 2) nghĩa là ba buổi, mỗi buổi có hai thông tin biết trước. Hai dòng assert ở cuối kiểm hai lỗi hay gặp nhất: để lọt chính đáp án vào input, và để lọt mã buổi vào làm feature. Nếu đổi câu hỏi thành “buổi này có ít nhất 25 người không”, nhãn trở thành 0, 0, 1. Vẫn là bảng dữ liệu ấy, nhưng bài toán đã chuyển từ regression sang classification.
Ví dụ 2: So baseline với một quy luật tuyến tính
Sáu buổi train dưới đây được dựng theo một quy luật giả định: attendance = 2 + 0.8 × registered − 6 × rain_forecast. Hai buổi validation lệch khỏi quy luật một người, để thay cho những yếu tố ta chưa ghi lại được. Câu hỏi là: dùng feature có giúp MAE giảm so với cách đoán bằng trung bình train không?
import numpy as np
import pandas as pd
from sklearn.dummy import DummyRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
train = pd.DataFrame({
"registered": [10, 20, 30, 10, 20, 30],
"rain_forecast": [0, 0, 0, 1, 1, 1],
"attendance": [10, 18, 26, 4, 12, 20],
})
valid = pd.DataFrame({
"registered": [25, 15],
"rain_forecast": [0.5, 0.5],
"attendance": [20, 10],
})
columns = ["registered", "rain_forecast"]
models = {"mean": DummyRegressor(), "linear": LinearRegression()}
valid_errors = {}
for name, model in models.items():
model.fit(train[columns], train["attendance"])
prediction = model.predict(valid[columns])
valid_errors[name] = mean_absolute_error(valid["attendance"], prediction)
print(f"{name}: prediction={np.round(prediction, 2).tolist()}, MAE={valid_errors[name]:.2f} người")
chosen = min(valid_errors, key=valid_errors.get)
print("Chọn bằng validation:", chosen)
print("Hệ số linear:", np.round(models["linear"].coef_, 2).tolist())
mean: prediction=[15.0, 15.0], MAE=5.00 người
linear: prediction=[19.0, 11.0], MAE=1.00 người
Chọn bằng validation: linear
Hệ số linear: [0.8, -6.0]
Trung bình của sáu target trong train là 15, nên baseline đoán cả hai buổi là 15, và sai trung bình 5 người. Linear đoán 19 và 11, mỗi buổi chỉ lệch 1 người. Hai hệ số 0.8 và −6 khớp đúng với quy luật đã dựng: thêm 10 người đăng ký thì có thêm khoảng 8 người đến, còn trời chắc chắn mưa thì bớt 6 người. Baseline luôn là việc nên làm đầu tiên, vì nó cho ta một mốc để biết model có thật sự giúp gì không. Ở đây kết quả chỉ kiểm quy trình trên dữ liệu giả lập, chưa nói gì về một câu lạc bộ thật.
Ví dụ 3: Dự đoán đúng, nhưng ghép nhầm mã buổi
Dữ liệu mới có các mã theo thứ tự S09, S07, S08, chứ không tăng dần. Một model học từ bốn buổi nhỏ sẽ dự đoán cho cả ba buổi, lần này không có target. Sau đó ta kiểm file CSV, và thử xem một lỗi sắp xếp làm hỏng kết quả ra sao.
from io import StringIO
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
train = pd.DataFrame({"registered": [10, 20, 30, 40]})
y_train = np.array([9, 17, 25, 33])
model = LinearRegression().fit(train, y_train)
new = pd.DataFrame({
"session_id": ["S09", "S07", "S08"],
"registered": [35, 15, 25],
})
prediction = np.round(model.predict(new[["registered"]]), 2)
result = pd.DataFrame({"session_id": new["session_id"], "attendance": prediction})
read_back = pd.read_csv(StringIO(result.to_csv(index=False)))
assert read_back.columns.tolist() == ["session_id", "attendance"]
assert read_back["session_id"].tolist() == new["session_id"].tolist()
assert read_back["session_id"].is_unique
assert np.isfinite(read_back["attendance"]).all()
print(read_back.to_string(index=False))
wrong = result.copy()
wrong["attendance"] = np.sort(prediction) # Số hàng vẫn đúng, nhưng mỗi dự đoán đã sang tay buổi khác.
print("Ghép đúng sau khi sort riêng prediction:", wrong.equals(result))
session_id attendance
S09 29.0
S07 13.0
S08 21.0
Ghép đúng sau khi sort riêng prediction: False
Buổi S09 có 35 người đăng ký, nên phải nhận dự đoán 29 người. Nếu sắp xếp riêng cột dự đoán, nó lại nhận 13 người, vốn là của S07. File vẫn đủ hàng, đủ cột, không có lỗi nào được báo, nhưng điểm sẽ tệ đi rất nhiều. Kiểm shape và tên cột là cần, nhưng chưa đủ, ta còn phải kiểm mỗi ID có đi cùng đúng dự đoán của nó không. Khi cần sắp theo ID, hãy sắp cả hàng của bảng kết quả, đừng sắp riêng một cột.