내 문제 : 최근 스플라인은 데이터 탐색에만 유용하고 과적 합되어 예측에 유용하지 않다는 통계학자를 만났습니다. 그는 간단한 다항식으로 탐색하는 것을 선호했습니다 ... 나는 스플라인을 좋아하는 팬이므로, 나는이 주장이 얼마나 유효한지, 그리고 안티 스플라인 그룹이 큰지에 관심이 있습니다. 거기 운동가 ?
배경 : 모델을 만들 때 Frank Harrell, Regression Modeling Strategies (1)을 따르려고합니다. 그는 제한된 입방 스플라인이 연속 변수를 탐색하기위한 유효한 도구라고 주장합니다. 그는 또한 다항식이 임계 값, 로그와 같은 특정 관계를 모델링하는 데 열악하다고 주장합니다 (2). 모델의 선형성을 테스트하기 위해 스플라인에 대한 분산 분석 테스트를 제안합니다.
스플라인으로 과적 합한 것으로 Google 검색했지만 그다지 유용하지는 않습니다 (매듭을 너무 많이 사용하지 않는다는 일반적인 경고 제외). 이 포럼에는 스플라인 모델링, Kolassa , Harrell , gung에 대한 선호가있는 것 같습니다 .
다항식에 대한 블로그 게시물을 찾았습니다 . 다항식 예측에 대해 이야기 하는 과적 합의 악마 . 게시물은 다음과 같은 주석으로 끝납니다.
다항식 회귀는 매우 비 강력한 것으로 알려져 있습니다. 실제로는 다항식보다 스플라인을 사용하는 것이 훨씬 좋습니다.
이제이 예제에서 스플라인의 성능을 확인하라는 메시지가 표시되었습니다.
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"))
다음 이미지를 제공합니다.
결론적으로 스플라인을 다시 생각하게 만드는 것을 많이 찾지 못했습니다. 무엇을 놓치고 있습니까?
- FE Harrell, 회귀 모델링 전략 : 선형 모형, 로지스틱 회귀 및 생존 분석에 대한 응용 프로그램을 사용하여 하드 커버 1 차 버전의 소프트 커버 재 인쇄. 2001. Springer, 2010.
- FE Harrell, KL Lee 및 BG Pollock,“임상 연구에서의 회귀 모델 : 예측 자와 반응 간의 관계 결정,”JNCI J Natl Cancer Inst, vol. 80 번 15, pp. 1198–1202, 1988 년 10 월.
최신 정보
의견은 데이터 범위 내에서 발생하지만 불편한 곡선으로 인해 궁금해했습니다. 위의 예에서 알 수 있듯이 대부분의 상황에서 데이터 경계를 벗어나지 않습니다. 이것이 예측으로 자격이 있는지 확실하지 않습니다 ...
어쨌든 여기에 다항식으로 변환 할 수없는보다 복잡한 선을 만드는 예가 있습니다. 대부분의 관측치가 데이터의 중심에 있기 때문에 나는 그것을 시뮬레이션하려고 시도했다.
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)
이것은 다음 플롯을 제공합니다.
업데이트 2
이 게시물 이후 로 큰 데이터 세트에서 연령에 따라 비선형으로 보이는 기사 를 게시 했습니다 . 부록은 다른 방법을 비교 하고 그것에 대해 블로그 게시물을 작성 했습니다 .