Mój problem : Niedawno spotkałem statystykę, który poinformował mnie, że splajny są przydatne tylko do eksploracji danych i podlegają nadmiernemu dopasowaniu, a zatem nie są przydatne w przewidywaniu. Wolał odkrywać za pomocą prostych wielomianów ... Ponieważ jestem wielkim fanem splajnów, a to wbrew mojej intuicji, jestem zainteresowany ustaleniem, jak ważne są te argumenty, a jeśli jest duża grupa anty-splajn- działacze tam?
Tło : Kiedy tworzę modele, staram się podążać za Frankiem Harrella, Strategie modelowania regresji (1). Twierdzi, że ograniczone splajny sześcienne są ważnym narzędziem do badania zmiennych ciągłych. Argumentuje również, że wielomiany słabo modelują pewne relacje, takie jak progi, logarytmika (2). Do przetestowania liniowości modelu sugeruje test ANOVA dla splajnu:
Zaszufladkowałem się za przeplatanie splajnami, ale nie znalazłem zbyt wiele przydatności (oprócz ogólnych ostrzeżeń o nie używaniu zbyt wielu węzłów). Na tym forum wydaje się preferowane modelowanie splajnu, Kolassa , Harrell , Gung .
Znalazłem jeden post na blogu o wielomianach, diabełu nadmiernego dopasowania, który mówi o przewidywaniu wielomianów. Post kończy się następującymi komentarzami:
W pewnym stopniu przykłady tu przedstawione są oszukiwaniem - wiadomo, że regresja wielomianowa jest wysoce niesolidna. Znacznie lepiej w praktyce jest używać splajnów niż wielomianów.
Teraz skłoniło mnie to do sprawdzenia, w jaki sposób splajny będą działać na przykładzie:
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"))
Daje następujący obraz:
Podsumowując, nie znalazłem wiele, co przekonałoby mnie do ponownego rozważenia splajnów, czego mi brakuje?
- FE Harrell, Strategie modelowania regresji: Z zastosowaniem modeli liniowych, regresji logistycznej i analizy przeżycia, przedruk miękkiej okładki w twardej oprawie, wydanie 1. 2001. Springer, 2010.
- FE Harrell, KL Lee i BG Pollock, „Modele regresji w badaniach klinicznych: określanie związków między predyktorami a odpowiedzią”, JNCI J Natl Cancer Inst, vol. 80, nr 15, s. 1198–1202, październik 1988 r.
Aktualizacja
Komentarze sprawiły, że zastanawiam się, co dzieje się w zakresie danych, ale z niewygodnymi krzywymi. W większości sytuacji nie wychodzę poza granice danych, jak pokazuje powyższy przykład. Nie jestem pewien, czy to kwalifikuje się jako prognoza ...
W każdym razie oto przykład, w którym tworzę bardziej złożoną linię, której nie można przetłumaczyć na wielomian. Ponieważ większość obserwacji znajduje się w centrum danych, próbowałem to również zasymulować:
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)
To daje następujący wykres:
Aktualizacja 2
Od tego postu opublikowałem artykuł, który analizuje nieliniowość ze względu na wiek na dużym zestawie danych. Suplement porównuje różne metody i napisałem o nim post na blogu .