En este tutorial, exploraremos una gama de visualizaciones de SHAP-IQ que proporcionan información sobre cómo llega un modelo de aprendizaje automático a sus predicciones. Estas imágenes ayudan a descomponer el comportamiento del modelo complejo en componentes interpretables, revelando las contribuciones individuales e interactivas de las características a una predicción específica. Mira el Códigos completos aquí.
Instalación de las dependencias
!pip install shapiq overrides scikit-learn pandas numpy seaborn
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
from tqdm.asyncio import tqdm
import shapiq
print(f"shapiq version: {shapiq.__version__}")
Importando el conjunto de datos
En este tutorial, usaremos el conjunto de datos MPG (millas por galón), que cargaremos directamente desde la Biblioteca SeaBorn. Este conjunto de datos contiene información sobre varios modelos de automóviles, incluidas características como caballos de fuerza, peso y origen. Mira el Códigos completos aquí.
import seaborn as sns
df = sns.load_dataset("mpg")
df
Procesar el conjunto de datos
Utilizamos la codificación de etiquetas para convertir las columnas categóricas en formato numérico, haciéndolas adecuadas para el entrenamiento modelo.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# Drop rows with missing values
df = df.dropna()
# Encoding the origin column
le = LabelEncoder()
df.loc[:, "origin"] = le.fit_transform(df["origin"])
df['origin'].unique()
for i, label in enumerate(le.classes_):
print(f"{label} → {i}")
Dividir los datos en subconjuntos de entrenamiento y prueba
# Select features and target
X = df.drop(columns=["mpg", "name"])
y = df["mpg"]
feature_names = X.columns.tolist()
x_data, y_data = X.values, y.values
# Train-test split
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=42)
Entrenamiento modelo
Entrenamos un regresor bosque aleatorio con una profundidad máxima de 10 y 10 árboles de decisión (N_estimators = 10). Un estado Random fijo garantiza la reproducibilidad.
# Train model
model = RandomForestRegressor(random_state=42, max_depth=10, n_estimators=10)
model.fit(x_train, y_train)
Evaluación del modelo
# Evaluate
mse = mean_squared_error(y_test, model.predict(x_test))
r2 = r2_score(y_test, model.predict(x_test))
print(f"Mean Squared Error: {mse:.2f}")
print(f"R2 Score: {r2:.2f}")
Explicando una instancia local
Elegimos una instancia de prueba específica (con instancia_id = 7) para explorar cómo llegó el modelo a su predicción. Imprimiremos el valor verdadero, el valor predicho y los valores de la función para esta instancia. Mira el Códigos completos aquí.
# select a local instance to be explained
instance_id = 7
x_explain = x_test[instance_id]
y_true = y_test[instance_id]
y_pred = model.predict(x_explain.reshape(1, -1))[0]
print(f"Instance {instance_id}, True Value: {y_true}, Predicted Value: {y_pred}")
for i, feature in enumerate(feature_names):
print(f"{feature}: {x_explain[i]}")
Generando explicaciones para órdenes de interacción múltiples
Generamos explicaciones basadas en Shapley para diferentes órdenes de interacción utilizando el paquete SHAPIQ. Específicamente, calculamos:
- Orden 1 (valores estándar de Shapley): contribuciones de características individuales
- Orden 2 (interacciones por pares): efectos combinados de pares de características
- Orden N (interacción completa): todas las interacciones hasta el número total de características
# create explanations for different orders
feature_names = list(X.columns) # get the feature names
n_features = len(feature_names)
si_order: dict[int, shapiq.InteractionValues] = {}
for order in tqdm([1, 2, n_features]):
index = "k-SII" if order > 1 else "SV" # will also be set automatically by the explainer
explainer = shapiq.TreeExplainer(model=model, max_order=order, index=index)
si_order[order] = explainer.explain(x=x_explain)
si_order
1. Gráfico de fuerza
El Gráfico de Force es una poderosa herramienta de visualización que nos ayuda a comprender cómo llegó un modelo de aprendizaje automático a una predicción específica. Muestra la predicción de línea de base (es decir, el valor esperado del modelo antes de ver cualquier característica), y luego muestra cómo cada característica “presiona” la predicción más alta o más baja.
En esta trama:
- Las barras rojas representan características o interacciones que aumentan la predicción.
- Las barras azules representan aquellas que lo disminuyen.
- La longitud de cada barra corresponde a la magnitud de su efecto.
Al usar valores de interacción Shapley, la gráfica de fuerza puede visualizar no solo las contribuciones individuales sino también las interacciones entre las características. Esto lo hace especialmente perspicaz al interpretar modelos complejos, ya que descompone visualmente cómo las combinaciones de características funcionan juntas para influir en el resultado. Mira el Códigos completos aquí.
sv = si_order[1] # get the SV
si = si_order[2] # get the 2-SII
mi = si_order[n_features] # get the Moebius transform
sv.plot_force(feature_names=feature_names, show=True)
si.plot_force(feature_names=feature_names, show=True)
mi.plot_force(feature_names=feature_names, show=True)
Desde la primera trama, podemos ver que el valor base es 23.5. Características como peso, cilindros, caballos de fuerza y desplazamiento tienen una influencia positiva en la predicción, empujándola por encima de la línea de base. Por otro lado, el año modelo y la aceleración tienen un impacto negativo, lo que retira la predicción hacia abajo.
2. Gráfico de cascada
Similar a la trama de fuerza, la trama de cascada es otra forma popular de visualizar los valores de Shapley, originalmente introducido con la Biblioteca SHAP. Muestra cómo diferentes características empujan la predicción más alta o más baja en comparación con la línea de base. Una ventaja clave de la trama de cascada es que agrupa automáticamente las características con impactos muy pequeños en una categoría de “otro”, lo que hace que el gráfico sea más limpio y más fácil de entender. Mira el Códigos completos aquí.
sv.plot_waterfall(feature_names=feature_names, show=True)
si.plot_waterfall(feature_names=feature_names, show=True)
mi.plot_waterfall(feature_names=feature_names, show=True)
3. Gráfico de red
La gráfica de red muestra cómo las características interactúan entre sí utilizando interacciones Shapley de primer y segundo orden. El tamaño del nodo refleja el impacto de las características individuales, mientras que el ancho de los bordes y el color muestran la fuerza y la dirección de la interacción. Es especialmente útil cuando se trata de muchas características, revelando interacciones complejas que las tramas más simples podrían perderse. Mira el Códigos completos aquí.
si.plot_network(feature_names=feature_names, show=True)
mi.plot_network(feature_names=feature_names, show=True)
4. Gráfico de gráficos de Si
El gráfico SI del gráfico extiende la gráfica de red visualizando todas las interacciones de orden superior como hiper-fedes que conectan múltiples características. El tamaño del nodo muestra un impacto individual en características, mientras que el ancho, el color y la transparencia del borde reflejan la fuerza y la dirección de las interacciones. Proporciona una visión integral de cómo las características influyen conjuntamente en la predicción del modelo. Mira el Códigos completos aquí.
# we abbreviate the feature names since, they are plotted inside the nodes
abbrev_feature_names = shapiq.plot.utils.abbreviate_feature_names(feature_names)
sv.plot_si_graph(
feature_names=abbrev_feature_names,
show=True,
size_factor=2.5,
node_size_scaling=1.5,
plot_original_nodes=True,
)
si.plot_si_graph(
feature_names=abbrev_feature_names,
show=True,
size_factor=2.5,
node_size_scaling=1.5,
plot_original_nodes=True,
)
mi.plot_si_graph(
feature_names=abbrev_feature_names,
show=True,
size_factor=2.5,
node_size_scaling=1.5,
plot_original_nodes=True,
)
5. Parcela de bar
La trama de bares está diseñada para explicaciones globales. Mientras que otras parcelas se pueden usar tanto locales como globalmente, el diagrama de barras resume la importancia general de las características (o interacciones de características) al mostrar los valores medios de Shapley (o interacción) absolutos en todas las instancias. En SHAPIQ, resalta que las interacciones contribuyen más en promedio. Mira el Códigos completos aquí.
explanations = []
explainer = shapiq.TreeExplainer(model=model, max_order=2, index="k-SII")
for instance_id in tqdm(range(20)):
x_explain = x_test[instance_id]
si = explainer.explain(x=x_explain)
explanations.append(si)
shapiq.plot.bar_plot(explanations, feature_names=feature_names, show=True)
La “distancia” y la “potencia” son las características más influyentes en general, lo que significa que tienen el impacto individual más fuerte en las predicciones del modelo. Esto es evidente a partir de sus valores de interacción de Shapley absoluto absoluto de alta media en la gráfica de barra.
Además, cuando se observa interacciones de segundo orden (es decir, cómo dos características interactúan juntas), las combinaciones “Corso de potencia × peso” y “distancia × caballos de fuerza” muestran una influencia articular significativa. Su atribución combinada es de alrededor de 1.4, lo que indica que estas interacciones juegan un papel importante en la configuración de las predicciones del modelo más allá de lo que cada característica contribuye individualmente. Esto resalta la presencia de relaciones no lineales entre las características en el modelo.
Mira el Códigos completos aquí. No dude en ver nuestro Página de Github para tutoriales, códigos y cuadernos. Además, siéntete libre de seguirnos Gorjeo Y no olvides unirte a nuestro Subreddit de 100k+ ml y suscribirse a Nuestro boletín.
