Wie kann ich einen Spline an Daten anpassen, die Werte und 1./2. Ableitungen enthalten?


13

Ich habe einen Datensatz, der zum Beispiel einige Messungen für Position, Geschwindigkeit und Beschleunigung enthält. Alle kommen aus dem gleichen "Lauf". Ich könnte ein lineares System konstruieren und all diesen Messungen ein Polynom zuordnen.

Aber kann ich das auch mit Splines machen? Was ist eine "R" -Methode, um dies zu tun?

Hier sind einige simulierte Daten, die ich anpassen möchte:

f <- function(x) 2+x-0.5*x^2+rnorm(length(x), mean=0, sd=0.1)
df <- function(x) 1-x+rnorm(length(x), mean=0, sd=0.3)
ddf <- function(x) -1+rnorm(length(x), mean=0, sd=0.6)

x_f <- runif(5, 0, 5)
x_df <- runif(8, 3, 8)
x_ddf <- runif(10, 4, 9)

data <- data.frame(type=rep('f'), x=x_f, y=f(x_f))
data <- rbind(data, data.frame(type=rep('df'), x=x_df, y=df(x_df)))
data <- rbind(data, data.frame(type=rep('ddf'), x=x_ddf, y=ddf(x_ddf)))

library(ggplot2)
ggplot(data, aes(x, y, color=type)) + geom_point()


library(splines)
m <- lm(data$y ~ bs(data$x, degree=6)) # but I want to fit on f, df, ddf. possible?

Bildbeschreibung hier eingeben


Ich kenne die Antwort auf Ihre Frage nicht, splinefunkann aber Ableitungen berechnen, und vermutlich können Sie diese als Ausgangspunkt verwenden, um die Daten mit einigen inversen Methoden anzupassen? Ich bin daran interessiert, die Lösung dafür zu erfahren.
David LeBauer

1
Dieses Problem wurde von Maurice Cox in seiner Arbeit von 1972 gelöst. Ich weiß nicht, ob R es unterstützt, aber der Suchbegriff lautet "Hermite Splines".
user14717

@DavidLeBauer das ist was ich gerade mache. Ich habe ein Optimierungsproblem formalisiert, das zu einer Reihe von Punkten passt, sodass der Spline und seine Ableitungen den Daten angenähert sind. Aber eine direktere Methode wäre großartig.
dani

3
Ein ganz normaler Ansatz ist die Kalman-Filterung. Der (nicht beobachtbare) Zustand enthält die genauen Ableitungen und die Beobachtungen sind verrauschte Versionen davon. Zum Beispiel sagt das Modell für einen kubischen Spline grob aus, dass die Ableitung zweiter Ordnung ein (zeitkontinuierliches) weißes Rauschen ist, aber es kann auch ein Modell höherer Ordnung verwendet werden. Sie müssen das Messrauschen in Abhängigkeit von der Ableitungsreihenfolge für die aktuelle Beobachtung beschreiben. In einem ersten Ansatz können drei (zu schätzende) Rauschabweichungen ausreichend sein.
Yves

2
Was ist ein Messfehler bei Derivaten? ist es viel höher als die Position? auch in deiner Handlung warum sind keine Punkte ausgerichtet? Was ist die X-Achse?
Aksakal

Antworten:


8

Wir werden beschreiben, wie ein Spline durch Kalman Filtering (KF) -Techniken in Verbindung mit einem State-Space-Modell (SSM) verwendet werden kann. Die Tatsache, dass einige Spline-Modelle von SSM dargestellt und mit KF berechnet werden können, wurde von CF Ansley und R. Kohn in den Jahren 1980-1990 offenbart. Die geschätzte Funktion und ihre Ableitungen sind die von den Beobachtungen abhängigen Erwartungen des Staates. Diese Schätzungen werden unter Verwendung einer festen Intervallglättung berechnet , eine Routineaufgabe bei Verwendung eines SSM.

Der Einfachheit halber sei angenommen, dass die Beobachtungen zu den Zeitpunkten und dass die Beobachtungszahl zu nur eine Ableitung mit der Ordnung in . Der Beobachtungsteil des Modells schreibt als wobei die nicht beobachtete wahre Funktion bezeichnet und ist ein Gaußscher Fehler mit der Varianz Abhängigkeit von der Ableitungsreihenfolge . Die (zeitkontinuierliche) Übergangsgleichung hat die allgemeine Form t1<t2<<tnktkdk{0,1,2}

(O1)y(tk)=f[dk](tk)+ε(tk)
f(t)ε(tk)H(tk)dk
(T1)ddtα(t)=Aα(t)+η(t)
wobei der unbeobachtete Zustandsvektor ist und ein Gaußsches weißes Rauschen mit Kovarianz , von dem angenommen wird, dass es unabhängig von dem ist Beobachtungsrauschen r.vs . Um einen Spline zu beschreiben, betrachten wir einen Zustand, der durch Stapeln der ersten Ableitungen erhalten wird, dh . Der Übergang ist α(t)η(t)Qε(tk)mα(t):=[f(t),f[1](t),,f[m1](t)]
[f[1](t)f[2](t)f[m1](t)f[m](t)]=[010001100][f(t)f[1](t)f[m2](t)f[m1](t)]+[000η(t)]
2m2m-1m=2>1 y ( t k ) und wir erhalten dann einen Polynom-Spline mit der Größenordnung (und Grad ). Während dem üblichen kubischen Spline entspricht,2m2m1m=2>1. Um an einem klassischen SSM-Formalismus festzuhalten, können wir (O1) umschreiben als wobei die Beobachtungsmatrix die geeignete Ableitung in und die Varianz von in Abhängigkeit von . Also wobei , und . In ähnlicher Weise ist
(O2)y(tk)=Z(tk)α(tk)+ε(tk),
Z(tk)α(tk)H(tk)ε(tk)dkZ(tk)=Zdk+1Z1:=[1,0,,0]Z2:=[0,1,0]Z3:=[0,0,1,0,]H(tk)=Hdk+1 H 1 H 2 H 3für drei Varianzen , und . H1H2H3

Obwohl der Übergang in kontinuierlicher Zeit erfolgt, handelt es sich bei der KF tatsächlich um eine diskrete Standardzeit . Tatsächlich werden wir in der Praxis konzentrieren sich auf Zeiten , wo wir eine Beobachtung haben, oder wo wollen wir die Derivate schätzen. Wir können die Menge als die Vereinigung dieser beiden Mengen von Zeiten annehmen und annehmen, dass die Beobachtung zu fehlen kann: Dies erlaubt es, die Ableitungen zu jedem Zeitpunkt unabhängig von der Existenz einer Beobachtung abzuschätzen . Es bleibt noch die diskrete SSM abzuleiten.t{tk}tkmtk

Wir verwenden Indizes für diskrete Zeiten und schreiben für und so weiter. Die zeitdiskrete SSM hat die Form wo die Matrizen und werden von (T1) und (O2) abgeleitet, während die Varianz von durch vorausgesetzt, dassαkα(tk)

(DT)αk+1=Tkαk+ηkyk=Zkαk+εk
TkQk:=Var(ηk)εkHk=Hdk+1ykTk=exp{δkA}=[ 1 δ 1 kfehlt nicht. Mit etwas Algebra können wir die Übergangsmatrix für die zeitdiskrete SSM finden. wobei für . Ebenso kann die Kovarianzmatrix für die zeitdiskrete SSM als angegeben werden
Tk=exp{δkA}=[1δk11!δk22!δkm1(m1)!01δk11!δk11!01],

δk:=tk+1tkk<nQk=Var(ηk)
Qk=ση2[δk2mij+1(mi)!(mj)!(2mij+1)]i,j
wobei die Indizes und zwischen und .ij1m

Um nun die Berechnung in R fortzusetzen, benötigen wir ein Paket, das sich mit KF befasst und zeitvariable Modelle akzeptiert. Das CRAN-Paket KFAS scheint eine gute Option zu sein. Wir können R-Funktionen schreiben, um die Matrizen und aus dem Vektor der Zeiten zu berechnen , um die SSM (DT) zu codieren. In den vom Paket verwendeten Notationen multipliziert eine Matrix das Rauschen in der Übergangsgleichung von (DT): Wir nehmen hier die Identität . Beachten Sie auch, dass hier eine diffuse initiale Kovarianz verwendet werden muss.TkQktkRkηkIm

EDIT Der ursprünglich geschriebene war falsch. Behoben (auch in R-Code und Bild).Q

CF Ansley und R. Kohn (1986) "Zur Äquivalenz zweier stochastischer Ansätze zur Spline-Glättung" J. Appl. Probab. 23, S. 391–405

R. Kohn und CF Ansley (1987) "Ein neuer Algorithmus zur Spline-Glättung basierend auf der Glättung eines stochastischen Prozesses" SIAM J. Sci. und Stat. Comput. 8 (1), S. 33–48

J. Helske (2017). KFAS: Modelle des exponentiellen Familienzustandsraums in R J. Stat. Sanft. 78 (10), S. 1-39

Glätten mit Derivaten

smoothWithDer <- function(t, y, d, m = 3,
                          Hstar = c(3, 0.2, 0.1)^2, sigma2eta = 1.0^2) {

    ## define the SSM matrices, depending on 'delta_k' or on 'd_k'
    Tfun <- function(delta) {
        mat <-  matrix(0, nrow = m, ncol = m)
        for (i in 0:(m-1)) {
            mat[col(mat) == row(mat) + i] <- delta^i / gamma(i + 1)
        }
        mat
    }
    Qfun <- function(delta) {
        im <- (m - 1):0
        x <- delta^im / gamma(im + 1)
        mat <- outer(X = x, Y = x, FUN = "*")
        im2 <- outer(im, im, FUN = "+")
        sigma2eta * mat * delta / (im2 + 1) 
    }
    Zfun <-  function(d) {
        Z <- matrix(0.0, nrow = 1, ncol = m)
        Z[1, d + 1] <- 1.0
        Z
    }
    Hfun <- function(d) ifelse(d >= 0, Hstar[d + 1], 0.0)
    Rfun <- function() diag(x = 1.0, nrow = m)

    ## define arrays by stacking the SSM matrices. We need one more
    ## 'delta' at the end of the series
    n <- length(t)
    delta <-  diff(t)
    delta <- c(delta, mean(delta))

    Ta <- Qa <- array(0.0, dim = c(m, m, n))
    Za <- array(0.0, dim = c(1, m, n))
    Ha <- array(0.0, dim = c(1, 1, n))
    Ra <-  array(0.0, dim = c(m, m, n))

    for (k in 1:n) {
        Ta[ , , k] <- Tfun(delta[k])
        Qa[ , , k] <- Qfun(delta[k])
        Za[ , , k] <- Zfun(d[k])
        Ha[ , , k] <- Hfun(d[k])
        Ra[ , , k] <- Rfun()
    }

    require(KFAS)
    ## define the SSM and perform Kalman Filtering and smoothing
    mod <- SSModel(y ~ SSMcustom(Z = Za, T = Ta, R = Ra, Q = Qa, n = n,
                                 P1 = matrix(0, nrow = m, ncol = m),
                                 P1inf = diag(1.0, nrow = m), 
                                 state_names = paste0("d", 0:(m-1))) - 1)
    out <- KFS(mod, smoothing = "state")
    list(t = t, filtered = out$att, smoothed = out$alphahat)

}

## An example function as in OP
f <- function(t, d = rep(0, length = length(t))) {
    f <- rep(NA, length(t))
    if (any(ind <- (d == 0))) f[ind] <- 2.0 + t[ind] - 0.5 * t[ind]^2
    if (any(ind <- (d == 1))) f[ind] <- 1.0 - t[ind]
    if (any(ind <- (d == 2))) f[ind] <- -1.0
    f
}

set.seed(123)
n <-  100
t <- seq(from = 0, to = 10, length = n)
Hstar <- c(3, 0.4, 0.2)^2
sigma2eta <- 1.0

fTrue <- cbind(d0 = f(t), d1 = f(t, d = 1), d2 = f(t, d = 2))

## ============================================================================
## use a derivative index of -1 to indicate non-observed values, where
## 'y' will be NA
##
## [RUN #0]  no derivative  m = 2 (cubic spline)
## ============================================================================
d0 <- sample(c(-1, 0), size = n, replace = TRUE, prob = c(0.7, 0.3))
ft0 <-  f(t, d0)
## add noise picking the right sd
y0 <- ft0 + rnorm(n = n, sd = c(0.0, sqrt(Hstar))[d0 + 2])
res0 <- smoothWithDer(t, y0, d0, m = 2, Hstar = Hstar)

## ============================================================================
## [RUN #1] Only first order derivative: we can take m = 2 (cubic spline)
## ============================================================================
d1 <- sample(c(-1, 0:1), size = n, replace = TRUE, prob = c(0.7, 0.15, 0.15))
ft1 <-  f(t, d1)
y1 <- ft1 + rnorm(n = n, sd = c(0.0, sqrt(Hstar))[d1 + 2])
res1 <- smoothWithDer(t, y1, d1, m = 2, Hstar = Hstar)

## ============================================================================
## [RUN #2] First and second order derivative: we can take m = 3
## (quintic spline)
## ============================================================================
d2 <- sample(c(-1, 0:2), size = n, replace = TRUE, prob = c(0.7, 0.1, 0.1, 0.1))
ft2 <-  f(t, d2)
y2 <- ft2 + rnorm(n = n, sd = c(0.0, sqrt(Hstar))[d2 + 2])
res2 <- smoothWithDer(t, y2, d2, m = 3, Hstar = Hstar)

## plots : a ggplot with facets would be better here.
for (run in 0:2) {
    resrun <- get(paste0("res", run))
    drun <- get(paste0("d", run))
    yrun <- get(paste0("y", run))
    matplot(t, resrun$smoothed, pch = 16, cex = 0.7, ylab = "", xlab = "")
    matlines(t, fTrue, lwd = 2, lty = 1)
    for (dv in 0:2) {
        points(t[drun == dv], yrun[drun == dv], cex = 1.2, pch = 22, lwd = 2,
               bg = "white", col = dv + 1)
    }
    title(main = sprintf("run %d. Dots = smooothed, lines = true, square = obs", run))
    legend("bottomleft", col = 1:3, legend = c("d0", "d1", "d2"), lty = 1)
}

Vielen Dank für Ihre Antwort. Das interessiert mich sehr. Gegenwärtig erlauben Sie nicht, dass der Wert von fund seine Ableitung zu einem bestimmten Zeitpunkt verwendet werden t. Wie ist es möglich, alle Informationen zu nutzen? Nochmals, merci für deine Antwort.
Dani

Meiner Lektüre nach dreht sich alles unter T1 um die Verwendung mehrerer Ableitungen im selben Inferenzverfahren. Yves kann das allerdings bestätigen.
eric_kernfeld

In der Tat können Sie für ein sagen: Derivate verwenden : Die Beobachtung ist dann ein Vektor, und enthält Zeilen, in denen die gewünschten Derivate ausgewählt werden. Ich bin sicher , dass eine gemeinsame Arbeiten mit KFAS , aber von Nas verwendet , kann es möglich sein , eine zeitlich veränderliche haben auch. t k y k Z k o k o > 1 ook>1tkykZkoko>1o
Yves

@Yves Verstehe ich Sie richtig: Wenn ich die erste und zweite Ableitung an einem Punkt in t_k haben, dann sieht das z_k wie folgt aus : matrix(c(0,0,0, 0,1,0, 0,0,1), nrow=length(d_k), ncol=m, byrow = T). Insgesamt wäre es also ein Würfel der Dimension 'höchste Ableitung' * 'Spline-Grad' * 'Anzahl der Zeitschritte'
dani

Ja @dani, fast: Die Anzahl der Zeilen für alle Matrizen beträgt dh im Beispiel. Dies ist die höchste Ableitungsreihenfolge plus eins. Auch der Grad des Splines beträgt , nicht . Da Sie in Ihrem Beispiel die Ableitung der Ordnung (die Funktion selbst) nicht beobachten , sollte sie in den Beobachtungen auf gesetzt werden, und Sie könnten auch die erste Zeile fallen lassen. Ich vermute jedoch, dass in diesem speziellen Fall das Problem schlecht gestellt ist und der SSM möglicherweise nicht beobachtbar ist . max k { d k +1}32m-1m0Zkmaxk{dk+1}32m1m0NA
Yves

4

Mit einer Standardroutine für kleinste Fehlerquadrate können Sie eine spektakuläre Leistung erbringen , vorausgesetzt, Sie haben eine vernünftige Vorstellung von der relativen Größe der zufälligen Fehler, die für jede Ableitung gemacht wurden. Die Anzahl der Messungen, die Sie für jeden Wert durchführen, ist nicht begrenzt. Sie können sogar gleichzeitig verschiedene Ableitungen an jedem Wert messen. Die einzige Einschränkung bei der Verwendung von Ordinary Least Squares (OLS) ist die übliche: Sie gehen davon aus, dass die Messungen unabhängig sind.x

Die Grundidee kann am klarsten ausgedrückt werden, indem das Problem abstrahiert wird. Ihr Modell verwendet eine Reihe von Funktionen (wie eine beliebige Spline-Basis) als Grundlage für die Vorhersage der Werte einer unbekannten Funktion an Punkten Dies bedeutet, dass Sie versuchen, die Koeffizienten zu schätzen, für die sich jede der linearen Kombinationen annähernd Nennen wir diesen (Vektor-) Raum linearer Kombinationenpfj:RR, j=1,2,,pyi=f(xi)f(x1,x2,,xn).βjjβjfj(xi)yi.F.

Das Besondere an diesem Problem ist, dass Sie das nicht unbedingt beachten müssenyi. Stattdessen gibt es eine definierte Menge von linearen Funktionalen die den Daten zugeordnet sind. Recall , dass ein Funktions ist eine "Funktion einer Funktion:" jeweils eine Nummer zugewiesen , um eine beliebige Funktion Das Modell postuliert , dassLiLiLi[f]fF.

(1)yi=Li[f]+σiεi

wo die Funktionalen gegeben sind, die sind bekannte Skalierungsfaktoren und die sind unabhängig und identisch verteilten Zufallsvariablen.Liσi>0εi

Zwei zusätzliche Annahmen machen OLS anwendbar und statistisch aussagekräftig:

  1. Die gemeinsame Verteilung des hat eine endliche Varianz.εi

  2. Jedes ist eine lineare Funktion. Ein funktionales ist linear, wenn für beliebige Elemente und entsprechende ZahlenLiLfjFαj,

    L[jαjfj]=jαjL[fj].

(2) erlaubt es, das Modell expliziter auszudrücken als(1)

yi=β1Li[f1]++βpLi[fp]+σiεi.

Der springende Punkt dieser Reduktion ist, dass, weil Sie alle Funktionalen alle Basisfunktionen und die Standardabweichungen die Werte alle Zahlen sind - -das sind nur die üblichen "Variablen" oder "Merkmale" eines Regressionsproblems - und das sind lediglich (relative) Gewichte. Somit ist OLS im optimalen Sinne des Gauß-Markov-Theorems ein großartiges Verfahren.Li,fj,σi,Li[fj]σi

Die an der Frage beteiligten Funktionen sind die folgenden:

  • Bewerten Sie an einem bestimmten Punkt Dies ist, was wir normalerweise tun. Dies ist linear, da per Definition lineare Funktionskombinationen punktweise ausgewertet werden.fx: L[f]=f(x).

  • Bewerten Sie die Ableitung an einem bestimmten Punkt Dies ist linear, weil die Differenzierung linear ist.fx: L[f]=f(x).

  • Bewerten Sie die zweite Ableitung an einem bestimmten Punktfx: L[f]=f(x).


Okay, wie gut funktioniert dieser Ansatz? Wie üblich werden wir die Residuen und die angepassten Werte mit den beobachteten Werten vergleichen. Da sich Positionen, Geschwindigkeiten und Beschleunigungen in unterschiedlichen Einheiten befinden, sollten sie auf separaten Achsen aufgezeichnet werden.y^iyiy^i

Zahl

In der obersten Zeile werden Kurven verwendet, um und die ersten beiden Ableitungen grafisch darzustellen. Die relevanten Datenpunkte sind über den Kurven aufgetragen: beobachtete Werte links, beobachtete Ableitungen in der Mitte und beobachtete zweite Ableitungen rechts.y^

In der unteren Zeile werden die entsprechenden Residuen eingetragen. Wie üblich suchen wir nach einem Mangel an nennenswerten Beziehungen: Wir hoffen, dass die Restwerte (ihre y-Koordinaten) von links nach rechts zufällig variieren und Unabhängigkeit und keine Trends aufweisen.

Die Datenwerte wurden genau wie in der Frage erzeugt (nachdem der Zufallszahlen-Startwert aus Gründen der Reproduzierbarkeit auf 17 gesetzt wurde ). Ich habe Anpassungen mit den von der Funktion generierten B-Spline-Räumen für die Stufen 1 bis 6 untersucht. Diese Abbildung zeigt die Ergebnisse für die Stufe 2, die der niedrigste Grad ist (dh das einfachste Modell) Es zeigt einen niedrigen AIC und ein gutes Restverhalten sowie das Modell, das durch eine ANOVA aller sechs (verschachtelten) Modelle angezeigt wird.n=23set.seed(17)FRbs

Die Passform ist

y^=27.48993+2.54078f1+2.97679f2

Dabei sind und die B-Spline-Basisfunktionen, die von erstellt wurden .f1f2bs

Die Reste verhalten sich gut. Die Passformen sind gut. Außerdem fand dieser Ansatz das richtige Modell: Die Daten wurden tatsächlich aus einer quadratischen Funktion (Grad 2) generiert. Darüber hinaus sind die Standardabweichungen der Residuen ungefähr die richtigen Größen: 0,11, 0,20 und 0,61 im Vergleich zu 0,1, 0,3 und 0,6, die zum Erzeugen der ursprünglichen Fehler verwendet werden. Das ist ziemlich erstaunlich, da diese Kurven offensichtlich die Beobachtungen (die nicht über hinausgehen ) extrapolieren und einen so kleinen Datensatz ( ) verwenden.x=5n=23

Schließlich sind die Residuen der Passungen für Splines höheren Grades qualitativ gleich. Sie verbessern sich nur geringfügig, wenn weniger plausible Modelle verwendet werden. Bei ausreichend hohen Graden beginnen sie beispielsweise bei kleinen Werten von zwischen den beobachteten Werten wild zu schwingen . Um dieses (schlechte) Verhalten zu veranschaulichen, ist hier die Anpassung mit Grad 9:x

Figur 2

Schließlich ist hier ein Beispiel, in dem mehrere Beobachtungen von verschiedenen linearen Funktionalen der Basis gemacht wurden. Der Code zum Erzeugen dieser Beobachtungen wurde von dem in der Frage zu geändert

mult <- 2
x_f <- rep(runif(5, 0, 5), mult)       # Two observations per point
x_df <- rep(runif(8, 3, 8), mult)      # Two derivatives per point
x_ddf <- c(x_df, rep(runif(10, 4, 9))  # Derivative and acceleration per point

Figur 3


Der RCode für diese Berechnungen ist eher allgemein gehalten. Insbesondere verwendet es eine numerische Differenzierung, um die Ableitungen zu finden, so dass es nicht von der Art des verwendeten Splines abhängig ist. Es behandelt die unterschiedlichen Werte von indem es die Beobachtungen proportional zu Es erstellt automatisch eine Reihe von Modellen und passt sie in eine Schleife ein. Die linearen Funktionen und die Standardabweichungen sind fest codiert. Es gibt jeweils drei, die entsprechend dem Wert der Variablen im Dataset ausgewählt werden.σi1/σi2.Liσitype

Als Beispiele dafür, wie Sie die Anpassungen verwenden können, druckt die Coda Zusammenfassungen, eine Liste ihrer AICs und eine ANOVA von allen.

#
# Estimate spline derivatives at points of `x`.
#
d <- function(x, s, order=1) {
  h <- diff(range(x, na.rm=TRUE))
  dh <- h * 1e-4
  lags <- seq(-order, order, length.out=order+1) * dh/2
  b <- choose(order, 0:order) * (-1)^(order:0)
  y <- b %*% matrix(predict(s, c(outer(lags, x, `+`))), nrow=length(lags))
  y <- matrix(y / (dh^order), nrow=length(x))
}
#
# Fit and plot models by degree.
#
data$order <- c(f=0, df=1, ddf=2)[data$type]
k <- max(data$order)
x <- data$x
w <- (c(0.1, 0.3, 0.6)^(-2))[data$order+1] # As specified in the question

fits <- lapply(1:6, function(deg) {
  #
  # Construct a model matrix.
  #
  s <- bs(x, degree=deg, intercept=TRUE)
  X.l <- lapply(seq.int(k+1)-1, function(i) {
    X <- subset(data, order==i)
    Y <- as.data.frame(d(X$x, s, order=i))
    cbind(X, Y)
  })
  X <- do.call("rbind", X.l)
  #
  # Fit WLS models.
  #
  f <- as.formula(paste("y ~ -1 +", paste0("V", 0:deg+1, collapse="+")))
  fit <- lm(f, X, weights=w)
  msr <- tapply(residuals(fit), data$order, function(r) {
    k <- length(r) - 1 - deg
    ifelse(k >= 1, sum(r^2) / k, 1)
  })
  #
  # Compute predicted values along the graphs.
  #
  X.new <- data.frame(x = seq(min(X$x), max(X$x), length.out=101))
  X.new$y.hat <- predict(s, X.new$x) %*% coefficients(fit)
  X.new$Dy.hat <- d(X.new$x, s, 1) %*% coefficients(fit)
  X.new$DDy.hat <- d(X.new$x, s, 2) %*% coefficients(fit)
  X$Residual <- residuals(fit)
  #
  # Return the model.
  #
  fit$msr <- msr
  fit
})
lapply(fits, function(f) sqrt(f$msr))
lapply(fits, summary)
lapply(fits, AIC)
do.call("anova", fits)

1

Zunächst möchte ich Ihnen dafür danken, dass Sie diese Frage gestellt haben. Es ist eine wirklich interessante Frage. Ich liebe Splines und die coolen Dinge, die man damit machen kann. Und das gab mir eine Entschuldigung, um etwas zu recherchieren. :-)

BLUF: Die kurze Antwort lautet nein. Ich kenne keine Funktionalität in R, die dies automatisch für Sie erledigt. Die lange Antwort ist ... viel komplizierter. Die Tatsache, dass die Ableitungen und Funktionswerte nicht an derselben Stelle abgetastet werden, erschwert dies. Und die Tatsache, dass Sie am rechten Ende des Intervalls keinen Funktionswert haben, macht dies möglicherweise unmöglich.

Beginnen wir mit dem kubischen Spline. Bei gegebenen Punkten und den entsprechenden zweiten Ableitungen ist der durch sie verlaufende kubische Spline:(xj,yj)zj

Sj(x)=Ayj+Byj+1+Czj+Dzj+1
wobei Es ist ziemlich einfach zu überprüfen, , , und . Dies garantiert, dass der Spline und seine zweite Ableitung kontinuierlich sind. Zu diesem Zeitpunkt haben wir jedoch keine kontinuierliche erste Ableitung. Um die Kontinuität der ersten Ableitung zu erzwingen, benötigen wir die folgende Einschränkung:
hj=xj+1xjA=xj+1xhjB=1AC=16(A3A)hj2D=16(B3B)hj2
Sj(xj)=yjSj(xj+1)=yj+1Sj(xj)=zjSj(xj+1)=zj+1
(1)6hj1yj1(6hj1+6hj)yj+6hjyj+1=hj1zj1+2(hj1+hj)zj+hjzj+1
In der klassischen kubischen Spline- setzen Sie voraus, dass Sie die Punkte und verwenden Gleichung (zusammen mit zwei zusätzlichen Randbedingungen), um das zu lösen . Sobald Sie das , ist der Spline vollständig spezifiziert und Sie können ihn verwenden, um an einem beliebigen Punkt zu interpolieren. Als zusätzlichen Bonus ergibt Gleichung eine tridiagonale Matrix, die in linearer Zeit gelöst werden kann!(xj,yj)(1)zjzj(1)

OK, nun nehmen , Sie kennen das , anstatt das kennen . Können Sie Gleichung , um für das zu lösen ? Aus rein algebraischer Sicht scheint es machbar. Es gibt Gleichungen und Unbekannte, also ... warum nicht? Aber es stellt sich heraus, dass Sie nicht können; Die Matrix wird singulär sein. Und das sollte nicht überraschen. Wie könnten Sie möglicherweise die Funktionswerte bei NUR den zweiten Ableitungen interpolieren? Zumindest benötigen Sie einen Anfangswert, genau wie eine Differentialgleichung.yjzj(1)yjNN

Was ist mit deiner Situation? Einige Ihrer Punkte haben Funktionswerte und einige Ihrer Punkte haben Ableitungen. Lassen Sie uns vorerst die ersten Ableitungen ignorieren (sie sind eine Art Chaos, mit dem man sich auf der kubischen Spline-Basis befassen muss). Formal sei die Menge von Punkten mit Funktionswerten und die Menge von Punkten mit zweiten Ableitungen. Wir haben immer noch Gleichungen mit Unbekannten. Es ist nur so, dass einige der Unbekannten und einige . Es stellt sich heraus, dass Sie eine Lösung erhalten, wenn 0, 1 oder 2 UND oder(xi,yi),iI(xj,zj),jJNNyjzjIN3,N2N1I. Mit anderen Worten, einer der ersten drei Punkte muss ein Funktionswert sein UND einer der letzten drei Punkte muss ein Funktionswert sein. Abgesehen von dieser Einschränkung können Sie beliebig viele Derivate einsetzen.

Wie wäre es mit diesen ersten Derivaten? Es ist durchaus möglich, erste Ableitungen in Ihren Spline aufzunehmen. Aber wie gesagt, es wird viel unordentlicher. Die erste Ableitung des Splines ist gegeben durch: Natürlich interessieren wir uns nur für die Ableitung an den Knoten, daher können wir dies ein wenig vereinfachen, indem wir sie bei : Sie können diese hinzufügen Einschränkungen für die Matrix, die Sie aus Gleichung

Sj(x)=yj+1yjhj3A216hjzj+3B216hjzj+1
xj
Sj(xj)=yj+1yjhj13hjzj16hjzj+1
(1)und der resultierende Spline wird die angegebenen ersten Ableitungen haben. Darüber hinaus hilft dies beim Singular-Matrix-Problem. Sie erhalten eine Lösung, wenn Sie entweder einen Funktionswert oder eine erste Ableitung in den ersten drei und den letzten drei Punkten haben.

Also habe ich das alles in einem Code zusammengefasst und hier ist das Bild, das ich habe:

Spline ist furchtbar schief gelaufen

Wie Sie sehen können, sind die Ergebnisse nicht großartig. Das liegt daran, dass dies ein regulärer Spline ist, der ALLE Daten berücksichtigen muss. Da die Daten stochastisch sind, müssen wir wirklich einen Regressionsspline verwenden. Das ist ein Thema für einen anderen Beitrag. Aber wenn Sie die Mathematik durcharbeiten, werden Sie am Ende eine quadratische Zielfunktion optimieren, die linearen Gleichheitsbeschränkungen unterliegt - und es gibt eine geschlossene Formlösung!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.