Моя проблема : я недавно встретил статистика, который сообщил мне, что сплайны полезны только для исследования данных и подвержены переобучению, таким образом, бесполезны при прогнозировании. Он предпочел исследовать с помощью простых полиномов ... Так как я большой поклонник сплайнов, и это противоречит моей интуиции, мне интересно узнать, насколько верны эти аргументы, и существует ли большая группа против сплайнов. активисты там?
Предыстория : я пытаюсь следовать Фрэнку Харреллу, стратегиям регрессионного моделирования (1), когда создаю свои модели. Он утверждает, что ограниченные кубические сплайны являются допустимым инструментом для исследования непрерывных переменных. Он также утверждает, что многочлены плохо моделируют определенные отношения, такие как пороговые значения, логарифмические (2). Для проверки линейности модели он предлагает тест ANOVA для сплайна:
Я гуглил по переоснащению сплайнами, но не нашел, что это очень полезно (кроме общих предупреждений о том, что не следует использовать слишком много узлов). На этом форуме, кажется, предпочтение для моделирования сплайна, Kolassa , Харрелл , Кун .
Я нашел одно сообщение в блоге о многочленах, дьяволе переоснащения, которое говорит о предсказании многочленов. Пост заканчивается этими комментариями:
В некоторой степени примеры, представленные здесь, являются мошенничеством - полиномиальная регрессия, как известно, весьма ненадежна. Гораздо лучше на практике использовать сплайны, а не полиномы.
Теперь это побудило меня проверить, как сплайны будут работать в следующем примере:
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.
- Ф.Э. Харрелл, К.Л. Ли и Б.Г. Поллок, «Модели регрессии в клинических исследованиях: определение взаимосвязей между предикторами и реакцией», JNCI J Natl Cancer Inst, vol. 80, нет 15, с. 1198–1202, октябрь 1988 г.
Обновить
Комментарии заставили меня задуматься о том, что происходит в пределах диапазона данных, но с неудобными кривыми. В большинстве случаев я не выхожу за границы данных, как показано в примере выше. Я не уверен, что это квалифицируется как предсказание ...
В любом случае, вот пример, где я создаю более сложную линию, которая не может быть переведена в полином. Так как большинство наблюдений находится в центре данных, я попытался смоделировать это также:
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
Начиная с этого поста, я опубликовал статью, которая рассматривает нелинейность для возраста в большом наборе данных. Приложение сравнивает различные методы, и я написал пост в блоге об этом .