ALGORITMO DE REGRESIÓN

Deslizándose a través de puntos para minimizar cuadrados

Cuando las personas empiezan a aprender sobre análisis de datos, normalmente empiezan con una regresión lineal. Hay una buena razón para ello: es una de las formas más útiles y sencillas de comprender cómo funciona la regresión. Los enfoques más comunes de regresión lineal se denominan «métodos de mínimos cuadrados»: funcionan encontrando patrones en los datos minimizando las diferencias al cuadrado entre las predicciones y los valores reales. El tipo más básico es Mínimos cuadrados ordinarios (OLS), que encuentra la mejor manera de dibujar una línea recta a través de sus puntos de datos.

Sin embargo, a veces OLS no es suficiente, especialmente cuando los datos tienen muchas características relacionadas que pueden hacer que los resultados sean inestables. Ahí es donde Regresión de cresta entra. La regresión de crestas hace el mismo trabajo que OLS pero agrega un control especial que ayuda a evitar que el modelo se vuelva demasiado sensible a una sola característica.

Aquí, nos deslizaremos a través de dos tipos clave de regresión de mínimos cuadrados, explorando cómo estos algoritmos se deslizan suavemente a través de sus puntos de datos y veremos sus diferencias en teoría.

Todos los elementos visuales: creados por el autor con Canva Pro. Optimizado para dispositivos móviles; Puede parecer de gran tamaño en el escritorio.

La regresión lineal es un método estadístico que predice valores numéricos utilizando una ecuación lineal. Modela la relación entre una variable dependiente y una o más variables independientes ajustando una línea recta (o plano, en múltiples dimensiones) a través de los puntos de datos. El modelo calcula coeficientes para cada característica, representando su impacto en el resultado. Para obtener un resultado, ingresa los valores de las características de sus datos en la ecuación lineal para calcular el valor predicho.

Para ilustrar nuestros conceptos, usaremos nuestro conjunto de datos estándar que predice el número de golfistas que visitarán un día determinado. Este conjunto de datos incluye variables como las perspectivas meteorológicas, la temperatura, la humedad y las condiciones del viento.

Columnas: ‘Perspectiva’ (codificada en caliente para soleado, nublado, lluvia), ‘Temperatura’ (en Fahrenheit), ‘Humedad’ (en %), ‘Viento’ (Sí/No) y ‘Número de jugadores’ (numérico , característica objetivo)
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# Create dataset
dataset_dict = {
'Outlook': ['sunny', 'sunny', 'overcast', 'rain', 'rain', 'rain', 'overcast', 'sunny', 'sunny', 'rain', 'sunny', 'overcast', 'overcast', 'rain', 'sunny', 'overcast', 'rain', 'sunny', 'sunny', 'rain', 'overcast', 'rain', 'sunny', 'overcast', 'sunny', 'overcast', 'rain', 'overcast'],
'Temp.': [85.0, 80.0, 83.0, 70.0, 68.0, 65.0, 64.0, 72.0, 69.0, 75.0, 75.0, 72.0, 81.0, 71.0, 81.0, 74.0, 76.0, 78.0, 82.0, 67.0, 85.0, 73.0, 88.0, 77.0, 79.0, 80.0, 66.0, 84.0],
'Humid.': [85.0, 90.0, 78.0, 96.0, 80.0, 70.0, 65.0, 95.0, 70.0, 80.0, 70.0, 90.0, 75.0, 80.0, 88.0, 92.0, 85.0, 75.0, 92.0, 90.0, 85.0, 88.0, 65.0, 70.0, 60.0, 95.0, 70.0, 78.0],
'Wind': [False, True, False, False, False, True, True, False, False, False, True, True, False, True, True, False, False, True, False, True, True, False, True, False, False, True, False, False],
'Num_Players': [52, 39, 43, 37, 28, 19, 43, 47, 56, 33, 49, 23, 42, 13, 33, 29, 25, 51, 41, 14, 34, 29, 49, 36, 57, 21, 23, 41]
}

df = pd.DataFrame(dataset_dict)

# One-hot encode 'Outlook' column
df = pd.get_dummies(df, columns=['Outlook'],prefix='',prefix_sep='')

# Convert 'Wind' column to binary
df['Wind'] = df['Wind'].astype(int)

# Split data into features and target, then into training and test sets
X, y = df.drop(columns='Num_Players'), df['Num_Players']
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

Si bien no es obligatorio, para utilizar eficazmente la regresión lineal (incluida la regresión de crestas) primero podemos estandarizar las características numéricas.

La escala estándar se aplica a «Temperatura» y «Humedad», mientras que la codificación one-hot se aplica a «Outlook» y «Viento».
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer

# Create dataset
data = {
'Outlook': ['sunny', 'sunny', 'overcast', 'rain', 'rain', 'rain', 'overcast', 'sunny', 'sunny',
'rain', 'sunny', 'overcast', 'overcast', 'rain', 'sunny', 'overcast', 'rain', 'sunny',
'sunny', 'rain', 'overcast', 'rain', 'sunny', 'overcast', 'sunny', 'overcast', 'rain', 'overcast'],
'Temperature': [85, 80, 83, 70, 68, 65, 64, 72, 69, 75, 75, 72, 81, 71, 81, 74, 76, 78, 82,
67, 85, 73, 88, 77, 79, 80, 66, 84],
'Humidity': [85, 90, 78, 96, 80, 70, 65, 95, 70, 80, 70, 90, 75, 80, 88, 92, 85, 75, 92,
90, 85, 88, 65, 70, 60, 95, 70, 78],
'Wind': [False, True, False, False, False, True, True, False, False, False, True, True, False,
True, True, False, False, True, False, True, True, False, True, False, False, True, False, False],
'Num_Players': [52, 39, 43, 37, 28, 19, 43, 47, 56, 33, 49, 23, 42, 13, 33, 29, 25, 51, 41,
14, 34, 29, 49, 36, 57, 21, 23, 41]
}

# Process data
df = pd.get_dummies(pd.DataFrame(data), columns=['Outlook'])
df['Wind'] = df['Wind'].astype(int)

# Split data
X, y = df.drop(columns='Num_Players'), df['Num_Players']
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Scale numerical features
numerical_cols = ['Temperature', 'Humidity']
ct = ColumnTransformer([('scaler', StandardScaler(), numerical_cols)], remainder='passthrough')

# Transform data
X_train_scaled = pd.DataFrame(
ct.fit_transform(X_train),
columns=numerical_cols + [col for col in X_train.columns if col not in numerical_cols],
index=X_train.index
)

X_test_scaled = pd.DataFrame(
ct.transform(X_test),
columns=X_train_scaled.columns,
index=X_test.index
)

La regresión lineal predice números haciendo una línea recta (o hiperplano) a partir de los datos:

  1. El modelo encuentra la mejor línea haciendo que las brechas entre los valores reales y los valores predichos de la línea sean lo más pequeñas posible. Esto se llama «mínimos cuadrados».
  2. Cada entrada obtiene un número (coeficiente/peso) que muestra cuánto cambia la respuesta final. También hay un número inicial (intersección/sesgo) que se usa cuando todas las entradas son cero.
  3. Para predecir una nueva respuesta, el modelo toma cada entrada, la multiplica por su número, la suma todas y suma el número inicial. Esto le da la respuesta prevista.

Comencemos con los mínimos cuadrados ordinarios (MCO), el enfoque fundamental de la regresión lineal. El objetivo de OLS es encontrar la línea que mejor se ajuste a través de nuestros puntos de datos. Hacemos esto midiendo qué tan «incorrectas» son nuestras predicciones en comparación con los valores reales y luego encontrando la línea que hace que estos errores sean lo más pequeños posible. Cuando decimos «error», nos referimos a la distancia vertical entre cada punto y nuestra línea; en otras palabras, qué tan lejos están nuestras predicciones de la realidad. Veamos primero qué pasó en el caso 2D.

En caso 2D

En el caso 2D, podemos imaginar el algoritmo de regresión lineal así:

Aquí está la explicación del proceso anterior:

1.Comenzamos con un conjunto de entrenamiento, donde cada fila tiene:
· incógnita : nuestra función de entrada (los números 1, 2, 3, 1, 2)
· y : nuestros valores objetivo (0, 1, 1, 2, 3)

2. Podemos trazar estos puntos en un diagrama de dispersión y queremos encontrar una línea. y = b₀ + bincógnita que mejor se ajuste a estos puntos

3. Para cualquier línea dada (cualquier b₀ y b₁), podemos medir qué tan bueno es mediante:
· Calcular la distancia vertical (d₁, d₂, d₃, d₄, d₅) desde cada punto hasta la recta
· Estas distancias son |y — (b₀ + bincógnita)| para cada punto

4. Nuestro objetivo de optimización es encontrar b₀ y b₁ que minimizan la suma de distancias al cuadrado: d₁² + d₂² + d₃² + d₄² + d₅². En notación vectorial, esto se escribe como ||y ||², donde incógnita = [1 x] contiene nuestros datos de entrada (con 1 para la intersección) y b = [ββ₁]ᵀ contiene nuestros coeficientes.

5. La solución óptima tiene forma cerrada: b = (incógnitaincógnita)⁻¹incógnitaᵀy. Calculando esto obtenemos b₀ = -0,196 (intersección), b₁ = 0,761 (pendiente).

Esta notación vectorial hace que la fórmula sea más compacta y muestra que en realidad estamos trabajando con matrices y vectores en lugar de puntos individuales. Veremos más detalles de nuestro cálculo a continuación en el caso multidimensional.

En caso multidimensional (📊 Conjunto de datos)

Nuevamente, el objetivo de MCO es encontrar coeficientes (b) que minimizan las diferencias al cuadrado entre nuestras predicciones y los valores reales. Matemáticamente, expresamos esto como minimizando ||y||², donde incógnita es nuestra matriz de datos y y contiene nuestros valores objetivo.

El proceso de formación sigue estos pasos clave:

Paso de entrenamiento

1. Prepare nuestra matriz de datos incógnita. Esto implica agregar una columna de unos para tener en cuenta el término de sesgo/intersección (b₀).

2. En lugar de buscar iterativamente los mejores coeficientes, podemos calcularlos directamente usando la ecuación normal:
b = (incógnitaincógnita)⁻¹incógnitay

dónde:
· b es el vector de coeficientes estimados,
· incógnita es la matriz del conjunto de datos (incluida una columna para la intersección),
· y es la etiqueta,
· incógnitaᵀ representa la transpuesta de la matriz incógnita,
· ⁻¹ representa la inversa de la matriz.

Analicemos esto:

a. multiplicamos incógnitaᵀ (incógnita transponer) por incógnitadándonos una matriz cuadrada

b. Calculamos la inversa de esta matriz.

do. calculamos incógnitay

d. Multiplicamos (incógnitaincógnita)⁻¹ y incógnitay para obtener nuestros coeficientes

Paso de prueba

Una vez que tenemos nuestros coeficientes, hacer predicciones es sencillo: simplemente multiplicamos nuestro nuevo punto de datos por estos coeficientes para obtener nuestra predicción.

En notación matricial, para un nuevo punto de datos incógnita*, la predicción y* se calcula como
y* = incógnita*b = [1, x₁, x₂, …, xₚ] × [β₀, β₁, β₂, …, βₚ]ᵀ,
dónde b₀ es la intersección y b₁ a través de bₚ son los coeficientes de cada característica.

Paso de evaluación

Podemos hacer el mismo proceso para todos los puntos de datos. Para nuestro conjunto de datos, aquí también está el resultado final con el RMSE.

Ahora, consideremos la regresión de crestas, que se basa en OLS y aborda algunas de sus limitaciones. La idea clave de la regresión de Ridge es que a veces la solución OLS óptima implica coeficientes muy grandeslo que puede provocar un sobreajuste.

Ridge Regression agrega un término de penalización (λ||b||²) a la función objetivo. Este término desalienta los coeficientes grandes al sumar sus valores al cuadrado a lo que estamos minimizando. El objetivo completo pasa a ser:

mín ||yincógnitaβ||² + λ||b||²

El λ El parámetro (lambda) controla cuánto penalizamos los coeficientes grandes. Cuando λ = 0, obtenemos MCO; como λ aumenta, los coeficientes se reducen hacia cero (pero nunca lo alcanzan).

Paso de entrenamiento

  1. Al igual que OLS, prepare nuestra matriz de datos incógnita. Esto implica agregar una columna de unos para tener en cuenta el término de intersección (b₀).
  2. El proceso de formación de Ridge sigue un patrón similar al de OLS, pero con una modificación. La solución de forma cerrada se convierte en:
    b = (incógnitaincógnita+ λI)⁻¹incógnitay

dónde:
· I es la matriz identidad (con el primer elemento, correspondiente a b₀, a veces establecido en 0 para excluir la intersección de la regularización en algunas implementaciones),
· λ es el valor de regularización.
· Y es el vector de valores observados de las variables dependientes.
· Otros símbolos permanecen como se definen en la sección OLS.

Analicemos esto:

a. agregamos λyo a incógnitaINCÓGNITA. el valor de λ puede ser cualquier número positivo (digamos 0,1).

b. Calculamos la inversa de esta matriz. Los beneficios de agregar λI a incógnitaincógnita antes de la inversión son:
· Hace que la matriz sea invertible, incluso si incógnitaincógnita no lo es (resolviendo un problema numérico clave con OLS)
· Reduce los coeficientes proporcionalmente a λ

do. Multiplicamos (incógnitaincógnita+ λyo)⁻¹ y incógnitay para obtener nuestros coeficientes

Paso de prueba

El proceso de predicción sigue siendo el mismo que el de MCO: multiplicar los nuevos puntos de datos por los coeficientes. La diferencia radica en los coeficientes mismos, que suelen ser más pequeños y más estables que sus homólogos MCO.

Paso de evaluación

Podemos hacer el mismo proceso para todos los puntos de datos. Para nuestro conjunto de datos, aquí también está el resultado final con el RMSE.

Comentarios finales: elegir entre OLS y Ridge

La elección entre OLS y Ridge a menudo depende de sus datos:

  • Utilice OLS cuando tenga datos que se comporten bien con poca multicolinealidad y suficientes muestras (en relación con las características)
  • Utilice Ridge cuando tenga:
    – Muchas características (en relación con las muestras)
    – Multicolinealidad en tus rasgos.
    – Signos de sobreajuste con OLS

Con Ridge, tendrás que elegir λ. Comience con un rango de valores (a menudo espaciados logarítmicamente) y elija el que proporcione el mejor rendimiento de validación.

Aparentemente, el valor predeterminado λ = 1 da el mejor RMSE para nuestro conjunto de datos.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.metrics import root_mean_squared_error
from sklearn.linear_model import Ridge

# Create dataset
data = {
'Outlook': ['sunny', 'sunny', 'overcast', 'rain', 'rain', 'rain', 'overcast', 'sunny', 'sunny',
'rain', 'sunny', 'overcast', 'overcast', 'rain', 'sunny', 'overcast', 'rain', 'sunny',
'sunny', 'rain', 'overcast', 'rain', 'sunny', 'overcast', 'sunny', 'overcast', 'rain', 'overcast'],
'Temperature': [85, 80, 83, 70, 68, 65, 64, 72, 69, 75, 75, 72, 81, 71, 81, 74, 76, 78, 82,
67, 85, 73, 88, 77, 79, 80, 66, 84],
'Humidity': [85, 90, 78, 96, 80, 70, 65, 95, 70, 80, 70, 90, 75, 80, 88, 92, 85, 75, 92,
90, 85, 88, 65, 70, 60, 95, 70, 78],
'Wind': [False, True, False, False, False, True, True, False, False, False, True, True, False,
True, True, False, False, True, False, True, True, False, True, False, False, True, False, False],
'Num_Players': [52, 39, 43, 37, 28, 19, 43, 47, 56, 33, 49, 23, 42, 13, 33, 29, 25, 51, 41,
14, 34, 29, 49, 36, 57, 21, 23, 41]
}

# Process data
df = pd.get_dummies(pd.DataFrame(data), columns=['Outlook'], prefix='', prefix_sep='', dtype=int)
df['Wind'] = df['Wind'].astype(int)
df = df[['sunny','overcast','rain','Temperature','Humidity','Wind','Num_Players']]

# Split data
X, y = df.drop(columns='Num_Players'), df['Num_Players']
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Scale numerical features
numerical_cols = ['Temperature', 'Humidity']
ct = ColumnTransformer([('scaler', StandardScaler(), numerical_cols)], remainder='passthrough')

# Transform data
X_train_scaled = pd.DataFrame(
ct.fit_transform(X_train),
columns=numerical_cols + [col for col in X_train.columns if col not in numerical_cols],
index=X_train.index
)

X_test_scaled = pd.DataFrame(
ct.transform(X_test),
columns=X_train_scaled.columns,
index=X_test.index
)

# Initialize and train the model
#model = LinearRegression() # Option 1: OLS Regression
model = Ridge(alpha=0.1) # Option 2: Ridge Regression (alpha is the regularization strength, equivalent to λ)

# Fit the model
model.fit(X_train_scaled, y_train)

# Make predictions
y_pred = model.predict(X_test_scaled)

# Calculate and print RMSE
rmse = root_mean_squared_error(y_test, y_pred)
print(f"RMSE: {rmse:.4f}")

# Additional information about the model
print("\nModel Coefficients:")
print(f"Intercept : {model.intercept_:.2f}")
for feature, coef in zip(X_train_scaled.columns, model.coef_):
print(f"{feature:13}: {coef:.2f}")