Partial-dependence Profiles vs Accumulated-local Profiles

Cách tính toán Partial Dependence Profiles (PDP)

Partial Dependence Profiles (PDP) được tính dựa trên việc ước lượng giá trị trung bình của đầu ra dự đoán khi thay đổi giá trị của một hoặc một nhóm đặc trưng cụ thể, trong khi giữ các đặc trưng còn lại cố định. Phương pháp này giúp hiểu ảnh hưởng trung bình của một đặc trưng đến dự đoán của mô hình.


Công thức tính toán PDP

Giả sử bạn có: - \(f(X)\): Hàm dự đoán của mô hình. - \(S\): Nhóm các đặc trưng được phân tích (có thể là một hoặc nhiều đặc trưng). - \(C\): Nhóm các đặc trưng còn lại không thuộc \(S\), tức \(C = X \setminus S\). - \(X_S\): Các giá trị có thể của \(S\). - \(X_C\): Các giá trị của các đặc trưng còn lại.

Partial Dependence của \(S\) được tính bằng cách trung bình hóa \(f(X)\) theo \(X_C\): \[ PD_S(x_S) = \frac{1}{N} \sum_{i=1}^N f(x_S, x_{C_i}) \] Trong đó: - \(x_S\): Giá trị cụ thể của các đặc trưng \(S\) mà bạn muốn phân tích. - \(x_{C_i}\): Các giá trị thực tế của các đặc trưng còn lại \(C\) từ dữ liệu huấn luyện. - \(N\): Số lượng mẫu trong tập dữ liệu huấn luyện.


Các bước tính toán PDP

  1. Xác định đặc trưng cần phân tích (\(S\)):
    • Chọn một hoặc nhiều đặc trưng mà bạn muốn kiểm tra tác động của nó lên đầu ra của mô hình.
  2. Giữ các đặc trưng còn lại cố định (\(X_C\)):
    • Duy trì giá trị thực tế của các đặc trưng không thuộc \(S\) từ dữ liệu huấn luyện.
  3. Thay đổi giá trị của đặc trưng phân tích (\(x_S\)):
    • Chọn một khoảng giá trị hoặc các giá trị mẫu cho \(x_S\).
  4. Tính giá trị dự đoán (\(f(x_S, x_{C_i})\)):
    • Tính toán dự đoán của mô hình cho từng giá trị \(x_S\) trong khi giữ các \(x_{C_i}\) cố định.
  5. Lấy trung bình:
    • Lấy trung bình các giá trị dự đoán trên toàn bộ tập dữ liệu huấn luyện để thu được Partial Dependence.

Ví dụ minh họa (bằng Python)

Giả sử bạn có một mô hình và dữ liệu như sau:

import numpy as np

# Hàm dự đoán của mô hình (giả định)
def f(x_s, x_c):
    return x_s * 2 + x_c * 0.5  # Ví dụ mô hình tuyến tính

# Dữ liệu mẫu
x_c_values = np.array([1, 2, 3, 4, 5])  # Các giá trị thực tế của X_C
x_s_values = np.linspace(0, 10, 100)    # Giá trị thay đổi của X_S

# Tính toán Partial Dependence
pd_values = []
for x_s in x_s_values:
    predictions = [f(x_s, x_c) for x_c in x_c_values]
    pd_values.append(np.mean(predictions))

# Kết quả
print(pd_values)

Đồ thị trực quan hóa PDP

Sau khi tính toán \(PD_S(x_S)\), bạn có thể vẽ đồ thị để hiểu mối quan hệ giữa \(x_S\) và giá trị trung bình đầu ra dự đoán.

import matplotlib.pyplot as plt

plt.plot(x_s_values, pd_values, label="Partial Dependence")
plt.xlabel("Feature Value (X_S)")
plt.ylabel("Average Prediction")
plt.title("Partial Dependence Plot")
plt.legend()
plt.show()

Một số lưu ý

  • PDP giả định rằng các đặc trưng không liên quan (independent), vì vậy nếu các đặc trưng có tương quan cao, kết quả PDP có thể không chính xác.
  • Khi sử dụng PDP cho nhóm đặc trưng, việc tính toán sẽ phức tạp hơn do cần đánh giá trên không gian đa chiều.

PDP là công cụ mạnh mẽ để giải thích mô hình, nhưng khi gặp dữ liệu phức tạp (đặc biệt khi có sự phụ thuộc giữa các đặc trưng), bạn có thể cân nhắc sử dụng các phương pháp giải thích như SHAP hoặc ALE (Accumulated Local Effects).

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import lightgbm as lgb
from sklearn.inspection import PartialDependenceDisplay
import matplotlib.pyplot as plt

# 1.1. Tải dữ liệu Wine Quality
from sklearn.datasets import fetch_openml
wine = fetch_openml(name='wine-quality-red', version=1, as_frame=True)
X = wine.data
y = wine.target.astype(int)  # Biến mục tiêu là chất lượng rượu

# 1.2. Chia dữ liệu thành tập huấn luyện và kiểm tra
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 1.3. Huấn luyện mô hình LightGBM
model = lgb.LGBMClassifier(random_state=42, verbosity = -1)
model.fit(X_train, y_train)

# 2.1. Chọn đặc trưng cần phân tích (ví dụ: 'alcohol')
feature_name = 'alcohol'

# 2.2. Sử dụng sklearn để tính Partial Dependence
PartialDependenceDisplay.from_estimator(
    model,
    X_train,
    [feature_name],
    target=model.classes_[1],
    grid_resolution=50
)
plt.show()

Accumulated Local Effects (ALE) là gì?

Accumulated Local Effects (ALE) là một phương pháp giải thích mô hình machine learning được sử dụng để hiểu mối quan hệ giữa một hoặc nhiều đặc trưng đầu vào với đầu ra dự đoán. ALE được thiết kế để giải quyết những hạn chế của Partial Dependence Plots (PDP), đặc biệt khi các đặc trưng có tương quan mạnh với nhau.

So sánh ALE với PDP

  • PDP: Giả định rằng các đặc trưng không phụ thuộc nhau. Nếu có mối tương quan giữa các đặc trưng, PDP có thể đưa ra kết quả sai lệch.
  • ALE: Không yêu cầu giả định về sự độc lập giữa các đặc trưng, tính toán hiệu ứng địa phương thay vì trung bình toàn cục.

Cách tính toán ALE

  1. Chia nhỏ giá trị của đặc trưng:
    • Chia phạm vi của đặc trưng thành nhiều khoảng (bins).
  2. Tính hiệu ứng cục bộ (local effect):
    • Tính hiệu ứng địa phương của mô hình bằng cách so sánh đầu ra dự đoán khi tăng giá trị của đặc trưng từ bin hiện tại lên bin tiếp theo.
  3. Tích lũy các hiệu ứng địa phương:
    • Tổng hợp các hiệu ứng địa phương để tạo thành giá trị tích lũy (accumulated).
  4. Chuẩn hóa (center):
    • Chuẩn hóa kết quả để đảm bảo giá trị ALE trung bình là 0, giúp dễ dàng so sánh.

Ưu điểm của ALE

  1. Xử lý tương quan giữa các đặc trưng: ALE chính xác hơn PDP khi các đặc trưng có tương quan cao.
  2. Độ phức tạp thấp hơn SHAP: Tính toán nhanh và ít tốn tài nguyên hơn so với SHAP.
  3. Dễ hiểu: Kết quả ALE thường dễ trực quan hóa và giải thích.

Nhược điểm

  • Không cung cấp thông tin chi tiết về đóng góp của từng mẫu (như SHAP).
  • Phụ thuộc vào cách chia khoảng (binning), có thể ảnh hưởng đến độ chính xác nếu số bin không phù hợp.

Phương pháp ALE là một lựa chọn tuyệt vời để hiểu mô hình trong trường hợp dữ liệu có tương quan cao hoặc khi muốn một giải pháp giải thích đơn giản và hiệu quả.

Python snippets use dalex

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from lightgbm import LGBMClassifier
from dalex import Explainer
import matplotlib.pyplot as plt

# Create Explainer with DALEX
explainer = Explainer(model, X_train, y_train, label="LightGBM - Wine Quality")

# Generate Partial Dependence Profile (PDP) for a selected feature (e.g., alcohol)
pdp = explainer.model_profile(variables="alcohol", type='partial')

# Generate Accumulated Local Profile (ALE) for the same feature
ale = explainer.model_profile(variables="alcohol", type='accumulated')
Preparation of a new explainer is initiated

  -> data              : 1279 rows 11 cols
  -> target variable   : Parameter 'y' was a pandas.Series. Converted to a numpy.ndarray.
  -> target variable   : 1279 values
  -> model_class       : lightgbm.sklearn.LGBMClassifier (default)
  -> label             : LightGBM - Wine Quality
  -> predict function  : <function yhat_proba_default at 0x000001BD4BD9E170> will be used (default)
  -> predict function  : Accepts pandas.DataFrame and numpy.ndarray.
  -> predicted values  : min = 9.3e-09, mean = 0.0336, max = 0.998
  -> model type        : classification will be used (default)
  -> residual function : difference between y and yhat (default)
  -> residuals         : min = 3.0, mean = 5.59, max = 8.0
  -> model_info        : package lightgbm

A new explainer has been created!
Calculating ceteris paribus: 100%|██████████| 1/1 [00:00<00:00,  4.84it/s]
Calculating ceteris paribus: 100%|██████████| 1/1 [00:00<00:00,  5.03it/s]
Calculating accumulated dependency: 100%|██████████| 1/1 [00:00<00:00, 10.60it/s]
# pdp.plot()
# ale.plot()
# Plot PDP and ALE in subplots
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# Plot PDP
axes[0].plot(pdp.result["_x_"], pdp.result["_yhat_"], label="PDP")
axes[0].set_title("Partial Dependence Profile (PDP) for Alcohol")
axes[0].set_xlabel("Alcohol")
axes[0].set_ylabel("Predicted Value")
axes[0].legend()

# Plot ALE
axes[1].plot(ale.result["_x_"], ale.result["_yhat_"], label="ALE", color="orange")
axes[1].set_title("Accumulated Local Effect (ALE) for Alcohol")
axes[1].set_xlabel("Alcohol")
axes[1].set_ylabel("Predicted Value")
axes[1].legend()

plt.tight_layout()
plt.show()

References

  • https://ema.drwhy.ai/partialDependenceProfiles.html
  • https://docs.seldon.io/projects/alibi/en/latest/methods/PartialDependence.html
  • https://www.blog.trainindata.com/partial-dependence-plots-with-python
  • https://www.analyticsvidhya.com/blog/2020/10/accumulated-local-effects-ale-feature-effects-global-interpretability/