样条 - 基函数 - 澄清

机器算法验证 自习 样条 基函数
2022-03-22 21:04:37

我一直在阅读http://freakonometrics.hypotheses.org/9184http://www.stats.uwo.ca/faculty/braun/ss3859/chapters/splines/splines.pdf上关于样条曲线的非常有用的介绍,以及 whuber 在此论坛上提供的非常有用的示例。我知道函数 h(x) 可以近似为

k=0dαk(xα)k+i=1jβi(xxi)+d

我很难理解这个公式如何链接到在 R 中的样条包中生成的实际基函数。例如 - 在下面的 R 代码之后,代码创建了 4 个我认为是基函数的列(每个点由 100 个点组成),根据下面的图表和/或下面的矩阵(头)看起来。这可能很简单——但是这些值如何链接回上面的公式?

为了进一步澄清 - 在样条回归中,在我的理解中,仍然是我们(一维)协变量的观察向量,并且我们添加了仅对大于这些节点的那些观察结果为正的截断幂项。因此,我会期望一组铰链函数在结之前为 0,然后继续使用导数所暗示的斜率。上升下降我认为这是相当基本的 - 但我只是没有解决这个问题。xβββ

set.seed(1)
n=10
xr = seq(0,n,by=.1)
yr = sin(xr/2)+rnorm(length(xr))/2
db = data.frame(x=xr,y=yr)
plot(db)

attach(db)
library(splines)
B=bs(xr,knots=c(2,5,8),Boundary.knots=c(0,10),degre=1)
B

matplot(xr,B,type="l")

reg=lm(yr~B)
lines(xr,predict(reg),col="red")

> B
#             1          2          3    4
# [1,] 0.00000000 0.00000000 0.00000000 0.00
# [2,] 0.05000000 0.00000000 0.00000000 0.00
# [3,] 0.10000000 0.00000000 0.00000000 0.00
# [4,] 0.15000000 0.00000000 0.00000000 0.00
# [5,] 0.20000000 0.00000000 0.00000000 0.00
# [6,] 0.25000000 0.00000000 0.00000000 0.00
# [7,] 0.30000000 0.00000000 0.00000000 0.00
# [8,] 0.35000000 0.00000000 0.00000000 0.00
# [9,] 0.40000000 0.00000000 0.00000000 0.00

在此处输入图像描述

2个回答

你不能从这里到达那里。图中的基本样条曲线并不是对您提供的方程的直接代数操作——至少对我来说并不简单。但这不是他们的来源。

基函数来自关于 B 样条的各种理论结果。样条函数是通过接近(或内插)采样函数值(结点)的最平滑函数。可以证明,这种优化的解决方案在于由分段多项式组成的有限维函数空间——其程度取决于您想要多少平滑度。多项式中的扭结发生在结点处。

所以现在我们去寻找合理的基函数。在你的情况下,你有分段线性函数..所以最简单的分段线性函数是一个帐篷函数......并且帐篷杆必须出现在一个结点,因为那是我们获得可微性中断的地方。R 提供的基函数不是唯一的选择,但它们产生了很好的能带矩阵,便宜且易于反转和以其他方式操作。

请注意,您的基函数还必须尊重您自己设置的问题的边界条件。上面的基函数只会给出函数。如果我将常量函数添加到我的基础中,我可以使用对函数进行插值。s(0)=0s(0)=c

现在说服自己上面显示的帐篷函数是必要样条空间的基础。考虑一下当您添加上面说明的函数的线性组合时会发生什么:它们都将具有线性部分,在结点处有扭结。这些都不能从其他人那里获得。最后,你需要证明你有正确的数量(我不记得公式,关于样条空间的尺寸,就结的数量和多边形的度数而言)。

通过增加多项式的次数可以获得更平滑的结果——你可以有分段二次或三次(通常的选择),然后你的基函数看起来像一个以结点为中心的铃铛序列。

方程中截断的多项式也可用于构建样条平滑器或插值,但它们不具有帐篷函数的有吸引力的数值属性......所以这就是 R 不提供它们的原因。

我不会尝试从上面引用的参考资料中了解样条函数。Ramsay 和 Hooker使用 R 和 Matlab 进行的功能数据分析在理论上与 R 中的实现联系在一起。您还可以挖掘 Kimeldorf 和 Wahba 关于平滑和插值样条曲线的原始论文。

我知道这是一个老问题,但也许我的回答将来对某人有用。

它在截断多项式函数基 (TPF) 和 B 样条之间存在联系。例如,在以下论文中对此进行了讨论:

  1. Paul HC Eilers 和 Brian D. Marx - Splines、Knots 和 Penalties,WIREs 计算统计(2010 年)。
  2. Harald Binder, Willi Sauerbrei - 通过去除结来增加加性样条模型的实用性,CSDA (2008)

我的答案将遵循 ref.1(可以在此处找到更多详细信息)。为了保持符号简单,我将使用在等间距节点上定义的 B 样条。我将用表示横坐标点的向量,并用表示一系列等间距的结。然后,通过计算得到 阶TPF基 1 阶 TPF 看起来像这样xt1<t2<...p

fijp(xi,tj)=(xitj)pI(xi>tj)

在此处输入图像描述

我们如何才能将这些折线“转换”成“三角形”?使这成为可能的算子是差分算子:B 样条可以计算为(适当缩放的)相邻 TPF 的差异。1 次 B 样条基(原始问题中的三角形之一)可以得到:

Bj1(x)=fj21(x)2fj11(x)+fj1(x)h

其中是 2 个连续结点之间的距离(这里是常数,因为我假设结点间距相等)。通过将此操作应用于上述 3 个 TPF,我们得到:h=t2t1=const

在此处输入图像描述

当然,该公式可以推广到任意程度 其中阶差分算子。再一次,这仅适用于等间距的结。如果连续结点之间的距离不是常数,则可以使用更复杂的变换。p

Bjp(x)=(1)p+1Δp+1fjp(x)hpp!
Δp+1p+1

重现我的示例的代码相当简单(见下文)。请注意,与原始问题不同,我将使用 R 函数 splineDesign() 创建 B 样条。bs() 函数实际上是基于 splineDesign() 的(参见 bs() 的帮助页面)。

# Libraries
library(colorout)
library(scales)

# Get some data
set.seed(1)
n = 100
x = seq(0, 1, len = n)

# B-splines stuffs
xr    = max(x)
xl    = min(x)
ndx   = 4
deg   = 1
dx    = (xr - xl) / ndx
knots = seq(xl - deg * dx, xr + deg * dx, by = dx)
B     = splineDesign(knots = knots, x = x, ord = deg + 1, 
                derivs = 0, outer.ok = TRUE)

# Compute tpf basis and B-slines from them
tpower = function(x, t, p)  (x - t) ^ p * (x > t)
P = outer(x, knots, tpower, deg)

# Plot TPFs 
matplot(x, P[, 3:5], pch = 16, col = alpha(1:3, 0.5), 
         ylab = "")
matlines(x, P[, 3:5], pch = 16, lty = 1, 
                col = alpha(1:3, 0.5))

# Compute B-splines as differences of TPFs
Bp = t(apply(P, 1, diff, diff = 2)) / dx

# Plot single B-spline and compare with splineDesign
plot(x, Bp[, 3], pch = 16, ylab=" ")
lines(x, B[, 3], pch = 16, lty = 1)

# Compare all with splineDesign B-splines
matplot(Bp,col = alpha(1:ncol(Bp), 0.5), pch = 16)
matlines(B,col = alpha(1:ncol(Bp), 0.5), lty = 1)

希望这在某种程度上有所帮助,并且它(至少部分地)回答了原始问题。