Abrir en Google Colab
|
|
Descargar notebook
|
Ejemplo: Comparando modelos utilizando 5x2 cross-validation
En este ejemplo, veremos como utilizar la técnica 5x2 cross-validation para la comparación de performance de dos modelos de aprendizaje automático. Para mas detalle de la técnica puede referirse aÑ
[1] Dietterich TG (1998) Approximate Statistical Tests for Comparing Supervised Classification Learning Algorithms. Neural Comput 10:1895–1923.
Introducción
Instalamos la librerias necesarias
[ ]:
!wget https://raw.githubusercontent.com/santiagxf/E72102/master/docs/develop/modeling/selection/code/5x2.txt \
--quiet --no-clobber
!pip install -r 5x2.txt --quiet
Sobre el conjunto de datos del censo UCI
El conjunto de datos del censo de la UCI es un conjunto de datos en el que cada registro representa a una persona. Cada registro contiene 14 columnas que describen a una una sola persona, de la base de datos del censo de Estados Unidos de 1994. Esto incluye información como la edad, el estado civil y el nivel educativo. La tarea es determinar si una persona tiene un ingreso alto (definido como ganar más de $50 mil al año). Esta tarea, dado el tipo de datos que utiliza, se usa a menudo en el estudio de equidad, en parte debido a los atributos comprensibles del conjunto de datos, incluidos algunos que contienen tipos sensibles como la edad y el género, y en parte también porque comprende una tarea claramente del mundo real.
Descargamos los datos
[5]:
!wget https://santiagxf.blob.core.windows.net/public/datasets/uci_census.zip \
--quiet --no-clobber
!mkdir -p datasets/uci_census
!unzip -qq uci_census.zip -d datasets/uci_census
Preparando nuestros conjuntos de datos
[6]:
import pandas as pd
import numpy as np
df = pd.read_csv('datasets/uci_census/data/adult-train.csv')
train = df.drop(['income'], axis=1)
target = df['income'].to_numpy()
Preparación de los datos para el ejemplo
Realizaremos un pequeño preprocesamiento antes de entrenar el modelo:
Imputaremos los valores faltantes de las caracteristicas numéricas con la media
Imputaremos los valores faltantes de las caracteristicas categóricas con el valor
?Escalaremos los valores numericos utilizando un
StandardScalerCodificaremos las variables categóricas utilizando
OneHotEncoder
[7]:
from typing import Tuple, List
import sklearn
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
def prepare(X: pd.DataFrame) -> Tuple[np.ndarray, sklearn.compose.ColumnTransformer]:
pipe_cfg = {
'num_cols': X.dtypes[X.dtypes == 'int64'].index.values.tolist(),
'cat_cols': X.dtypes[X.dtypes == 'object'].index.values.tolist(),
}
num_pipe = Pipeline([
('num_imputer', SimpleImputer(strategy='median')),
('num_scaler', StandardScaler())
])
cat_pipe = Pipeline([
('cat_imputer', SimpleImputer(strategy='constant', fill_value='?')),
('cat_encoder', OneHotEncoder(handle_unknown='ignore', sparse=False))
])
transformations = ColumnTransformer([
('num_pipe', num_pipe, pipe_cfg['num_cols']),
('cat_pipe', cat_pipe, pipe_cfg['cat_cols'])
])
X = transformations.fit_transform(X)
return X, transformations
train, transformations = prepare(train)
Definiendo nuestros modelos a comparar
Para demostrar la técnica, utilizaremos dos clasificadores basados en LightGBM
[57]:
from lightgbm import LGBMClassifier
clf1 = LGBMClassifier(n_estimators=100, n_jobs=2)
clf2 = LGBMClassifier(n_estimators=100, reg_alpha=1, reg_lambda=1, min_split_gain=2, n_jobs=2)
Procedimiento de 5x2
Utilizaremos la libreria mlxtend que dispone de una implementation de este procedimiento. La utilización de la misma es bastante sencilla:
[65]:
from mlxtend.evaluate import paired_ttest_5x2cv
Iniciamos el test:
[69]:
statistic, pvalue = paired_ttest_5x2cv(clf1, clf2,
X=train, y=target, scoring='accuracy')
Notemos que aqui las hipótesis nula y alternativa son como sigue:
H0: La diferencia en performance de los dos modelos es zero (los modelos son iguales).
HA: La diferencia en performance de los modelos es distinta de zero (los modelos son distintos).
Tomamos una decisión:
[70]:
if pvalue > 0.05:
print("No podemos tomar ninguna conclusión. No se puede rechazar la idea de que ambos modelos son equivalente")
else:
print("Existe suficiente evidencia para rechazar la idea de que los modelos son equivalentes en favor de \
una alternativa de que los modelos son distintos.")
print("\nValor estadístico:", statistic)
print("p-value:", pvalue)
No podemos tomar ninguna conclusión. No se puede rechazar la idea de que ambos modelos son equivalente
Valor estadístico: 1.281174535572354
p-value: 0.25633323457069157
Abrir en Google Colab
Descargar notebook