Forma Matricial de los Coeficientes de Regresión¶
Fórmula principal:¶
$$\boldsymbol{\beta} = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y}$$
Componentes matriciales:¶
Matriz X (n × k):¶
$$\mathbf{X} = \begin{bmatrix} 1 & x_{11} & x_{12} & \cdots & x_{1,k-1} \\ 1 & x_{21} & x_{22} & \cdots & x_{2,k-1} \\ 1 & x_{31} & x_{32} & \cdots & x_{3,k-1} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_{n1} & x_{n2} & \cdots & x_{n,k-1} \end{bmatrix}$$
Vector y (n × 1):¶
$$\mathbf{y} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \\ \vdots \\ y_n \end{bmatrix}$$
Vector β (k × 1):¶
$$\boldsymbol{\beta} = \begin{bmatrix} \beta_0 \\ \beta_1 \\ \beta_2 \\ \vdots \\ \beta_{k-1} \end{bmatrix}$$
Matriz X^T X (k × k):¶
$$\mathbf{X}^T\mathbf{X} = \begin{bmatrix} n & \sum x_{i1} & \sum x_{i2} & \cdots & \sum x_{i,k-1} \\ \sum x_{i1} & \sum x_{i1}^2 & \sum x_{i1}x_{i2} & \cdots & \sum x_{i1}x_{i,k-1} \\ \sum x_{i2} & \sum x_{i1}x_{i2} & \sum x_{i2}^2 & \cdots & \sum x_{i2}x_{i,k-1} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ \sum x_{i,k-1} & \sum x_{i1}x_{i,k-1} & \sum x_{i2}x_{i,k-1} & \cdots & \sum x_{i,k-1}^2 \end{bmatrix}$$
Vector X^T y (k × 1):¶
$$\mathbf{X}^T\mathbf{y} = \begin{bmatrix} \sum y_i \\ \sum x_{i1}y_i \\ \sum x_{i2}y_i \\ \vdots \\ \sum x_{i,k-1}y_i \end{bmatrix}$$
Resultado final:¶
$$\boldsymbol{\beta} = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y} = \begin{bmatrix} \beta_0 \\ \beta_1 \\ \beta_2 \\ \vdots \\ \beta_{k-1} \end{bmatrix}$$
Donde:¶
- n = número total de observaciones
- k = número total de parámetros (incluyendo intercepto)
- ∑ denota suma sobre todas las observaciones i = 1, 2, ..., n
- β₀ = intercepto
- βⱼ = coeficiente de la j-ésima variable explicativa
1) Diseño e Implementación¶
Para imprimir la forma (shape) de cada matriz y resultado intermedio para reforzar el aprendizaje conceptual se utilizo la libreria Sympy y se creo una función especifica y universal que fue utilizada a lo largo del ejercicio.
import numpy as np
import matplotlib.pyplot as plt
from sympy import Matrix
from sympy import init_printing
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['xtick.labelsize'] = 10
plt.rcParams['ytick.labelsize'] = 10
# Activamos la impresión de SymPy para mostrar matrices de manera optima
init_printing()
def mostrar_matriz_formato(matriz, nombre="Matriz"):
"""
Muestra una matriz de SymPy con formato matemático elegante.
Parámetros:
-----------
matriz : sympy.Matrix
Matriz a mostrar
nombre : str
Nombre de la matriz para la etiqueta
"""
if not isinstance(matriz, Matrix):
raise TypeError("Se esperaba una matriz de tipo sympy.Matrix.")
filas, columnas = matriz.shape
elementos_str = [[str(matriz[i, j]) for j in range(columnas)] for i in range(filas)]
anchos = [max(max(len(row[j]) for row in elementos_str), 4) for j in range(columnas)]
nombre_columna = f"{nombre} = "
for i in range(filas):
borde_izq = "⎡" if i == 0 else "⎢" if i < filas - 1 else "⎣"
borde_der = "⎤" if i == 0 else "⎥" if i < filas - 1 else "⎦"
linea = nombre_columna if i == 0 else " " * len(nombre_columna)
linea += borde_izq
for j in range(columnas):
linea += elementos_str[i][j].rjust(anchos[j])
if j < columnas - 1:
linea += " "
linea += f" {borde_der}"
print(linea)
def numpy_a_sympy(array_numpy, precision=4):
"""
Convierte un array de NumPy a una matriz de SymPy con precisión controlada.
Parámetros:
-----------
array_numpy : numpy.ndarray
Array de NumPy a convertir
precision : int
Número de decimales para redondear
Retorna:
--------
sympy.Matrix
Matriz de SymPy equivalente
"""
if array_numpy.ndim == 1:
array_numpy = array_numpy.reshape(-1, 1)
# Redondear para evitar números con muchos decimales
array_redondeado = np.round(array_numpy, precision)
return Matrix(array_redondeado.tolist())
def generar_datos(n=100):
"""
Genera datos sintéticos para regresión lineal con ruido gaussiano.
El modelo verdadero es: y = 4 + 3*x + ruido
Parámetros:
-----------
n : int
Número de observaciones a generar
Retorna:
--------
x : numpy.ndarray
Array de características de forma (n, 1)
y : numpy.ndarray
Array de valores observados de forma (n, 1)
"""
print(f"🔸 Generando {n} observaciones...")
# FijaMOS semilla para reproducibilidad Posterior
np.random.seed(42)
# Generar características x uniformemente distribuidas en [0, 1]
x = np.random.rand(n, 1)
print(f" • x generado: forma {x.shape}, rango [{x.min():.3f}, {x.max():.3f}]")
# Generar valores y con relación lineal + ruido gaussiano
# Modelo verdadero: y = 4 + 3*x + ε, donde ε ~ N(0, 1)
y = 4 + 3 * x + np.random.randn(n, 1)
print(f" • y generado: forma {y.shape}, rango [{y.min():.3f}, {y.max():.3f}]")
print(f" • Modelo verdadero: y = 4 + 3*x + ruido")
return x, y
def demostrar_operaciones_matriciales(X, y):
"""
Demuestra las operaciones matriciales básicas utilizadas en la regresión.
Parámetros:
-----------
X : numpy.ndarray
Matriz de diseño
y : numpy.ndarray
Vector de valores observados
"""
print("\n" + "="*60)
print("🔸 DEMOSTRACIÓN GRAFICA DE OPERACIONES MATRICIALES")
print("="*60)
# Convertir a matrices de SymPy para visualización elegante
X_sympy = numpy_a_sympy(X[:8]) # Mostrar solo las primeras 8 filas
y_sympy = numpy_a_sympy(y[:8]) # Mostrar solo los primeros 8 valores
# 1. Información básica de las matrices
print(f"🔹 Matriz de diseño X (primeras 8 filas):")
print(f" • Forma completa: {X.shape}")
mostrar_matriz_formato(X_sympy, "X")
print(f"\n🔹 Vector y (primeros 8 valores):")
print(f" • Forma completa: {y.shape}")
mostrar_matriz_formato(y_sympy, "y")
# 2. Transpuesta de X
X_T = X.T
X_T_sympy = numpy_a_sympy(X_T)
print(f"\n🔹 Transpuesta X^T:")
print(f" • X^T tiene forma: {X_T.shape}")
mostrar_matriz_formato(X_T_sympy, "X^T")
# 3. Producto X^T @ X
XTX = X_T @ X
XTX_sympy = numpy_a_sympy(XTX)
print(f"\n🔹 Producto X^T @ X:")
print(f" • (X^T @ X) tiene forma: {XTX.shape}")
mostrar_matriz_formato(XTX_sympy, "X^T @ X")
# 4. Determinante de X^T @ X
det_XTX = np.linalg.det(XTX)
print(f" • Determinante de (X^T @ X): {det_XTX:.6f}")
print(f" • {'✓ Matriz invertible' if abs(det_XTX) > 1e-10 else '✗ Matriz singular'}")
# 5. Inversa de X^T @ X
XTX_inv = np.linalg.inv(XTX)
XTX_inv_sympy = numpy_a_sympy(XTX_inv)
print(f"\n🔹 Inversa (X^T @ X)^(-1):")
mostrar_matriz_formato(XTX_inv_sympy, "(X^T @ X)^(-1)")
# 6. Verificación de la inversa
identidad = XTX @ XTX_inv
identidad_sympy = numpy_a_sympy(identidad)
print(f"\n🔹 Verificación de la inversa:")
print(f" • (X^T @ X) @ (X^T @ X)^(-1) =")
mostrar_matriz_formato(identidad_sympy, "Identidad")
print(f" • {'✓ Inversa correcta' if np.allclose(identidad, np.eye(2)) else '✗ Error en la inversa'}")
# 7. Producto X^T @ y
XTy = X_T @ y
XTy_sympy = numpy_a_sympy(XTy)
print(f"\n🔹 Producto X^T @ y:")
print(f" • (X^T @ y) tiene forma: {XTy.shape}")
mostrar_matriz_formato(XTy_sympy, "X^T @ y")
return XTX_inv, XTy
def ajustar_modelo(x, y):
"""
Calcula los parámetros β de la regresión lineal usando álgebra matricial.
Implementa la fórmula: β = (X^T X)^(-1) X^T y
Parámetros:
-----------
x : numpy.ndarray
Array de características de forma (n, 1)
y : numpy.ndarray
Array de valores observados de forma (n, 1)
Retorna:
--------
beta : numpy.ndarray
Vector de parámetros ajustados [β₀, β₁]
X : numpy.ndarray
Matriz de diseño utilizada
"""
print("\n" + "="*60)
print("🔸 AJUSTE DEL MODELO DE REGRESIÓN LINEAL")
print("="*60)
n = x.shape[0]
print(f"🔹 Construyendo matriz de diseño X:")
# Crear matriz de diseño: columna de unos + columna de características
columna_unos = np.ones((n, 1))
X = np.hstack([columna_unos, x])
print(f" • Columna de unos: forma {columna_unos.shape}")
print(f" • Características x: forma {x.shape}")
print(f" • Matriz X final: forma {X.shape}")
print(f" • X = [columna_unos | x]")
# Demostrar operaciones matriciales paso a paso
XTX_inv, XTy = demostrar_operaciones_matriciales(X, y)
# Calcular β = (X^T X)^(-1) X^T y
print(f"\n🔹 Cálculo final de β:")
print(f" • Fórmula: β = (X^T X)^(-1) @ X^T @ y")
beta = XTX_inv @ XTy
beta_sympy = numpy_a_sympy(beta)
print(f" • Resultado:")
mostrar_matriz_formato(beta_sympy, "β")
print(f" • β₀ (intercepto) = {beta[0, 0]:.6f}")
print(f" • β₁ (pendiente) = {beta[1, 0]:.6f}")
# Comparar con valores verdaderos
print(f"\n🔹 Comparación con modelo verdadero:")
print(f" • Verdadero: β₀ = 4.000, β₁ = 3.000")
print(f" • Estimado: β₀ = {beta[0, 0]:.3f}, β₁ = {beta[1, 0]:.3f}")
print(f" • Error β₀: {abs(4 - beta[0, 0]):.6f}")
print(f" • Error β₁: {abs(3 - beta[1, 0]):.6f}")
return beta, X
def calcular_metricas_modelo(y_real, y_pred):
"""
Calcula métricas de evaluación del modelo.
Parámetros:
-----------
y_real : numpy.ndarray
Valores reales observados
y_pred : numpy.ndarray
Valores predichos por el modelo
Retorna:
--------
dict : Diccionario con las métricas calculadas
"""
# Error Cuadrático Medio (MSE)
mse = np.mean((y_real - y_pred) ** 2)
# Raíz del Error Cuadrático Medio (RMSE)
rmse = np.sqrt(mse)
# Error Absoluto Medio (MAE)
mae = np.mean(np.abs(y_real - y_pred))
# Coeficiente de Determinación (R²)
ss_res = np.sum((y_real - y_pred) ** 2) # Suma de cuadrados residuales
ss_tot = np.sum((y_real - np.mean(y_real)) ** 2) # Suma total de cuadrados
r2 = 1 - (ss_res / ss_tot)
return {
'MSE': mse,
'RMSE': rmse,
'MAE': mae,
'R²': r2,
'SS_res': ss_res,
'SS_tot': ss_tot
}
def graficar_resultado(x, y, beta):
"""
Grafica los datos originales y la recta de regresión ajustada.
Parámetros:
-----------
x : numpy.ndarray
Array de características
y : numpy.ndarray
Array de valores observados
beta : numpy.ndarray
Vector de parámetros ajustados [β₀, β₁]
"""
print("\n" + "="*60)
print("🔸 GENERANDO VISUALIZACIÓN")
print("="*60)
# Crear figura con subplots
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# === GRÁFICO PRINCIPAL ===
# Graficar datos originales
ax1.scatter(x, y, color='steelblue', alpha=0.6, s=50,
label='Datos observados', edgecolors='navy', linewidth=0.5)
# Crear línea de regresión
x_line = np.linspace(0, 1, 100).reshape(-1, 1)
y_line_ajustada = beta[0] + beta[1] * x_line
ax1.plot(x_line, y_line_ajustada, color='red', linewidth=3,
label=f'Modelo ajustado: y = {beta[0,0]:.3f} + {beta[1,0]:.3f}x')
# Línea del modelo verdadero para comparación
y_line_verdadera = 4 + 3 * x_line
ax1.plot(x_line, y_line_verdadera, color='green', linewidth=2,
linestyle='--', label='Modelo verdadero: y = 4 + 3x')
ax1.set_xlabel('x (Características)', fontsize=12)
ax1.set_ylabel('y (Valores observados)', fontsize=12)
ax1.set_title('Regresión Lineal - Ajuste del Modelo', fontsize=14, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
# === GRÁFICO DE RESIDUOS ===
# Calcular predicciones y residuos
y_pred = beta[0] + beta[1] * x
residuos = y - y_pred
ax2.scatter(y_pred, residuos, color='purple', alpha=0.6, s=50,
edgecolors='indigo', linewidth=0.5)
ax2.axhline(y=0, color='red', linestyle='--', linewidth=2, alpha=0.8)
ax2.set_xlabel('Valores Predichos', fontsize=12)
ax2.set_ylabel('Residuos (y - ŷ)', fontsize=12)
ax2.set_title('Análisis de Residuos', fontsize=14, fontweight='bold')
ax2.grid(True, alpha=0.3)
# Calcular y mostrar métricas
metricas = calcular_metricas_modelo(y, y_pred)
# Añadir texto con métricas al gráfico
texto_metricas = f"""Métricas del Modelo:
MSE: {metricas['MSE']:.4f}
RMSE: {metricas['RMSE']:.4f}
MAE: {metricas['MAE']:.4f}
R²: {metricas['R²']:.4f}"""
ax1.text(0.02, 0.98, texto_metricas, transform=ax1.transAxes,
verticalalignment='top', fontsize=9,
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
plt.tight_layout()
plt.show()
# Imprimir resumen de métricas
print("🔹 Métricas de evaluación del modelo:")
for metrica, valor in metricas.items():
if metrica not in ['SS_res', 'SS_tot']: # No imprimir estas métricas intermedias
print(f" • {metrica}: {valor:.6f}")
return metricas
def main_encabezado():
"""
Función principal que ejecuta regresión lineal.
Se enfoca directamente en la regresión sin ejemplos previos.
"""
print("="*80)
print("🚀 SISTEMA DE REGRESIÓN LINEAL CON ÁLGEBRA MATRICIAL")
print("="*80)
print("📝 Implementación de: β = (X^T X)^(-1) X^T y")
print("="*80)
def main_parte1():
"""
PARTE 1: Generación de datos sintéticos
"""
print("="*50)
print("1️⃣ GENERACIÓN DE DATOS SINTÉTICOS")
print("="*50)
x, y = generar_datos(n=100)
print(f"✅ Datos generados:")
print(f" • Observaciones: {len(x)}")
print(f" • Rango X: [{x.min():.3f}, {x.max():.3f}]")
print(f" • Rango Y: [{y.min():.3f}, {y.max():.3f}]")
print(f" • Primeras 3: X={x[:3]} Y={y[:3]}")
return x, y
def main_parte2(x, y):
"""
PARTE 2: Ajuste del modelo de regresión
"""
print("="*50)
print("2️⃣ AJUSTE DEL MODELO")
print("="*50)
beta, X = ajustar_modelo(x, y)
print(f"✅ Modelo ajustado:")
print(f" • Matriz X: {X.shape}")
print(f" • β₀ (intercepto): {beta[0,0]:.6f}")
print(f" • β₁ (pendiente): {beta[1,0]:.6f}")
print(f" • Ecuación: y = {beta[0,0]:.3f} + {beta[1,0]:.3f}x")
return beta, X
def main_parte3(x, y, beta):
"""
PARTE 3: Visualización y métricas
"""
print("="*50)
print("3️⃣ VISUALIZACIÓN Y MÉTRICAS")
print("="*50)
metricas = graficar_resultado(x, y, beta)
calidad = ('Excelente' if metricas['R²'] > 0.9 else
'Bueno' if metricas['R²'] > 0.7 else 'Regular')
print(f"✅ Resultados:")
print(f" • R² = {metricas['R²']:.4f}")
print(f" • Varianza explicada: {metricas['R²']*100:.1f}%")
print(f" • Calidad: {calidad}")
return metricas
def main_parte4(x, y, beta, X, metricas):
"""
PARTE 4: Resumen final
"""
print("="*50)
print("4️⃣ RESUMEN FINAL")
print("="*50)
calidad = ('Excelente' if metricas['R²'] > 0.9 else
'Bueno' if metricas['R²'] > 0.7 else 'Regular')
print(f"📊 Datos procesados: {len(x)} observaciones")
print(f"🔧 Parámetros:")
print(f" • β₀ (intercepto): {beta[0,0]:.6f}")
print(f" • β₁ (pendiente): {beta[1,0]:.6f}")
print(f"📈 Rendimiento: R² = {metricas['R²']:.4f} ({calidad})")
print(f"⚡ {'Excelente ajuste' if metricas['R²'] > 0.9 else 'Buen ajuste' if metricas['R²'] > 0.7 else 'Ajuste regular'}")
return {
'datos': len(x),
'beta_0': beta[0,0],
'beta_1': beta[1,0],
'r_cuadrado': metricas['R²'],
'calidad': calidad
}
def main_completo():
"""
Función que ejecuta todas las partes de una vez (como tu original)
"""
# Mostrar encabezado principal
main_encabezado()
print()
# Ejecutar todas las partes
x, y = main_parte1()
print()
beta, X = main_parte2(x, y)
print()
metricas = main_parte3(x, y, beta)
print()
resumen = main_parte4(x, y, beta, X, metricas)
return beta, X, metricas, resumen
2) Implementacion en Python una solución de regresión lineal basada en álgebra matricial, aplicando el modelo:¶
# CELDA 0: Encabezado del modelo y su forma
main_encabezado()
================================================================================ 🚀 SISTEMA DE REGRESIÓN LINEAL CON ÁLGEBRA MATRICIAL ================================================================================ 📝 Implementación de: β = (X^T X)^(-1) X^T y ================================================================================
3) Generación de datos sintéticos (x, y) con ruido gaussiano.¶
# CELDA 1: Generación de datos sinteticos
x, y = main_parte1()
================================================== 1️⃣ GENERACIÓN DE DATOS SINTÉTICOS ================================================== 🔸 Generando 100 observaciones... • x generado: forma (100, 1), rango [0.006, 0.987] • y generado: forma (100, 1), rango [2.815, 8.455] • Modelo verdadero: y = 4 + 3*x + ruido ✅ Datos generados: • Observaciones: 100 • Rango X: [0.006, 0.987] • Rango Y: [2.815, 8.455] • Primeras 3: X=[[0.37454012] [0.95071431] [0.73199394]] Y=[[5.21066742] [6.55313557] [6.2877426 ]]
4) Creación de la matriz X e implementación del cálculo matricial paso a paso usando NumPy.¶
# CELDA 2: Ajuste del modelo y calculo grafico de matrices
beta, X = main_parte2(x, y)
================================================== 2️⃣ AJUSTE DEL MODELO ================================================== ============================================================ 🔸 AJUSTE DEL MODELO DE REGRESIÓN LINEAL ============================================================ 🔹 Construyendo matriz de diseño X: • Columna de unos: forma (100, 1) • Características x: forma (100, 1) • Matriz X final: forma (100, 2) • X = [columna_unos | x] ============================================================ 🔸 DEMOSTRACIÓN DE OPERACIONES MATRICIALES ============================================================ 🔹 Matriz de diseño X (primeras 8 filas): • Forma completa: (100, 2) X = ⎡1.00000000000000 0.374500000000000 ⎤ ⎢1.00000000000000 0.950700000000000 ⎥ ⎢1.00000000000000 0.732000000000000 ⎥ ⎢1.00000000000000 0.598700000000000 ⎥ ⎢1.00000000000000 0.156000000000000 ⎥ ⎢1.00000000000000 0.156000000000000 ⎥ ⎢1.00000000000000 0.0581000000000000 ⎥ ⎣1.00000000000000 0.866200000000000 ⎦ 🔹 Vector y (primeros 8 valores): • Forma completa: (100, 1) y = ⎡5.21070000000000 ⎤ ⎢6.55310000000000 ⎥ ⎢6.28770000000000 ⎥ ⎢3.80840000000000 ⎥ ⎢4.24840000000000 ⎥ ⎢4.82510000000000 ⎥ ⎢5.65210000000000 ⎥ ⎣6.08030000000000 ⎦ 🔹 Transpuesta X^T: • X^T tiene forma: (2, 100) X^T = ⎡ 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 1.00000000000000 ⎤ ⎣0.374500000000000 0.950700000000000 0.732000000000000 0.598700000000000 0.156000000000000 0.156000000000000 0.0581000000000000 0.866200000000000 0.601100000000000 0.708100000000000 0.0206000000000000 0.969900000000000 0.832400000000000 0.212300000000000 0.181800000000000 0.183400000000000 0.304200000000000 0.524800000000000 0.431900000000000 0.291200000000000 0.611900000000000 0.139500000000000 0.292100000000000 0.366400000000000 0.456100000000000 0.785200000000000 0.199700000000000 0.514200000000000 0.592400000000000 0.0465000000000000 0.607500000000000 0.170500000000000 0.0651000000000000 0.948900000000000 0.965600000000000 0.808400000000000 0.304600000000000 0.0977000000000000 0.684200000000000 0.440200000000000 0.122000000000000 0.495200000000000 0.0344000000000000 0.909300000000000 0.258800000000000 0.662500000000000 0.311700000000000 0.520100000000000 0.546700000000000 0.184900000000000 0.969600000000000 0.775100000000000 0.939500000000000 0.894800000000000 0.597900000000000 0.921900000000000 0.0885000000000000 0.196000000000000 0.0452000000000000 0.325300000000000 0.388700000000000 0.271300000000000 0.828700000000000 0.356800000000000 0.280900000000000 0.542700000000000 0.140900000000000 0.802200000000000 0.0746000000000000 0.986900000000000 0.772200000000000 0.198700000000000 0.00550000000000000 0.815500000000000 0.706900000000000 0.729000000000000 0.771300000000000 0.0740000000000000 0.358500000000000 0.115900000000000 0.863100000000000 0.623300000000000 0.330900000000000 0.0636000000000000 0.311000000000000 0.325200000000000 0.729600000000000 0.637600000000000 0.887200000000000 0.472200000000000 0.119600000000000 0.713200000000000 0.760800000000000 0.561300000000000 0.771000000000000 0.493800000000000 0.522700000000000 0.427500000000000 0.0254000000000000 0.107900000000000 ⎦ 🔹 Producto X^T @ X: • (X^T @ X) tiene forma: (2, 2) X^T @ X = ⎡100.000000000000 47.0181000000000 ⎤ ⎣47.0181000000000 30.8685000000000 ⎦ • Determinante de (X^T @ X): 876.149502 • ✓ Matriz invertible 🔹 Inversa (X^T @ X)^(-1): (X^T @ X)^(-1) = ⎡ 0.0352000000000000 -0.0537000000000000 ⎤ ⎣-0.0537000000000000 0.114100000000000 ⎦ 🔹 Verificación de la inversa: • (X^T @ X) @ (X^T @ X)^(-1) = Identidad = ⎡1.00000000000000 0.0 ⎤ ⎣ 0.0 1.00000000000000 ⎦ • ✓ Inversa correcta 🔹 Producto X^T @ y: • (X^T @ y) tiene forma: (2, 1) X^T @ y = ⎡540.946200000000 ⎤ ⎣276.598700000000 ⎦ 🔹 Cálculo final de β: • Fórmula: β = (X^T X)^(-1) @ X^T @ y • Resultado: β = ⎡4.21510000000000 ⎤ ⎣2.54020000000000 ⎦ • β₀ (intercepto) = 4.215096 • β₁ (pendiente) = 2.540227 🔹 Comparación con modelo verdadero: • Verdadero: β₀ = 4.000, β₁ = 3.000 • Estimado: β₀ = 4.215, β₁ = 2.540 • Error β₀: 0.215096 • Error β₁: 0.459773 ✅ Modelo ajustado: • Matriz X: (100, 2) • β₀ (intercepto): 4.215096 • β₁ (pendiente): 2.540227 • Ecuación: y = 4.215 + 2.540x
5) Predicción de valores y graficación de resultados.¶
# CELDA 3: Mostramos graficos
metricas = main_parte3(x, y, beta)
================================================== 3️⃣ VISUALIZACIÓN Y MÉTRICAS ================================================== ============================================================ 🔸 GENERANDO VISUALIZACIÓN ============================================================
🔹 Métricas de evaluación del modelo: • MSE: 0.806585 • RMSE: 0.898101 • MAE: 0.701043 • R²: 0.412086 ✅ Resultados: • R² = 0.4121 • Varianza explicada: 41.2% • Calidad: Regular
6)Resumen final del modelo-¶
#Parte 4- Mostramos resultados de parametros
resumen = main_parte4(x, y, beta, X, metricas)
================================================== 4️⃣ RESUMEN FINAL ================================================== 📊 Datos procesados: 100 observaciones 🔧 Parámetros: • β₀ (intercepto): 4.215096 • β₁ (pendiente): 2.540227 📈 Rendimiento: R² = 0.4121 (Regular) ⚡ Ajuste regular
📌 Conclusiones y Documentación del Modelo de Regresión Lineal¶
🧠 Descripción de Funciones (con docstrings incluidos en el código)¶
generar_datos(n=100)
Genera datos sintéticos con una relación lineal más ruido gaussiano.- Entrada: número de datos
n
. - Salida: arrays
x
(independiente) ey
(dependiente). - Propósito: Simular una situación real de datos dispersos en torno a una tendencia.
- Entrada: número de datos
ajustar_modelo(x, y)
Aplica álgebra matricial para estimar los coeficientes del modelo de regresión lineal.- Entrada: vectores
x
ey
. - Salida: vector
beta
con los parámetros ajustados (intercepto y pendiente). - Propósito: Resolver el modelo β = (XᵀX)⁻¹Xᵀy mediante operaciones matriciales.
- Entrada: vectores
graficar_resultado(x, y, beta)
Visualiza los datos originales y la línea ajustada.- Entrada:
x
,y
, y los parámetrosbeta
. - Salida: gráfica de dispersión + línea de regresión.
- Propósito: Validar visualmente el ajuste del modelo sobre los datos generados.
- Entrada:
🔁 Flujo del Modelo y Explicaciones Clave¶
Generación de datos: Se simula un conjunto de puntos que siguen una relación lineal (pendiente = 3, intercepto = 4), pero con ruido, para representar incertidumbre o errores de medición reales.
Construcción de la matriz X: En regresión lineal, necesitamos una matriz de diseño con una columna de 1s (para el término independiente) y la variable independiente
x
.Uso de la fórmula matricial:
Se aplica la expresión:$$ \boldsymbol{\beta} = (X^T X)^{-1} X^T y $$
que permite resolver la regresión lineal sin métodos iterativos, aprovechando el álgebra matricial como herramienta eficiente y precisa.
Cálculo paso a paso:
- Transpuesta de
X
(X.T
) - Producto matricial
X.T @ X
- Inversa de la matriz resultante
- Multiplicación final para obtener
β
- Transpuesta de
Visualización:
Es crucial para interpretar la calidad del modelo, evaluando si la recta estimada refleja correctamente la tendencia central de los datos.
📘 README: ¿Por qué usar Álgebra Matricial en Machine Learning?¶
La regresión lineal es uno de los modelos fundamentales del aprendizaje automático. Su implementación con álgebra matricial permite:
- Resolver el modelo de manera vectorizada y eficiente.
- Extender fácilmente a regresión múltiple (con varias variables).
- Comprender mejor algoritmos más avanzados que se basan en principios similares, como redes neuronales y métodos de mínimos cuadrados generalizados.
- Aprovechar librerías optimizadas como NumPy y acelerar cálculos para grandes volúmenes de datos.
Por tanto, dominar este enfoque no solo facilita la comprensión de la regresión lineal, sino que sienta las bases para algoritmos de mayor complejidad en el campo del ML.
✅ Duración estimada de la actividad: 2 a 3 horas
👥 Trabajo en parejas
🔁 Semilla fija utilizada: np.random.seed(42)
📊 Número de datos generados: n = 100
▶️ Bonus: Gráfico Animado¶
# Librerías necesarias
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
np.random.seed(42)
n = 100
x = np.random.rand(n, 1)
ruido = np.random.randn(n, 1)
y = 4 + 3 * x + ruido # modelo verdadero
# Coeficientes estimados reales de tu ejercicio
beta_0_est = 4.215096
beta_1_est = 2.540227
fig, ax = plt.subplots()
ax.set_xlim(0, 1)
ax.set_ylim(2, 9)
ax.set_title("Animación del ajuste del modelo")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Puntos de datos originales con ruido
ax.scatter(x, y, color='blue', alpha=0.6, label='Datos reales')
# ✅ Línea de la curva verdadera: y = 4 + 3x (sin ruido)
x_real = np.linspace(0, 1, 100).reshape(-1, 1)
y_real = 4 + 3 * x_real
ax.plot(x_real, y_real, 'g--', linewidth=2, label='Curva verdadera: y = 4 + 3x')
linea, = ax.plot([], [], 'r-', linewidth=2, label='Recta en ajuste')
# Leyenda
ax.legend()
# Función de animación
def animar(frame):
progreso = frame / 100 # va de 0 a 1
b0 = 2 + (beta_0_est - 2) * progreso
b1 = 1 + (beta_1_est - 1) * progreso
y_pred = b0 + b1 * x
linea.set_data(x, y_pred)
return linea,
anim = FuncAnimation(fig, animar, frames=101, interval=60)
plt.close(fig)
HTML(anim.to_jshtml())