Overfitting y underfitting
Sobreaprendizaje (Overfitting) y Subaprendizaje (Underfitting) en Ciencia de Datos
1. Definición
- Sobreaprendizaje (Overfitting): El sobreaprendizaje ocurre cuando un modelo es demasiado complejo y se ajusta demasiado bien a los datos de entrenamiento, capturando tanto la señal real como el ruido o las peculiaridades de los datos. Como resultado, el modelo tiene un rendimiento muy bueno en el conjunto de entrenamiento, pero falla al generalizar en datos nuevos o no vistos, es decir, tiene un mal rendimiento en el conjunto de prueba.
- Subaprendizaje (Underfitting): El subaprendizaje ocurre cuando el modelo es demasiado simple para capturar la estructura subyacente de los datos. Esto lleva a un rendimiento pobre tanto en el conjunto de entrenamiento como en el conjunto de prueba, ya que el modelo no puede captar las relaciones complejas entre las variables de entrada y salida.
2. Ejemplos Teóricos
- Sobreaprendizaje Teórico: Imagina que tienes datos con una relación lineal simple entre dos variables. Si utilizas un modelo polinomial de grado muy alto para ajustarlo, el modelo podría aprender detalles innecesarios y ruido de los datos de entrenamiento, logrando una precisión alta en el entrenamiento, pero fallando en el conjunto de prueba.
- Subaprendizaje Teórico: Si tomas los mismos datos con una relación lineal y utilizas un modelo demasiado simple, como una constante, no podrás captar la relación lineal subyacente, lo que llevará a un mal rendimiento tanto en los datos de entrenamiento como en los de prueba.
3. Ejemplo Real en Python usando un Conjunto de Datos Sintético
Vamos a crear un conjunto de datos con una relación polinomial y luego aplicaremos regresión lineal, regresión polinomial y veremos ejemplos de sobreaprendizaje y subaprendizaje.
Código Real de Ejemplo
import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split # Generar datos sintéticos con una relación cuadrática np.random.seed(42) X = np.linspace(-3, 3, 40).reshape(-1, 1) y = X**2 + np.random.normal(0, 0.5, X.shape) # Relación cuadrática con ruido # Dividir los datos en conjunto de entrenamiento y prueba X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # Aplicar regresión polinomial de alto grado para inducir overfitting (grado 15) poly_features = PolynomialFeatures(degree=15) X_poly_train = poly_features.fit_transform(X_train) X_poly_test = poly_features.transform(X_test) # Crear el modelo de regresión lineal y ajustar con los datos polinomiales poly_model = LinearRegression() poly_model.fit(X_poly_train, y_train) # Predicciones para los datos de entrenamiento y prueba y_pred_train = poly_model.predict(X_poly_train) y_pred_test = poly_model.predict(X_poly_test) # Calcular el error en entrenamiento y prueba train_error = mean_squared_error(y_train, y_pred_train) test_error = mean_squared_error(y_test, y_pred_test) train_score = r2_score(y_train, y_pred_train) test_score= r2_score(y_test, y_pred_test) # Imprimir errores print("Error en conjunto de entrenamiento:", train_error) print("Error en conjunto de prueba:", test_error) print("Error en conjunto de entrenamiento:", train_score) print("Error en conjunto de prueba:", test_score) # Visualizar el overfitting plt.figure(figsize=(10, 6)) # Datos reales plt.scatter(X_train, y_train, color='blue', label='Datos de entrenamiento') plt.scatter(X_test, y_test, color='green', label='Datos de prueba') # Predicciones del modelo X_range = np.linspace(-3, 3, 300).reshape(-1, 1) # Rango más denso para la gráfica X_range_poly = poly_features.transform(X_range) y_range_pred = poly_model.predict(X_range_poly) plt.plot(X_range, y_range_pred, color='red', label='Modelo Polinomial Grado 15 (Overfitting)') plt.title('Ejemplo de Overfitting con Regresión Polinomial') plt.xlabel('X') plt.ylabel('y') plt.legend() plt.show()
Si en el modelo anterior sustituimos los grados de libertad por 2 -que es la verdadera curva del modelo- vemos que el ajuste es casi perfecto
En el siguiente ejemplo vemos el resultado de hacer una regresión lineal y una cuadrática:
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.preprocessing import PolynomialFeatures from sklearn.metrics import mean_squared_error # Crear datos no lineales (cuadráticos) np.random.seed(0) X = np.random.rand(100, 1) * 10 # 100 puntos entre 0 y 10 y = 3 * X**2 + 2 * X + np.random.randn(100, 1) * 10 # Relación cuadrática + ruido # Ajustar el modelo lineal (subajuste) model_linear = LinearRegression() model_linear.fit(X, y) y_pred_linear = model_linear.predict(X) # Ajustar el modelo polinomial (grado 2) poly_features = PolynomialFeatures(degree=2) X_poly = poly_features.fit_transform(X) # Crear características polinómicas (X^2, X) model_poly = LinearRegression() model_poly.fit(X_poly, y) y_pred_poly = model_poly.predict(X_poly) # Calcular el error cuadrático medio mse_linear = mean_squared_error(y, y_pred_linear) mse_poly = mean_squared_error(y, y_pred_poly) # Visualizar los datos y los modelos ajustados plt.scatter(X, y, color='blue', label='Datos originales') plt.plot(X, y_pred_linear, color='red', label='Modelo lineal (subajuste)') plt.scatter(X, y_pred_poly, color='green', label='Modelo polinomial (grado 2)') plt.xlabel('X') plt.ylabel('Y') plt.title('Comparación: Modelo Lineal vs Polinomial') plt.legend() plt.show() print(f"Error Cuadrático Medio - Modelo Lineal (subajuste): {mse_linear:.2f}") print(f"Error Cuadrático Medio - Modelo Polinomial (grado 2): {mse_poly:.2f}")
4. Análisis de Resultados
- Subaprendizaje (Underfitting):
- Error en entrenamiento alto: El modelo lineal no puede capturar la complejidad de la relación cúbica en los datos.
- Error en prueba alto: El modelo también falla en predecir correctamente en los datos de prueba, lo que indica que no está aprendiendo la relación correcta.
- Sobreaprendizaje (Overfitting):
- Error en entrenamiento bajo: El modelo polinomial de grado 10 ajusta perfectamente los datos de entrenamiento.
- Error en prueba alto: El modelo polinomial se ajusta demasiado a los datos de entrenamiento, capturando ruido, lo que lleva a un mal rendimiento en los datos de prueba.
5. Conclusión
- El subaprendizaje ocurre cuando el modelo es demasiado simple para captar las complejidades de los datos. En este ejemplo, el modelo lineal no pudo aprender la relación cúbica, lo que llevó a errores altos en entrenamiento y prueba.
- El sobreaprendizaje ocurre cuando el modelo es demasiado complejo, ajustándose demasiado a los datos de entrenamiento y fallando en la generalización. El modelo polinomial de grado 10 ajustó tanto los datos reales como el ruido, lo que resultó en un bajo error en el conjunto de entrenamiento pero un alto error en el conjunto de prueba.