Rò rỉ dữ liệu trong tiền xử lý: Sai lầm đảo thứ tự khiến mô hình gian lận điểm số kiểm thử

Trong bài toán hồi quy dự báo giá xe ô tô bằng mô hình MLPRegressor trên tập dữ liệu gồm 193 mẫu, việc đảo ngược thứ tự thực thi của hai dòng mã tiền xử lý đã khiến hệ số xác định $R^2$ kiểm thử tăng vọt giả tạo từ 0.767 lên 0.887. Sai số trung bình bình phương (MSE) bị bóp méo từ 26,2 triệu xuống còn 6,9 triệu, tương đương sai số thực tế RMSE bị che giấu từ khoảng $5.120 xuống $2.630 mỗi xe. Bản chất của hiện tượng này là data leakage (rò rỉ dữ liệu) ở mức độ vi mô nhưng để lại sai lệch lớn trên độ đo đánh giá.

So sánh hiệu năng giữa pipeline rò rỉ dữ liệu và pipeline hiệu chỉnh trên hệ thống theo dõi thực nghiệm Weights & Biases.
So sánh hiệu năng giữa pipeline rò rỉ dữ liệu và pipeline hiệu chỉnh trên hệ thống theo dõi thực nghiệm Weights & Biases.

Bản chất hiện tượng rò rỉ dữ liệu trong tiền xử lý

Nghiên cứu kinh điển của Kaufman, Rosset, Perlich và Stitelman (2012) trên tạp chí ACM Transactions on Knowledge Discovery from Data với tiêu đề “Leakage in Data Mining: Formulation, Detection, and Avoidance” chỉ ra rằng: rò rỉ dữ liệu xuất hiện bất cứ khi nào mô hình vô tình tiếp cận thông tin lẽ ra phải được bảo mật tại thời điểm đánh giá. Một trường hợp điển hình diễn ra tại cuộc thi INFORMS 2010 Data Mining Challenge, nơi các thí sinh đã đảo ngược danh tính cổ phiếu ẩn trong tập kiểm thử bằng cách khớp mẫu với dữ liệu tài chính công khai, tạo ra điểm số vượt trội không phản ánh năng lực khái quát hóa thực tế của thuật toán.

Tuy nhiên, các lỗi rò rỉ phổ biến trong thực tế kỹ thuật thường tinh vi hơn rất nhiều. Hiện tượng này phát sinh trực tiếp từ việc tính toán các thống kê mô tả (distributional statistics) trên toàn bộ tập dữ liệu trước khi phân tách tập kiểm thử (train-test split).

Thực nghiệm trên tập dữ liệu Automobile

Thực nghiệm được triển khai trên tập dữ liệu Automobile của UCI (được Jeffrey Schlimmer đóng góp năm 1987, trích xuất từ 1985 Ward’s Automotive Yearbook, cấp phép CC BY 4.0). Sau khi loại bỏ các thuộc tính chứa lượng lớn giá trị khuyết thiếu và lọc sạch các hàng còn lại, tập dữ liệu chuẩn hóa gồm 193 bản ghi với 24 biến dự báo (16 biến định lượng như mã lực, dung tích động cơ, khối lượng bản thân; 8 biến định danh như loại nhiên liệu, vị trí đặt động cơ) và biến mục tiêu là giá bán.

Kiến trúc mô hình được cố định là mạng nơ-ron truyền thẳng Multilayer Perceptron (MLP) với cấu hình hai tầng ẩn:

MLPRegressor(
    hidden_layer_sizes=(64, 64),
    max_iter=1000,
    random_state=42,
)

Tập dữ liệu 193 bản ghi được phân chia thành ba phần độc lập:

  • Tập huấn luyện (Training set): 60% (115 bản ghi), dùng để tối ưu hóa trọng số mô hình.
  • Tập kiểm định (Validation set): 20% (39 bản ghi), phục vụ tinh chỉnh siêu tham số và kiểm soát quá khớp.
  • Tập kiểm thử (Test set): 20% (39 bản ghi), chỉ đánh giá một lần duy nhất khi mô hình hoàn tất.
Cấu trúc phân chia tập dữ liệu Automobile gồm 193 bản ghi thành ba tập huấn luyện, kiểm định và kiểm thử.
Cấu trúc phân chia tập dữ liệu Automobile gồm 193 bản ghi thành ba tập huấn luyện, kiểm định và kiểm thử.

Sai lầm đảo thứ tự trong luồng tiền xử lý

Trong quy trình có lỗi rò rỉ, mã nguồn thực hiện làm sạch dữ liệu ngoại lai bằng phương pháp chặn khoảng tứ phân vị (IQR capping), chuẩn hóa biến định lượng bằng StandardScaler và mã hóa biến định danh qua OneHotEncoder trên toàn bộ ma trận dữ liệu trước khi gọi hàm train_test_split:

# Outlier handling via IQR capping
for col in numerical_cols + ["price"]:
    Q1 = df[col].quantile(0.25)
    Q3 = df[col].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    df[col] = df[col].clip(lower=lower_bound, upper=upper_bound)

# Preprocessing pipeline
preprocessor = ColumnTransformer(transformers=[
    ("num", StandardScaler(), numerical_cols),
    ("cat", OneHotEncoder(handle_unknown="ignore"), categorical_cols),
])

# Transform the data
X_processed = preprocessor.fit_transform(X)

# Train-validation-test split
X_train_val, X_test, y_train_val, y_test = train_test_split(
    X_processed, y, test_size=0.2, random_state=42
)

Vấn đề kỹ thuật cốt lõi nằm ở vị trí gọi hàm fit_transform. Khi chạy trên toàn bộ tập $X$:

  • Ngưỡng chặn ngoại lai $[Q_1 – 1.5 \times IQR, Q_3 + 1.5 \times IQR]$ tính toán dựa trên cả các điểm dữ liệu thuộc tập kiểm thử tương lai.
  • StandardScaler sử dụng kỳ vọng $\mu$ và độ lệch chuẩn $\sigma$ của toàn thể tập hợp (bao gồm tập kiểm thử).
  • OneHotEncoder ghi nhận không gian nhãn định danh từ cả tập kiểm thử.

Hiện tượng này không làm trùng lặp bản ghi, nhưng các giá trị phân phối của tập kiểm thử đã gián tiếp điều chỉnh trọng số chuẩn hóa và biên dữ liệu, làm phát sinh điểm kiểm thử ảo $R^2 = 0.887$.

Sơ đồ quy trình tiền xử lý sai thứ tự dẫn đến hiện tượng rò rỉ thống kê từ tập kiểm thử sang tập huấn luyện.
Sơ đồ quy trình tiền xử lý sai thứ tự dẫn đến hiện tượng rò rỉ thống kê từ tập kiểm thử sang tập huấn luyện.

Tái cấu trúc pipeline loại bỏ hoàn toàn rò rỉ dữ liệu

Giải pháp chuẩn mực yêu cầu phân tách tập dữ liệu thành các phân vùng độc lập trước tiên. Mọi phép ước lượng thống kê (phương thức fit hoặc fit_transform) tuyệt đối chỉ được thực thi trên tập training. Các tập validation và test chỉ áp dụng các tham số đã học qua phương thức transform:

X_train_val, X_test, y_train_val, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
X_train, X_val, y_train, y_val = train_test_split(
    X_train_val, y_train_val, test_size=0.25, random_state=42
)

# IQR bounds computed from the training rows only
bounds = {}
for col in numerical_cols:
    Q1 = X_train[col].quantile(0.25)
    Q3 = X_train[col].quantile(0.75)
    IQR = Q3 - Q1
    bounds[col] = (Q1 - 1.5 * IQR, Q3 + 1.5 * IQR)

def apply_bounds(frame):
    frame = frame.copy()
    for col, (lower, upper) in bounds.items():
        frame[col] = frame[col].clip(lower=lower, upper=upper)
    return frame

X_train = apply_bounds(X_train)
X_val = apply_bounds(X_val)
X_test = apply_bounds(X_test)

# Cap outlier prices in the training target only, using bounds from
# training prices. Validation and test prices are left as observed,
# since scoring against a clipped target would hide real errors.
price_q1, price_q3 = y_train.quantile(0.25), y_train.quantile(0.75)
price_iqr = price_q3 - price_q1
y_train = y_train.clip(
    lower=price_q1 - 1.5 * price_iqr, upper=price_q3 + 1.5 * price_iqr
)

preprocessor = ColumnTransformer(transformers=[
    ("num", StandardScaler(), numerical_cols),
    ("cat", OneHotEncoder(handle_unknown="ignore"), categorical_cols),
])

X_train_p = preprocessor.fit_transform(X_train)
X_val_p = preprocessor.transform(X_val)
X_test_p = preprocessor.transform(X_test)

mlp = MLPRegressor(hidden_layer_sizes=(64, 64), max_iter=1000, random_state=42)
mlp.fit(X_train_p, y_train)

Một nguyên tắc quan trọng: việc xử lý ngoại lai trên biến mục tiêu price chỉ áp dụng cho y_train. Nhãn trên tập y_val và y_test phải giữ nguyên giá trị quan sát gốc, bởi việc cắt xén nhãn kiểm thử sẽ che giấu sai số thực của mô hình khi triển khai.

Phân phối sai số dự báo và chênh lệch R bình phương giữa hai phương án tiền xử lý dữ liệu.
Phân phối sai số dự báo và chênh lệch R bình phương giữa hai phương án tiền xử lý dữ liệu.

Định lượng tổn thất kỹ thuật từ rò rỉ dữ liệu

Toàn bộ số liệu thực nghiệm được đồng bộ trên báo cáo Weights & Biases (W&B), xác nhận độ chênh lệch hiệu năng giữa hai thiết lập:

  • Hệ số xác định $R^2$ kiểm thử: Giảm từ 0.887 xuống 0.767 (chênh lệch 12 điểm phần trăm).
  • Sai số toàn phương trung bình (MSE): Tăng từ 6,9 triệu lên xấp xỉ 26,2 triệu (tăng gần gấp 4 lần).
  • Sai số tuyệt căn trung bình (RMSE): Tăng từ $2.630 lên $5.120 trên mỗi đơn vị xe.

Khoảng cách 12 điểm $R^2$ này là ranh giới giữa một mô hình biểu kiến xuất sắc và một mô hình ở mức độ chấp nhận được. Trên các tập dữ liệu nhỏ (193 dòng, kiểm thử 39 dòng), sự dịch chuyển kỳ vọng và phương sai do các mẫu kiểm thử gây ra tác động mạnh hơn so với các tập dữ liệu quy mô lớn. Dù vậy, khuynh hướng thổi phồng độ chính xác kiểm thử luôn tồn tại trong mọi quy mô dữ liệu nếu vi phạm thứ tự pipeline.

Vai trò thẩm định của tập kiểm định độc lập

Việc khởi tạo tập validation nhưng không thực thi suy luận đánh giá là một thiếu sót phổ biến trong thực hành kỹ nghệ dữ liệu. Khi đánh giá pipeline hiệu chỉnh trên cả ba tập dữ liệu, khoảng cách giữa $R^2$ huấn luyện và $R^2$ kiểm thử đạt khoảng 0.10. Đây là mức suy giảm thông thường phản ánh đúng tính tổng quát hóa của mạng nơ-ron hai tầng ẩn 64 đơn vị khi huấn luyện trên tập dữ liệu giới hạn.

Nguồn: Towards Data Science

LIÊN HỆ TƯ VẤN CÁC DỊCH VỤ AI
Hỗ trợ tư vấn, đào tạo và chuyển giao giải pháp AI cho cá nhân, doanh nghiệp và tổ chức.
Chia sẻ tới bạn bè và gia đình
Chat Zalo Chat Zalo
Gọi ngay Chat