Laboratorio 10: Interpretabilidad 🤖

MDS7202: Laboratorio de Programación Científica para Ciencia de Datos

Cuerpo Docente:¶

  • Profesor: Pablo Badilla y Ignacio Meza D.
  • Auxiliar: Sebastián Tinoco
  • Ayudante: Felipe Arias y Diego Cortez

Equipo: SUPER IMPORTANTE - notebooks sin nombre no serán revisados¶

  • Nombre de alumno 1: Johnny Godoy

Link de repositorio de GitHub: https://github.com/johnny-godoy/laboratorios-mds/blob/main/2023/lab10/laboratorio_10.ipynb¶

Indice¶

  1. Temas a tratar
  2. Descripcción del laboratorio
  3. Desarrollo

Temas a tratar¶

  • Clasificación usando XGBoost.
  • Métodos Agnósticos Globales de Interpretabilidad (Partial Dependence Plot, Permutation Feature Importance)
  • Métodos Agnósticos Locales de Interpretabilidad (Scoped Rules, SHAP)

Reglas:¶

  • Grupos de 2 personas
  • Asistencia obligatoria a instrucciones del lab (viernes 16.15). Luego, pueden quedarse trabajando en las salas o irse.
  • No se revisarán entregas de personas ausentes.
  • Cualquier duda fuera del horario de clases al foro. Mensajes al equipo docente serán respondidos por este medio.
  • Prohibidas las copias.
  • Pueden usar cualquer matrial del curso que estimen conveniente.

Objetivos principales del laboratorio¶

  • Generar un pipeline de clasificación con XGBoost.
  • Implementar modelos de interpretabilidad para explicar el funcionamiento del modelo de clasificación.

El laboratorio deberá ser desarrollado sin el uso indiscriminado de iteradores nativos de python (aka "for", "while"). La idea es que aprendan a exprimir al máximo las funciones optimizadas que nos entrega pandas, las cuales vale mencionar, son bastante más eficientes que los iteradores nativos sobre DataFrames.

1. Problemas Clínicos del Dr. Simi¶

El reconocido Dr. Simi, famoso vendedor de medicamentos en latinoamerica, debido a la creciente prevalencia de enfermedades crónicas, como la diabetes, decidió abrir una clínica especializada en el tratamiento de esta enfermedad en nuestro país.

La clínica del Doctor Simi se convirtió en un lugar donde los pacientes con diabetes podrían recibir atención médica integral. El personal médico estaba compuesto por especialistas en endocrinología, nutrición y enfermería, todos capacitados en el manejo de la diabetes.

Sin embargo él se ha dado cuenta que los tiempos han cambiado y gracias a las tecnologías es posible generar mejores predicciones en la diabetes conociendo el historial médico de las personas. Por esto, el doctor se ha colocado una meta de incluir modelos de machine learning dentro de sus clínicas, para ello le ha solicitado crear un modelo capaz de predecir/clasificar diabetes pero le rogó que el desarrollo del modelo tuviera un especial enfoque en la interpretabilidad de lo que hace su modelo.

Para que usted pueda entrenar el modelo, Dr. Simi le ha entregado un dataset de todos los clientes que fueron detectados con diabetes a lo largo de la historia de la clinica. Con ello, adjunta el historial médico de las personas en forma de datos tabulares para que usted pueda realizar fácilmente la clasificación.

In [24]:
import os
import pickle
import warnings

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import xgboost as xgb
from IPython.display import HTML, display
from sklearn.inspection import PartialDependenceDisplay, permutation_importance
from sklearn.metrics import ConfusionMatrixDisplay, confusion_matrix
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.utils import resample
In [25]:
with warnings.catch_warnings():
    warnings.filterwarnings("ignore", message=".*The 'nopython' keyword.*")
    import shap
    import ydata_profiling
    from alibi.explainers import AnchorTabular
In [26]:
df = pd.read_csv("data/input/diabetes_data.csv").drop_duplicates()
df.head(4)
Out[26]:
Age Sex HighChol CholCheck BMI Smoker HeartDiseaseorAttack PhysActivity Fruits Veggies HvyAlcoholConsump GenHlth MentHlth PhysHlth DiffWalk Stroke HighBP Diabetes
0 4.0 1.0 0.0 1.0 26.0 0.0 0.0 1.0 0.0 1.0 0.0 3.0 5.0 30.0 0.0 0.0 1.0 0.0
1 12.0 1.0 1.0 1.0 26.0 1.0 0.0 0.0 1.0 0.0 0.0 3.0 0.0 0.0 0.0 1.0 1.0 0.0
2 13.0 1.0 0.0 1.0 26.0 0.0 0.0 1.0 1.0 1.0 0.0 1.0 0.0 10.0 0.0 0.0 0.0 0.0
3 11.0 1.0 1.0 1.0 28.0 1.0 0.0 1.0 1.0 1.0 0.0 3.0 0.0 3.0 0.0 0.0 1.0 0.0
In [27]:
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 64020 entries, 0 to 70691
Data columns (total 18 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Age                   64020 non-null  float64
 1   Sex                   64020 non-null  float64
 2   HighChol              64020 non-null  float64
 3   CholCheck             64020 non-null  float64
 4   BMI                   64020 non-null  float64
 5   Smoker                64020 non-null  float64
 6   HeartDiseaseorAttack  64020 non-null  float64
 7   PhysActivity          64020 non-null  float64
 8   Fruits                64020 non-null  float64
 9   Veggies               64020 non-null  float64
 10  HvyAlcoholConsump     64020 non-null  float64
 11  GenHlth               64020 non-null  float64
 12  MentHlth              64020 non-null  float64
 13  PhysHlth              64020 non-null  float64
 14  DiffWalk              64020 non-null  float64
 15  Stroke                64020 non-null  float64
 16  HighBP                64020 non-null  float64
 17  Diabetes              64020 non-null  float64
dtypes: float64(18)
memory usage: 9.3 MB
In [28]:
df.describe()
Out[28]:
Age Sex HighChol CholCheck BMI Smoker HeartDiseaseorAttack PhysActivity Fruits Veggies HvyAlcoholConsump GenHlth MentHlth PhysHlth DiffWalk Stroke HighBP Diabetes
count 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000 64020.000000
mean 8.607420 0.455983 0.539550 0.973211 30.178554 0.490706 0.159950 0.678366 0.590862 0.771587 0.046345 2.921103 4.130537 6.385020 0.277007 0.068510 0.581756 0.521681
std 2.860717 0.498063 0.498437 0.161466 7.287730 0.499918 0.366563 0.467107 0.491679 0.419813 0.210233 1.107991 8.466301 10.368493 0.447524 0.252621 0.493275 0.499534
min 1.000000 0.000000 0.000000 0.000000 12.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
25% 7.000000 0.000000 0.000000 1.000000 25.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
50% 9.000000 0.000000 1.000000 1.000000 29.000000 0.000000 0.000000 1.000000 1.000000 1.000000 0.000000 3.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1.000000
75% 11.000000 1.000000 1.000000 1.000000 34.000000 1.000000 0.000000 1.000000 1.000000 1.000000 0.000000 4.000000 3.000000 7.000000 1.000000 0.000000 1.000000 1.000000
max 13.000000 1.000000 1.000000 1.000000 98.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 5.000000 30.000000 30.000000 1.000000 1.000000 1.000000 1.000000

No hay valores faltantes. Los atributos categóricos ya están codificados numéricamente. Solamente hay jóvenes. Varios atributos son discretos-ordinales o binarios, lo que sirve para modelos de árboles. El problema está bien balanceado.

In [57]:
filename = "output/report.html"
if not os.path.exists(filename):
    profile = ydata_profiling.ProfileReport(df, title="EDA")
    profile.to_file(filename)
display(HTML(filename=filename))
EDA
EDA
  • Overview
  • Variables
  • Interactions
  • Correlations
  • Missing values
  • Sample

Overview

  • Overview
  • Alerts 5
  • Reproduction

Dataset statistics

Number of variables18
Number of observations64020
Missing cells0
Missing cells (%)0.0%
Duplicate rows0
Duplicate rows (%)0.0%
Total size in memory11.3 MiB
Average record size in memory185.0 B

Variable types

Numeric4
Categorical14

Alerts

CholCheck is highly imbalanced (82.2%)Imbalance
HvyAlcoholConsump is highly imbalanced (72.9%)Imbalance
Stroke is highly imbalanced (64.0%)Imbalance
MentHlth has 41555 (64.9%) zerosZeros
PhysHlth has 33432 (52.2%) zerosZeros

Reproduction

Analysis started2023-06-29 20:54:28.398598
Analysis finished2023-06-29 20:54:36.531913
Duration8.13 seconds
Software versionydata-profiling vv4.1.2
Download configurationconfig.json

Variables

Age
Real number (ℝ)

Distinct13
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Infinite0
Infinite (%)0.0%
Mean8.6074196
Minimum1
Maximum13
Zeros0
Zeros (%)0.0%
Negative0
Negative (%)0.0%
Memory size3.0 MiB
2023-06-29T16:54:36.588295image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • Statistics
  • Histogram
  • Common values
  • Extreme values

Quantile statistics

Minimum1
5-th percentile3
Q17
median9
Q311
95-th percentile13
Maximum13
Range12
Interquartile range (IQR)4

Descriptive statistics

Standard deviation2.8607167
Coefficient of variation (CV)0.33235474
Kurtosis-0.21594326
Mean8.6074196
Median Absolute Deviation (MAD)2
Skewness-0.54511156
Sum551047
Variance8.1836998
MonotonicityNot monotonic
2023-06-29T16:54:36.691100image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram with fixed size bins (bins=13)
ValueCountFrequency (%)
10 9589
15.0%
9 9121
14.2%
8 7829
12.2%
11 7307
11.4%
7 6202
9.7%
13 5105
8.0%
12 5035
7.9%
6 4194
6.6%
5 3170
 
5.0%
4 2489
 
3.9%
Other values (3) 3979
6.2%
  • Minimum 10 values
  • Maximum 10 values
ValueCountFrequency (%)
1 892
 
1.4%
2 1263
 
2.0%
3 1824
 
2.8%
4 2489
 
3.9%
5 3170
 
5.0%
6 4194
6.6%
7 6202
9.7%
8 7829
12.2%
9 9121
14.2%
10 9589
15.0%
ValueCountFrequency (%)
13 5105
8.0%
12 5035
7.9%
11 7307
11.4%
10 9589
15.0%
9 9121
14.2%
8 7829
12.2%
7 6202
9.7%
6 4194
6.6%
5 3170
 
5.0%
4 2489
 
3.9%

Sex
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
34828 
1.0
29192 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row1.0
2nd row1.0
3rd row1.0
4th row1.0
5th row0.0

Common Values

ValueCountFrequency (%)
0.0 34828
54.4%
1.0 29192
45.6%

Length

2023-06-29T16:54:36.802555image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:36.943191image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 34828
54.4%
1.0 29192
45.6%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 98848
51.5%
. 64020
33.3%
1 29192
 
15.2%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 98848
77.2%
1 29192
 
22.8%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 98848
51.5%
. 64020
33.3%
1 29192
 
15.2%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 98848
51.5%
. 64020
33.3%
1 29192
 
15.2%

HighChol
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
34542 
0.0
29478 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row1.0
3rd row0.0
4th row1.0
5th row0.0

Common Values

ValueCountFrequency (%)
1.0 34542
54.0%
0.0 29478
46.0%

Length

2023-06-29T16:54:37.036947image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:37.156245image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 34542
54.0%
0.0 29478
46.0%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 93498
48.7%
. 64020
33.3%
1 34542
 
18.0%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 93498
73.0%
1 34542
 
27.0%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 93498
48.7%
. 64020
33.3%
1 34542
 
18.0%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 93498
48.7%
. 64020
33.3%
1 34542
 
18.0%

CholCheck
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
62305 
0.0
 
1715
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row1.0
2nd row1.0
3rd row1.0
4th row1.0
5th row1.0

Common Values

ValueCountFrequency (%)
1.0 62305
97.3%
0.0 1715
 
2.7%

Length

2023-06-29T16:54:37.265628image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:37.375010image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 62305
97.3%
0.0 1715
 
2.7%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 65735
34.2%
. 64020
33.3%
1 62305
32.4%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 65735
51.3%
1 62305
48.7%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 65735
34.2%
. 64020
33.3%
1 62305
32.4%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 65735
34.2%
. 64020
33.3%
1 62305
32.4%

BMI
Real number (ℝ)

Distinct80
Distinct (%)0.1%
Missing0
Missing (%)0.0%
Infinite0
Infinite (%)0.0%
Mean30.178554
Minimum12
Maximum98
Zeros0
Zeros (%)0.0%
Negative0
Negative (%)0.0%
Memory size3.0 MiB
2023-06-29T16:54:37.500018image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • Statistics
  • Histogram
  • Common values
  • Extreme values

Quantile statistics

Minimum12
5-th percentile21
Q125
median29
Q334
95-th percentile43
Maximum98
Range86
Interquartile range (IQR)9

Descriptive statistics

Standard deviation7.2877303
Coefficient of variation (CV)0.24148706
Kurtosis6.8303595
Mean30.178554
Median Absolute Deviation (MAD)4
Skewness1.669602
Sum1932031
Variance53.111013
MonotonicityNot monotonic
2023-06-29T16:54:37.640653image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram with fixed size bins (bins=50)
ValueCountFrequency (%)
27 5411
 
8.5%
26 4293
 
6.7%
28 4055
 
6.3%
30 3951
 
6.2%
29 3834
 
6.0%
24 3684
 
5.8%
25 3485
 
5.4%
31 3475
 
5.4%
32 3223
 
5.0%
33 2948
 
4.6%
Other values (70) 25661
40.1%
  • Minimum 10 values
  • Maximum 10 values
ValueCountFrequency (%)
12 1
 
< 0.1%
13 8
 
< 0.1%
14 8
 
< 0.1%
15 30
 
< 0.1%
16 70
 
0.1%
17 168
 
0.3%
18 348
 
0.5%
19 635
 
1.0%
20 1123
1.8%
21 1748
2.7%
ValueCountFrequency (%)
98 4
 
< 0.1%
95 4
 
< 0.1%
92 9
< 0.1%
89 4
 
< 0.1%
87 13
< 0.1%
86 1
 
< 0.1%
85 1
 
< 0.1%
84 13
< 0.1%
83 1
 
< 0.1%
82 11
< 0.1%

Smoker
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
32605 
1.0
31415 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row1.0
3rd row0.0
4th row1.0
5th row1.0

Common Values

ValueCountFrequency (%)
0.0 32605
50.9%
1.0 31415
49.1%

Length

2023-06-29T16:54:37.765661image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:37.890670image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 32605
50.9%
1.0 31415
49.1%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 96625
50.3%
. 64020
33.3%
1 31415
 
16.4%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 96625
75.5%
1 31415
 
24.5%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 96625
50.3%
. 64020
33.3%
1 31415
 
16.4%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 96625
50.3%
. 64020
33.3%
1 31415
 
16.4%

HeartDiseaseorAttack
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
53780 
1.0
10240 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row0.0
3rd row0.0
4th row0.0
5th row0.0

Common Values

ValueCountFrequency (%)
0.0 53780
84.0%
1.0 10240
 
16.0%

Length

2023-06-29T16:54:37.995962image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:38.120971image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 53780
84.0%
1.0 10240
 
16.0%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 117800
61.3%
. 64020
33.3%
1 10240
 
5.3%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 117800
92.0%
1 10240
 
8.0%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 117800
61.3%
. 64020
33.3%
1 10240
 
5.3%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 117800
61.3%
. 64020
33.3%
1 10240
 
5.3%

PhysActivity
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
43429 
0.0
20591 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row1.0
2nd row0.0
3rd row1.0
4th row1.0
5th row1.0

Common Values

ValueCountFrequency (%)
1.0 43429
67.8%
0.0 20591
32.2%

Length

2023-06-29T16:54:38.214729image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:38.339736image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 43429
67.8%
0.0 20591
32.2%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 84611
44.1%
. 64020
33.3%
1 43429
22.6%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 84611
66.1%
1 43429
33.9%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 84611
44.1%
. 64020
33.3%
1 43429
22.6%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 84611
44.1%
. 64020
33.3%
1 43429
22.6%

Fruits
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
37827 
0.0
26193 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row1.0
3rd row1.0
4th row1.0
5th row1.0

Common Values

ValueCountFrequency (%)
1.0 37827
59.1%
0.0 26193
40.9%

Length

2023-06-29T16:54:38.477951image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:38.588055image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 37827
59.1%
0.0 26193
40.9%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 90213
47.0%
. 64020
33.3%
1 37827
19.7%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 90213
70.5%
1 37827
29.5%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 90213
47.0%
. 64020
33.3%
1 37827
19.7%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 90213
47.0%
. 64020
33.3%
1 37827
19.7%

Veggies
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
49397 
0.0
14623 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row1.0
2nd row0.0
3rd row1.0
4th row1.0
5th row1.0

Common Values

ValueCountFrequency (%)
1.0 49397
77.2%
0.0 14623
 
22.8%

Length

2023-06-29T16:54:38.697437image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:38.822446image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 49397
77.2%
0.0 14623
 
22.8%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 78643
40.9%
. 64020
33.3%
1 49397
25.7%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 78643
61.4%
1 49397
38.6%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 78643
40.9%
. 64020
33.3%
1 49397
25.7%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 78643
40.9%
. 64020
33.3%
1 49397
25.7%

HvyAlcoholConsump
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
61053 
1.0
 
2967
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row0.0
3rd row0.0
4th row0.0
5th row0.0

Common Values

ValueCountFrequency (%)
0.0 61053
95.4%
1.0 2967
 
4.6%

Length

2023-06-29T16:54:38.970500image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:39.082967image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 61053
95.4%
1.0 2967
 
4.6%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 125073
65.1%
. 64020
33.3%
1 2967
 
1.5%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 125073
97.7%
1 2967
 
2.3%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 125073
65.1%
. 64020
33.3%
1 2967
 
1.5%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 125073
65.1%
. 64020
33.3%
1 2967
 
1.5%

GenHlth
Categorical

Distinct5
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
3.0
21755 
2.0
16853 
4.0
13170 
1.0
6463 
5.0
5779 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters7
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row3.0
2nd row3.0
3rd row1.0
4th row3.0
5th row2.0

Common Values

ValueCountFrequency (%)
3.0 21755
34.0%
2.0 16853
26.3%
4.0 13170
20.6%
1.0 6463
 
10.1%
5.0 5779
 
9.0%

Length

2023-06-29T16:54:39.176724image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:39.317358image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
3.0 21755
34.0%
2.0 16853
26.3%
4.0 13170
20.6%
1.0 6463
 
10.1%
5.0 5779
 
9.0%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
. 64020
33.3%
0 64020
33.3%
3 21755
 
11.3%
2 16853
 
8.8%
4 13170
 
6.9%
1 6463
 
3.4%
5 5779
 
3.0%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 64020
50.0%
3 21755
 
17.0%
2 16853
 
13.2%
4 13170
 
10.3%
1 6463
 
5.0%
5 5779
 
4.5%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
. 64020
33.3%
0 64020
33.3%
3 21755
 
11.3%
2 16853
 
8.8%
4 13170
 
6.9%
1 6463
 
3.4%
5 5779
 
3.0%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
. 64020
33.3%
0 64020
33.3%
3 21755
 
11.3%
2 16853
 
8.8%
4 13170
 
6.9%
1 6463
 
3.4%
5 5779
 
3.0%

MentHlth
Real number (ℝ)

Distinct31
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Infinite0
Infinite (%)0.0%
Mean4.1305373
Minimum0
Maximum30
Zeros41555
Zeros (%)64.9%
Negative0
Negative (%)0.0%
Memory size3.0 MiB
2023-06-29T16:54:39.442367image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • Statistics
  • Histogram
  • Common values
  • Extreme values

Quantile statistics

Minimum0
5-th percentile0
Q10
median0
Q33
95-th percentile30
Maximum30
Range30
Interquartile range (IQR)3

Descriptive statistics

Standard deviation8.466301
Coefficient of variation (CV)2.0496852
Kurtosis3.6862398
Mean4.1305373
Median Absolute Deviation (MAD)0
Skewness2.2243058
Sum264437
Variance71.678253
MonotonicityNot monotonic
2023-06-29T16:54:39.586840image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram with fixed size bins (bins=31)
ValueCountFrequency (%)
0 41555
64.9%
30 4304
 
6.7%
2 3212
 
5.0%
5 2509
 
3.9%
1 2019
 
3.2%
3 1954
 
3.1%
10 1920
 
3.0%
15 1766
 
2.8%
20 1124
 
1.8%
4 977
 
1.5%
Other values (21) 2680
 
4.2%
  • Minimum 10 values
  • Maximum 10 values
ValueCountFrequency (%)
0 41555
64.9%
1 2019
 
3.2%
2 3212
 
5.0%
3 1954
 
3.1%
4 977
 
1.5%
5 2509
 
3.9%
6 288
 
0.4%
7 825
 
1.3%
8 198
 
0.3%
9 28
 
< 0.1%
ValueCountFrequency (%)
30 4304
6.7%
29 53
 
0.1%
28 99
 
0.2%
27 17
 
< 0.1%
26 17
 
< 0.1%
25 425
 
0.7%
24 10
 
< 0.1%
23 13
 
< 0.1%
22 22
 
< 0.1%
21 84
 
0.1%

PhysHlth
Real number (ℝ)

Distinct31
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Infinite0
Infinite (%)0.0%
Mean6.3850203
Minimum0
Maximum30
Zeros33432
Zeros (%)52.2%
Negative0
Negative (%)0.0%
Memory size3.0 MiB
2023-06-29T16:54:40.088650image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • Statistics
  • Histogram
  • Common values
  • Extreme values

Quantile statistics

Minimum0
5-th percentile0
Q10
median0
Q37
95-th percentile30
Maximum30
Range30
Interquartile range (IQR)7

Descriptive statistics

Standard deviation10.368493
Coefficient of variation (CV)1.6238779
Kurtosis0.70396533
Mean6.3850203
Median Absolute Deviation (MAD)0
Skewness1.5130199
Sum408769
Variance107.50566
MonotonicityNot monotonic
2023-06-29T16:54:40.260627image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram with fixed size bins (bins=31)
ValueCountFrequency (%)
0 33432
52.2%
30 7897
 
12.3%
2 4047
 
6.3%
1 2803
 
4.4%
3 2424
 
3.8%
5 2327
 
3.6%
10 1977
 
3.1%
15 1912
 
3.0%
4 1374
 
2.1%
7 1323
 
2.1%
Other values (21) 4504
 
7.0%
  • Minimum 10 values
  • Maximum 10 values
ValueCountFrequency (%)
0 33432
52.2%
1 2803
 
4.4%
2 4047
 
6.3%
3 2424
 
3.8%
4 1374
 
2.1%
5 2327
 
3.6%
6 447
 
0.7%
7 1323
 
2.1%
8 276
 
0.4%
9 55
 
0.1%
ValueCountFrequency (%)
30 7897
12.3%
29 95
 
0.1%
28 211
 
0.3%
27 34
 
0.1%
26 26
 
< 0.1%
25 557
 
0.9%
24 24
 
< 0.1%
23 27
 
< 0.1%
22 31
 
< 0.1%
21 229
 
0.4%

DiffWalk
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
46286 
1.0
17734 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row0.0
3rd row0.0
4th row0.0
5th row0.0

Common Values

ValueCountFrequency (%)
0.0 46286
72.3%
1.0 17734
 
27.7%

Length

2023-06-29T16:54:40.386101image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:40.511109image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 46286
72.3%
1.0 17734
 
27.7%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 110306
57.4%
. 64020
33.3%
1 17734
 
9.2%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 110306
86.1%
1 17734
 
13.9%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 110306
57.4%
. 64020
33.3%
1 17734
 
9.2%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 110306
57.4%
. 64020
33.3%
1 17734
 
9.2%

Stroke
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
0.0
59634 
1.0
 
4386
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row1.0
3rd row0.0
4th row0.0
5th row0.0

Common Values

ValueCountFrequency (%)
0.0 59634
93.1%
1.0 4386
 
6.9%

Length

2023-06-29T16:54:40.616934image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:40.730840image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
0.0 59634
93.1%
1.0 4386
 
6.9%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 123654
64.4%
. 64020
33.3%
1 4386
 
2.3%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 123654
96.6%
1 4386
 
3.4%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 123654
64.4%
. 64020
33.3%
1 4386
 
2.3%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 123654
64.4%
. 64020
33.3%
1 4386
 
2.3%

HighBP
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
37244 
0.0
26776 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row1.0
2nd row1.0
3rd row0.0
4th row1.0
5th row0.0

Common Values

ValueCountFrequency (%)
1.0 37244
58.2%
0.0 26776
41.8%

Length

2023-06-29T16:54:40.824782image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:40.965417image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 37244
58.2%
0.0 26776
41.8%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 90796
47.3%
. 64020
33.3%
1 37244
19.4%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 90796
70.9%
1 37244
29.1%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 90796
47.3%
. 64020
33.3%
1 37244
19.4%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 90796
47.3%
. 64020
33.3%
1 37244
19.4%

Diabetes
Categorical

Distinct2
Distinct (%)< 0.1%
Missing0
Missing (%)0.0%
Memory size3.0 MiB
1.0
33398 
0.0
30622 
  • Overview
  • Categories
  • Words
  • Characters

Length

Max length3
Median length3
Mean length3
Min length3

Characters and Unicode

Total characters192060
Distinct characters3
Distinct categories2 ?
Distinct scripts1 ?
Distinct blocks1 ?
The Unicode Standard assigns character properties to each code point, which can be used to analyse textual variables.

Unique

Unique0 ?
Unique (%)0.0%

Sample

1st row0.0
2nd row0.0
3rd row0.0
4th row0.0
5th row0.0

Common Values

ValueCountFrequency (%)
1.0 33398
52.2%
0.0 30622
47.8%

Length

2023-06-29T16:54:41.074982image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Histogram of lengths of the category

Common Values (Plot)

2023-06-29T16:54:41.198198image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
ValueCountFrequency (%)
1.0 33398
52.2%
0.0 30622
47.8%
  • Characters
  • Categories
  • Scripts
  • Blocks

Most occurring characters

ValueCountFrequency (%)
0 94642
49.3%
. 64020
33.3%
1 33398
 
17.4%

Most occurring categories

ValueCountFrequency (%)
Decimal Number 128040
66.7%
Other Punctuation 64020
33.3%

Most frequent character per category

Decimal Number
ValueCountFrequency (%)
0 94642
73.9%
1 33398
 
26.1%
Other Punctuation
ValueCountFrequency (%)
. 64020
100.0%

Most occurring scripts

ValueCountFrequency (%)
Common 192060
100.0%

Most frequent character per script

Common
ValueCountFrequency (%)
0 94642
49.3%
. 64020
33.3%
1 33398
 
17.4%

Most occurring blocks

ValueCountFrequency (%)
ASCII 192060
100.0%

Most frequent character per block

ASCII
ValueCountFrequency (%)
0 94642
49.3%
. 64020
33.3%
1 33398
 
17.4%

Interactions

  • Age
  • BMI
  • MentHlth
  • PhysHlth
  • PhysHlth
  • Age
  • BMI
  • MentHlth
2023-06-29T16:54:35.379214image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.183765image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.664926image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:34.143054image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • PhysHlth
  • Age
  • BMI
  • MentHlth
2023-06-29T16:54:35.497533image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.298654image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.791435image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:34.272678image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • PhysHlth
  • Age
  • BMI
  • MentHlth
2023-06-29T16:54:35.618987image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.421961image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.899172image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:34.388335image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
  • PhysHlth
  • Age
  • BMI
  • MentHlth
2023-06-29T16:54:35.749767image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:33.552859image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:34.024911image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
2023-06-29T16:54:34.511180image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/

Correlations

  • Auto
  • Heatmap
  • Table
2023-06-29T16:54:41.307580image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
AgeBMIMentHlthPhysHlthSexHighCholCholCheckSmokerHeartDiseaseorAttackPhysActivityFruitsVeggiesHvyAlcoholConsumpGenHlthDiffWalkStrokeHighBPDiabetes
Age1.000-0.060-0.1830.0430.0290.2560.1120.1120.2280.1020.0910.0270.0620.0880.2040.1270.3350.287
BMI-0.0601.0000.0640.1400.1210.1190.0530.0170.0460.1480.0620.0380.0640.1270.2330.0070.2240.276
MentHlth-0.1830.0641.0000.3150.1110.0770.0030.0840.0630.1130.0470.0370.0150.1720.2360.0780.0560.075
PhysHlth0.0430.1400.3151.0000.0770.1410.0430.1100.1870.2130.0260.0460.0480.3210.4770.1530.1710.206
Sex0.0290.1210.1110.0771.0000.0060.0070.1080.0990.0550.0850.0530.0160.0300.0860.0020.0310.035
HighChol0.2560.1190.0770.1410.0061.0000.0930.0750.1750.0750.0340.0310.0310.2160.1540.0970.2900.264
CholCheck0.1120.0530.0030.0430.0070.0931.0000.0000.0490.0150.0120.0020.0250.0750.0530.0260.1130.126
Smoker0.1120.0170.0840.1100.1080.0750.0001.0000.1150.0640.0590.0160.0750.1310.1080.0600.0670.062
HeartDiseaseorAttack0.2280.0460.0630.1870.0990.1750.0490.1151.0000.0820.0020.0220.0440.2730.2200.2190.2030.202
PhysActivity0.1020.1480.1130.2130.0550.0750.0150.0640.0821.0000.1130.1300.0290.2490.2550.0680.1190.139
Fruits0.0910.0620.0470.0260.0850.0340.0120.0590.0020.1131.0000.2250.0260.0660.0280.0000.0210.031
Veggies0.0270.0380.0370.0460.0530.0310.0020.0160.0220.1300.2251.0000.0300.0890.0630.0370.0510.062
HvyAlcoholConsump0.0620.0640.0150.0480.0160.0310.0250.0750.0440.0290.0260.0301.0000.0770.0600.0280.0340.107
GenHlth0.0880.1270.1720.3210.0300.2160.0750.1310.2730.2490.0660.0890.0771.0000.4870.1930.2970.387
DiffWalk0.2040.2330.2360.4770.0860.1540.0530.1080.2200.2550.0280.0630.0600.4871.0000.1820.2270.262
Stroke0.1270.0070.0780.1530.0020.0970.0260.0600.2190.0680.0000.0370.0280.1930.1821.0000.1260.120
HighBP0.3350.2240.0560.1710.0310.2900.1130.0670.2030.1190.0210.0510.0340.2970.2270.1261.0000.351
Diabetes0.2870.2760.0750.2060.0350.2640.1260.0620.2020.1390.0310.0620.1070.3870.2620.1200.3511.000

Missing values

  • Count
  • Matrix
2023-06-29T16:54:35.940427image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
A simple visualization of nullity by column.
2023-06-29T16:54:36.293237image/svg+xmlMatplotlib v3.6.3, https://matplotlib.org/
Nullity matrix is a data-dense display which lets you quickly visually pick out patterns in data completion.

Sample

  • First rows
  • Last rows
AgeSexHighCholCholCheckBMISmokerHeartDiseaseorAttackPhysActivityFruitsVeggiesHvyAlcoholConsumpGenHlthMentHlthPhysHlthDiffWalkStrokeHighBPDiabetes
04.01.00.01.026.00.00.01.00.01.00.03.05.030.00.00.01.00.0
112.01.01.01.026.01.00.00.01.00.00.03.00.00.00.01.01.00.0
213.01.00.01.026.00.00.01.01.01.00.01.00.010.00.00.00.00.0
311.01.01.01.028.01.00.01.01.01.00.03.00.03.00.00.01.00.0
48.00.00.01.029.01.00.01.01.01.00.02.00.00.00.00.00.00.0
51.00.00.01.018.00.00.01.01.01.00.02.07.00.00.00.00.00.0
613.01.01.01.026.01.00.01.01.01.01.01.00.00.00.00.00.00.0
76.01.00.01.031.01.00.00.01.01.00.04.00.00.00.00.00.00.0
83.00.00.01.032.00.00.01.01.01.00.03.00.00.00.00.00.00.0
96.01.00.01.027.01.00.00.01.01.00.03.00.06.00.00.00.00.0
AgeSexHighCholCholCheckBMISmokerHeartDiseaseorAttackPhysActivityFruitsVeggiesHvyAlcoholConsumpGenHlthMentHlthPhysHlthDiffWalkStrokeHighBPDiabetes
706829.00.00.01.037.00.00.00.00.00.00.04.00.030.01.00.01.01.0
7068310.00.00.01.028.00.00.00.00.01.00.02.00.00.00.00.01.01.0
706849.01.01.01.027.00.01.01.00.01.00.04.030.05.00.00.01.01.0
706857.00.00.01.038.00.00.01.00.01.00.04.00.00.00.00.01.01.0
7068611.01.01.01.027.00.00.01.01.00.00.04.00.030.00.00.00.01.0
706876.00.01.01.037.00.00.00.00.01.00.04.00.00.00.00.00.01.0
7068810.01.01.01.029.01.01.00.01.01.00.02.00.00.01.00.00.01.0
7068913.00.01.01.025.00.01.00.01.00.00.05.015.00.01.00.01.01.0
7069011.00.01.01.018.00.00.00.00.00.00.04.00.00.01.00.01.01.0
706919.00.01.01.025.00.01.01.01.00.00.02.00.00.00.00.01.01.0

Report generated by YData.

Cabe destacar que el BMI debe ser un atributo porcentual (normalizado al rango 0-100 en algún conjunto de datos), pues pocas personas en la historia han tenido valor cercano a 100. Si fuera BMI real la mayoría del conjunto de datos tendría obesidad mórbida.

2. Clasificación de pacientes con diabetes (0.5 pt)¶

In [29]:
X = df.drop(columns=["Diabetes"])
y = df["Diabetes"]
X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    random_state=0,
    stratify=y,
    test_size=0.2,
)

Notamos que todas las variables son numéricas y no hay valores faltantes, por lo que bastará utilizar XGBoost sin un Pipeline o ColumnTransformer. Se realizará GridSearchCV con 5 folds, y se medirá el f1 score para seleccionar el mejor modelo. En pruebas con optuna, no se logró encontrar mejores hiperparámetros que los por defecto, por lo que solamente se probará con un rango pequeño de valores cercanos a los por defecto.

f1 score se escoge debido a que es una medida robusta que balancea la precisión y el recall sin tener que pensar mucho más profundamente en la decisión. Podremos interpretar esta medida como un error total de clasificación.

Para validar el modelo, se verá la matriz de confusión.

In [30]:
gridsearch_root = "output/gridsearch.pkl"
try:
    with open(gridsearch_root, "rb") as f:
        grid = pickle.load(f)
except FileNotFoundError:
    base_clf = xgb.XGBClassifier(random_state=0, n_jobs=5)
    param_grid = {
        "n_estimators": [100, 150, 200],
        "max_depth": [5, 6, 7],
        "learning_rate": [0.15, 0.3, 0.6],
    }
    grid = GridSearchCV(
        base_clf,
        param_grid,
        scoring="f1",
    )
    grid.fit(X_train, y_train)
    with open(gridsearch_root, "wb") as f:
        pickle.dump(grid, f)

Puntajes en validación:

In [31]:
index = grid.best_index_
pd.DataFrame(grid.cv_results_).loc[index]
Out[31]:
mean_fit_time                                                              1.027432
std_fit_time                                                                0.19584
mean_score_time                                                            0.015004
std_score_time                                                             0.002098
param_learning_rate                                                            0.15
param_max_depth                                                                   5
param_n_estimators                                                              100
params                 {'learning_rate': 0.15, 'max_depth': 5, 'n_estimators': 100}
split0_test_score                                                          0.765355
split1_test_score                                                          0.753739
split2_test_score                                                          0.767167
split3_test_score                                                          0.764041
split4_test_score                                                          0.759648
mean_test_score                                                             0.76199
std_test_score                                                             0.004814
rank_test_score                                                                   1
Name: 0, dtype: object

Vemos que el f1-score no es tan alto para lo que queremos (0.76 en promedio), pero es muy estable (0.004 de desviación estándar). Esto indica que el modelo no está sobreajustando a cada fold.

Nos interesa más aún saber si este puntaje generaliza bien a datos de prueba, y saber si el modelo está sesgado hacia alguna clase:

In [32]:
clf = grid.best_estimator_
conf = confusion_matrix(y_test, clf.predict(X_test))
disp = ConfusionMatrixDisplay(conf, display_labels=["No diabetes", "Diabetes"])
disp.plot();

Tanto en los conjuntos validación como en el de prueba, el modelo se equivoca cerca de 1/4 de las veces en cualquiera de las dos clases. Esto muestra que el modelo no está sesgado hacia ninguna clase, y que la validación es representativa del error de generalización en el conjunto de prueba.

El error sí es más alto de lo deseado dado la importancia del problema, pero no se logró encontrar una mejora simple de implementar.

Con esto, respondemos las preguntas:

  • ¿Es acaso un buen predictor de diabetes? R: Muestra un buen puntaje de

clasificación al realizar validación cruzada, pero ésto es solamente un proxy del error de generalización verdadero. En realidad, no sabemos si los datos proporcionados son suficientemente representativos de la población de pacientes, y no se realizó un EDA para validar que éstos datos permitan una capacidad de generalizar para pacientes reales.

  • ¿Qué buscan explicar las métricas utilizadas? R: Que el modelo sea capaz de

clasificar correctamente a los pacientes fuera de la muestra de entrenamiento (pero dentro del conjunto de prueba).

  • ¿Las métricas utilizadas para medir la predictibilidad le permiten asegurar que su

modelo una buena elección de las features? R: No, solamente determinan que el modelo es preciso, pero XGBoost no realiza una selección de características, y puede ajustarse al ruido específico de este conjunto de datos. Debido a que utiliza mecanismos como column subsampling, el modelo puede terminar utilizando características inútiles, y estará sesgado hacia utilizar más frecuentemente características repetidas.

3. Importancia de las features con XGBoost (0.5 pt)¶

Se crea cada uno de los gráficos de importancia de características.

In [33]:
fig, axes = plt.subplots(ncols=3, figsize=(30, 10))
importance_types = ("weight", "cover", "gain")
for method, ax in zip(importance_types, axes):
    xgb.plot_importance(
        clf, importance_type=method, title=method, ax=ax, show_values=False
    )
plt.tight_layout()

Para responder respecto a la consistencia, se creará un gráfico que compare la posición de ranking de cada característica en cada método, conectando con una línea las posiciónes de cada característica en cada método. Líneas horizontales indicarían que ambos métodos coinciden en ranking, pero estas no se dibujarán por claridad. Es decir, la presencia de una línea en el gráfico indica un desacuerdo en el ranking de distintos métodos. Líneas más largas indican un mayor desacuerdo.

In [34]:
booster = clf.get_booster()
importances = {
    method: pd.Series(booster.get_score(importance_type=method))
    .sort_values(ascending=False)
    .index
    for method in importance_types
}
weight = importances["weight"]
x = np.zeros_like(weight, dtype=np.float32)
ns = np.arange(len(weight))
fig, ax = plt.subplots(figsize=(10, 10))
for i, method in enumerate(importance_types):
    ax.scatter(x + i, ns, marker="o")
ax.scatter(x + len(importance_types), ns, marker="o")

weight_indices = np.arange(len(weight))
gain_indices = importances["gain"].values.argsort()
cover_indices = importances["cover"].values.argsort()

weight_gain_mask = weight_indices != gain_indices
gain_cover_mask = gain_indices != cover_indices
cover_weight_mask = cover_indices != weight_indices

ax.plot(
    [0, 1],
    np.column_stack((weight_indices, gain_indices))[weight_gain_mask].T,
    color="k",
)
ax.plot(
    [1, 2], np.column_stack((gain_indices, cover_indices))[gain_cover_mask].T, color="k"
)
ax.plot(
    [2, 3],
    np.column_stack((cover_indices, weight_indices))[cover_weight_mask].T,
    color="k",
)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    ax.set_yticklabels(weight)
    ax.set_yticks(ns)
    ax.set_xticklabels(["weight", "gain", "cover", "weight"])
    ax.set_xticks([0, 1, 2, 3])
ax.set_title("Comparación de rankings para cada método");

Se puede observar muchas líneas, y líneas con gran pendiente, indicando que los rankings son muy inconsistentes.

Este desacuerdo se explica porque cada importancia mide algo distinto. Según la documentación de XGBoost:

  • ”weight” is the number of times a feature appears in a tree

  • ”gain” is the average gain of splits which use the feature

  • ”cover” is the average coverage of splits which use the feature where coverage is defined as the number of samples affected by the split

Que no necesariamente coinciden, pero las tres están relacionadas por como los árboles utilizan la característica para realizar las particiones. Esto significa que existe un sesgo por características que tienen más valores únicos, pues hay más chances para dividirse.

Sin embargo, sí hay algunos acuerdos generales:

  • CholCheck siempre es una de las características más importantes (sus puntos están

arriba en el gráfico)

  • MentlHlth siempre es una de las características menos importantes (sus puntos

están abajo en el gráfico)

  • PhysHlth y Stroke tienen mucha variabilidad en los ranking (líneas largas)

Para responder las otras preguntas planteadas:

  • ¿Las importancias obtenidas son suficientes para obtener la interpretabilidad de un

modelo que utiliza árboles? R: No, solamente tenemos una indicación global (y sesgada) de la importancia de cada característica, pero no podemos reconstruir cómo el modelo toma las decisiones, cómo se puede para un árbol de decisión, que se puede graficar de una manera que permite interpretabilidad global (viendo la estrcutura del árbol) y local (siguiendo un camino hacia una hoja), ambas exactas.

  • ¿Qué debilidad presenta este método? R: La interpretación es inexacta, sesgada. No indica signos, es decir, si una característica aumenta o disminuye la probabilidad de diabetes. Esconde la relacíón con la distribución de cada variable (en particular, valores únicos). No permite reconstruir el modelo.
In [35]:
scores = []
for i in range(1, 50):
    tree = DecisionTreeClassifier(max_depth=i, random_state=0)
    tree.fit(X_train, y_train)
    scores.append(tree.score(X_test, y_test))
best_depth = np.argmax(scores) + 1
In [36]:
fig, ax = plt.subplots(ncols=2, figsize=(30, 15))
ax[0].plot(scores)
ax[0].set_title("Precisión en función de la profundidad")
ax[0].set_xlabel("Profundidad")
ax[0].set_ylabel("Precisión")
ax[0].axvline(best_depth, color="k", linestyle="--")
ax[0].text(
    best_depth + 1,
    scores[best_depth - 1],
    f"Profundidad óptima: {best_depth}, precisión: {scores[best_depth - 1]:.2f}",
    va="center",
    ha="left",
)
tree = DecisionTreeClassifier(max_depth=best_depth, random_state=0)
tree.fit(X_train, y_train)
plot_tree(
    tree,
    max_depth=3,  # Tamaño más pequeño para que se vea bien
    ax=ax[1],
    feature_names=X.columns,
    filled=True,
    fontsize=10,
    class_names=["No diabetes", "Diabetes"],
)
ax[1].set_title("Árbol de decisión de profundidad óptima");

4. Métodos Agnósticos Globales (1 pt)¶

In [37]:
perm_importance = permutation_importance(
    clf, X_test, y_test, n_repeats=30, random_state=0, n_jobs=-1
)
perm_importance_df = pd.DataFrame(
    {
        "importances_mean": perm_importance.importances_mean,
        "importances_std": perm_importance.importances_std,
    },
    index=X_test.columns,
).sort_values(by="importances_mean", ascending=True)
plt.figure(figsize=(15, 15))
plt.barh(
    range(X.shape[1]),
    perm_importance_df.importances_mean,
    xerr=perm_importance_df.importances_std,
)
plt.yticks(range(X.shape[1]), X.columns)
plt.title("Importancia de características para el predictor de diabetes")
plt.xlabel("Importancia");

Respondiendo lo pedido:

  • La desviación estándar indica la variabilidad de los resultados, pues la

permutación es aleatoria. Si bien se espera que en principio las permutaciones deben empeorar los resultados, por la aleatoriedad puede haber casos en que mejoren. En este caso, la mayoría de importancias tiene una desviación estándar baja, lo que muestra que el método es consistente.

  • La importancia de una característica se mide como la pérdida de

puntaje que incurre el modelo al permutar los valores de una característica.

  • Las 5 características de mayor impacto al modelo son:
    • HighBP (presión sangínea alta)
    • Stroke (si tuvo un ataque cerebrovascular)
    • DiffWalk (dificultad para caminar)
    • PhysHealth (puntaje de salud física)
    • MentHealth (puntaje de salud mental)
  • Todas éstas tienen que ver con la salud, y tiene sentido que se correlacionen con

la diabetes. Es importante destacar que no necesariamente implican una relación causal. Consultando con un médico, se verificó que si bien se conoce de la relación entre los ataques cerebrovasculares y la diabetes, no se ha determinado una causalidad desde la fisiopatología. El único caso donde se puede afirmar que hay una relación causal es en la dificultad para caminar, pues esta causa sedentarismo.

  • Existen dos diferencias muy grandes a las importancias anteriores: CholCheck se

considera dañino para el modelo (importancia negativa), y MentlHlth se considera muy buen predictor. Esto no es explicado por la cantidad de valores únicos que tiene cada variable, pues CholCheck tiene 2 y MentlHlth tiene 31 valores. Sin embargo, sí se puede explicar porque ahora las interacciones sí se toman en cuenta.

  • Ventajas: Este modelo toma en cuenta interacciones. Logra una mejor interpretación

global en términos del error del modelo, sin requerir reentrenamiento. Más aún, es agnóstico y comparable entre modelos.

  • Desventajas: El error está enlazado al error del modelo. Caracerísticas

correlacionadas pueden causar sesgos, pues las permutaciones no deberían ser independientes para generar datos de la distribución original. Como la importancia se divide en todas las características correlacionadas, si hay varias entonces se diluye la importancia de cada una.

In [38]:
X.nunique().sort_values(ascending=False)
Out[38]:
BMI                     80
PhysHlth                31
MentHlth                31
Age                     13
GenHlth                  5
Veggies                  2
Stroke                   2
DiffWalk                 2
HvyAlcoholConsump        2
Fruits                   2
Sex                      2
PhysActivity             2
HeartDiseaseorAttack     2
Smoker                   2
CholCheck                2
HighChol                 2
HighBP                   2
dtype: int64

5. Métodos Agnósticos Locales (2 pt)¶

Parte A (0.4 pt)¶

Se calcularon los valores de SHAP para todo el dataset en vez de solamente el conjunto de entrenamiento como se vé en algunos ejemplos. Esto de debido a que después se pide explicar instancias específicas que podrían formar parte de cualquiera de los dos conjuntos dependiendo de como se dividieron los datos.

Acá un signo positivo significa que aumentos en la característica aumentan la probabilidad de tener diabetes, mientras que un signo negativo significa que aumentos en la característica disminuyen la probabilidad de tener diabetes. En general, una variable tendrá tanto valores positivos como negativos, pues el modelo no es lineal. Esto significa que para algunos pacientes una característica puede implicar un aumento de probabilidad de diabetes, mientras que para otros pacientes este mismo valor implica una disminución.

In [39]:
explainer = shap.TreeExplainer(clf)
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    shap_values = explainer.shap_values(X)
pd.DataFrame(shap_values, columns=X.columns, index=X.index).head()
Out[39]:
Age Sex HighChol CholCheck BMI Smoker HeartDiseaseorAttack PhysActivity Fruits Veggies HvyAlcoholConsump GenHlth MentHlth PhysHlth DiffWalk Stroke HighBP
0 -1.026560 0.008977 -0.439114 0.029464 -0.342847 0.008693 -0.061154 0.004153 0.000423 -0.024877 0.029179 0.054244 -0.184836 0.092628 -0.089071 -0.022545 0.428644
1 0.245925 0.064547 0.163573 0.017317 -0.293388 -0.032035 -0.044783 0.073778 0.026808 0.069421 0.041073 0.084423 0.020633 0.005599 -0.064335 0.114233 0.347924
2 0.792307 0.219198 -0.151763 0.030192 -0.291248 -0.007490 -0.037095 -0.032856 -0.026772 -0.021163 0.047696 -0.887070 0.048786 0.100116 -0.087138 -0.019266 -0.563719
3 0.320420 0.077391 0.186606 0.024601 -0.149637 -0.011896 -0.036314 -0.029691 -0.017971 -0.028286 0.039637 0.077160 0.011180 -0.009014 -0.090873 -0.007912 0.307017
4 -0.045402 -0.080013 -0.232086 0.030714 0.104037 -0.003471 -0.048577 -0.004121 0.006378 -0.017323 0.043292 -0.546284 0.084615 0.044429 -0.035780 -0.017352 -0.530409

Parte B (0.4 pt)¶

Se grafica el aporte para las instancias 1, 9 y 50, para responder cada pregunta.

In [40]:
indice_instancias = [1, 9, 150]
instancias = X.iloc[indice_instancias, :]
valores = shap_values[indice_instancias, :]
for instancia, valor in zip(instancias.iterrows(), valores):
    shap.force_plot(
        explainer.expected_value,
        valor,
        instancia[1],
        matplotlib=True,
        link="logit",
    )
  • ¿Qué variables afectan de manera positiva/negativa a la probabilidad de poseer diabetes? R: Ignorando los efectos muy pequeños para ser significativos, vemos cada instancia por separado
    • Instancia 1:
      • Aumento de probabilidad: Por haber tenido un ataque cerebrovascular, alto colesterol y alta presión sanguínea. También contribuye la falta de vegetales y actividad física. Otros factores de aumento es tener 12 años, salud general 3, y pertenecer al sexo 1.
      • Disminución: Por tener un BMI de 26%
    • Instancia 3:
      • Aumento: Salud general 3.
      • Disminución: Por no tener alta presión sanguínea, alto colesterol, ataque/enfermedad de corazón. También por tener 6 años y un BMI de 27%.
    • Instancia 50:
      • Aumento: Por haber tenido alta presión sanguínea y ataque/enfermedad de corazón. También por tener 13 años, salud general 3 y pertenecer al sexo 1.
      • Disminución: Por tener salud física 8 y BMI de 23%.
  • ¿Existe algún patrón común entre las instancias analizadas? R: Existen varios

patrones comunes que ocurren en las 3 instancias: - Tener alta presión sanguínea aumenta la probabilidad de diabetes, y no tenerla disminuye la probabilidad considerablemente. - En los 3 casos se tenía una salud general 3, lo que aumentaba las probabilidades de diabetes. - Tener 12/13 años aumenta la probabilidad, pero tener 6 la disminuye. - El BMI está cercano al primer cuartil, y esto siempre disminuye la probabilidad.

También se detecta que puede haber otros patrones más débiles (son un efecto fuerte para 2 instancias, pero no para las 3):
- Pertenecer al sexo 1 causa aumento de probabilidad considerable
- Alto colesterol aumenta la probabilidad, no tener alto colesterol la disminuye
- Tener un ataque/enfermedad cardíaca aumenta la probabilidad, no tenerla la disminuye
En general, no se vieron que dos instancias muestren un efecto contradictorio para cada variable (en términos de signos distintos), pero sí de magnitudes distintas (modelando no-linealidad).
  • ¿Es posible generalizar estas conclusiones a todo el dataset? R: No, la interpretación que proveen los SHAP values es una local, que solamente afecta a las predicciones vistas.

Parte C (0.4 pt)¶

Genere ahora una visualización donde se grafique el aporte de cada feature a nivel global e interprete sus resultados. ¿Qué diferencias existen con las conclusiones generadas a nivel de instancia?

In [41]:
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    shap.summary_plot(shap_values, X)
  • En varias variables binarias (HighBP, HighCol, HeartDiseaseOrAttack, DiffWalk, Sex, CholCheck, HvyAlcholConsump, PhysActivity) se vén dos agrupaciones de valores, una positiva y otra negativa, mostrando que el signo del efecto es independiente de otras variables. Tiene sentido esperar que en todos los pacientes con alta presión sanguínea haya un aumento de probabilidad de diabetes (y viceversa), pero esto puede combinarse con otros factores de forma no lineal. En el caso de CholCheck hay mucha mayor variabilidad para aquellos con valor 0, con distintas magnitudes de disminución de probabilidad, pero cuando tienen valor 1, es un aumento ligero.
  • Las 6 variables inferiores en el gráfico no parecen ser muy importantes: Las magnitudes de sus valores de SHAP son pequeñas y tienen efectos confusos (valores similares tienen impactos con signo distinto).
  • La relación de los valores de SHAP con el valor de GenHealth no es monótona. Sin entender la distribución de la variable, cuesta determinar si coincide con la interpretación local.
  • Vemos que se siguen patrones de la pregunta anterior, como que menor edad implica menor valor de SHAP, que sexo 1 implica uno mayor.
  • No hay diferencias mayores con la interpretación local que se puedan detectar solamente a partir del gráfico. Se nota que el valor de Veggies es poco relevante en general (y tiene una relación no monótona discontinua extraña), pero fue importante para una de las instancias estudiadas.

Parte D (0.4 pt)¶

In [42]:
def shap_to_probability(shap_value: np.ndarray) -> np.ndarray:
    """Convierte un valor de SHAP a una probabilidad."""
    odd_shift = np.exp(shap_value)
    return odd_shift / (1 + odd_shift)
In [43]:
top = 5
indexes = np.argsort(np.abs(shap_values).mean(0))[-top:]
fig, axes = plt.subplots(nrows=top, figsize=(10, 8 * top))
for ax, feature in zip(axes, indexes):
    shap_x = shap_values[:, feature]
    scatter = ax.scatter(
        X.iloc[:, feature], shap_x, c=shap_to_probability(shap_x), vmin=0.0, vmax=1.0
    )
    ax.set_xlabel(X.columns[feature])
    ax.set_ylabel("Valor de SHAP")
    ax.set_title("Importancia de cada característica")
    fig.colorbar(scatter)

Ninguna de las relaciones es precisamente monótona, pero 4 de las variables son categóricas (la excepción es BMI), y el valor SHAP promedio de cada categoría sí es monótono creciente, es decir, las 4 características aumentan más la probabilidad de diabetes al aumentar, al menos en promedio.

Para HighBP y HighChol, esto es de esperarse. Todos son jóvenes, así que no se esperaría un cambio tan grande por la edad, pero sí está presente. No se sabe el significado de GenHlth, por lo que es más difícil de entender su monotonía creciente.

Para el BMI, la relación parece ser cuadrática con coeficiente principal negativo, presentando un punto máximo en torno al BMI 70%, aunque para valores al principio de la curva sí hay algunos valores más altos. Diabetes tipo 1 es más prevalente en los jóvenes de las edades en el dataset, el cuál se presenta comúnmente en personas con bajo peso, explicando este cambio de pendiente. Luego de esto, la probabilidad disminuye, lo que no es un resultado esperable. Los valores son mucho más dispersos después de este valor, y hay pocos datos, por lo que se espera que el modelo haya aprendido peor sobre esta parte de la población (lo cual indica un sesgo preocupante en los datos que fue aprendido por el modelo).

Parte E (0.4 pt)¶

Generando el PDP de las variables anteriores:

In [58]:
categorical = ["HighChol", "HighBP", "GenHlth"]
best_five = X.columns[indexes]
submuestra = resample(X_test, n_samples=1_000, random_state=0, stratify=y_test)
fig, ax = plt.subplots(
    ncols=5, nrows=2, figsize=(25, 10), constrained_layout=True, sharex="col"
)
display = PartialDependenceDisplay.from_estimator(
    clf, submuestra, best_five, ax=ax[0], categorical_features=categorical
)
for i, feature in enumerate(best_five):
    sns.histplot(
        data=submuestra,
        x=feature,
        ax=ax[1, i],
        multiple="stack",
        bins=10,
    )

Acá tenemos relaciones muy similares a las vistas con los valores de SHAP, pero resumidas a importancias promedio. Para varias características esto no da nada nuevo, pero en el BMI es más clara la reducción de probabilidad para valores muy altos y el aumento de probabilidad para valores muy bajos (y un comportamiento monótono creciente en el medio).

¿Qué relación existe entre la salida promedio del modelo y cada feature analizada? R: Un punto $(x_j, y)$ en uno de estos gráficos de la característica $j$ indica que el valor promedio de la salida del modelo para instancias con valor $x_j$ en la característica $j$ es $y$.

¿Son estas conclusiones generalizables para todo el conjunto de datos? R: Sí, las interpretaciones obtenidas son globales y nos dan el comportamiento promedio de los datos. Sin embargo, cabe recordar que los promedios son una medida de tendencia central y no nos dan información sobre la dispersión de la dependencia parcial.

6. Sistema de Reglas! (1 pt)¶

Creando los sistemas de reglas:

In [45]:
explainer = AnchorTabular(
    clf.predict,
    X_train.columns,
    seed=0,
)
explainer.fit(X_train.values)
Out[45]:
AnchorTabular(meta={
    'name': 'AnchorTabular',
    'type': ['blackbox'],
    'explanations': ['local'],
    'params': {'seed': 0, 'disc_perc': (25, 50, 75)}
})
In [46]:
indice_instancias = [1000, 3001, 5751]
instancias = X.iloc[indice_instancias, :]
predicciones = explainer.predictor(instancias.values)
nombres = ("No tiene diabetes", "Tiene diabetes")
for indice, instancia, prediccion in zip(
    indice_instancias, instancias.values, predicciones
):
    print(f"Instancia {indice}")
    print("-" * 14)
    print(f"Predicción: {prediccion}")
    explicacion = explainer.explain(instancia)
    print("Regla:", " y ".join(explicacion.anchor))
    print(f"Precisión: {explicacion.precision}")
    print(f"Cobertura: {explicacion.coverage}")
    print(f"Población explicada: {int(explicacion.coverage*len(X))}")
    print()
Instancia 1000
--------------
Predicción: 0
Regla: GenHlth <= 2.00 y HighBP <= 0.00 y Age <= 7.00
Precisión: 0.9958932238193019
Cobertura: 0.3132224304904717
Población explicada: 20052

Instancia 3001
--------------
Predicción: 0
Regla: GenHlth <= 2.00 y HighBP <= 0.00 y Age <= 7.00
Precisión: 0.9924078091106291
Cobertura: 0.3132224304904717
Población explicada: 20052

Instancia 5751
--------------
Predicción: 0
Regla: BMI <= 25.00 y HighBP <= 0.00 y Age <= 7.00
Precisión: 0.9720101781170484
Cobertura: 0.3132224304904717
Población explicada: 20052

¿Tienen sentido sus reglas propuestas para las observaciones?. Fundamente su respuesta señalando el impacto que tienen sus reglas sobre todo el conjunto de datos.

R: Se predice que ninguna de las instancias tiene diabetes. En los 3 casos se utilizaron las reglas que no tuviera alta presión sanguínea y menos de 7 años, que coincide con lo visto en las partes anteriores, y son reglas que se esperarían. Las primeras dos instancias además tienen la regla GenHlth <= 2 (donde ya vimos que GenHelth es monótonamente creciente en probabilidad de diabetes en promedio) y BMI <= 25, que está en el rango de crecencia visto en los valores de SHAP y PDP.

Todas las reglas tienen altísima precisión, que muestra que son muy localmente precisas en estas instancias, pero no habla de su generalización. La cobertura es 0.31, es decir, explica poco menos de un tercio de los datos. Esto puede parecer bajo, pero si consideramos que es una regla de solamente 3 condiciones para explicar un modelo de ensamblaje 100 de árboles de profundidad pequeña (recordando que cada árbol es esencialmente un sistema de reglas binarias recursivas, y que sumar árboles es equivalente a reglas más complicadas), es una compresión impresionante. Ésto indica que es un buen problema para utilizar un sistema de reglas optimizado globalmente (como lo es CORELS o GOSDT), que son modelos exactamente interpretables sin requerir explicadores post-hoc aproximados, y que pueden alcanzar un desempeño tan alto como XGBoost, en especial en este problema donde el modelo de ensamblaje está mostrando ser bien aproximado por un sistema de reglas muy pequeño.

Retrospectiva... (1 pt)¶

En base a los diferentes métodos que implementa y ha comentado en este laboratorio, comente qué métodos le permiten entregar mejores conclusiones para la tarea de clasificación de diabetes. Por otro lado, ¿qué métodos son más útiles para el problema del doctor Simi, métodos agnosticos locales o globales?

El Doctor Simi pidió que "el desarrollo del modelo tuviera un especial enfoque en la interpretabilidad de lo que hace su modelo." En este sentido, parece tener mayor interés en la interpretabilidad global del modelo, para entender lo que hace. Cabe destacar que también le es útil tener interpretabilidad local, para poder mostrarle cómo funcionan ejemplos particulares, pero pidió sobre el modelo y no sobre cada una de sus predicciones, así que un resumen global es más útil.

Respecto a las conclusiones de cada método:

  • Importancia de permutación es un resumen global en cabe en una slide para

presentarle al doctor Simi, pero comprime demasiado la información y esconde varios de los patrones descubiertos en el resto del laboratorio. Es un buen comienzo si solamente quiere entender qué variables son importantes, pero no sus relaciones con la diabetes.

  • Los valores de SHAP permitieron dar muchas más conclusiones sobre el modelo,

identificando un potencial sesgo en el modelo y dando una explicación más completa con una variedad de visualizaciones. Recomendaría utilizar los scatterplots y summary plots para presentar con mucho más detalle el modelo.

  • PDP no permitió sacar conclusiones que no se sabían desde antes, pero sí permitió

ver algunos de los patrones de los scatterplots anteriores de manera más clara.

  • Las reglas de ancla permitieron dar una explicación extremadamente compacta de las

decisiones locales. No es tan útil para entender probabilidades como lo hacen los valores de SHAP. Sin embargo, sí nos permite calcular la cobertura, que nos da una noción de que tan bien "globaliza" la explicación local, lo cuál dió un resultado interesante.

Conclusión¶

Eso ha sido todo para el lab de hoy, recuerden que el laboratorio tiene un plazo de entrega de una semana. Cualquier duda del laboratorio, no duden en contactarnos por mail o U-cursos.

Gracias Totales!

Created in deepnote.com Created in Deepnote