Explainability en Machine Learning: Abriendo la Black Box

Autumn 2025

Recordemos

  • Un AI interpretable describe cómo llega a su predicción (modelo simple).
  • Un modelo white-box es aquel cuya estructura interna y lógica son accesibles para inspección y análisis.

Recordemos

  • Un AI interpretable describe cómo llega a su predicción (modelo simple).

  • Un modelo white-box es aquel cuya estructura interna y lógica son accesibles para inspección y análisis.

  • Un AI explicable (explainable) describe por qué el modelo hizo una predicción (modelos complejos).

  • Un modelo black-box es aquel cuyo funcionamiento interno es desconocido, enfocándose en las relaciones entre input y output.

¿Por qué Necesitamos Explainability?

¿Por qué Necesitamos Explainability?

  • Los modelos de ML se usan cada vez más en áreas críticas (salud, derecho, finanzas).

¿Por qué Necesitamos Explainability?

  • Los modelos de ML se usan cada vez más en áreas críticas (salud, derecho, finanzas).
  • Muchos modelos de alto rendimiento (por ejemplo, redes neuronales, ensembles) son black boxes.

¿Por qué Necesitamos Explainability?

  • Los modelos de ML se usan cada vez más en áreas críticas (salud, derecho, finanzas).
  • Muchos modelos de alto rendimiento (por ejemplo, redes neuronales, ensembles) son black boxes.
  • Necesitamos confiar, entender, y validar las decisiones complejas del modelo.

¿Qué es un Black Box Model?

¿Qué es un Black Box Model?

  • Modelos complejos con alto poder predictivo pero baja interpretability
  • No pueden explicar fácilmente por qué se tomó una decisión.

¿Qué es Explainability?

¿Qué es Explainability?

  • Capacidad de describir la mecánica interna de un sistema en términos comprensibles para humanos

¿Qué es Explainability?

  • Capacidad de describir la mecánica interna de un sistema en términos comprensibles para humanos
  • Tipos:
    • Global explainability: comprender el comportamiento del modelo en general

¿Qué es Explainability?

  • Capacidad de describir la mecánica interna de un sistema en términos comprensibles para humanos
  • Tipos:
    • Global explainability: comprender el comportamiento del modelo en general
    • Local explainability: explicar predicciones individuales

Técnicas de XAI populares

  • Model-specific vs. Model-agnostic

Técnicas de XAI populares

  • Model-specific vs. Model-agnostic
  • Métodos Global vs. Local

Model-specific vs. Model-agnostic

Model-specific vs. Model-agnostic

  • Los métodos model-specific aprovechan la estructura interna de un modelo.

Model-specific vs. Model-agnostic

  • Los métodos model-specific aprovechan la estructura interna de un modelo.

Por ejemplo, puedes analizar los caminos de decisión en un decision tree o los pesos en un modelo lineal. Sin embargo, estos métodos solo funcionan para ese tipo específico de modelo.

Model-specific vs. Model-agnostic

  • Los métodos model-specific aprovechan la estructura interna de un modelo.

Por ejemplo, puedes analizar los caminos de decisión en un decision tree o los pesos en un modelo lineal. Sin embargo, estos métodos solo funcionan para ese tipo específico de modelo.

  • Los métodos model-agnostic tratan al modelo como una black box: no dependen del funcionamiento interno. En cambio, usan los inputs y outputs para inferir cómo se comporta el modelo.

Model-specific vs. Model-agnostic

  • Los métodos model-specific aprovechan la estructura interna de un modelo.

Por ejemplo, puedes analizar los caminos de decisión en un decision tree o los pesos en un modelo lineal. Sin embargo, estos métodos solo funcionan para ese tipo específico de modelo.

  • Los métodos model-agnostic tratan al modelo como una black box: no dependen del funcionamiento interno. En cambio, usan los inputs y outputs para inferir cómo se comporta el modelo.

Por ejemplo, puedes analizar cómo cambian las predicciones en respuesta a cambios en el input, sin necesidad de inspeccionar la lógica interna.

Interpretando Black Box Models

Explicaciones tabulares:

Interpretando Black Box Models

Explicaciones textuales:

Interpretando Black Box Models

Explicaciones de imagen:

Interpretando Black Box Models

  • Métodos clave para datos tabulares:
    • LIME (Local Interpretable Model-Agnostic Explanations)
    • SHAP (SHapley Additive exPlanations)

Interpretando Black Box Models

  • Métodos clave para datos tabulares y textuales:
    • LIME (Local Interpretable Model-Agnostic Explanations)
    • SHAP (SHapley Additive exPlanations)

Interpretando Black Box Models

  • Métodos clave para datos tabulares y textuales:
    • LIME (Local Interpretable Model-Agnostic Explanations)
    • SHAP (SHapley Additive exPlanations)
  • Métodos clave para datos de imagen:
    • LIME (Local Interpretable Model-Agnostic Explanations)
    • SHAP (SHapley Additive exPlanations)
    • CAM (Class Activation MAps)

Local Interpretable Model-Agnostic Explanations (LIME)

  • ¿Qué es LIME?

Local Interpretable Model-Agnostic Explanations (LIME)

  • ¿Qué es LIME?
    • LIME es una librería de python que explica la predicción de cualquier classifier aprendiendo un modelo interpretable localmente alrededor de la predicción

Local Interpretable Model-Agnostic Explanations (LIME)

  • ¿Qué es LIME?
    • LIME es una librería de python que explica la predicción de cualquier classifier aprendiendo un modelo interpretable localmente alrededor de la predicción
  • ¿Por qué LIME es un buen explicador de modelos?

Local Interpretable Model-Agnostic Explanations (LIME)

  • ¿Qué es LIME?
    • LIME es una librería de python que explica la predicción de cualquier classifier aprendiendo un modelo interpretable localmente alrededor de la predicción
  • ¿Por qué LIME es un buen explicador de modelos?
    • Interpretable por no expertos
    • Fidelidad local (replica el comportamiento del modelo en la vecindad de la instancia siendo predicha)
    • Model agnostic (no hace ninguna suposición sobre el modelo)
    • Perspectiva global (cuando se usa sobre un conjunto representativo, LIME puede dar una intuición global del modelo)

¿Cómo funciona LIME?

  • Explica la predicción de cualquier classifier black-box aproximándolo localmente con un modelo interpretable.

  • Ideas clave:

    • Se enfoca en una única predicción (explicación local).
    • Crea muestras perturbadas alrededor de la instancia de input.
    • Observa cómo cambian las predicciones.
    • Entrena un modelo simple, interpretable (por ejemplo, regresión lineal) para imitar al modelo complejo en esa región local.

Función Objetivo

LIME resuelve el siguiente problema de optimización:

\(\epsilon(x) = \underset{g \in G}{\mathrm{argmin }} \text{ } \mathcal{L}(f, g, \pi_x) + \Omega(g)\)

Función Objetivo

LIME resuelve el siguiente problema de optimización:

\(\epsilon(x) = \underset{g \in G}{\mathrm{argmin }} \text{ } \mathcal{L}(f, g, \pi_x) + \Omega(g)\)

Donde:

  • \(x\) es la instancia de input a explicar.
  • f: el modelo complejo (black-box) original.
  • g: el modelo sustituto interpretable (por ejemplo, un modelo lineal)
  • G: la familia de modelos interpretables.

Función Objetivo

LIME resuelve el siguiente problema de optimización:

\(\epsilon(x) = \underset{g \in G}{\mathrm{argmin }} \text{ } \mathcal{L}(f, g, \pi_x) + \Omega(g)\)

Donde:

  • \(\mathcal{L}(f, g, \pi_x)\) es la pérdida de fidelidad local: qué tan bien g aproxima a f alrededor de x, ponderada por \(\pi_x\) (pérdida de error cuadrático).
  • \(\pi_x(z)\): medida de proximidad — qué tan cerca está la muestra perturbada z de x (típicamente un kernel exponencial).
  • \(\Omega(g)\): penalización de complejidad para asegurar interpretability (por ejemplo, limitar el número de coeficientes no nulos), usualmente ridge o lasso.

LIME: modelo sustituto (surrogate)

Un surrogate model es un modelo más simple e interpretable que se entrena para aproximar las predicciones de un modelo más complejo (black-box) — especialmente en una región específica del espacio de input.

LIME: modelo sustituto (surrogate)

Un surrogate model es un modelo más simple e interpretable que se entrena para aproximar las predicciones de un modelo más complejo (black-box) — especialmente en una región específica del espacio de input.

  • El surrogate model típicamente es un modelo lineal o un decision tree.
  • No se usa para hacer predicciones reales en producción.
  • Su único propósito es ayudar a explicar cómo se comporta el modelo black-box alrededor de un input específico.

LIME: modelo sustituto (surrogate)

Un surrogate model es un modelo más simple e interpretable que se entrena para aproximar las predicciones de un modelo más complejo (black-box) — especialmente en una región específica del espacio de input.

LIME: modelo sustituto (surrogate)

Un surrogate model es un modelo más simple e interpretable que se entrena para aproximar las predicciones de un modelo más complejo (black-box) — especialmente en una región específica del espacio de input.

Ejemplo de LIME en Python

Primero importamos las librerías relevantes:

import pandas as pd, numpy as np
from sklearn import datasets
from sklearn.decomposition import PCA
from matplotlib import pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
import lime, lime.lime_tabular, shap

Ejemplo de LIME en Python

Recordemos el dataset Iris, que contiene flores que pueden clasificarse en 3 subespecies basándose en 4 características:

data = datasets.load_iris()

X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target

X[0:3]
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2

Ejemplo de LIME en Python

Ignoramos la Clase 0 por ahora (veremos por qué en un momento), y dividimos los datos en un training set (80%) y test set (20%):

#Ignoring one of the three classes

X = X[y != 0]
y = y[y != 0]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)

Ejemplo de LIME en Python

Entrenamos un random forest classifier en nuestro training set, y generamos predicciones para nuestro test set:

classifier = RandomForestClassifier(random_state=42)

classifier.fit(X_train, y_train)

predicted = classifier.predict(X_test)

pre  = precision_score(y_test, predicted)
rec  = recall_score(y_test, predicted)
acc = accuracy_score(y_test, predicted)

print("Precisión: ", pre)
print("Recall: ", rec)
print("Exactitud: ", acc)
Precisión:  1.0
Recall:  0.9166666666666666
Exactitud:  0.95

Ejemplo de LIME en Python

Usamos lime para crear un explainer basado en nuestro training set, y generamos una explicación para la décima muestra de nuestro test set:

explainer1 = lime.lime_tabular.LimeTabularExplainer(X_train.values,
                                                   feature_names=X_train.columns.values.tolist(),
                                                   class_names=['class 1', 'class 2'],
                                                   verbose=True,
                                                   mode='classification',
                                                   random_state=42)

lime_values = explainer1.explain_instance(X_test.values[10], classifier.predict_proba, num_features=4)
##some lime_values properties intercept, local_pred, score
Intercept 0.6704191905472919
Prediction_local [0.233346]
Right: 0.22

Ejemplo de LIME en Python

  • Vemos que esta explicación tiene tres partes:
    • A la izquierda, vemos que el classifier estimó una probabilidad de 78% de que la muestra fuera de la Clase 1, y 22% de que fuera de la Clase 2
    • En el centro, vemos que el largo y ancho del pétalo aumentaron la probabilidad de que la muestra fuera de la Clase 1, mientras que el largo y ancho del sépalo aumentaron la probabilidad de que fuera de la Clase 2. El largo y ancho del pétalo también tuvieron mayor influencia en su respectivo aumento que el largo y ancho del sépalo
    • A la derecha, vemos los valores reales de LIME para cada característica. El color de cada fila corresponde a la clase por la que esa característica está "votando"
from IPython.display import display, HTML  # lime still imports from the removed IPython.core.display path
display(HTML(lime_values.as_html()))

Resumen

LIME para datos Tabulares:

Resumen

LIME para datos de Texto:

Resumen

LIME para datos de Imagen:

Class Activation Maps (CAM)

  • ¿Qué es CAM?

Class Activation Maps (CAM)

  • ¿Qué es CAM?
    • CAM es una técnica usada para visualizar qué partes de una imagen de input (típicamente en CNNs) son importantes para una predicción de clase en particular.

Class Activation Maps (CAM)

  • ¿Qué es CAM?
    • CAM es una técnica usada para visualizar qué partes de una imagen de input (típicamente en CNNs) son importantes para una predicción de clase en particular.
  • ¿Por qué CAM es un buen explicador de modelos?

Class Activation Maps (CAM)

  • ¿Qué es CAM?
    • CAM es una técnica usada para visualizar qué partes de una imagen de input (típicamente en CNNs) son importantes para una predicción de clase en particular.
  • ¿Por qué CAM es un buen explicador de modelos?
    • Interpretabilidad visual por no expertos
    • Explicaciones específicas por clase
    • No necesita reentrenar el modelo
    • Model agnostic (no hace ninguna suposición sobre el modelo)
    • Perspectiva local (CAM genera diferentes activation maps para cada clase predicha, ayudando a entender por qué se eligió una clase sobre otras).

¿Cómo funciona CAM?

  • Solo funciona para arquitecturas CNN que terminan en Global Average Pooling (GAP) + Fully Connected Layer.

¿Cómo funciona CAM?

  • Solo funciona para arquitecturas CNN que terminan en Global Average Pooling (GAP) + Fully Connected Layer.
  • Cada feature map se promedia espacialmente y se pondera por pesos específicos de la clase para generar un heatmap.

Función Objetivo

CAM calcula las características más importantes siguiendo la ecuación:

\(CAM_c = \sum_k w_k^c F_k\)

Función Objetivo

CAM calcula las características más importantes siguiendo la ecuación:

\(CAM_c = \sum_k w_k^c F_k\)

Donde:

  • \(CAM_c\): es el activation map para la clase c.
  • \(w_k^c\): peso para la clase c desde la capa final fully connected correspondiente al feature map k.
  • \(F_k\): es el GAP aplicado sobre todo el feature map \(F_k\). Global Average Pooling: \(F_k=\frac{1}{Z} \sum_i \sum_j A_k(i,j)\) donde Z es el número de píxeles en el feature map. \(A_k\): es el feature map k de una capa de convolución seleccionada.

CAM: visión general

CAM: visión general

Limitación: requiere una arquitectura específica (GAP + capa FC) y no puede aplicarse directamente a la mayoría de las CNNs pre-entrenadas.

Grad-CAM (Gradient-weighted CAM)

  • ¿Qué es Grad-CAM?

Grad-CAM (Gradient-weighted CAM)

  • ¿Qué es Grad-CAM?
    • Grad-CAM es una extensión más general y flexible de CAM. Usa los gradientes de cualquier clase objetivo que fluyen hacia una capa convolucional para producir un heatmap, mostrando qué regiones de la imagen influyen en la predicción de clase.

Grad-CAM (Gradient-weighted CAM)

  • ¿Qué es Grad-CAM?
    • Grad-CAM es una extensión más general y flexible de CAM. Usa los gradientes de cualquier clase objetivo que fluyen hacia una capa convolucional para producir un heatmap, mostrando qué regiones de la imagen influyen en la predicción de clase.
  • ¿Por qué grad-CAM es un mejor explicador de modelos?

Grad-CAM (Gradient-weighted CAM)

  • ¿Qué es Grad-CAM?
    • Grad-CAM es una extensión más general y flexible de CAM. Usa los gradientes de cualquier clase objetivo que fluyen hacia una capa convolucional para producir un heatmap, mostrando qué regiones de la imagen influyen en la predicción de clase.
  • ¿Por qué grad-CAM es un mejor explicador de modelos?
    • Funciona con cualquier arquitectura basada en CNN, incluyendo ResNet, VGG, etc.
    • Puede usarse para explicar tareas tanto de classification como de regression (con adaptación)
    • Ampliamente usado para debugging visual de modelos, construcción de confianza, y detección de sesgos.

Grad-CAM: visión general

Grad-CAM

Calcula las características más importantes usando los gradientes de backpropagation:

\(\mathcal{L}_c ^{Grad-CAM} = ReLU(\sum_k w^c _k A_k)\)

Donde:

  • \(\mathcal{L}_c ^{Grad-CAM}\): el heatmap de Grad-CAM para la clase c.
  • \(A_k\): feature map k de una capa de convolución seleccionada.
  • \(w^c_k\): peso de importancia del feature map k para la clase c, calculado por: \(w^c_k = \frac{1}{Z} \sum_i \sum_j \frac{\partial y^c}{\partial A_k(i,j)}\) donde Z es el número de píxeles en el feature map.
  • \(y^c\): puntaje para la clase c (antes de softmax). \(y^c = \sum_k w^c_k \sum_i \sum_j A_k(i,j)\)

Grad-CAM++

Mejora a Grad-CAM al capturar múltiples ocurrencias de objetos en la misma imagen. Usa gradientes de orden superior para dar una mejor localización espacial.

Ecuación:

\(\mathcal{L}_c ^{Grad-CAM++} = ReLU(\sum_k w^c_k A_k)\)

Donde:

  • \(w^c_k\): peso de importancia del feature map k para la clase c, calculado por: \(w^c_k = \sum_i \sum_j \alpha^{c}_k(i,j) ReLU(\frac{\partial y^c}{\partial A_k(i,j)})\) Donde \(\alpha^{c}_k(i,j)\) es el coeficiente de ponderación para los gradientes por píxel para la clase c y el feature map convolucional \(A_k\). \(\alpha^{c}_k(i,j) = \frac{(\frac{\partial S^c}{\partial A^k(i,j)})^2}{ 2 (\frac{\partial S^c}{\partial A^k(i,j)})^2 + \sum_a \sum_b A_k(a,b) (\frac{\partial S^c}{\partial A^k(i,j)})^3}\)

  • \(S^c\): es el puntaje de la penúltima capa para la clase c, calculado por: \(S^c=Ln(y^c)\)

Score-CAM

Evita los gradientes por completo. En cambio, cada activation map se usa como una máscara sobre la imagen de input, y el puntaje de output del modelo se usa para medir la importancia.

Ecuación:

\(\mathcal{L}_c ^{Score-CAM} = ReLU(\sum_k w^c_k A_k\))

Donde:

  • \(w^c_k\) es el Channel-wise Increase of Confidence (CIC), calculado por: \(w^c_k = f(x \odot Upsample(A_k)) - f(x_{baseline})\) donde \(f(x)\) es el puntaje del modelo para la clase c cuando el input está enmascarado. \(\odot\): multiplicación elemento a elemento \(x_{baseline}\): referencia no informativa (por ejemplo, una imagen negra)

Ablation-CAM

Deshabilita (ablate) cada feature map uno por uno y mide la caída en el puntaje de clase. Cuanto mayor la caída, más importante el feature map.

Ecuación:

\(\mathcal{L}_c ^{Ablation-CAM} = ReLU(\sum_k w^c_k A_k\))

Donde:

  • \(w^c_k\): fracción del peso de importancia de la caída en el activation score de la clase c cuando se elimina el feature map \(A_k\). Se calcula por: \(w^c_k = \frac{y^c - y^c_k}{ ||A_k|| }\) Donde \(y^c_k\) es el valor de la función para la ausencia de la unidad k y actúa como línea base para \(A_k\).

Layer-CAM

En lugar de promediar los gradientes (como Grad-CAM), usa el producto elemento a elemento de activation y gradient — preservando la información espacial.

Ecuación:

\(\mathcal{L}_c ^{Layer-CAM} = ReLU(\sum_k \hat{A}_k\))

Donde:

  • \(\hat{A}_k\): es la combinación lineal a lo largo de la dimensión de canal para obtener el class activation map k. Donde \(\hat{A}_k = \sum_i \sum_j w^c_k(i, j) A_k(i,j)\) Lo cual significa que primero multiplica el valor de activation de cada ubicación en el feature map por un peso. Además, \(w^c_k(i, j) = ReLU( \frac{\partial y^c}{\partial A_k(i,j)} )\) es el peso de la ubicación espacial \((i, j)\) en el k-ésimo feature map.

Eigen-CAM

Aplica PCA a los feature maps de una capa convolucional y usa el componente principal más importante como el saliency map.

Ecuación:

\(\mathcal{L}_c ^{Eigen-CAM} = v^T_1 A_k'\)

Donde:

  • \(A_k'\) es el resultado de la matriz de covarianza \(\Sigma = A'_k A_k^T\).
  • \(v^T_1\) es la transpuesta del primer componente principal de \(A_k\)

XGrad-CAM

XGrad-CAM mejora a Grad-CAM modificando cómo se calculan los pesos de importancia de los feature maps.

Mientras que Grad-CAM usa global average pooling (GAP) de los gradientes para obtener un peso por cada feature map (es decir, canal), XGrad-CAM incorpora las activaciones del feature map en sí a la fórmula de ponderación.

Esto significa que calcula la importancia del canal basándose en cómo tanto los gradientes como las activaciones contribuyen al output — llevando a visualizations más nítidas y enfocadas.

Ecuación:

\(\mathcal{L}_c ^{XGrad-CAM} = ReLU(\sum_k w^c_k A_k\))

Donde:

  • \(w^c_k\) es la importancia del modelo. Donde \(w^c_k = \sum_i \sum_j A_k(i, j) \frac{\partial y^c}{\partial A^k(i,j)})\)
  • \(A_k(i, j)\) es el valor del activation map en la ubicación espacial \((i,j)\) para el canal k.

¡Hay más!!

  • Saliency Maps: resalta los píxeles de la imagen que más influyen en el output calculando el gradiente del class score respecto a la imagen de input.
  • Integrated gradients: calcula el promedio de los gradientes a medida que el input cambia desde una línea base (por ejemplo, una imagen negra) hasta la imagen real.
  • Occlusion Sensitivity: enmascara sistemáticamente parches de la imagen y observa cómo cambia la predicción.
  • RISE (Randomized Input Sampling for Explanation): genera muchas máscaras aleatorias, pasa las imágenes enmascaradas al modelo, y pondera las máscaras por el output del modelo.
  • SmoothGrad: promedia muchos saliency maps ruidosos creados agregando ruido Gaussiano al input.
  • etc.

Referencias

Sharma, Abhishek. 2020. «Decrypting your machine learning model using lime». Medium. Towards Data Science. https://towardsdatascience.com/decrypting-your-machine-learning-model-using-lime-5adc035109b5.