Mi problema: hace poco conocí a un estadístico que me informó de que los splines son sólo útiles para la exploración de datos y son objeto de sobreajuste, por lo tanto no es útil en la predicción. Prefería explorar con simple polinomios... Como yo soy un gran fan de splines, y esto va en contra de mi intuición estoy interesado en averiguar la validez de estos argumentos son, y si hay un gran grupo de anti-spline-activistas por ahí?
Antecedentes: intento seguir Frank Harrell, la Regresión de la Modelización de Estrategias (1), cuando puedo crear mis propios modelos. Él sostiene que la restricción de splines cúbicos son una herramienta válida para la exploración de las variables continuas. También sostiene que los polinomios son buenos en el modelado de ciertas relaciones, tales como umbrales, logarítmica (2). Para la prueba de la linealidad del modelo sugiere una prueba de ANOVA para la spline:
$H_0: \beta_2 = \beta_3 = ... = \beta_{k-1} = 0 $
He buscado en google para el sobreajuste con estrías pero no se ha encontrado que mucho más útil (aparte de las advertencias generales acerca de no usar demasiados nudos). En este foro parece ser que hay una preferencia por la spline modelado, Kolassa, Harrell, gung.
He encontrado una entrada de blog acerca de polinomios, el diablo de sobreajuste que habla acerca de la predicción de polinomios. El post termina con estos comentarios:
En cierta medida, los ejemplos que aquí se presentan están engañando - polinomio la regresión es conocido por ser altamente no-robusto. Mucho mejor en la práctica es el uso de splines en lugar de polinomios.
Ahora, esto me llevó a comprobar cómo splines que iba a realizar con el ejemplo:
library(rms)
p4 <- poly(1:100, degree=4)
true4 <- p4 %*% c(1,2,-6,9)
days <- 1:70
set.seed(7987)
noise4 <- true4 + rnorm(100, sd=.5)
reg.n4.4 <- lm(noise4[1:70] ~ poly(days, 4))
reg.n4.4ns <- lm(noise4[1:70] ~ ns(days,4))
dd <- datadist(noise4[1:70], days)
options("datadist" = "dd")
reg.n4.4rcs_ols <- ols(noise4[1:70] ~ rcs(days,5))
plot(1:100, noise4)
nd <- data.frame(days=1:100)
lines(1:100, predict(reg.n4.4, newdata=nd), col="orange", lwd=3)
lines(1:100, predict(reg.n4.4ns, newdata=nd), col="red", lwd=3)
lines(1:100, predict(reg.n4.4rcs_ols, newdata=nd), col="darkblue", lwd=3)
legend("top", fill=c("orange", "red","darkblue"),
legend=c("Poly", "Natural splines", "RCS - ols"))
Da la siguiente imagen:
En conclusión, no he encontrado mucho de lo que me convencerían de reconsiderar splines, ¿qué me estoy perdiendo?
- F. E. Harrell, modelos de Regresión de Estrategias: Con Aplicaciones a Modelos Lineales de Regresión Logística y Análisis de Supervivencia, tapa Blanda reimpresión de tapa dura 1ª ed. 2001. Springer, 2010.
- F. E. Harrell, K. L. Lee, y B. G. Pollock, "Modelos de Regresión en los Estudios Clínicos: la Determinación de las Relaciones Entre los Predictores y la Respuesta," JNCI J Natl Cancer Inst, vol. 80, no. 15, pp 1198-1202, Oct. 1988.
Actualización
El comentario me hizo pensar en lo que sucede dentro de los datos útil sino por la incomodidad de las curvas. En la mayoría de las situaciones no voy fuera del límite de datos, como el ejemplo de arriba indica. No estoy seguro de que este califica como la predicción...
De todos modos aquí está un ejemplo en donde puedo crear un más complejo que no puede ser traducido en un polinomio. Dado que la mayoría de las observaciones se encuentran en el centro de los datos que he intentado simular que así:
library(rms)
cmplx_line <- 1:200/10
cmplx_line <- cmplx_line + 0.05*(cmplx_line - quantile(cmplx_line, .7))^2
cmplx_line <- cmplx_line - 0.06*(cmplx_line - quantile(cmplx_line, .3))^2
center <- (length(cmplx_line)/4*2):(length(cmplx_line)/4*3)
cmplx_line[center] <- cmplx_line[center] +
dnorm(6*(1:length(center)-length(center)/2)/length(center))*10
ds <- data.frame(cmplx_line, x=1:200)
days <- 1:140/2
set.seed(1234)
sample <- round(rnorm(600, mean=100, 60))
sample <- sample[sample <= max(ds$x) &
sample >= min(ds$x)]
sample_ds <- ds[sample, ]
sample_ds$noise4 <- sample_ds$cmplx_line + rnorm(nrow(sample_ds), sd=2)
reg.n4.4 <- lm(noise4 ~ poly(x, 6), data=sample_ds)
dd <- datadist(sample_ds)
options("datadist" = "dd")
reg.n4.4rcs_ols <- ols(noise4 ~ rcs(x, 7), data=sample_ds)
AIC(reg.n4.4)
plot(sample_ds$x, sample_ds$noise4, col="#AAAAAA")
lines(x=ds$x, y=ds$cmplx_line, lwd=3, col="black", lty=4)
nd <- data.frame(x=ds$x)
lines(ds$x, predict(reg.n4.4, newdata=ds), col="orange", lwd=3)
lines(ds$x, predict(reg.n4.4rcs_ols, newdata=ds), col="lightblue", lwd=3)
legend("bottomright", fill=c("black", "orange","lightblue"),
legend=c("True line", "Poly", "RCS - ols"), inset=.05)
Esto le da la siguiente trama:
Actualización 2
Desde este post he publicado un artículo en el que se ve en la no-linealidad de edad en un gran conjunto de datos. El suplemento compara los diferentes métodos y he escrito un post en el blog sobre ella.