Al ajustar los modelos, nuestro objetivo es aumentar el rendimiento general del modelo en datos no vistos. El ajuste de hiperparámetros puede conducir a un rendimiento mucho mejor en los conjuntos de prueba. Sin embargo, la optimización de los parámetros para el conjunto de prueba puede generar fugas de información, lo que hace que el modelo funcione peor en datos no vistos. Para corregir esto, podemos realizar una validación cruzada.
Para comprender mejor el CV, realizaremos diferentes métodos en el conjunto de datos del iris. Primero carguemos y separemos los datos.
from sklearn import datasets X, y = datasets.load_iris(return_X_y=True)
Hay muchos métodos para la validación cruzada. Comenzaremos analizando la validación cruzada k-fold.
K-Fold
Los datos de entrenamiento utilizados en el modelo se dividen en k número de conjuntos más pequeños, que se utilizarán para validar el modelo. Luego, el modelo se entrena en k-1 pliegues del conjunto de entrenamiento. El pliegue restante se usa luego como un conjunto de validación para evaluar el modelo.
Como intentaremos clasificar diferentes especies de flores de iris, necesitaremos importar un modelo clasificador, para este ejercicio usaremos un DecisionTreeClassifier. También necesitaremos importar módulos de CV de sklearn.
from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import KFold, cross_val_score
Con los datos cargados, ahora podemos crear y ajustar un modelo para la evaluación.
clf = DecisionTreeClassifier(random_state=42)
Ahora vamos a evaluar nuestro modelo y ver cómo se comporta en cada k-Fold.
k_folds = KFold(n_splits = 5)
scores = cross_val_score(clf, X, y, cv = k_folds)
También es una buena práctica ver cómo se desempeñó CV en general promediando las puntuaciones de todos los pliegues.
Ejemplo
Ejecutar k-fold CV:
from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import KFold, cross_val_score X, y = datasets.load_iris(return_X_y=True) clf = DecisionTreeClassifier(random_state=42) k_folds = KFold(n_splits = 5) scores = cross_val_score(clf, X, y, cv = k_folds) print("Cross Validation Scores: ", scores) print("Average CV Score: ", scores.mean()) print("Number of CV Scores used in Average: ", len(scores))
K-Fold estratificado
En los casos en que las clases están desequilibradas, necesitamos una forma de tener en cuenta el desequilibrio tanto en el tren como en los conjuntos de validación. Para hacerlo, podemos estratificar las clases objetivo, lo que significa que ambos conjuntos tendrán una proporción igual de todas las clases.
Ejemplo
from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import StratifiedKFold, cross_val_score X, y = datasets.load_iris(return_X_y=True) clf = DecisionTreeClassifier(random_state=42) k_folds = KFold(n_splits = 5) scores = cross_val_score(clf, X, y, cv = k_folds) print("Cross Validation Scores: ", scores) print("Average CV Score: ", scores.mean()) print("Number of CV Scores used in Average: ", len(scores))
Si bien el número de pliegues es el mismo, el CV promedio aumenta desde el k-pliegue básico cuando se asegura que haya clases estratificadas.
Dejar uno fuera: Leave-One-Out (LOO)
En lugar de seleccionar el número de divisiones en el conjunto de datos de entrenamiento como LeaveOneOut de k-fold, utilice 1 observación para validar y n-1 observaciones para entrenar. Este método es una técnica exaustiva.
Ejemplo
Ejecutar LOO CV:
from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import LeaveOneOut, cross_val_score X, y = datasets.load_iris(return_X_y=True) clf = DecisionTreeClassifier(random_state=42) loo = LeaveOneOut() scores = cross_val_score(clf, X, y, cv = loo) print("Cross Validation Scores: ", scores) print("Average CV Score: ", scores.mean()) print("Number of CV Scores used in Average: ", len(scores))
Podemos observar que el número de puntuaciones de validación cruzada realizadas es igual al número de observaciones en el conjunto de datos. En este caso, hay 150 observaciones en el conjunto de datos del iris.
La puntuación CV media es del 94 %.
Leave-P-Out (LPO)
Leave-P-Out es simplemente una diferencia matizada de la idea Leave-One-Out, en la que podemos seleccionar el número de p para usar en nuestro conjunto de validación.
Ejemplo
Ejecutar LPO CV:
from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import LeavePOut, cross_val_score X, y = datasets.load_iris(return_X_y=True) clf = DecisionTreeClassifier(random_state=42) lpo = LeavePOut(p=2) scores = cross_val_score(clf, X, y, cv = lpo) print("Cross Validation Scores: ", scores) print("Average CV Score: ", scores.mean()) print("Number of CV Scores used in Average: ", len(scores))
Como podemos ver, este es un método exhaustivo, se calculan muchos más puntajes que Leave-One-Out, incluso con una p = 2, pero logra aproximadamente el mismo puntaje de CV promedio.
División aleatoria
A diferencia de KFold, ShuffleSplit omite un porcentaje de los datos, que no se utilizará en los conjuntos de entrenamiento o validación. Para ello debemos decidir cuáles son los tamaños de tren y de prueba, así como el número de splits.
Ejemplo
Ejecutar Shuffle Split CV:
from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import ShuffleSplit, cross_val_score X, y = datasets.load_iris(return_X_y=True) clf = DecisionTreeClassifier(random_state=42) ss = ShuffleSplit(train_size=0.6, test_size=0.3, n_splits = 5) scores = cross_val_score(clf, X, y, cv = ss) print("Cross Validation Scores: ", scores) print("Average CV Score: ", scores.mean()) print("Number of CV Scores used in Average: ", len(scores))
Notas Importantes
Estos son solo algunos de los métodos de CV que se pueden aplicar a los modelos. Hay muchas más clases de validación cruzada, y la mayoría de los modelos tienen su propia clase. Consulte la validación cruzada de sklearns para obtener más opciones de CV.