Mein Problem : Ich habe kürzlich einen Statistiker getroffen, der mir mitteilte, dass Splines nur zum Durchsuchen von Daten nützlich sind und einer Überanpassung unterliegen und daher für die Vorhersage nicht hilfreich sind. Er zog es vor, mit einfachen Polynomen zu erforschen ... Da ich ein großer Fan von Splines bin und dies meiner Intuition zuwiderläuft, möchte ich herausfinden, wie gültig diese Argumente sind und ob es eine große Gruppe von Anti-Spline- Aktivisten da draußen?
Hintergrund : Ich versuche, bei der Erstellung meiner Modelle Frank Harrell, Regressionsmodellierungsstrategien (1), zu folgen. Er argumentiert, dass eingeschränkte kubische Splines ein gültiges Werkzeug für die Untersuchung kontinuierlicher Variablen sind. Er argumentiert auch, dass die Polynome nicht in der Lage sind, bestimmte Beziehungen wie Schwellenwerte und Logarithmen zu modellieren (2). Um die Linearität des Modells zu testen, schlägt er einen ANOVA-Test für den Spline vor:
Ich habe wegen Überanpassung mit Splines gegoogelt, fand aber nicht viel hilfreich (abgesehen von allgemeinen Warnungen, dass nicht zu viele Knoten verwendet werden). In diesem Forum scheint es eine Vorliebe für Spline-Modellierung zu geben, Kolassa , Harrell , Gung .
Ich fand einen Blog-Beitrag über Polynome, den Teufel der Überanpassung , der über die Vorhersage von Polynomen spricht. Der Beitrag endet mit diesen Kommentaren:
In gewissem Maße handelt es sich bei den hier vorgestellten Beispielen um Betrug - die polynomiale Regression ist bekanntermaßen äußerst unrobust. In der Praxis ist es viel besser, Splines anstelle von Polynomen zu verwenden.
Dies veranlasste mich nun zu prüfen, wie sich Splines im folgenden Beispiel verhalten würden:
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"))
Gibt das folgende Bild:
Abschließend habe ich nicht viel gefunden, was mich davon überzeugen würde, Splines zu überdenken. Was fehle ich?
- FE Harrell, Regressionsmodellierungsstrategien: Mit Anwendungen auf lineare Modelle, logistische Regression und Überlebensanalyse, Softcover-Nachdruck von Hardcover 1. Aufl. 2001. Springer, 2010.
- FE Harrell, KL Lee und BG Pollock, "Regressionsmodelle in klinischen Studien: Bestimmung der Beziehungen zwischen Prädiktoren und Antwort", JNCI J Natl Cancer Inst, vol. 80, nein. 15, S. 1198–1202, Oktober 1988.
Aktualisieren
Die Kommentare ließen mich fragen, was innerhalb der Datenspanne passiert, aber mit unangenehmen Kurven. In den meisten Situationen überschreite ich nicht die Datengrenze, wie das obige Beispiel zeigt. Ich bin nicht sicher, ob dies als Vorhersage qualifiziert ist ...
Hier ist ein Beispiel, in dem ich eine komplexere Linie erstelle, die nicht in ein Polynom übersetzt werden kann. Da die meisten Beobachtungen im Mittelpunkt der Daten stehen, habe ich auch versucht, dies zu simulieren:
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)
Dies ergibt das folgende Diagramm:
Update 2
Seit diesem Beitrag habe ich einen Artikel veröffentlicht , der sich mit der Nichtlinearität des Alters in einem großen Datensatz befasst. Die Beilage vergleicht verschiedene Methoden und ich habe einen Blog-Beitrag darüber geschrieben .