Explicabilidad de modelos de Machine Learning#
Muchos modelos modernos de Machine Learning (Random Forest, Gradient Boosting, Redes Neuronales Artificiales, SVM con kernel) pueden alcanzar niveles de precisión altos, pero son difíciles de interpretar. Este hecho plantea problemas para aplicaciones en campos como la medicina, las finanzas, la seguridad y otros sistemas críticos, incluso, existen normativas internacionales que exigen a los diseñadores de aplicaciones que basadas en IA/ML poder responder a preguntas como:
¿Por qué el modelo tomó esta decisión?
¿Qué variables fueron más importantes?
¿Qué pasaría si cambiamos una característica?
Tipos de explicabilidad#
Según el alcance
Global: comportamiento general del modelo (similar a las técnicas que estiman la importancia de variables)
Local: explicación de una predicción concreta
Según el modelo
Model-specific: dependen del modelo (árboles, redes)
Model-agnostic: aplicables a cualquier modelo
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
# Cargar datos
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
# Split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42
)
# Modelo
model = RandomForestClassifier(
n_estimators=200,
random_state=42
)
model.fit(X_train, y_train)
RandomForestClassifier(n_estimators=200, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
Parameters
SHAP Values#
SHAP (SHapley Additive exPlanations) [1] se basa en la teoría de juegos cooperativos. Cada variable es vista como un jugador que contribuye a la predicción final, la cual se descompone como:
donde
\(\phi_0 = \mathbb{E}[f(X)]\) es el baseline (predicción media del modelo)
\(\phi_i({\bf{x}})\) es la contribución local de la característica \(i\)
La contribución \(\phi_i({\bf{x}})\) se estima como:
donde
\(N = \{1, \dots, d\}\) el conjunto de características
\(S \subseteq N \setminus \{i\}\) un subconjunto de características
\(f_S(x)\) el modelo evaluado usando solo las características en \(S\).
import shap
y_est = model.predict(X_test)
# Inicializar explicador
explainer = shap.TreeExplainer(model)
# Calcular SHAP values
shap_values = explainer(X_test)
Explicación global#
shap.summary_plot(
shap_values[:,:,1],
X_test
)
shap.plots.beeswarm(shap_values[:,:,1])
Explicación local: una observación#
i = 10
shap.plots.waterfall(shap_values[i,:,y_est[i]])
shap.force_plot(explainer.expected_value[1], shap_values.values[i,:,1],X.iloc[i,:], plot_cmap="DrDb")
Have you run `initjs()` in this notebook? If this notebook was from another user you must also trust this notebook (File -> Trust notebook). If you are viewing this notebook on github the Javascript has been stripped for security. If you are using JupyterLab this error is because a JupyterLab extension has not yet been written.
LIME#
LIME (Local Interpretable Model-agnostic Explanations) [2] explica una predicción local aproximando el modelo complejo por un modelo simple local. El procedimiento que sigue LIMe es el siguiente:
Dada una muestra \(\bf{x}\), genera un conjunto de datos “falso”, aplicando ligeras perturbaciones aleatorias a las características de la muestra.
Estima un peso para cada una de las muestras falsas con base en la distancia a la muestra original.
Para cada una de las muestras generadas, obtiene las predicciones del modelo entrenado previamente.
Entrena un modelo sustituto simple, por ejemplo, una regresión lineal, y los pesos asignados por el modelo durante el entrenamiento son usados como medidas que explican la importancia de las variables en la predicción.
from lime.lime_tabular import LimeTabularExplainer
explainer_lime = LimeTabularExplainer(
training_data=X_train.values,
feature_names=X_train.columns,
class_names=["maligno", "benigno"],
mode="classification"
)
exp = explainer_lime.explain_instance(
X_test.iloc[i].values,
model.predict_proba,
num_features=8
)
exp.show_in_notebook()
/Users/julian/opt/anaconda3/envs/ml_base/lib/python3.13/site-packages/sklearn/utils/validation.py:2691: UserWarning: X does not have valid feature names, but RandomForestClassifier was fitted with feature names
warnings.warn(