Preguntas de Entrevista para Ingenieros de Machine Learning Clásico
15 preguntas seleccionadas de entrevista sobre machine learning clásico, agrupadas por nivel de experiencia. Úsalas para repasar los fundamentos, las compensaciones prácticas y el razonamiento de producción a nivel senior.
1¿Cuál es la diferencia entre un parámetro del modelo y un hiperparámetro en el aprendizaje supervisado?
En el aprendizaje automático supervisado, los parámetros del modelo son variables internas que se aprenden directamente a partir de los datos de entrenamiento mediante un algoritmo de optimización (como el descenso de gradiente o las ecuaciones normales). Entre los ejemplos se incluyen los pesos y el sesgo (bias) de regresión en modelos lineales o los umbrales de división en árboles de decisión. Por el contrario, los hiperparámetros son ajustes de configuración externos especificados antes del entrenamiento que rigen el proceso de aprendizaje, la capacidad del modelo o la arquitectura. Normalmente se seleccionan fuera del procedimiento interno de ajuste de parámetros del modelo. Algunos pueden optimizarse con métodos basados en validación u otros métodos de bucle externo; la distinción no significa que sean matemáticamente imposibles de aprender. Minimizar únicamente el error de entrenamiento puede favorecer una capacidad excesiva y no estima la generalización. Entre los ejemplos se incluyen la tasa de aprendizaje, la fuerza de regularización (lambda/C), el número de árboles en un bosque y la profundidad máxima del árbol. Los hiperparámetros se ajustan mediante datos de validación o validación cruzada.
from sklearn.linear_model import Ridge
import numpy as np
X = np.array([[1.0], [2.0], [3.0]])
y = np.array([2.0, 4.0, 6.0])
# Hyperparameter: alpha (regularization strength set beforehand)
model = Ridge(alpha=1.0)
# Fitting optimizes internal parameters on training data
model.fit(X, y)
# Learned parameters
print(f"Weight (Parameter): {model.coef_[0]:.4f}")
print(f"Intercept (Parameter): {model.intercept_:.4f}")
2¿Qué supuestos hace la regresión lineal por mínimos cuadrados ordinarios y cómo revelarían los diagnósticos de residuos las violaciones de estos supuestos?
OLS minimiza la suma de los residuos al cuadrado; calcular un ajuste no requiere errores distribuidos normalmente. Para obtener un vector de coeficientes único, la matriz de diseño debe tener rango de columna completo, lo que excluye la dependencia lineal exacta en lugar de toda correlación entre predictores. Para la interpretación habitual de modelo lineal insesgado, se asume una media condicional correctamente especificada E[y|X] = X beta, lo que equivale a E[epsilon|X] = 0. Errores homocedásticos y no correlacionados proporcionan el resultado clásico de eficiencia de Gauss–Markov y la fórmula de covarianza estándar. La normalidad condicional respalda adicionalmente la inferencia t/F exacta en muestras finitas; métodos adecuados para muestras grandes o robustos pueden funcionar sin ella bajo sus propios supuestos. Los residuos ajustados son estimaciones de los errores y generalmente están correlacionados, incluso cuando los errores subyacentes son independientes. Graficar los residuos frente a los valores ajustados permite detectar curvatura y cambios en la varianza; frente al tiempo, dependencia; y usar un gráfico Q–Q permite observar desviaciones en la distribución. El apalancamiento (leverage) y la distancia de Cook señalan observaciones influyentes. Estos diagnósticos sugieren problemas, pero no pueden demostrar la exogeneidad ni descartar variables de confusión omitidas.
import numpy as np
import statsmodels.api as sm
np.random.seed(42)
X = np.linspace(1, 10, 50)
# Quadratic underlying pattern creates a linearity violation
y = 2 * X + 0.5 * (X ** 2) + np.random.normal(0, 2, 50)
X_with_const = sm.add_constant(X)
model = sm.OLS(y, X_with_const).fit()
residuals = model.resid
print(f"Mean Residual: {np.mean(residuals):.4f}")
print(f"Curvature in residuals indicates model misspecification.")
3¿Cómo modela la regresión logística la clasificación binaria y cuál es el papel de la función sigmoide?
La regresión logística modela la clasificación binaria estimando la probabilidad de clase posterior $P(Y=1|X)$. Para asegurar que las probabilidades predichas se mantengan acotadas dentro de $(0, 1)$, la regresión logística modela las log-odds (logit) de la clase positiva como una función lineal de las entradas: $\ln\left(\frac{p}{1-p}\right) = w^T x + b$. La función sigmoide (logística), $\sigma(z) = \frac{1}{1 + e^{-z}}$, sirve como la función de enlace que mapea cualquier puntuación lineal de valor real $z = w^T x + b \in (-\infty, +\infty)$ monótonamente a una probabilidad válida $p \in (0, 1)$. Las decisiones de clase discretas se toman aplicando un umbral de decisión $\tau$ (típicamente 0.5): $\hat{y} = 1$ si $P(Y=1|X) \ge \tau$, de lo contrario $0$. Debido a que $\sigma(z) = 0.5$ ocurre precisamente cuando $z = 0$, el límite de decisión en el espacio de características es el hiperplano lineal $w^T x + b = 0$, lo que convierte a la regresión logística estándar en un clasificador lineal.
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
w = np.array([1.5, -2.0])
b = 0.5
x = np.array([2.0, 1.0])
z = np.dot(w, x) + b
prob = sigmoid(z)
threshold = 0.5
pred = int(prob >= threshold)
print(f"Log-odds (z): {z:.2f}")
print(f"Probability: {prob:.4f}")
print(f"Class Prediction: {pred}")
4¿Qué es la regularización L2 y cómo cambia la regresión Ridge la función objetivo y las estimaciones de los coeficientes?
La regularización L2 (regresión Ridge) añade una penalización proporcional a la suma de los pesos al cuadrado a la función de pérdida de mínimos cuadrados ordinarios (OLS): $$\min_w \|y - Xw\|_2^2 + \lambda \|w\|_2^2$$ Analíticamente, Ridge modifica las ecuaciones normales añadiendo $\lambda I$ a la matriz de Gram antes de la inversión: $$w_{\text{ridge}} = (X^T X + \lambda I)^{-1} X^T y$$ Impactos clave en el objetivo y en las estimaciones de los coeficientes: 1. Contracción (shrinkage): los coeficientes se contraen hacia cero en proporción a la varianza y correlación de las características, lo que reduce la complejidad del modelo sin forzarlos a ser exactamente cero. 2. Multicolinealidad e invertibilidad: cuando las características son colineales o $p > N$, $X^T X$ es singular o está mal condicionada. Para $\lambda > 0$, añadir $\lambda I$ asegura que $(X^T X + \lambda I)$ sea estrictamente definida positiva e invertible, estabilizando las estimaciones de los parámetros. 3. Compensación sesgo-varianza: aumentar $\lambda$ introduce un sesgo intencional en las estimaciones de los coeficientes mientras reduce la varianza bajo el modelo habitual de diseño fijo; el beneficio predictivo neto depende del problema y de la fuerza de la penalización, por lo que debe seleccionarse mediante validación. 4. Requisito de escalado de características: dado que la penalización trata a todos los pesos por igual, una característica con una escala numérica mayor puede producir el mismo efecto con un coeficiente más pequeño y menos penalizado. La estandarización suele ser útil para que las penalizaciones sean comparables, pero es una elección de modelado más que un requisito matemático. Ajuste el escalado solo en los subconjuntos (folds) de entrenamiento y, por lo general, deje el intercepto sin penalizar.
import numpy as np
def ridge_regression(X, y, alpha):
X_std = (X - np.mean(X, axis=0)) / np.std(X, axis=0)
n_features = X_std.shape[1]
I = np.eye(n_features)
beta = np.linalg.inv(X_std.T @ X_std + alpha * I) @ X_std.T @ y
return beta
X = np.array([[1.0, 2.0], [2.0, 4.1], [3.0, 5.9], [4.0, 8.2]])
y = np.array([2.1, 4.0, 6.2, 8.1])
weights = ridge_regression(X, y, alpha=1.0)
print('Ridge Weights:', weights)
5¿Cómo un árbol de decisión particiona recursivamente el espacio de características y qué criterios se utilizan para elegir las divisiones de clasificación?
Un árbol de decisión particiona el espacio de características mediante un algoritmo codicioso, de arriba hacia abajo, llamado **particionamiento binario recursivo**. Comenzando en el nodo raíz con todos los datos de entrenamiento, el algoritmo busca en todas las características y posibles valores umbral para encontrar la única división alineada con los ejes ($X_j \le t$) que maximiza la reducción de impureza. El conjunto de datos se divide en dos nodos hijos, y este procedimiento se aplica recursivamente en cada nodo hijo hasta que se alcanza un criterio de detención (por ejemplo, profundidad máxima, número mínimo de muestras por hoja o nodos puros). Debido a que las divisiones evalúan una característica a la vez contra un umbral, los límites de decisión resultantes son hiperplanos ortogonales (regiones rectangulares alineadas con los ejes en el espacio de características).
Para evaluar y seleccionar la mejor división en los árboles de clasificación, se utilizan dos criterios principales de impureza:
1. **Impureza de Gini (utilizada en CART)**: Mide la probabilidad de que una muestra elegida aleatoriamente sea mal clasificada si se etiqueta aleatoriamente según la distribución de clases del nodo. Para $K$ clases con proporciones $p_k$: $$I_G = 1 - \sum_{k=1}^K p_k^2$$
2. **Entropía y Ganancia de Información (utilizadas en ID3, C4.5)**: La entropía mide la incertidumbre en un nodo: $H = -\sum_{k=1}^K p_k \log_2(p_k)$. La división se elige para maximizar la **Ganancia de Información**, que es la entropía del nodo padre menos la entropía promedio ponderada de los nodos hijos: $$IG = H(\text{padre}) - \sum_{c \in \{\text{izquierda, derecha}\}} \frac{N_c}{N} H(c)$$
Ambas métricas alcanzan 0 cuando un nodo es completamente puro (todas las muestras pertenecen a una sola clase) y alcanzan su máximo cuando las clases están igualmente distribuidas.
6¿Qué es k-nearest neighbors (kNN) y cómo realiza predicciones para clasificación y regresión?
k-Nearest Neighbors (kNN) es un algoritmo de aprendizaje supervisado no paramétrico, basado en instancias (o 'perezoso'). No entrena un modelo paramétrico explícito; en su lugar, almacena el conjunto de datos de entrenamiento y realiza todos los cálculos durante la inferencia. Flujo de trabajo de predicción: 1. Cálculo de la distancia: Cuando se evalúa una instancia de consulta, el algoritmo calcula su distancia a todas las instancias de entrenamiento almacenadas utilizando una métrica específica (como la distancia euclidiana, de Manhattan o de Minkowski). 2. Selección de vecinos: Selecciona las $k$ instancias de entrenamiento con las distancias más pequeñas a la instancia de consulta. 3. Agregación: - Clasificación: Asigna la clase mediante voto mayoritario (moda) entre los $k$ vecinos (o voto ponderado por la distancia). - Regresión: Predice el objetivo continuo tomando el promedio local (media o mediana) de los valores objetivo de los $k$ vecinos (o promedio ponderado por la distancia). Debido a que los cálculos de distancia dependen directamente de las escalas de las características, la normalización o estandarización de características es esencial para evitar que las características de gran magnitud dominen los cálculos de distancia.
7Exponga el supuesto de independencia condicional de Naive Bayes y explique por qué Naive Bayes puede seguir funcionando bien cuando se viola.
El supuesto de independencia condicional de Naive Bayes establece que, dada la etiqueta de clase Y = y, todas las características X_1, X_2, ..., X_d son mutuamente independientes: P(X_1, ..., X_d | Y = y) = \prod_{j=1}^d P(X_j | Y = y). Usando el teorema de Bayes, la probabilidad posterior es: P(Y = y | X) \propto P(Y = y) \prod_{j=1}^d P(X_j | Y = y), donde P(Y = y) es la probabilidad a priori de la clase y P(X_j | Y = y) es la verosimilitud condicional de la clase (por ejemplo, Gaussiana para características continuas, Multinomial para recuentos). Naive Bayes a menudo funciona bien en la práctica a pesar de las violaciones de independencia porque la clasificación se basa en la regla de decisión argmax (argmax_y P(Y=y | X)) en lugar de una calibración precisa de la probabilidad. Incluso si las correlaciones de características hacen que las probabilidades predichas se vuelvan demasiado confiadas o distorsionadas, la clase correcta a menudo conserva la clasificación relativa más alta. Siempre y cuando la correlación no invierta la clasificación de las verosimilitudes de clase, la decisión de clasificación 0-1 sigue siendo precisa.
from sklearn.naive_bayes import GaussianNB
import numpy as np
X = np.array([[1.0, 1.1], [1.2, 0.9], [-1.0, -1.2], [-0.8, -1.1]])
y = np.array([1, 1, 0, 0])
model = GaussianNB()
model.fit(X, y)
# Prediction uses argmax over class posterior scores
print("Predicted class:", model.predict([[1.1, 1.0]]))
8Derivar o explicar la solución de forma cerrada de los Mínimos Cuadrados Ordinarios (OLS) y establecer cuándo existe de forma única.
El objetivo de los Mínimos Cuadrados Ordinarios (OLS) minimiza la suma de los cuadrados residuales: $S(\beta) = \|y - X\beta\|^2 = (y - X\beta)^T (y - X\beta) = y^T y - 2\beta^T X^T y + \beta^T X^T X \beta$. Igualando el gradiente con respecto a $\beta$ a cero: $$\nabla_\beta S(\beta) = -2 X^T y + 2 X^T X \beta = 0 \implies X^T X \beta = X^T y$$ Estas son las ecuaciones normales. Cuando $X^T X$ no es singular (invertible), la solución de forma cerrada única es: $$\hat{\beta} = (X^T X)^{-1} X^T y$$ Geométricamente, $\hat{y} = X\hat{\beta} = X(X^T X)^{-1} X^T y = H y$ representa la proyección ortogonal del vector objetivo $y$ sobre el espacio de columnas de la matriz de diseño $X$, donde $H$ es la matriz de proyección (hat). La solución existe de forma única si y solo si $X^T X$ es invertible, lo que requiere que la matriz de diseño $N \times P$, $X$, tenga rango de columna completo ($Rank(X) = P$). Esto requiere $N \ge P$ y que no haya multicolinealidad exacta (ninguna característica es una combinación lineal de otras). Si $X$ es de rango deficiente, $X^T X$ es singular, lo que lleva a infinitas soluciones, a menudo abordadas mediante regularización o la pseudoinversa de Moore-Penrose $X^+ y$.
import numpy as np
# Design matrix X (with intercept column) and target y
X = np.array([[1, 1], [1, 2], [1, 3], [1, 4]])
y = np.array([2.1, 3.9, 6.2, 8.0])
# Normal equations: (X^T X)^(-1) X^T y
beta_hat = np.linalg.inv(X.T @ X) @ X.T @ y
H = X @ np.linalg.inv(X.T @ X) @ X.T
y_hat = H @ y
print(f"Beta: {beta_hat}")
print(f"Predictions: {y_hat}")
9¿Qué es la estimación de máxima verosimilitud, y cómo conduce a la función objetivo de entropía cruzada de la regresión logística?
La Estimación de Máxima Verosimilitud (MLE) es un método para estimar los parámetros del modelo $\theta$ eligiendo valores que maximicen la verosimilitud $L(\theta) = P(\mathcal{D}|\theta)$ del conjunto de datos observado. En la regresión logística binaria, cada etiqueta $y_i \in \{0, 1\}$ se modela como una variable aleatoria de Bernoulli independiente condicionada a $x_i$, con una probabilidad de éxito $p_i = \sigma(w^T x_i + b)$. La función de masa de probabilidad para la observación $i$ es $P(y_i|x_i) = p_i^{y_i} (1 - p_i)^{1 - y_i}$. Asumiendo muestras i.i.d., la verosimilitud conjunta es: $$L(w, b) = \prod_{i=1}^N p_i^{y_i} (1 - p_i)^{1 - y_i}$$ Tomar el logaritmo natural convierte el producto en una suma de verosimilitudes logarítmicas computacionalmente manejable: $$\ell(w, b) = \sum_{i=1}^N \left[ y_i \ln(p_i) + (1 - y_i) \ln(1 - p_i) \right]$$ Dado que los algoritmos de optimización se plantean normalmente como problemas de minimización, negamos la verosimilitud logarítmica y normalizamos por el tamaño de la muestra $N$, obteniendo la Verosimilitud Logarítmica Negativa (NLL), que es exactamente la función objetivo de Entropía Cruzada Binaria (pérdida logarítmica): $$J(w, b) = -\frac{1}{N} \sum_{i=1}^N \left[ y_i \ln(p_i) + (1 - y_i) \ln(1 - p_i) \right]$$ Este objetivo es convexo con respecto a los logits/pesos lineales, por lo que los solucionadores numéricos apropiados optimizan un objetivo global. La convexidad estricta y una MLE único finito requieren condiciones adicionales como un rango de características suficiente, regularización y ninguna separación de clases perfecta.
10¿Cómo optimiza el descenso de gradiente un objetivo de aprendizaje automático (ML) clásico y cómo afectan la tasa de aprendizaje, la convergencia y la convexidad al entrenamiento?
El descenso de gradiente minimiza una función de pérdida empírica actualizando iterativamente los parámetros del modelo en la dirección opuesta al gradiente de la función objetivo con respecto a esos parámetros: $\theta_{t+1} = \theta_t - \eta \nabla L(\theta_t)$. Los factores clave que influyen en el entrenamiento incluyen: 1. **Tasa de Aprendizaje ($\eta$):** Controla el tamaño del paso. Si se establece demasiado pequeña, la convergencia es excesivamente lenta y el entrenamiento puede estancarse. Si se establece demasiado grande, las actualizaciones sobrepasarán el mínimo, causando oscilación o divergencia numérica. 2. **Convergencia:** Se determina monitoreando criterios de parada como una pequeña norma del gradiente ($||\nabla L(\theta)|| \le \epsilon$), un cambio mínimo de parámetros o una estabilización de la pérdida en iteraciones consecutivas. 3. **Convexidad:** En objetivos convexos (por ejemplo, regresión lineal de mínimos cuadrados ordinarios (OLS) estándar o regresión logística), cualquier mínimo local está garantizado para ser un mínimo global, permitiendo que el descenso de gradiente converja de forma fiable con tamaños de paso apropiados. En objetivos no convexos (por ejemplo, redes neuronales multicapa), el paisaje de pérdida contiene múltiples mínimos locales, puntos de silla y mesetas, lo que hace que la solución final sea sensible a la inicialización. 4. **Optimización vs. Generalización:** La convergencia en la pérdida de entrenamiento refleja el éxito de la optimización, mientras que la pérdida de validación evalúa la generalización. Alcanzar una pérdida de entrenamiento baja con un error de validación alto indica sobreajuste (overfitting) en lugar de un fallo de optimización.
import numpy as np
def gradient_descent(X, y, lr=0.01, max_iters=1000, tol=1e-6):
n_samples, n_features = X.shape
theta = np.zeros(n_features)
prev_loss = float('inf')
for i in range(max_iters):
predictions = X @ theta
error = predictions - y
loss = (1 / (2 * n_samples)) * np.dot(error, error)
if abs(prev_loss - loss) < tol:
print(f'Converged at iteration {i}')
break
prev_loss = loss
grad = (1 / n_samples) * (X.T @ error)
theta -= lr * grad
return theta
11Compare la regularización L1, L2 y ElasticNet en términos de dispersión, características correlacionadas y selección práctica de modelos.
La regularización L1 (Lasso), L2 (Ridge) y ElasticNet difieren en la formulación de la penalización, la geometría de la restricción, la dispersión y el manejo de predictores correlacionados:
1. **Dispersión y Geometría:**
- L1 utiliza una penalización de valor absoluto ($\lambda \|w\|_1$). Su límite de restricción es un diamante/politopo con vértices agudos en los ejes de coordenadas. Cuando los contornos de pérdida se intersecan con estas esquinas, los pesos se reducen a cero exacto, realizando una selección automática de características.
- L2 utiliza una penalización de norma euclidiana al cuadrado ($\lambda \|w\|_2^2$). Su límite de restricción es una hiperesfera suave sin esquinas, que encoge los pesos hacia cero asintóticamente pero rara vez los establece a cero exacto.
2. **Características Correlacionadas:**
- Bajo una fuerte colinealidad, L1 tiende a elegir arbitrariamente una característica de un grupo de predictores correlacionados y establece los coeficientes restantes a cero, lo que resulta en estimaciones inestables a través de las remuestras.
- L2 retiene todas las características correlacionadas, distribuyendo los pesos entre ellas y encogiéndolas conjuntamente.
3. **ElasticNet:**
- Combina ambas penalizaciones: $\lambda_1 \|w\|_1 + \lambda_2 \|w\|_2^2$ (a menudo parametrizado con $\alpha$ y $l_1\_\text{ratio}$).
- Ofrece la dispersión y selección de características de Lasso mientras preserva el efecto de agrupamiento de Ridge, seleccionando clústeres de predictores correlacionados conjuntamente. Es especialmente útil cuando $p > N$ o bajo una multicolinealidad severa.
12¿Cuál es la diferencia, a alto nivel, entre la regresión Ridge, la Regresión de Componentes Principales y los Mínimos Cuadrados Parciales?
La Regresión Ridge, la Regresión de Componentes Principales (PCR) y los Mínimos Cuadrados Parciales (PLS) son tres técnicas lineales utilizadas para manejar la multicolinealidad y la alta dimensionalidad, pero difieren en cómo reducen la varianza y si la reducción es continua o supervisada:
1. **Regresión Ridge**: Retiene todas las $p$ características originales y aplica una contracción continua a las magnitudes de los coeficientes mediante una penalización L2. No construye componentes latentes de menor dimensión ni descarta dimensiones de características; más bien, encoge la varianza a lo largo de las direcciones de autovalor bajo de $X^T X$.
2. **Regresión de Componentes Principales (PCR)**: Un método de reducción de dimensionalidad no supervisado de dos pasos. Primero aplica el Análisis de Componentes Principales (PCA) estrictamente a la matriz de predictores $X$ para encontrar direcciones ortogonales de varianza máxima, mantiene los $k$ componentes principales superiores y ajusta una regresión OLS (Mínimos Cuadrados Ordinarios) sobre esos $k$ componentes. Dado que PCA ignora la variable objetivo $y$, PCR corre el riesgo de descartar componentes que tienen baja varianza en $X$ pero un alto poder predictivo para $y$.
3. **Mínimos Cuadrados Parciales (PLS)**: Un método de reducción de dimensionalidad supervisado. Construye $k$ componentes latentes ortogonales al encontrar combinaciones lineales de $X$ que maximizan la covarianza entre $X$ y la respuesta $y$. Al incorporar explícitamente información del objetivo, PLS identifica componentes que explican tanto la varianza de las características como la variación de la respuesta.
from sklearn.linear_model import Ridge, LinearRegression
from sklearn.decomposition import PCA
from sklearn.cross_decomposition import PLSRegression
from sklearn.pipeline import make_pipeline
# 1. Ridge: Regularized full feature space
ridge = Ridge(alpha=1.0)
# 2. PCR: Unsupervised PCA followed by OLS
pcr = make_pipeline(PCA(n_components=2), LinearRegression())
# 3. PLS: Supervised latent component projection and regression
pls = PLSRegression(n_components=2)
13¿Cómo optimizan el entrenamiento o manejan de manera diferente las características tabulares las implementaciones modernas de gradient boosting como XGBoost, LightGBM y CatBoost?
Los frameworks modernos de Gradient Boosting Decision Trees (GBDT) difieren sustancialmente en sus algoritmos de búsqueda de divisiones, estrategias de crecimiento de árboles y manejo de características tabulares/categóricas:
1. **XGBoost**: Tradicionalmente se basa en la búsqueda de divisiones exacta codiciosa (greedy) o de boceto de cuantiles aproximado (y más tarde Fast Hist), utiliza un crecimiento de árbol por niveles (level-wise o depth-wise) y maneja los valores faltantes aprendiendo una dirección de rama predeterminada óptima durante la búsqueda de divisiones.
2. **LightGBM**: Utiliza la búsqueda de divisiones basada en histogramas (agrupando características continuas en cubos discretos, típicamente 256), un crecimiento de árbol por hojas (leaf-wise o best-first) para una reducción más rápida de la pérdida, Gradient-based One-Side Sampling (GOSS) para mantener instancias con gradientes grandes mientras se submuestrean las de gradientes pequeños, y Exclusive Feature Bundling (EFB) para fusionar características dispersas mutuamente excluyentes. Para las variables categóricas, encuentra divisiones óptimas ordenando los bins del histograma categórico ($O(K \log K)$).
3. **CatBoost**: Utiliza árboles de decisión 'oblivious' (simétricos) donde todos los nodos a una profundidad dada comparten exactamente la misma división, lo que permite una puntuación vectorizada rápida en CPU/GPU. Su principal innovación son las Estadísticas de Objetivo Ordenadas (Ordered Target Statistics) y el 'boosting' ordenado, que calcula las estadísticas de objetivo sobre permutaciones aleatorias de los datos de entrenamiento para evitar la fuga de objetivo (target leakage) y el desplazamiento de predicción (prediction shift).
14¿Cómo decidiría si una función de pérdida personalizada es apropiada para un modelo de *gradient boosting* bajo costos empresariales asimétricos?
Decidir si implementar una función de pérdida personalizada en el *gradient boosting* bajo costos empresariales asimétricos requiere evaluar si la asimetría puede ser manejada *downstream* mediante la calibración de probabilidad y el ajuste de umbrales, o si altera fundamentalmente el panorama de optimización durante la inducción del árbol:
1. **Ajuste de Umbral vs. Pérdida Personalizada:** Para tareas de clasificación con costos de error asimétricos (p. ej., falsos negativos que cuestan `10×` más que los falsos positivos), la *cross-entropy* estándar es una regla de puntuación adecuada que tiene como objetivo estimar las probabilidades posteriores `P(y=1|x)`. Sin embargo, la calibración debe verificarse y, si es necesario, corregirse en los datos de validación. Mover el umbral de decisión de clasificación basado en la matriz de costos empresariales `$\tau = \frac{C_{FP}}{C_{FP} + C_{FN}}$` o aplicar pesos de muestra suele ser más limpio y evita derivadas personalizadas. No obstante, para regresión asimétrica (p. ej., pérdida *pinball* asimétrica para la demanda de inventario) o penalizaciones empresariales no lineales donde los objetivos estándar no pueden guiar la búsqueda de divisiones, se justifica una función de pérdida personalizada.
2. **Requisitos Matemáticos para GBDT (Gradient Boosting Decision Trees):** En los *boosters* de segundo orden (XGBoost, LightGBM), una función de pérdida personalizada `L(y, \hat{y})` normalmente necesita gradientes de primer orden calculables (`$g_i = \partial L / \partial \hat{y}_i$`) y valores de curvatura/Hessianos de segundo orden válidos (`$h_i = \partial^2 L / \partial \hat{y}_i^2$`) para el cálculo de la ganancia de división y los pesos de las hojas (`$w^* = -\sum g_i / (\sum h_i + \lambda)$`). Los Hessianos deben ser no negativos o aproximarse/recortarse de forma segura para la estabilidad numérica; algunas implementaciones soportan objetivos de primer orden o aproximados, por lo que el requisito es específico del *framework*. Las métricas de negocio no diferenciables o discontinuas deben reemplazarse con aproximaciones *surrogate* suaves (p. ej., variantes Huberizadas o *log-cosh*).
import numpy as np
import xgboost as xgb
def asymmetric_mse_objective(preds, dtrain):
labels = dtrain.get_label()
residual = preds - labels
# Penalize underestimation (residual < 0) 5x more heavily than overestimation
penalty = np.where(residual < 0, 5.0, 1.0)
grad = 2.0 * penalty * residual
hess = 2.0 * penalty
return grad, hess
# Usage:
# model = xgb.train(params, dtrain, obj=asymmetric_mse_objective)
15¿Qué es LambdaMART y cómo adapta el gradient boosting para objetivos de learning-to-rank?
LambdaMART combina árboles de regresión con gradient boosting con las actualizaciones por pares ponderadas por métricas de LambdaRank. Para los documentos i y j dentro de la misma consulta donde i es más relevante, utilice la pérdida logística por pares log(1 + exp(-sigma * (s_i - s_j))). Sea a_ij = sigma * abs(Delta NDCG_ij) / (1 + exp(sigma * (s_i - s_j))). Bajo una convención de gradiente negativo, este par aporta +a_ij al documento i y -a_ij al documento j, empujando el elemento preferido hacia arriba. Sume estas contribuciones con signo sobre los pares seleccionados para cada documento y luego ajuste las actualizaciones de boosting, a menudo utilizando estimaciones de curvatura correspondientes para los valores de las hojas. Delta NDCG mide el cambio en la métrica resultante de intercambiar sus posiciones actuales de ranking. Esto genera una señal sustituta alineada con la calidad del ranking; no es una derivada ordinaria de la función discreta NDCG y no garantiza un óptimo global de la métrica. Mantenga los grupos de consultas intactos en el entrenamiento y la evaluación; el muestreo de pares, el truncamiento de métricas y los casos con ganancia cero dependen de la implementación.
import lightgbm as lgb
import numpy as np
# Simulated query-grouped data: 2 queries with 3 docs each
X = np.random.randn(6, 10)
y = np.array([3, 1, 0, 2, 0, 1]) # Relevance grades (0-3)
group = [3, 3] # Query group sizes
train_data = lgb.Dataset(X, label=y, group=group)
params = {
'objective': 'lambdarank',
'metric': 'ndcg',
'ndcg_eval_at': [1, 3],
'learning_rate': 0.1,
'n_estimators': 50
}
ranker = lgb.train(params, train_data)