División de conjunto de entrenamiento y de prueba
En el mundo del aprendizaje automático, los datos son el combustible que impulsa todos los modelos. Sin embargo, la forma en que uses correctamente este combustible determina si tu modelo es un motor inteligente capaz de predecir el futuro con precisión, o una simple grabadora que solo repite de memoria.
Hoy profundizaremos en un concepto fundamental y de vital importancia en el aprendizaje automático:la división del conjunto de entrenamiento y del conjunto de prueba. Este es el primer paso para construir cualquier modelo fiable y la clave para evaluar la verdadera capacidad del modelo.
En pocas palabras, dividir el conjunto de entrenamiento y el de prueba es como el estudio y los exámenes en la época escolar:
- Conjunto de entrenamientoes el libro de texto y los ejercicios del estudiante; el modelo lo utiliza para aprender las reglas y patrones de los datos.
- Conjunto de pruebaes el examen final; el modelo lo utiliza para comprobar si realmente ha dominado el conocimiento, en lugar de simplemente recordar las respuestas de los ejercicios (el conjunto de entrenamiento).
¿Por qué es necesario dividir en conjunto de entrenamiento y conjunto de prueba?
Imagina que un estudiante solo repasa los exámenes simulados que le dio el profesor y, además, el examen real contiene exactamente los mismos ejercicios. Obtiene una calificación perfecta. ¿Eso demuestra que realmente comprende la asignatura? Evidentemente no. Puede que solo haya memorizado las respuestas.
En el aprendizaje automático, si entrenamos el modelo contodos los datosy luego usamos esosmismos datospara evaluar su rendimiento, cometeremos el mismo error. El modelo se desempeñará de forma inusualmente excelente porque ya ha "visto" y "memorizado" los detalles de todos los datos, incluidos el ruido y la casualidad. Este fenómeno se conoce comosobreajuste。
Un modelo sobreajustado es como un estudiante que solo memoriza ejemplos; en cuanto se encuentra con problemas nuevos o desconocidos (datos nuevos), su rendimiento es deficiente. Su "capacidad de generalización" es débil.
Por lo tanto, debemos dividir los datos en dos partes:
- Conjunto de entrenamiento: se usa paraEnseñarentrenar el modelo, para que aprenda.
- Conjunto de prueba: se usa paraexamenevaluar el modelo, comprobar cómo manejanuevos datos nunca antes vistossu capacidad.
El conjunto de prueba debe estar completamente aislado del conjunto de entrenamiento y, durante todo el proceso de entrenamiento del modelo,nodebe ser visto por el modelo. Solo así los resultados de la evaluación en el conjunto de prueba pueden reflejar objetivamente la verdadera capacidad de generalización del modelo.
Cómo dividir: métodos y estrategias comunes
Dividir los datos suena sencillo, pero encierra bastante técnica. Las distintas estrategias de división se aplican a diferentes escenarios.
1. División aleatoria simple
Es el método más básico y más utilizado. Se barajan aleatoriamente todos los datos y luego se dividen en dos partes según una proporción determinada.
Ejemplo
from sklearn.model_selection import train_test_split
# Supongamos que X son los datos de características e y son las etiquetas
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Número de muestras de entrenamiento: {len(X_train)}")
print(f"Número de muestras de prueba: {len(X_test)}")
Explicación del código:
train_test_split: es la función principal de scikit-learn para dividir datos.X, y: los datos de características de entrada y las etiquetas correspondientes.test_size=0.2: especifica que el tamaño del conjunto de prueba es del 20% (es decir, el conjunto de entrenamiento ocupa el 80%). También puedes usartrain_size=0.8para especificarlo.random_state=42: establece una semilla aleatoria. Esto garantiza que cada vez que ejecutes el código, el resultado de la división sea exactamente el mismo, algo crucial para la reproducibilidad de los experimentos. Puedes asignarle cualquier número entero.
2. División por muestreo estratificado
En problemas de clasificación, si la distribución de clases del conjunto de datos no es equilibrada (por ejemplo, 90% son de la clase A y 10% de la clase B), una división aleatoria simple puede hacer que las proporciones de cada clase en el conjunto de entrenamiento y en el de prueba difieran mucho, afectando la equidad de la evaluación.
El muestreo estratificadopuede garantizar que, en los conjuntos de entrenamiento y prueba resultantes, las proporciones de cada clase se mantengan coherentes con las del conjunto de datos original.
Ejemplo
from sklearn.model_selection import train_test_split
# Supongamos que y son las etiquetas de clasificación
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
# Revisar las proporciones de clases tras la división
from collections import Counter
print("Distribución de clases en los datos originales:", Counter(y))
print("Distribución de clases en el conjunto de entrenamiento:", Counter(y_train))
print("Distribución de clases en el conjunto de prueba:", Counter(y_test))
Explicación del código:
stratify=y: este es el parámetro clave. Le indica a la función que, según las etiquetasy, realice el muestreo estratificado según la distribución de clases.
3. División de datos de series temporales
Para datos de series temporales (como precios de acciones o temperaturas diarias), existe una dependencia temporal entre los puntos de datos. No podemos barajarlos aleatoriamente porque los datos futuros no pueden usarse para predecir el pasado.
La práctica habitual es dividirlos en orden cronológico:Usar los datos del primer 80% del periodo como conjunto de entrenamiento y los del último 20% como conjunto de prueba.。
Ejemplo
split_index = int(len(X) * 0.8) # Calcular el índice en la posición del 80%
X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]
print(f"Rango temporal del conjunto de entrenamiento: primeros {split_index} muestras")
print(f"Rango temporal del conjunto de prueba: últimas {len(X) - split_index} muestras")
¿Cómo elegir la proporción de división?
Es una pregunta frecuente, pero no hay una respuesta fija. Las proporciones más comunes son:
| Proporción (entrenamiento:prueba) | Escenario adecuado | Ventajas | Desventajas |
|---|---|---|---|
| 70:30 | Elección clásica para conjuntos de datos pequeños o medianos (de miles a decenas de miles de muestras). | Equilibra la cantidad de datos de entrenamiento y la fiabilidad de la evaluación. | Para conjuntos de datos muy pequeños, un 30% de prueba puede tener demasiadas pocas muestras y la evaluación resulta inestable. |
| 80:20 | Actualmente es la opción predeterminada más popular, especialmente adecuada para el aprendizaje profundo. | Proporciona al modelo más datos para aprender. | El conjunto de prueba es relativamente pequeño, por lo que la varianza de la evaluación puede ser ligeramente mayor. |
| 90:10 o 95:5 | Cuando la cantidad de datos es muy limitada | Maximiza el uso de los datos limitados para el entrenamiento. | El conjunto de prueba es demasiado pequeño; los resultados de la evaluación pueden no ser fiables y tener baja confianza. |
Principio fundamental:
- Asegúrate de que el conjunto de entrenamiento sea lo suficientemente grande: el modelo necesita datos suficientes para aprender patrones eficaces.
- Asegúrate de que el conjunto de prueba sea lo suficientemente grande: el conjunto de prueba debe ofrecer una evaluación del rendimiento estadísticamente fiable. Normalmente, el conjunto de prueba debe tener al menos unos cientos de muestras para que el resultado de la evaluación sea estable.
- Cuanto mayor sea la cantidad de datos, la proporción asignada al conjunto de prueba puede ser relativamentemenor, porque incluso una proporción muy pequeña puede representar una gran cantidad de muestras.
Conceptos avanzados: conjunto de validación y validación cruzada
En proyectos reales, no solo necesitamos evaluar el modelo final, sino también ajustar loshiperparámetros(como la tasa de aprendizaje, la profundidad de los árboles, etc.). Si usamos directamente el conjunto de prueba para ajustar los parámetros, el conjunto de prueba se "contamina" de nuevo y pierde la imparcialidad como "examinador final".
Para ello, introducimos elconjunto de validación。
División en tres conjuntos de datos: entrenamiento, validación y prueba
- Conjunto de entrenamiento: se utiliza para el aprendizaje de los parámetros del modelo.
- Conjunto de validación: se utiliza para ajustar los hiperparámetros durante el entrenamiento, seleccionar el modelo o aplicar la parada temprana. Equivale a un "examen de simulación".
- Conjunto de prueba: se utiliza para la evaluación final y única del rendimiento una vez que el modelo y los hiperparámetros están definidos. Es el "examen final".
Ejemplo
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.15, random_state=42) # Separar primero un 15% como conjunto de prueba final
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.176, random_state=42) # Del 85% restante, separar aproximadamente un 15% como conjunto de validación
# Cálculo de la proporción: 0.85 * 0.176 ≈ 0.15, la proporción final es aproximadamente 70:15:15
print(f"Conjunto de entrenamiento: {len(X_train)}, conjunto de validación: {len(X_val)}, conjunto de prueba: {len(X_test)}")
Validación cruzada K-fold
Cuando la cantidad de datos no es grande, reservar un conjunto de validación por separado reduce aún más los datos de entrenamiento.La validación cruzada K-foldes una solución más potente.
Su proceso es el siguiente y permite aprovechar al máximo los datos limitados:
Ejemplo
A[Conjunto de datos original] --> B[Mezclar aleatoriamente y dividir uniformemente en K partes]
B --> C{Realizar K rondas de bucle}
C --> D[Ronda i: usar la i-ésima parte como conjunto de validación]
D --> E[Combinar las K-1 partes restantes como conjunto de entrenamiento]
E --> F[Entrenar el modelo en el conjunto de entrenamiento de esta ronda]
F --> G[Evaluar la puntuación Si en el conjunto de validación de esta ronda]
G --> C
C -- Al completar K rondas --> H[Calcular el promedio de las K puntuaciones como evaluación final]
Ejemplo
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
scores = cross_val_score(model, X, y, cv=5) # cv=5 indica validación cruzada de 5 pliegues
print(f"Puntuaciones de cada pliegue: {scores}")
print(f"Puntuación media: {scores.mean():.4f} (+/- {scores.std()*2:.4f})") # Imprime la puntuación media y la desviación estándar
Ventajas de la validación cruzada:
- Utiliza completamente todos los datos para el entrenamiento y la validación.
- Los resultados de la evaluación son más estables y fiables (porque son el promedio de múltiples evaluaciones).
- Es el estándar de oro para la selección de modelos y el ajuste de hiperparámetros en conjuntos de datos pequeños y medianos.
Práctica: experimenta con la división de datos
Ahora, pongámoslo en práctica con un conjunto de datos simple.
Ejemplo
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 2. Cargar el conjunto de datos Iris
iris = load_iris()
X, y = iris.data, iris.target
print(f"Forma del conjunto de datos: características {X.shape}, etiquetas {y.shape}")
# 3. División aleatoria simple (80% entrenamiento, 20% prueba)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"División aleatoria -> Entrenamiento: {X_train.shape}, Prueba: {X_test.shape}")
# 4. División aleatoria estratificada
X_train_s, X_test_s, y_train_s, y_test_s = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
print(f"División estratificada -> Entrenamiento: {X_train_s.shape}, Prueba: {X_test_s.shape}")
# 5. Verificar el efecto de la estratificación
print("\nDistribución de categorías de los datos originales:", np.bincount(y))
print("Distribución del conjunto de prueba después de la división aleatoria:", np.bincount(y_test)) # Puede estar desequilibrado
print("Distribución del conjunto de prueba después de la división estratificada:", np.bincount(y_test_s)) # Debe ser proporcional a la distribución original
Tu tarea:
- Ejecuta el código anterior y observa los resultados.
- Intenta modificar
test_sizea 0.3, observa los cambios en el tamaño del conjunto de entrenamiento y del conjunto de prueba. - Intenta modificar
random_statea otro número (por ejemplo, 7), ejecuta de nuevo y observa si el resultado de la división cambia. - (Desafío) No establecer
random_stateel parámetro, ejecuta el código varias veces y observa si el resultado de la división es el mismo cada vez.
Resumen y puntos clave
- Objetivo principal: dividir el conjunto de entrenamiento y el de prueba es paraevaluar la capacidad de generalización del modelo, prevenir el sobreajuste y asegurar que el modelo pueda manejar datos nuevos.
- Regla de oro:El conjunto de prueba debe mantenerse completamente confidencial durante todo el proceso de entrenamiento, y usarse solo para la evaluación final.
- Métodos de división:
- División aleatoria: la más común.
- División estratificada: adecuada para datos desequilibrados en problemas de clasificación.
- División secuencial: adecuada para datos de series temporales.
- Proporción de división: no hay un estándar absoluto; hay que sopesar entre "suficiente entrenamiento" y "evaluación fiable". 80:20 o 70:30 son puntos de partida habituales.
- Herramientas avanzadas:
- Conjunto de validación: se usa para ajustar el modelo y proteger la pureza del conjunto de prueba.
- Validación cruzada de K pliegues: una herramienta excelente para la evaluación y el ajuste de conjuntos de datos pequeños y medianos, con resultados más robustos.