私の問題:最近、統計学者に会いましたが、スプラインはデータの探索にのみ有用であり、オーバーフィットの影響を受けるため、予測には役立ちません。彼は単純な多項式で探索することを好みました...私はスプラインの大ファンなので、これは私の直感に反するので、これらの引数がどのくらい有効であるか、そしてアンチスプラインの大規模なグループがある場合、活動家はいますか?
背景:モデルを作成するときは、フランクハレルの回帰モデリング戦略(1)を追います。彼は、制限された3次スプラインが連続変数を探索するための有効なツールであると主張します。彼はまた、多項式はしきい値、対数などの特定の関係のモデリングが不十分であると主張しています(2)。モデルの線形性をテストするために、彼はスプラインの分散分析テストを提案しています。
私はスプラインでオーバーフィッティングすることをグーグルで調べましたが、それほど便利ではありませんでした(あまり多くのノットを使用しないことに関する一般的な警告は別として)。このフォーラムでは、スプラインモデリング、Kolassa、Harrell、gungが優先されているようです。
多項式についてのブログ投稿を1つ見つけました。これは、多項式の予測について語る過剰適合の悪魔です。投稿はこれらのコメントで終わります:
ここで紹介する例はある程度不正です—多項式回帰は非常にロバストでないことが知られています。実際には、多項式よりもスプラインを使用する方がはるかに優れています。
ここで、この例でスプラインがどのように機能するかを確認するように促されました。
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ハレル、回帰モデリング戦略:線形モデルへの適用、ロジスティック回帰、および生存分析、ハードカバー第1版のソフトカバー再版。2001年。スプリンガー、2010年。
- FEハレル、KLリー、およびBGポロック、「臨床研究における回帰モデル:予測因子と応答の関係の決定」、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
この投稿以来、大規模なデータセットの年齢の非線形性を調べる記事を公開しました。補足は異なる方法を比較します、そして、私はそれに関するブログ投稿を書きました。