print(“\n” + “=”*72) print(“PARTE 3: Descomposición de la interacción”) print(“=”*72) inter = tree_expl.shap_interaction_values(X_te.iloc[:500]) inter_abs = np.abs(inter).media(0) diag = np.diagonal(inter_abs).copia() off = inter_abs.copia(); np.fill_diagonal(off, 0) main_share = diag.sum() / (diag.sum() + off.sum()) print(f”Masa de atribución total: {main_share*100:.1f}% efectos principales, ” f”{(1-main_share)*100:.1f}% interacciones”) pares = [(X.columns[i]X.columnas[j]apagado[i, j]) para i en el rango (forma X.[1]) para j en el rango (i+1, forma X.[1])]pares.sort(clave=lambda t: -t[2]) print(“\nTop 5 pares de interacción (media |φ_ij|):”) para a, b, v en pares[:5]: print(f” {a:10s} × {b:10s} → {v:.4f}”) fig, ax = plt.subplots(figsize=(7.5, 6)) im = ax.imshow(off, cmap=”viridis”) ax.set_xticks(range(X.shape[1])); ax.set_xticklabels(X.columnas, rotación=45, ha=”derecha”) ax.set_yticks(range(X.shape[1])); ax.set_yticklabels(X.columns) plt.colorbar(im, label=”media |φ_ij|”); plt.title(“Fuerza de la interacción por pares”) plt.tight_layout(); plt.show() a, b, _ = pares[0]
i, j = X.columnas.get_loc(a), X.columnas.get_loc(b) xs = X_te.iloc[:500][a].valores; cs = X_te.iloc[:500][b].values fig, ejes = plt.subplots(1, 2, figsize=(13, 4), sharex=True) ejes[0].scatter(xs, entre[:, i, i]c=cs, s=12, cmap=”coolwarm”) ejes[0].set_title(f”Efecto principal de {a}”); ejes[0].set_xlabel(a); ejes[0].set_ylabel(“φ_{ii}”) sc = ejes[1].dispersión(xs, 2*inter[:, i, j]c=cs, s=12, cmap=”coolwarm”) ejes[1].set_title(f”Interacción {a} × {b}”); ejes[1].set_xlabel(a); ejes[1].set_ylabel(“2·φ_{ij}”) plt.colorbar(sc, ax=ejes[1]etiqueta=b); plt.tight_layout(); plt.show() print(“\n” + “=”*72) print(“PARTE 4: Funciones de enlace: logit vs espacio de probabilidad”) print(“=”*72) cancer = load_breast_cancer() Xc = pd.DataFrame(cancer.data, columns=cancer.feature_names) yc = pd.Series(cancer.target) clf = xgb.XGBClassifier(n_estimators=300, profundidad_max=4, tasa_de_aprendizaje=0.05, eval_metric=”logloss”, estado_aleatorio=42).fit(Xc_tr, yc_tr) print(f”AUC = {roc_auc_score(yc_te, clf.predict_proba(Xc_te)[:,1]):.3f}”) expl_logit = shap.TreeExplainer(clf) sv_logit = expl_logit(Xc_te) expl_prob = shap.TreeExplainer(clf, Xc_tr.sample(100, random_state=42), model_output=”probabilidad”) sv_prob = expl_prob(Xc_te) print(f”\nReconstrucción de muestra 0 (φ debe sumar f – E[f]):”) print(f” log-probabilidades: base + Σφ = {sv_logit.base_values[0] + sv_logit.valores[0].sum():+.3f}”) print(f” problema: base + Σφ = {sv_prob.base_values[0] + sv_prob.valores[0].sum():.3f} ” f”(modelo proba = {clf.predict_proba(Xc_te.iloc[[0]])[0,1]:.3f})”) fig, ejes = plt.subplots(1, 2, figsize=(15, 5)) plt.sca(ejes[0]); shap.plots.cascada(sv_logit[0]max_display=8, mostrar=Falso); ejes[0].set_title(“Espacio de probabilidades de registro”) plt.sca(ejes[1]); shap.plots.cascada(sv_prob[0]max_display=8, mostrar=Falso); ejes[1].set_title(“Espacio de probabilidad”) plt.tight_layout(); plt.mostrar()
i, j = X.columnas.get_loc(a), X.columnas.get_loc(b) xs = X_te.iloc[:500][a].valores; cs = X_te.iloc[:500][b].values fig, ejes = plt.subplots(1, 2, figsize=(13, 4), sharex=True) ejes[0].scatter(xs, entre[:, i, i]c=cs, s=12, cmap=”coolwarm”) ejes[0].set_title(f”Efecto principal de {a}”); ejes[0].set_xlabel(a); ejes[0].set_ylabel(“φ_{ii}”) sc = ejes[1].dispersión(xs, 2*inter[:, i, j]c=cs, s=12, cmap=”coolwarm”) ejes[1].set_title(f”Interacción {a} × {b}”); ejes[1].set_xlabel(a); ejes[1].set_ylabel(“2·φ_{ij}”) plt.colorbar(sc, ax=ejes[1]etiqueta=b); plt.tight_layout(); plt.show() print(“\n” + “=”*72) print(“PARTE 4: Funciones de enlace: logit vs espacio de probabilidad”) print(“=”*72) cancer = load_breast_cancer() Xc = pd.DataFrame(cancer.data, columns=cancer.feature_names) yc = pd.Series(cancer.target) clf = xgb.XGBClassifier(n_estimators=300, profundidad_max=4, tasa_de_aprendizaje=0.05, eval_metric=”logloss”, estado_aleatorio=42).fit(Xc_tr, yc_tr) print(f”AUC = {roc_auc_score(yc_te, clf.predict_proba(Xc_te)[:,1]):.3f}”) expl_logit = shap.TreeExplainer(clf) sv_logit = expl_logit(Xc_te) expl_prob = shap.TreeExplainer(clf, Xc_tr.sample(100, random_state=42), model_output=”probabilidad”) sv_prob = expl_prob(Xc_te) print(f”\nReconstrucción de muestra 0 (φ debe sumar f – E[f]):”) print(f” log-probabilidades: base + Σφ = {sv_logit.base_values[0] + sv_logit.valores[0].sum():+.3f}”) print(f” problema: base + Σφ = {sv_prob.base_values[0] + sv_prob.valores[0].sum():.3f} ” f”(modelo proba = {clf.predict_proba(Xc_te.iloc[[0]])[0,1]:.3f})”) fig, ejes = plt.subplots(1, 2, figsize=(15, 5)) plt.sca(ejes[0]); shap.plots.cascada(sv_logit[0]max_display=8, mostrar=Falso); ejes[0].set_title(“Espacio de probabilidades de registro”) plt.sca(ejes[1]); shap.plots.cascada(sv_prob[0]max_display=8, mostrar=Falso); ejes[1].set_title(“Espacio de probabilidad”) plt.tight_layout(); plt.mostrar()