Material de consulta: se mira cuando hace falta
Dpto. de Fundamentos del Análisis Económico. Universidad de Alicante
Lo que hay aquí amplía el Tema 05: intervalos por fórmula, funciones que hacen el bootstrap y la validación cruzada sin bucle, tablas de resultados, criterios para comparar modelos sin partir la muestra, más métricas de clasificación, el logit con más de dos clases, y la discusión larga de predicción frente a causalidad
Se consulta cuando hace falta en un trabajo; en clase no se ve
confint()qnorm) o de la t de Student (qt, que es lo que usa confint()):summary(modelo)$sigma^2, \(n\) = nobs(modelo) y \(k\) el número de coeficientes:renta 0,380 a 0,606 por fórmula, 0,370 a 0,604 por bootstrap. Las dos cosas miden lo mismo; el bootstrap no necesita el supuestopredict() puede dar, además del valor esperado, dos intervalos distintos:Confianza ("confidence"): dónde está el gasto medio de todos los clientes con esas características; solo recoge la incertidumbre de los coeficientes
Predicción ("prediction"): dónde caerá el gasto de un cliente concreto; añade la varianza de \(u\), y por eso es mucho más ancho. Es el que responde a “cuánto gastará este cliente”
rsample::bootstraps() y boot::boot()map_dbl() (purrr, dentro de tidyverse) aplica la misma función a cada elemento de una lista y devuelve un vector: el bucle for en una línearsample también parte la muestra (initial_split()) y crea los bloques de la validación cruzada (vfold_cv())K bloques (la del tema): K = 5 o 10. Cada observación hace de prueba una vez
Dejar uno fuera (leave-one-out, LOOCV): K = \(n\). Se estima \(n\) veces con \(n - 1\) observaciones y se evalúa en la que falta. Sin azar, pero caro, y con mucha varianza entre iteraciones
Particiones aleatorias repetidas: se repite muchas veces la partición entrenamiento/prueba con reemplazamiento del sorteo; una observación puede caer varias veces en prueba
Validación cruzada repetida: K bloques, varias veces con distintas semillas, y se promedia todo. Es lo más estable
Con rsample:
Se divide la muestra al azar en K bloques. Uno hace de prueba y los K-1 restantes de entrenamiento, en K iteraciones
Evita depender de una partición concreta y usa todas las observaciones para estimar y para evaluar, aunque nunca a la vez
set.seed(12345678)
bloque <- sample(rep(1:5,
length.out = nrow(tienda)))
errores <- numeric(5)
for (k in 1:5) {
entr <- tienda[bloque != k, ]
prue <- tienda[bloque == k, ]
m <- lm(ventas ~ poly(edad, 3),
data = entr)
pred <- predict(m, prue)
e <- prue$ventas - pred
errores[k] <- mean(e^2)
}
mean(errores)¿Por qué renunciar a parte de los datos? Evaluar bien el modelo importa más que un tamaño muestral algo mayor
La estimación del error en prueba puede ser volátil, según las observaciones que caigan en cada grupo
Al aumentar la flexibilidad, el MSE baja siempre en entrenamiento y forma una U en prueba
El MSE en entrenamiento suele ser menor que en prueba
\[ \small E\left[\left(y-\hat{f}(x)\right)^2\right] = \underbrace{\left[E\left(\hat{f}(x)\right)-f(x)\right]^2}_{\text{sesgo}^2} + \underbrace{E\left(\left[\hat{f}(x)-E\left(\hat{f}(x)\right)\right]^2\right)}_{\text{varianza}} + \text{Var}(u) \]
Sesgo: error por supuestos erróneos sobre \(f\). Se pierden relaciones relevantes entre \(X\) e \(Y\) (underfit)
Varianza: sensibilidad a las fluctuaciones de la muestra de entrenamiento. Si el modelo aprende puro ruido, ajusta bien allí y predice mal casos nuevos (overfit)
Es fácil construir un modelo con poco sesgo y mucha varianza, y al revés. El desafío es encontrar una flexibilidad con los dos bajos
Grado 1: las 50 rectas caen casi en el mismo sitio y todas lejos de la curva: sesgo. Grado 2: abrazan la curva. Grado 12: cada muestra da una curva distinta: varianza
Con la tienda, 200 remuestras bootstrap y la predicción para un cliente de 65 años:
| Grado | Predicción media | Desviación típica entre remuestras |
|---|---|---|
| 1 | 3.993 | 110 |
| 2 | 3.380 | 107 |
| 5 | 3.424 | 136 |
| 12 | 3.105 | 164 |
tidy() (paquete broom) convierte la salida de lm() en una tabla, que se puede manipular y presentar con kable(). La celda necesita #| results: markupmodelsummary() pone varios modelos en columnas, con estrellas de significatividad y las medidas de ajuste que se pidan:library(modelsummary)
modelos <- list(
"Lineal" = lm(ventas ~ renta + descuento + zona, data = tienda),
"Logaritmo" = lm(ventas ~ log(renta) + descuento + zona, data = tienda),
"Parábola" = lm(ventas ~ renta + descuento + zona +
edad + I(edad^2), data = tienda),
"Interacción" = lm(ventas ~ renta * mujer + descuento + zona, data = tienda)
)
modelsummary(modelos, stars = TRUE,
gof_map = c("nobs", "r.squared", "adj.r.squared", "rmse"))El \(R^2\) sube siempre al añadir variables. Tres criterios lo penalizan por el número de coeficientes \(k\):
\(R^2\) ajustado: \(\bar{R}^2 = 1 - \dfrac{(1 - R^2)(n - 1)}{n - k - 1}\). Baja si la variable añadida aporta menos que un coeficiente al azar
AIC y BIC: \(-2 \log L + 2k\) y \(-2 \log L + k \log n\). Menor es mejor; BIC penaliza más y elige modelos más pequeños
Sirven para comparar modelos de la misma \(y\) en los mismos datos. Son aproximaciones a lo que mide la validación cruzada; en el curso se elige con datos de prueba, que es lo que vale para cualquier modelo (también los de T07 y T08)
Significatividad individual con varios términos de la misma variable (polinomio, tramos) engaña: los términos están correlacionados. Se contrasta el grupo entero (test F, anova(modelo_chico, modelo_grande))
summary() supone varianza constante de \(u\). Si varía con las \(X\) (heterocedasticidad, lo habitual con gasto o renta), los coeficientes siguen bien y los errores estándar no. Se corrigen con errores estándar robustos:El bootstrap de filas del tema también es robusto a esto
A menudo se proponen “pruebas” de los supuestos del modelo lineal (normalidad, linealidad, colinealidad, heterocedasticidad). En este curso se tratan así:
No linealidad: se modeliza (Parte III del tema), no se contrasta
No normalidad: innecesaria con \(n\) grande o con bootstrap
Colinealidad: dos variables que miden casi lo mismo; se quita una o se acepta el error estándar grande
Heterocedasticidad: errores estándar robustos
| Métrica | Fórmula | Qué responde |
|---|---|---|
| Exactitud | \((VP + VN) / n\) | aciertos totales; engaña con clases desequilibradas |
| Sensibilidad (recall) | \(VP / (VP + FN)\) | de los positivos reales, cuántos detecto |
| Especificidad | \(VN / (VN + FP)\) | de los negativos reales, cuántos descarto |
| Precisión | \(VP / (VP + FP)\) | de los marcados como positivos, cuántos lo son |
| Exactitud equilibrada | (sens. + espec.) / 2 | exactitud sin premiar a la clase mayoritaria |
| \(F_\beta\) | \((1 + \beta^2)\, \text{prec} \cdot \text{sens} / (\beta^2\, \text{prec} + \text{sens})\) | \(\beta = 1\): media armónica; \(\beta > 1\) pesa más la sensibilidad |
| Kappa | exactitud corregida por el acierto esperado al azar | parecido a la exactitud equilibrada |
yardstick (Tema 07): precision(), f_meas(), kap(), bal_accuracy()library(yardstick)
logit <- glm(descuento ~ renta + edad + zona,
data = tienda, family = "binomial")
datos <- tienda |>
mutate(prob = predict(logit, type = "response"),
descuento = factor(descuento, levels = c(1, 0)))
pr_curve(datos, truth = descuento, prob)
pr_auc(datos, truth = descuento, prob)
roc_curve(datos, truth = descuento, prob)
roc_auc(datos, truth = descuento, prob)Otras funciones de pérdida que no fijan umbral: la log-loss (menos la log-verosimilitud media), que penaliza dar probabilidad alta a la clase equivocada, y la curva de ganancia, que ordena por probabilidad y dice qué fracción de positivos se captura contactando al x% con mayor probabilidad
Con más de dos clases se calcula una ROC por clase (esa clase frente a todas las demás) y se promedian, con o sin ponderar por el tamaño de cada clase (roc_aunu(), roc_aunp())
Reducir el umbral clasifica más observaciones como positivas, verdaderas y falsas: nos movemos hacia arriba y a la derecha
Por debajo de la diagonal, el clasificador predice más positivos entre los negativos que entre los positivos
\[ \small L(\beta) = \prod_{i:\, y_i = 1} p(x_i) \prod_{i:\, y_i = 0} \left(1 - p(x_i)\right), \qquad p(x) = \Lambda(\beta_0 + \beta_1 x_1 + \ldots) \]
La probabilidad relativa (odds) es \(\dfrac{p}{1 - p} = e^{\beta_0 + \beta_1 x_1 + \ldots}\), así que el log-odds es lineal: \(\beta_j\) es el cambio en el logaritmo de la probabilidad relativa por una unidad de \(x_j\), y \(e^{\beta_j}\) el factor por el que se multiplica la odds
El efecto sobre la probabilidad depende del punto: \(\partial p / \partial x_j = \beta_j\, p\, (1 - p)\). Máximo en \(p = 0{,}5\) y casi nulo en los extremos. Un resumen habitual es el efecto medio sobre los clientes de la muestra:
\[ \small \Pr(Y = c \mid X) = \frac{e^{\beta_{0c} + \beta_{1c} x_1 + \ldots}}{\sum_{l = 1}^{C} e^{\beta_{0l} + \beta_{1l} x_1 + \ldots}} \]
nnet::multinom() con fórmula; glmnet con matrices (es lo que usa el Tema 06 para regularizar):library(nnet)
multinom(zona ~ renta + edad, data = tienda)
library(glmnet)
x <- model.matrix(zona ~ renta + edad, data = tienda)[, -1]
mod <- glmnet(x, tienda$zona, family = "multinomial", lambda = 0)
predict(mod, newx = x, type = "response") # una probabilidad por clase
predict(mod, newx = x, type = "class") # la clase más probableEstos modelos informan de la relación entre los regresores y la variable dependiente. Correlación no implica causalidad, salvo en ensayos aleatorios controlados o pruebas A/B
La selección de variables es importante, porque evita sesgos y afecta a la variabilidad:
| cliente | descuento | gasto con descuento | gasto sin descuento | efecto |
|---|---|---|---|---|
| 1 | 1 | 4.284 | ? | ? |
| 2 | 0 | ? | 3.773 | ? |
lm(ventas ~ descuento), y responde mal a la pregunta 2lm(ventas ~ descuento + renta) da +320 euroslm(ventas ~ descuento) lo estima bien\[ \small \beta_1 + \beta_2 \cdot \delta, \qquad \text{donde } \delta \text{ es la pendiente de } z \text{ sobre } x \]
El signo del sesgo es el producto de los signos: efecto de \(z\) sobre \(y\) (\(\beta_2\)) por relación entre \(z\) y \(x\) (\(\delta\))
El caso del tema: \(x\) = descuento, \(z\) = renta. La renta sube el gasto (\(\beta_2 > 0\)) y el descuento fue a rentas bajas (\(\delta < 0\)): sesgo negativo, y el +500 se queda en -97 al omitir la renta
Lo mismo con el modelo completo: si la tienda eligió además por algo que no está en la tabla y que se relaciona con el gasto, el coeficiente sigue sesgado. Con datos observacionales nunca se sabe que no queda nada fuera
La única forma de que \(\delta = 0\) para todas las variables, observadas o no, es que \(x\) se asigne al azar: ensayo aleatorio controlado. En empresa, prueba A/B: la mitad de los clientes (al azar) recibe el descuento, la otra mitad no, y se compara el gasto
Con asignación al azar, lm(ventas ~ descuento) sí estima el efecto: los dos grupos son iguales en todo lo demás, en promedio
Lo que puede fallar incluso así: que los clientes no usen el descuento (incumplimiento), que se vayan antes de medir (desgaste), que el descuento de unos afecte a otros (interferencia)
Sin experimento hay métodos para aproximarse (diferencias en diferencias, variables instrumentales, discontinuidades) que son materia de Econometría. En este curso la regla es la del tema: un coeficiente predictivo no dice qué pasaría si cambiamos la variable
discount.csv (página Datos): ventas y porcentaje medio de descuento de 404 clientes, con su rentaLa misma estructura que en la tienda: los descuentos mayores fueron a rentas bajas. Separando por renta, la pendiente cambia de signo
Es un ejercicio de cinco minutos para comprobar que se ha entendido la regla del signo