Overfitting vs Underfitting

Overfitting vs Underfitting: Cân bằng nghệ thuật trong Machine Learning

Một trong những thách thức lớn nhất khi xây dựng mô hình machine learning là tìm được điểm cân bằng tối ưu giữa hai hiện tượng đối lập: overfitting (quá khớp) và underfitting (kém khớp). Bài viết này sẽ giải thích chi tiết về hai hiện tượng này, nguyên nhân cơ bản đằng sau chúng thông qua bias-variance tradeoff, cách nhận diện qua learning curves, và các kỹ thuật regularization để đạt được mô hình cân bằng.

1. Overfitting và Underfitting: Định nghĩa và nhận diện

Overfitting (Quá khớp)

Overfitting xảy ra khi mô hình học quá kỹ từ dữ liệu huấn luyện, đến mức "học thuộc lòng" cả nhiễu (noise) thay vì chỉ học các mẫu tổng quát. Mô hình overfitting có đặc điểm:

  • Hiệu suất rất tốt trên tập huấn luyện (training set)

  • Hiệu suất kém trên tập kiểm thử (test set) hoặc dữ liệu mới

  • Mô hình phức tạp với nhiều tham số

  • Có xu hướng "uốn cong" để phù hợp với từng điểm dữ liệu

Tưởng tượng một học sinh học thuộc lòng tất cả các bài tập và câu hỏi đã được giải trong sách, nhưng lại không hiểu nguyên tắc cơ bản để áp dụng cho các bài toán mới trong kỳ thi.

Underfitting (Kém khớp)

Underfitting xảy ra khi mô hình quá đơn giản và không thể nắm bắt được mối quan hệ cơ bản trong dữ liệu. Mô hình underfitting có đặc điểm:

  • Hiệu suất kém ngay cả trên tập huấn luyện

  • Hiệu suất kém trên tập kiểm thử

  • Mô hình quá đơn giản

  • Không thể nắm bắt được các mẫu và xu hướng phức tạp

Tương tự như một học sinh chỉ học qua loa về các khái niệm cơ bản mà không đi sâu vào chi tiết, dẫn đến không thể giải được các bài tập căn bản.

2. Bias-Variance Tradeoff: Cốt lõi của vấn đề

Để hiểu sâu hơn về nguyên nhân dẫn đến overfitting và underfitting, chúng ta cần tìm hiểu về khái niệm bias-variance tradeoff - một trong những nguyên lý cơ bản nhất trong machine learning.

Bias (Độ chệch)

Bias là sai số hệ thống của mô hình, phản ánh mức độ đơn giản hóa của mô hình so với mối quan hệ thực tế trong dữ liệu.

  • High bias: Mô hình quá đơn giản, bỏ qua nhiều mối quan hệ quan trọng trong dữ liệu → dẫn đến underfitting

  • Low bias: Mô hình phức tạp, có khả năng nắm bắt được các mối quan hệ phức tạp

Variance (Độ phương sai)

Variance thể hiện độ nhạy cảm của mô hình đối với sự thay đổi nhỏ trong dữ liệu huấn luyện. Nó đo lường mức độ mà mô hình thay đổi khi được huấn luyện trên các tập dữ liệu khác nhau.

  • High variance: Mô hình quá nhạy cảm với dữ liệu huấn luyện, không tổng quát hóa tốt → dẫn đến overfitting

  • Low variance: Mô hình ổn định, ít thay đổi giữa các tập dữ liệu huấn luyện khác nhau

Tổng lỗi và Tradeoff

Tổng lỗi (total error) của một mô hình có thể được phân tích thành tổng của ba thành phần:

Total Error = Bias² + Variance + Irreducible Error

Trong đó, irreducible error (lỗi không khử được) là nhiễu cố hữu trong dữ liệu mà không mô hình nào có thể giải quyết.

Cốt lõi của bias-variance tradeoff là khi chúng ta giảm bias (bằng cách làm mô hình phức tạp hơn), variance thường tăng lên, và ngược lại. Nghệ thuật của machine learning là tìm được điểm cân bằng tối ưu giữa bias và variance.

Visualizing the Tradeoff

  • Mô hình đơn giản (ví dụ: hồi quy tuyến tính): High bias, Low variance

  • Mô hình phức tạp (ví dụ: cây quyết định sâu): Low bias, High variance

  • Mô hình cân bằng (ví dụ: các mô hình với regularization phù hợp): Moderate bias, Moderate variance

3. Learning Curves: Công cụ chẩn đoán

Learning curves là công cụ trực quan và mạnh mẽ để chẩn đoán overfitting, underfitting, và xác định xem mô hình có thể được cải thiện bằng cách nào.

Cách đọc Learning Curves

Learning curves biểu diễn mối quan hệ giữa lỗi huấn luyện (training error) và lỗi kiểm thử (validation error) khi kích thước tập huấn luyện tăng dần.

Mẫu Learning Curves của mô hình Underfitting:

  • Training error: Cao và không giảm nhiều khi tăng dữ liệu

  • Validation error: Cao, gần với training error

  • Khoảng cách: Nhỏ giữa hai đường

  • Đặc điểm: Cả hai đường đều hội tụ ở mức lỗi cao

Mẫu Learning Curves của mô hình Overfitting:

  • Training error: Thấp và tiếp tục giảm khi tăng dữ liệu

  • Validation error: Ban đầu giảm, sau đó tăng lên hoặc dao động

  • Khoảng cách: Lớn giữa hai đường

  • Đặc điểm: Training error thấp hơn nhiều so với validation error

Mẫu Learning Curves của mô hình Cân bằng:

  • Training error: Tương đối thấp

  • Validation error: Tiếp tục giảm và tiến gần đến training error khi có thêm dữ liệu

  • Khoảng cách: Hẹp và tiếp tục thu nhỏ

  • Đặc điểm: Cả hai đường hội tụ ở mức lỗi thấp

Ứng dụng thực tế của Learning Curves

  1. Chẩn đoán hiện tượng: Xác định nhanh chóng mô hình đang underfitting hay overfitting

  2. Đánh giá lợi ích của dữ liệu: Xác định xem việc thu thập thêm dữ liệu có giúp cải thiện mô hình không

  3. Điều chỉnh độ phức tạp: Hướng dẫn việc tăng/giảm độ phức tạp của mô hình

4. Regularization: Kỹ thuật chống Overfitting

Regularization là nhóm kỹ thuật được thiết kế để chống overfitting bằng cách thêm vào hàm mất mát (loss function) các ràng buộc làm "đơn giản hóa" mô hình, khuyến khích các trọng số nhỏ hơn hoặc các mô hình đơn giản hơn.

L1 Regularization (Lasso)

L1 Regularization thêm vào hàm mất mát một số hạng tỷ lệ với tổng giá trị tuyệt đối của các trọng số:

Loss = Original Loss + λ * Σ|w_i|

Đặc điểm:

  • Thúc đẩy các trọng số bằng không (sparse models)

  • Tự động thực hiện feature selection

  • Phù hợp khi nghi ngờ một số features không liên quan

  • Hiệu quả trong không gian nhiều chiều thưa thớt (sparse)

L2 Regularization (Ridge)

L2 Regularization thêm vào hàm mất mát một số hạng tỷ lệ với tổng bình phương các trọng số:

Loss = Original Loss + λ * Σ(w_i²)

Đặc điểm:

  • Khuyến khích các trọng số nhỏ nhưng không nhất thiết bằng không

  • Xử lý tốt vấn đề đa cộng tuyến (multicollinearity)

  • Phân phối ảnh hưởng đều giữa các features

  • Phổ biến hơn trong các mô hình neural network (weight decay)

Elastic Net

Elastic Net kết hợp cả L1 và L2 regularization:

Loss = Original Loss + λ1 * Σ|w_i| + λ2 * Σ(w_i²)

Đặc điểm:

  • Kết hợp ưu điểm của cả L1 và L2

  • Linh hoạt hơn, có thể điều chỉnh cân bằng giữa feature selection và shrinkage

  • Hiệu quả khi số lượng features lớn hơn số lượng mẫu

Dropout (cho Neural Networks)

Dropout là kỹ thuật regularization đặc biệt cho neural networks, hoạt động bằng cách ngẫu nhiên "tắt" một tỷ lệ các neuron trong quá trình huấn luyện:

Đặc điểm:

  • Buộc mạng học các biểu diễn mạnh mẽ hơn

  • Tương tự như huấn luyện nhiều mạng lưới và lấy trung bình (ensemble)

  • Đơn giản để triển khai và hiệu quả trong thực tế

  • Tỷ lệ dropout (thường 0.2-0.5) là hyperparameter cần điều chỉnh

Early Stopping

Early Stopping không phải là regularization theo nghĩa truyền thống, nhưng có tác dụng tương tự:

Đặc điểm:

  • Dừng huấn luyện khi validation error bắt đầu tăng

  • Ngăn mô hình học quá mức từ dữ liệu huấn luyện

  • Đơn giản, hiệu quả và không tốn thêm chi phí tính toán

  • Yêu cầu một tập validation riêng biệt

5. Các Chiến lược Thực tiễn để Cân bằng Bias-Variance

Khi gặp Underfitting:

  1. Tăng độ phức tạp của mô hình:

    • Thêm các features/tính năng mới

    • Tăng độ sâu/rộng của mô hình (ví dụ: thêm hidden layers trong neural network)

    • Sử dụng mô hình phức tạp hơn (ví dụ: từ linear models đến polynomial hay non-linear models)

  2. Giảm regularization:

    • Giảm giá trị λ trong L1/L2 regularization

    • Giảm tỷ lệ dropout

  3. Feature engineering:

    • Tạo các tính năng kết hợp, tương tác

    • Khám phá các biến đổi phi tuyến của features

Khi gặp Overfitting:

  1. Thu thập thêm dữ liệu:

    • Dữ liệu huấn luyện nhiều hơn giúp mô hình tổng quát hóa tốt hơn

    • Data augmentation (cho computer vision, NLP, v.v.)

  2. Giảm độ phức tạp của mô hình:

    • Giảm số lượng layers/units trong neural networks

    • Giảm độ sâu của cây quyết định

    • Chọn mô hình đơn giản hơn

  3. Tăng regularization:

    • Tăng giá trị λ trong các kỹ thuật regularization

    • Tăng tỷ lệ dropout

    • Áp dụng batch normalization

  4. Feature selection:

    • Loại bỏ các features ít quan trọng hoặc nhiễu

    • Sử dụng PCA hoặc các kỹ thuật giảm chiều khác

  5. Cross-validation:

    • Sử dụng k-fold cross-validation để đánh giá mô hình một cách mạnh mẽ hơn

    • Giúp chọn hyperparameters phù hợp

6. Ví dụ thực tế và Mã Python

Visualizing Overfitting và Underfitting

Để hiểu trực quan về overfitting và underfitting, hãy xem xét ví dụ hồi quy đa thức với độ phức tạp tăng dần:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_squared_error

# Tạo dữ liệu mẫu
np.random.seed(0)
X = np.sort(np.random.rand(30) * 2 - 1)
X = X.reshape(-1, 1)
y = np.sin(2 * np.pi * X).ravel() + np.random.randn(30) * 0.1

# Tạo các mô hình với độ phức tạp tăng dần
degrees = [1, 3, 15]  # Bậc của đa thức
plt.figure(figsize=(14, 4))

X_test = np.linspace(-1, 1, 100).reshape(-1, 1)

for i, degree in enumerate(degrees):
    ax = plt.subplot(1, 3, i + 1)
    
    # Tạo pipeline cho mô hình đa thức
    model = Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('linear', LinearRegression())
    ])
    
    # Huấn luyện mô hình
    model.fit(X, y)
    
    # Dự đoán và tính toán lỗi
    y_pred_train = model.predict(X)
    y_pred_test = model.predict(X_test)
    mse_train = mean_squared_error(y, y_pred_train)
    
    # Vẽ đồ thị
    ax.plot(X_test, np.sin(2 * np.pi * X_test), label="True function", color='green')
    ax.scatter(X, y, label="Samples", color='black', s=20)
    ax.plot(X_test, y_pred_test, label=f"Model (degree={degree})", color='red')
    ax.set_ylim((-2, 2))
    ax.set_title(f"Degree {degree}\nMSE = {mse_train:.4f}")
    ax.legend()
    
    if i == 0:
        plt.annotate("Underfitting", xy=(0.05, 0.85), xycoords='axes fraction', 
                    fontsize=14, color='blue')
    elif i == 2:
        plt.annotate("Overfitting", xy=(0.05, 0.85), xycoords='axes fraction', 
                    fontsize=14, color='blue')
    else:
        plt.annotate("Good balance", xy=(0.05, 0.85), xycoords='axes fraction', 
                    fontsize=14, color='blue')

plt.tight_layout()
plt.show()

Plotting Learning Curves

from sklearn.model_selection import learning_curve

def plot_learning_curve(estimator, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 10)):
    train_sizes, train_scores, val_scores = learning_curve(
        estimator, X, y, cv=cv, train_sizes=train_sizes, scoring='neg_mean_squared_error')
    
    # Chuyển đổi sang MSE
    train_scores_mean = -np.mean(train_scores, axis=1)
    val_scores_mean = -np.mean(val_scores, axis=1)
    
    plt.figure(figsize=(10, 6))
    plt.plot(train_sizes, train_scores_mean, 'o-', color='blue', label='Training error')
    plt.plot(train_sizes, val_scores_mean, 'o-', color='red', label='Validation error')
    
    plt.xlabel('Training Set Size')
    plt.ylabel('Mean Squared Error')
    plt.title('Learning Curve')
    plt.legend(loc='best')
    plt.grid(True)
    
    # Ghi chú dựa trên hình dạng của learning curve
    gap = val_scores_mean[-1] - train_scores_mean[-1]
    level = val_scores_mean[-1]
    
    if gap > 0.1 and train_scores_mean[-1] < 0.1:
        plt.annotate("Likely Overfitting", xy=(0.7, 0.9), xycoords='axes fraction', 
                     fontsize=14, color='blue')
    elif level > 0.2 and gap < 0.1:
        plt.annotate("Likely Underfitting", xy=(0.7, 0.9), xycoords='axes fraction', 
                     fontsize=14, color='blue')
    else:
        plt.annotate("Good Balance", xy=(0.7, 0.9), xycoords='axes fraction', 
                     fontsize=14, color='blue')
    
    plt.show()

# Sử dụng cho các mô hình với độ phức tạp khác nhau
for degree in [1, 3, 15]:
    model = Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('linear', LinearRegression())
    ])
    
    plot_learning_curve(model, X, y)

Comparing Regularization Techniques

from sklearn.linear_model import Ridge, Lasso, ElasticNet

# Tạo dữ liệu mẫu với nhiều features
np.random.seed(42)
X_multi = np.random.randn(100, 20)
true_weights = np.zeros(20)
true_weights[:5] = [1.0, -2.0, 3.0, -4.0, 5.0]  # Chỉ 5 features đầu tiên thực sự quan trọng
y_multi = X_multi @ true_weights + np.random.randn(100) * 0.5

# Chia dữ liệu
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_multi, y_multi, test_size=0.3, random_state=42)

# Huấn luyện và so sánh các mô hình với các kỹ thuật regularization khác nhau
models = {
    "Linear Regression": LinearRegression(),
    "Ridge (L2)": Ridge(alpha=1.0),
    "Lasso (L1)": Lasso(alpha=0.1),
    "ElasticNet": ElasticNet(alpha=0.1, l1_ratio=0.5)
}

plt.figure(figsize=(14, 10))

for i, (name, model) in enumerate(models.items()):
    model.fit(X_train, y_train)
    
    # So sánh trọng số thực với trọng số được học
    ax = plt.subplot(2, 2, i + 1)
    plt.bar(range(20), model.coef_, alpha=0.7, label='Predicted weights')
    plt.bar(range(20), true_weights, alpha=0.5, color='red', label='True weights')
    plt.axhline(y=0, color='gray', linestyle='-', alpha=0.3)
    plt.title(f"{name}\nTest Score: {model.score(X_test, y_test):.4f}")
    plt.xlabel("Feature Index")
    plt.ylabel("Weight Value")
    plt.legend()
    
    # Chỉ hiển thị nhãn trục x cho một số điểm
    ax.set_xticks(range(0, 20, 4))

plt.tight_layout()
plt.show()

Kết luận

Overfitting và underfitting là hai thái cực trong machine learning. Hiểu được bias-variance tradeoff, biết cách phân tích learning curves, và sử dụng các kỹ thuật regularization phù hợp là những kỹ năng thiết yếu để xây dựng các mô hình cân bằng, có khả năng tổng quát hóa tốt.

Nghệ thuật xây dựng mô hình machine learning không chỉ nằm ở việc chọn thuật toán phù hợp, mà còn ở việc điều chỉnh độ phức tạp của mô hình để cân bằng giữa bias và variance. Đây là quá trình lặp đi lặp lại, đòi hỏi sự kết hợp giữa kiến thức lý thuyết, kinh nghiệm thực tế, và thử nghiệm có hệ thống.

Bằng cách áp dụng các nguyên tắc và kỹ thuật trong bài viết này, bạn sẽ có khả năng xây dựng các mô hình machine learning mạnh mẽ, có khả năng dự đoán chính xác trên dữ liệu mới, không chỉ "học thuộc" dữ liệu huấn luyện.

Last updated