# 📌 Importamos todas las librerías que utilizaremos para los modelos y visualizaciones
# Manipulación de datos
import pandas as pd
import numpy as np
# Visualización
import matplotlib.pyplot as plt
import seaborn as sns
# Preprocesamiento y métricas
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.metrics import mean_squared_error, r2_score
# Modelos
from sklearn.linear_model import LinearRegression
from sklearn.neural_network import MLPRegressor
Run to view results
# 📌 Cargamos el dataset desde la URL
url = "https://raw.githubusercontent.com/Machine1314/natural_computing/main/data_regression.csv"
df = pd.read_csv(url)
# 🔍 Mostramos las primeras filas
print("Primeras filas del dataset:")
display(df.head())
# Información básica del dataset
print("\nInformación general del dataset:")
df.info()
# Estadísticas descriptivas
print("\nEstadísticas básicas:")
display(df.describe())
Run to view results
# 📈 Gráfico de dispersión para observar la relación entre xi y yi
plt.figure(figsize=(8, 5))
sns.scatterplot(x='xi', y='yi', data=df, color='royalblue')
plt.title("Relación entre la variable independiente xi y la dependiente yi")
plt.xlabel("xi")
plt.ylabel("yi")
plt.show()
Run to view results
# 🔁 Escalado de xi para estabilizar el aprendizaje
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X = scaler.fit_transform(df[['xi']].values) # xi escalada
y = df['yi'].values # yi sin cambios
Run to view results
# Generar características cuadráticas (x y x²)
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X)
# Entrenar modelo
modelo_analitico = LinearRegression()
modelo_analitico.fit(X_poly, y)
# Predicción
y_pred_analitico = modelo_analitico.predict(X_poly)
# Evaluación
mse_analitico = mean_squared_error(y, y_pred_analitico)
r2_analitico = r2_score(y, y_pred_analitico)
print(f"🔍 MSE del modelo analítico: {mse_analitico:.4f}")
print(f"📈 R² del modelo analítico: {r2_analitico:.4f}")
Run to view results
# Inversión del escalado para visualización
X_original = scaler.inverse_transform(X)
# Gráfico
plt.figure(figsize=(8, 5))
plt.scatter(X_original, y, color='blue', label="Datos reales")
plt.plot(X_original, y_pred_analitico, color='red', linewidth=2, label="Modelo analítico")
plt.title("Regresión cuadrática (modelo analítico)")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.show()
Run to view results
# Función de predicción cuadrática
def predict(X, a0, a1, a2):
return a0 + a1*X.flatten() + a2*(X.flatten()**2)
# Función de costo (MSE)
def compute_mse(y_true, y_pred):
return np.mean((y_true - y_pred) ** 2)
Run to view results
# Inicializar coeficientes
a0, a1, a2 = np.random.randn(3)
# Hiperparámetros
learning_rate = 0.0001
epochs = 5000
mse_history = []
for epoch in range(epochs):
y_pred = predict(X, a0, a1, a2)
if np.isnan(y_pred).any():
print(f"🚨 NaN detectado en la iteración {epoch}. Se detiene el entrenamiento.")
break
error = y_pred - y
grad_a0 = 2 * np.mean(error)
grad_a1 = 2 * np.mean(error * X.flatten())
grad_a2 = 2 * np.mean(error * (X.flatten() ** 2))
a0 -= learning_rate * grad_a0
a1 -= learning_rate * grad_a1
a2 -= learning_rate * grad_a2
mse = compute_mse(y, y_pred)
mse_history.append(mse)
if epoch % 500 == 0:
print(f"Iteración {epoch} - MSE: {mse:.4f}")
print(f"Coeficientes: a0 = {a0:.4f}, a1 = {a1:.4f}, a2 = {a2:.4f}")
Run to view results
# Evaluación final
y_pred_grad = predict(X, a0, a1, a2)
mse_grad = compute_mse(y, y_pred_grad)
r2_grad = r2_score(y, y_pred_grad)
print(f"\n✅ Descenso de Gradiente Finalizado")
print(f"MSE: {mse_grad:.4f}")
print(f"R²: {r2_grad:.4f}")
Run to view results
# ✅ Ordenamos los datos para una línea continua correcta
X_sorted_indices = np.argsort(X_original.flatten())
X_sorted = X_original.flatten()[X_sorted_indices]
y_sorted = y_pred_grad[X_sorted_indices]
# 📈 Visualización del modelo GD corregida
plt.figure(figsize=(8, 5))
plt.scatter(X_original, y, color='blue', label="Datos reales")
plt.plot(X_sorted, y_sorted, color='green', linewidth=2, label="Modelo GD (ajuste ordenado)")
plt.title("Modelo cuadrático con descenso de gradiente (ordenado)")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.show()
Run to view results
# Escalar también la variable dependiente yi
scaler_y = StandardScaler()
y_scaled = scaler_y.fit_transform(df[['yi']])
# Reutilizamos la variable X que ya estaba escalada
X_flat = X.flatten()
x2 = X_flat**2
y_flat = y_scaled.flatten()
Run to view results
# Reentrenar con mejoras
a0, a1, a2 = np.random.randn(3) # Nuevos coeficientes
learning_rate = 0.01 # Tasa mejorada
epochs = 5000 # Más iteraciones
mse_history = []
def predict_improved(X, a0, a1, a2):
X_flat = X.flatten()
return a0 + a1 * X_flat + a2 * X_flat**2
for epoch in range(epochs):
y_pred = predict_improved(X, a0, a1, a2)
error = y_flat - y_pred
grad_a0 = -2 * np.mean(error)
grad_a1 = -2 * np.mean(error * X_flat)
grad_a2 = -2 * np.mean(error * (X_flat**2))
a0 -= learning_rate * grad_a0
a1 -= learning_rate * grad_a1
a2 -= learning_rate * grad_a2
mse = np.mean(error ** 2)
mse_history.append(mse)
if epoch % 500 == 0:
print(f"Iteración {epoch} - MSE: {mse:.4f}")
print(f"Coeficientes finales: a0={a0:.4f}, a1={a1:.4f}, a2={a2:.4f}")
Run to view results
# Predicciones y desescalado de yi
y_pred_scaled = predict_improved(X, a0, a1, a2)
y_pred_original = scaler_y.inverse_transform(y_pred_scaled.reshape(-1, 1))
# Ordenar para graficar
X_original = scaler.inverse_transform(X)
X_sorted_indices = np.argsort(X_original.flatten())
X_sorted = X_original.flatten()[X_sorted_indices]
y_sorted = y_pred_original.flatten()[X_sorted_indices]
# Gráfica
plt.figure(figsize=(8, 5))
plt.scatter(X_original, df['yi'], color='blue', label="Datos reales")
plt.plot(X_sorted, y_sorted, color='green', linewidth=2, label="GD mejorado")
plt.title("Mejora del ajuste con descenso de gradiente")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.grid(True)
plt.show()
Run to view results
from sklearn.metrics import r2_score, mean_squared_error
mse_mejorado = mean_squared_error(df['yi'], y_pred_original)
r2_mejorado = r2_score(df['yi'], y_pred_original)
print(f"✅ Evaluación tras mejoras:")
print(f"MSE: {mse_mejorado:.4f}")
print(f"R²: {r2_mejorado:.4f}")
Run to view results
from sklearn.neural_network import MLPRegressor
# Crear y entrenar modelo MLP con una capa oculta de 10 neuronas
mlp_10 = MLPRegressor(hidden_layer_sizes=(10,),
activation='relu',
solver='adam',
max_iter=5000,
random_state=42)
mlp_10.fit(X, y_scaled.flatten()) # y debe estar escalado para que funcione bien
Run to view results
# Predecimos usando el modelo entrenado
y_pred_mlp_10_scaled = mlp_10.predict(X)
# Desescalar predicciones
y_pred_mlp_10 = scaler_y.inverse_transform(y_pred_mlp_10_scaled.reshape(-1, 1))
Run to view results
# Ordenar para graficar curva suave
X_original = scaler.inverse_transform(X)
sorted_indices = np.argsort(X_original.flatten())
X_sorted = X_original.flatten()[sorted_indices]
y_sorted = y_pred_mlp_10.flatten()[sorted_indices]
# Gráfica
plt.figure(figsize=(8, 5))
plt.scatter(X_original, df['yi'], color='blue', label="Datos reales")
plt.plot(X_sorted, y_sorted, color='orange', linewidth=2, label="MLP (10 neuronas)")
plt.title("MLP con 10 neuronas ocultas (Red Simple)")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.grid(True)
plt.show()
Run to view results
mse_mlp_10 = mean_squared_error(df['yi'], y_pred_mlp_10)
r2_mlp_10 = r2_score(df['yi'], y_pred_mlp_10)
print("🔍 Evaluación del MLP (10 neuronas):")
print(f"MSE: {mse_mlp_10:.4f}")
print(f"R²: {r2_mlp_10:.4f}")
Run to view results
# MLP con capacidad excesiva (250 neuronas ocultas)
mlp_250 = MLPRegressor(hidden_layer_sizes=(250,),
activation='relu',
solver='adam',
max_iter=5000,
random_state=42)
mlp_250.fit(X, y_scaled.flatten())
Run to view results
# Predicción y desescalado
y_pred_mlp_250_scaled = mlp_250.predict(X)
y_pred_mlp_250 = scaler_y.inverse_transform(y_pred_mlp_250_scaled.reshape(-1, 1))
Run to view results
# Ordenar para graficar correctamente
sorted_indices = np.argsort(X_original.flatten())
X_sorted = X_original.flatten()[sorted_indices]
y_sorted = y_pred_mlp_250.flatten()[sorted_indices]
# Gráfica
plt.figure(figsize=(8, 5))
plt.scatter(X_original, df['yi'], color='blue', label="Datos reales")
plt.plot(X_sorted, y_sorted, color='red', linewidth=2, label="MLP (250 neuronas)")
plt.title("MLP con 250 neuronas ocultas ")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.grid(True)
plt.show()
Run to view results
mse_mlp_250 = mean_squared_error(df['yi'], y_pred_mlp_250)
r2_mlp_250 = r2_score(df['yi'], y_pred_mlp_250)
print("🔍 Evaluación del MLP (250 neuronas):")
print(f"MSE: {mse_mlp_250:.4f}")
print(f"R²: {r2_mlp_250:.4f}")
Run to view results
mlp_1000 = MLPRegressor(hidden_layer_sizes=(1000,),
activation='relu',
solver='adam',
max_iter=5000,
random_state=42)
mlp_1000.fit(X, y_scaled.flatten())
Run to view results
# Predicción y desescalado
y_pred_mlp_1000_scaled = mlp_1000.predict(X)
y_pred_mlp_1000 = scaler_y.inverse_transform(y_pred_mlp_1000_scaled.reshape(-1, 1))
Run to view results
# Ordenar para graficar correctamente
sorted_indices = np.argsort(X_original.flatten())
X_sorted = X_original.flatten()[sorted_indices]
y_sorted = y_pred_mlp_1000.flatten()[sorted_indices]
# Gráfica
plt.figure(figsize=(8, 5))
plt.scatter(X_original, df['yi'], color='blue', label="Datos reales")
plt.plot(X_sorted, y_sorted, color='purple', linewidth=2, label="MLP (1000 neuronas)")
plt.title("MLP con 1000 neuronas ocultas (Modelo Complejo)")
plt.xlabel("xi")
plt.ylabel("yi")
plt.legend()
plt.grid(True)
plt.show()
Run to view results
# Crear la tabla con los resultados actualizados
tabla_resultados = pd.DataFrame({
"Modelo": [
"Regresión Analítica",
"Descenso de Gradiente (fallido)",
"Descenso de Gradiente (mejorado)",
"MLP (10 neuronas)",
"MLP (250 neuronas)",
"MLP (1000 neuronas)"
],
"MSE": [
mse_analitico,
mse_grad,
mse_mejorado,
mse_mlp_10,
mse_mlp_250,
mse_mlp_1000
],
"R²": [
r2_analitico,
r2_grad,
r2_mejorado,
r2_mlp_10,
r2_mlp_250,
r2_mlp_1000
],
"Comentarios": [
"Curva exacta",
"No converge",
"Curva cuadrática perfecta",
"Subajuste (underfitting)",
"Muy buen ajuste (óptimo)",
"Capacidad extrema, posible sobreajuste"
]
})
# Mostrar la tabla ordenada por R²
tabla_resultados.sort_values(by="R²", ascending=False).reset_index(drop=True)
Run to view results