为了以非参数方式拟合类似 sigmoid 的函数,我们可以使用单调样条。这是在 R 包中实现的(这里引用的所有 R 包都在 CRAN 上)splines2
。我将从@Chaconne 的答案中借用一些 R 代码,并根据我的需要进行修改。
splines2
提供函数mSpline
,实现 M 样条,它是一个无处不在的非负(在定义的区间上)样条基,和iSpline
,M 样条基的积分。最后一个是单调递增的,因此我们可以通过将它们用作回归样条基础来拟合递增函数,并拟合限制系数为非负的线性模型。最后一个由 R 包以用户友好的方式实现colf
,“线性函数的约束优化”。合身看起来像:
使用的 R 代码:
library(splines2) # includes monotone splines, M-splines, I-splines.
library(colf) # constrained optimization on linear functions
txt <- "| 0 | 0 |
| 1.6366666667 | -12.2012787905 |
| 3.2733333333 | -13.7833876716 |
| 4.91 | -10.5943208589 |
| 6.5466666667 | -1.3584575518 |
| 8.1833333333 | 8.1590423167 |
| 9.82 | 13.8827937482 |
| 10.4746666667 | 18.4965880076 |
| 11.4566666667 | 42.1205206106 |
| 11.784 | 45.0528073182 |
| 12.4386666667 | 76.8150755186 |
| 13.0933333333 | 80.0883540997 |
| 14.73 | 89.7784173678 |
| 16.3666666667 | 98.8113459392 |
| 19.64 | 104.104366506 |
| 22.9133333333 | 105.9929585305 |
| 26.1866666667 | 94.0070414695 |"
dat <- read.table(text=txt, sep="|")[,2:3]
names(dat) <- c("x", "y")
plot(dat$y ~ dat$x, pch = 19, xlab = "x", ylab = "y", main = "Monotone Splines with Varying df")
Imod_df_4 <- colf_nls(y ~ 1 + iSpline(x, df=4), data=dat, lower=c(-Inf, rep(0, 4)), control=nls.control(maxiter=1000, tol=1e-09, minFactor=1/2048) )
lines(dat$x, fitted(Imod_df_4), col="blue")
Imod_df_6 <- colf_nls(y ~ 1 + iSpline(x, df=6), data=dat, lower=c(-Inf, rep(0, 6)), control=nls.control(maxiter=1000, tol=1e-09, minFactor=1/2048) )
lines(dat$x, fitted(Imod_df_6), col="orange")
Imod_df_8 <- colf_nls(y ~ 1 + iSpline(x, df=8), data=dat, lower=c(-Inf, rep(0, 8)), control=nls.control(maxiter=1000, tol=1e-09, minFactor=1/2048) )
lines(dat$x, fitted(Imod_df_8), col="red")
EDIT
样条上的单调限制是形状限制样条的一种特殊情况,现在有一个(实际上是几个)R 包实现了那些简化它们的使用。我将使用其中一个包再次执行上述示例。R代码如下,使用上面读取的数据:
library(cgam)
mod_cgam0 <- cgam(y ~ 1+s.incr(x), data=dat, family=gaussian)
summary(mod_cgam0)
Call:
cgam(formula = y ~ 1 + s.incr(x), family = gaussian, data = dat)
Coefficients:
Estimate StdErr t.value p.value
(Intercept) 43.4925 2.7748 15.674 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for gaussian family taken to be 102.2557)
Null deviance: 33749.25 on 16 degrees of freedom
Residual deviance: 1636.091 on 12.5 observed degrees of freedom
Approximate significance of smooth terms:
edf mixture.of.Beta p.value
s.incr(x) 3 0.9515 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
CIC: 7.6873
这样,结(和自由度)已被自动选择。要固定自由度的数量,请使用:
mod_cgam1 <- cgam(y ~ 1+s.incr(x, numknots=5), data=dat, family=gaussian)
一篇介绍 cgam 的论文在这里(arxiv)。