75 votos

¿Cómo dividir el conjunto de datos para la validación cruzada, la curva de aprendizaje y la evaluación final?

¿Cuál es la estrategia adecuada para dividir el conjunto de datos?

Pido opiniones sobre el siguiente enfoque (no en los parámetros individuales como test_size o n_iter , pero si usara X , y , X_train , y_train , X_test y y_test adecuadamente y si la secuencia tiene sentido):

(ampliando este ejemplo de la documentación de scikit-learn)

1. Cargar el conjunto de datos

from sklearn.datasets import load_digits
digits = load_digits()
X, y = digits.data, digits.target

2. Dividir en conjunto de entrenamiento y prueba (por ejemplo, 80/20)

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

3. Elegir el estimador

from sklearn.svm import SVC
estimator = SVC(kernel='linear')

4. Elegir el iterador de validación cruzada

from sklearn.cross_validation import ShuffleSplit
cv = ShuffleSplit(X_train.shape[0], n_iter=10, test_size=0.2, random_state=0)

5. Afinar los hiperparámetros

aplicando el iterador de validación cruzada en el conjunto de entrenamiento

from sklearn.grid_search import GridSearchCV
import numpy as np
gammas = np.logspace(-6, -1, 10)
classifier = GridSearchCV(estimator=estimator, cv=cv, param_grid=dict(gamma=gammas))
classifier.fit(X_train, y_train)

6. Algoritmo de depuración con curva de aprendizaje

X_train se divide aleatoriamente en un conjunto de entrenamiento y otro de prueba 10 veces ( n_iter=10 ). Cada punto de la curva de puntuaciones de entrenamiento es la media de 10 puntuaciones en las que el modelo fue entrenado y evaluado en la primera i ejemplos de formación. Cada punto de la curva de puntuación de validación cruzada es la media de 10 puntuaciones en las que el modelo fue entrenado en el primer i ejemplos de entrenamiento y evaluados en todos los ejemplos del conjunto de pruebas.

from sklearn.learning_curve import learning_curve
title = 'Learning Curves (SVM, linear kernel, $\gamma=%.6f$)' %classifier.best_estimator_.gamma
estimator = SVC(kernel='linear', gamma=classifier.best_estimator_.gamma)
plot_learning_curve(estimator, title, X_train, y_train, cv=cv)
plt.show()

Learning curve

trazar_curva_de_aprendizaje() se puede encontrar en la versión actual de scikit-learn (0.15-git).

7. Evaluación final en el conjunto de pruebas

classifier.score(X_test, y_test)

7a. Prueba de sobreajuste en la selección de modelos con validación cruzada anidada (utilizando todo el conjunto de datos)

from sklearn.cross_validation import cross_val_score
cross_val_score(classifier, X, y)

Pregunta adicional: ¿Tiene sentido sustituir el paso 7 por una validación cruzada anidada? ¿O debería considerarse la cv anidada como un complemento del paso 7

(el código parece funcionar con la validación cruzada k-fold en scikit-learn, pero no con shuffle & split. Así que cv debe cambiarse arriba para que el código funcione)

8. Entrenar el modelo final en todo el conjunto de datos

classifier.fit(X, y)

EDIT: Ahora estoy de acuerdo con cbeleites en que el paso 7a no tiene mucho sentido en esta secuencia. Así que yo no lo adoptaría.

42voto

cbeleites Puntos 12461

No estoy seguro de lo que quieres hacer en el paso 7a. Tal y como lo entiendo ahora mismo, no tiene sentido para mí.

Así es como entiendo su descripción: en el paso 7, quiere comparar el rendimiento de la retención con los resultados de una validación cruzada que abarque los pasos 4 - 6. (así que sí, eso sería una configuración anidada).

Los puntos principales por los que no creo que esta comparación tenga mucho sentido son:

  • Esta comparación no puede detectar dos de las principales fuentes de resultados de validación demasiado optimistas que encuentro en la práctica:

    • fugas de datos (dependencia) entre los datos de entrenamiento y los de prueba, causadas por una estructura de datos jerárquica (también conocida como clúster), y que no se tienen en cuenta en la división. En mi campo, normalmente tenemos múltiples (a veces miles) de lecturas (= filas en la matriz de datos) del mismo paciente o réplica biológica de un experimento. Éstas no son independientes, por lo que la división de la validación debe hacerse a nivel de paciente. Sin embargo, si se produce una fuga de datos, la tendrá tanto en la división para el conjunto de retención como en la división de validación cruzada. La validación cruzada es tan optimista como la retención de datos.

    • El preprocesamiento de los datos se realiza en toda la matriz de datos, donde los cálculos no son independientes para cada fila, sino que se utilizan muchas/todas las filas para calcular los parámetros del preprocesamiento. Ejemplos típicos serían, por ejemplo, una proyección PCA antes de la clasificación "real".
      De nuevo, eso afectaría tanto a su retención como a la validación cruzada exterior, por lo que no se puede detectar.

    Para los datos con los que trabajo, ambos errores pueden hacer que la fracción de clasificaciones erróneas se subestime fácilmente en un orden de magnitud.

  • Si se limita a este tipo de rendimiento de fracción contada de casos de prueba, las comparaciones de modelos necesitan un número extremadamente grande de casos de prueba o diferencias ridículamente grandes en el rendimiento real. Comparación de 2 clasificadores con datos de entrenamiento ilimitados puede ser un buen punto de partida para seguir leyendo.

Sin embargo, comparar la calidad del modelo que afirma la validación cruzada interna para el modelo "óptimo" y la validación cruzada externa o hold out tiene sentido: si la discrepancia es alta, es cuestionable si su optimización de la búsqueda de la cuadrícula funcionó (es posible que haya descremado la varianza debido a la alta varianza de la medida de rendimiento). Esta comparación es más fácil en el sentido de que puede detectar los problemas si la estimación interna es ridícula en comparación con la otra; si no lo es, no tiene que preocuparse tanto por su optimización. Pero en cualquier caso, si su medida exterior (7) del rendimiento es honesta y sólida, al menos tiene una estimación útil del modelo obtenido, sea óptimo o no.

En mi opinión, medir la curva de aprendizaje es un problema diferente. Probablemente me ocuparía de eso por separado, y creo que tienes que definir más claramente para qué necesitas la curva de aprendizaje (¿necesitas la curva de aprendizaje para a conjunto de datos del problema dado, los datos y el método de clasificación o la curva de aprendizaje para este conjunto de datos del problema, los datos y el método de clasificación dados), y un montón de decisiones más (por ejemplo, ¿cómo tratar la complejidad del modelo en función del tamaño de la muestra de entrenamiento? ¿Optimizar de nuevo, utilizar hiperparámetros fijos, decidir la función para fijar los hiperparámetros dependiendo del tamaño del conjunto de entrenamiento?)

(Mis datos suelen tener tan pocos casos independientes como para conseguir que la medición de la curva de aprendizaje sea lo suficientemente precisa como para utilizarla en la práctica, pero es posible que te vaya mejor si tus 1200 filas son realmente independientes)


actualización: ¿Qué es lo que está "mal" en el ejemplo de scikit-learn?

En primer lugar, no hay nada malo en la validación cruzada anidada. La validación anidada es de suma importancia para la optimización basada en datos, y la validación cruzada es un enfoque muy potente (especialmente si se repite).

Entonces, que haya algo malo depende de tu punto de vista: mientras hagas una validación anidada honesta (manteniendo los datos de prueba externos estrictamente independientes), la validación externa es una medida adecuada del rendimiento del modelo "óptimo". No hay nada malo en ello.

Pero hay varias cosas que pueden fallar, y de hecho lo hacen, en la búsqueda de cuadrículas de estas medidas de rendimiento de tipo proporcional para el ajuste de hiperparámetros de la SVM. Básicamente significan que usted puede (¿probablemente?) no confiar en la optimización. Sin embargo, siempre y cuando su división externa se hizo correctamente, incluso si el modelo no es el mejor posible, usted tiene una estimación honesta del rendimiento del modelo que obtuvo.

Intentaré dar explicaciones intuitivas de por qué la optimización puede tener problemas:

  • Matemáticamente/estadísticamente hablando, el problema de las proporciones es que las proporciones medidas $\hat p$ están sujetas a una enorme varianza debido al tamaño finito de la muestra de la prueba $n$ (dependiendo también del rendimiento real del modelo, $p$ ):
    $Var (\hat p) = \frac{p (1 - p)}{n}$

    Se necesita un número ridículamente enorme de casos (al menos en comparación con el número de casos que puedo tener normalmente) para conseguir la precisión necesaria (sentido de sesgo/varianza) para estimar el recuerdo, la precisión (sentido de rendimiento del aprendizaje automático). Esto, por supuesto, se aplica también a los ratios que se calculan a partir de dichas proporciones. Eche un vistazo a los intervalos de confianza de las proporciones binomiales. Son sorprendentemente grandes. A menudo son mayores que la verdadera mejora del rendimiento con respecto a la cuadrícula de hiperparámetros. Y, estadísticamente hablando, la búsqueda en la rejilla es un problema masivo de comparación múltiple: cuantos más puntos de la rejilla se evalúen, mayor será el riesgo de encontrar alguna combinación de hiperparámetros que accidentalmente parezca muy buena para la división tren/prueba que se está evaluando. Esto es lo que quiero decir con la varianza de descremado. El conocido sesgo optimista de la validación interna (optimización) es sólo un síntoma de este descremado de la varianza.

  • Intuitivamente, considere un hipotético cambio de un hiperparámetro, que lentamente hace que el modelo se deteriore: un caso de prueba se mueve hacia el límite de decisión. Las medidas de rendimiento de proporción "dura" no lo detectan hasta que el caso cruza la frontera y se encuentra en el lado equivocado. Entonces, sin embargo, asignan inmediatamente un error completo para un cambio infinitamente pequeño en el hiperparámetro.
    Para realizar una optimización numérica, es necesario que la medida de rendimiento tenga un buen comportamiento. Es decir: ni la parte saltarina (no continuamente diferenciable) de la medida de rendimiento de tipo proporcional ni el hecho de que, aparte de ese salto, no se detecten los cambios que realmente se producen son adecuados para la optimización.
    Las reglas de puntuación adecuadas se definen de una forma especialmente adecuada para la optimización. Tienen su máximo global cuando las probabilidades predichas coinciden con las probabilidades reales de que cada caso pertenezca a la clase en cuestión.

  • En el caso de las SVM, existe el problema adicional de que no sólo las medidas de rendimiento, sino también el modelo, reaccionan de forma irregular: los pequeños cambios de los hiperparámetros no cambian nada. El modelo sólo cambia cuando los hiperparámetros cambian lo suficiente como para que algún caso deje de ser vector de soporte o se convierta en vector de soporte. De nuevo, estos modelos son difíciles de optimizar.

Literatura:


Actualización II: Descremación de la varianza

lo que puede permitirse en términos de comparación de modelos depende obviamente del número de casos independientes. Hagamos una simulación rápida y sucia sobre el riesgo de descremar la varianza aquí:

scikit.learn dice que tienen 1797 están en el digits datos.

  • se supone que se comparan 100 modelos, por ejemplo, un $10 \times 10$ rejilla para 2 parámetros.

  • suponer que ambos parámetros (rangos) no afectan en absoluto a los modelos,

  • es decir, todos los modelos tienen el mismo rendimiento real de, por ejemplo, el 97 % (rendimiento típico del digits conjunto de datos).

  • Ejecutar $10^4$ simulaciones de "prueba de estos modelos" con tamaño de muestra = 1797 filas en el digits conjunto de datos

    p.true = 0.97 # hypothetical true performance for all models
    n.models = 100 # 10 x 10 grid
    
    n.rows = 1797 # rows in scikit digits data
    
    sim.test <- replicate (expr= rbinom (n= nmodels, size= n.rows, prob= p.true), 
                           n = 1e4)
    sim.test <- colMaxs (sim.test) # take best model
    
    hist (sim.test / n.rows, 
          breaks = (round (p.true * n.rows) : n.rows) / n.rows + 1 / 2 / n.rows, 
          col = "black", main = 'Distribution max. observed performance',
          xlab = "max. observed performance", ylab = "n runs")
    abline (v = p.outer, col = "red")

Esta es la distribución para el mejor rendimiento observado:

skimming variance simulation

La línea roja marca el rendimiento real de todos nuestros modelos hipotéticos. En promedio, observamos sólo 2/3 de la tasa de error verdadera para el aparentemente mejor de los 100 modelos comparados (para la simulación sabemos que todos rinden igual con un 97% de predicciones correctas).

Esta simulación está obviamente muy simplificada:

  • Además de la varianza del tamaño de la muestra de prueba, existe al menos la varianza debida a la inestabilidad del modelo, por lo que estamos subestimando la varianza
  • El ajuste de los parámetros que afectan a la complejidad del modelo suele abarcar conjuntos de parámetros en los que los modelos son inestables y, por lo tanto, tienen una alta varianza.
  • En el caso de los dígitos de la UCI del ejemplo, la base de datos original tiene unos 11.000 dígitos escritos por 44 personas. ¿Qué ocurre si los datos se agrupan según la persona que los escribió? (Es decir, ¿es más fácil reconocer un 8 escrito por alguien si se sabe cómo escribe esa persona, por ejemplo, un 3?
  • El ajuste de los hiperparámetros del modelo puede conducir a la correlación entre los modelos (de hecho, eso se consideraría un buen comportamiento desde la perspectiva de la optimización numérica). Es difícil predecir su influencia (y sospecho que es imposible sin tener en cuenta el tipo real de clasificador).

Sin embargo, en general, tanto el bajo número de casos de prueba independientes como el elevado número de modelos comparados aumentan el sesgo. Además, el artículo de Cawley y Talbot ofrece un comportamiento empírico observado.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X