Come posso adattare una spline a dati che contengono valori e derivazioni 1st / 2nd?


14

Ho un set di dati che contiene, diciamo, alcune misure per posizione, velocità e accelerazione. Tutti provengono dalla stessa "corsa". Potrei costruire un sistema lineare e adattare un polinomio a tutte quelle misurazioni.

Ma posso fare lo stesso con le spline? Qual è un modo "R" per farlo?

Ecco alcuni dati simulati che vorrei inserire:

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?

inserisci qui la descrizione dell'immagine


Non conosco la risposta alla tua domanda, ma splinefunposso calcolare derivati ​​e presumibilmente potresti usarlo come punto di partenza per adattare i dati usando alcuni metodi inversi? Sono interessato a imparare la soluzione a questo.
David LeBauer,

1
Questo problema è stato risolto da Maurice Cox nel suo articolo del 1972. Non so se R lo supporti, ma il termine di ricerca è "Spline di Hermite".
user14717

@DavidLeBauer questo è quello che sto facendo attualmente. Ho formalizzato un problema di ottimizzazione che si adatta a un numero di punti tale che la spline e i suoi derivati ​​approssimano i dati. Ma un metodo più diretto sarebbe fantastico.
dani,

3
Un approccio abbastanza standard è attraverso il filtro Kalman. Lo stato (non osservabile) contiene i derivati esatti e le osservazioni sono versioni rumorose di questi. Ad esempio, il modello per una spline cubica dice approssimativamente che la derivata del secondo ordine è un rumore bianco (tempo continuo), ma può anche essere usato un modello di ordine superiore. Dovrai descrivere il rumore di misurazione in base all'ordine di derivazione per l'osservazione corrente. Tre varianze di rumore (da stimare) possono essere sufficienti in un primo approccio.
Yves,

2
qual è l'errore di misurazione sui derivati? è molto più alto della posizione? anche nella tua trama perché i punti arent non sono allineati? cos'è l'asse x?
Aksakal,

Risposte:


9

Descriveremo come utilizzare una spline attraverso le tecniche di filtraggio Kalman (KF) in relazione a un modello spazio-stato (SSM). Il fatto che alcuni modelli di spline possano essere rappresentati da SSM e calcolati con KF è stato rivelato da CF Ansley e R. Kohn negli anni 1980-1990. La funzione stimata e i suoi derivati ​​sono le aspettative dello stato subordinate alle osservazioni. Queste stime vengono calcolate utilizzando un livellamento ad intervallo fisso , un'attività di routine quando si utilizza un SSM.

Per semplicità, supponiamo che le osservazioni siano fatte a volte t1<t2<<tn e che il numero di osservazione k at tk coinvolga solo una derivata con ordine dk in {0,1,2} . La parte di osservazione del modello scrive come

(O1)y(tk)=f[dk](tk)+ε(tk)
dovef(t) indica laverafunzionenon osservataeε(tk) è un errore gaussiano con varianzaH(tk) base all'ordine di derivazionedk. L'equazione di transizione (tempo continuo) assume la forma generale dove è il vettore di stato non osservato e è un rumore bianco gaussiano con covarianza , assunto come indipendente dal rumore di osservazione r.vs . Per descrivere una spline, consideriamo uno stato ottenuto impilando i primi derivati, ovvero . La transizione è
(T1)ddtα(t)=Aα(t)+η(t)
α(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 ) e quindi otteniamo una spline polinomiale con ordine (e grado ). Mentre corrisponde alla solita spline cubica,2m2m1m=2>1. Per attenerci a un formalismo SSM classico possiamo riscrivere (O1) come dove la matrice di osservazione seleziona la derivata adatta in e la varianza di viene scelta in base a . Quindi dove , e . Allo stesso modo
(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 3per tre varianze , e . H1H2H3

Sebbene la transizione avvenga in un tempo continuo, il KF è in realtà un tempo discreto standard . Infatti, ci sarà a fuoco pratica sui tempi di dove abbiamo un'osservazione, o dove vogliamo stimare i derivati. Possiamo considerare l'insieme come l'unione di questi due insiemi di tempi e supporre che l'osservazione in possa mancare: ciò consente di stimare le derivate in qualsiasi momento indipendentemente dall'esistenza di un'osservazione. Resta da derivare il SSM discreto.t{tk}tkmtk

Useremo gli indici per tempi discreti, scrivendo per e così via. L'MVU a tempo discreto assume la forma dove le matrici e sono derivati ​​da (T1) e (O2) mentre la varianza di è data da condizione cheαkα(tk)

(DT)αk+1=Tkαk+ηkyk=Zkαk+εk
TkQk:=Var(ηk)εkHk=Hdk+1yknon manca. Usando un po 'di algebra possiamo trovare la matrice di transizione per il SSM a tempo discreto dove per . Allo stesso modo la matrice di covarianza per il SSM a tempo discreto può essere data come
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
ij1m dove gli indici e sono compresi tra e .ij1m

Ora per portare avanti il ​​calcolo in R abbiamo bisogno di un pacchetto dedicato a KF e che accetti modelli variabili nel tempo; il pacchetto CRAN KFAS sembra una buona opzione. Possiamo scrivere funzioni R per calcolare le matrici e dal vettore dei tempi per codificare il SSM (DT). Nelle notazioni usate dal pacchetto, una matrice viene per moltiplicare il rumore nell'equazione di transizione di (DT): la prendiamo qui come identità . Si noti inoltre che una covarianza iniziale diffusa deve essere utilizzata qui.TkQktkRkηkIm

EDIT La come inizialmente scritta era sbagliata. Risolto (anche nel codice R e nell'immagine).Q

CF Ansley e R. Kohn (1986) "Sull'equivalenza di due approcci stocastici al livellamento della spline" J. Appl. Probab. , 23, pagg. 391–405

R. Kohn e CF Ansley (1987) "Un nuovo algoritmo per il livellamento della spline basato sul livellamento di un processo stocastico" SIAM J. Sci. e Stat. Comput. , 8 (1), pagg. 33–48

J. Helske (2017). "KFAS: modelli esponenziali dello spazio familiare in R" J. Stat. Morbido. , 78 (10), pagg. 1-39

levigante con derivati

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)
}

La ringrazio per la risposta. Sono molto interessato a questo. Attualmente, non si consente di avere il valore fe la sua derivata da utilizzare in alcuni casi t. Come è possibile utilizzare tutte le informazioni? Ancora una volta, merci per la tua risposta.
dani,

La mia lettura è che tutto sotto T1 riguarda l'uso di più derivati ​​nella stessa procedura di inferenza. Yves può confermare però.
eric_kernfeld,

In effetti, puoi usare le dire per un : l'osservazione è quindi un vettore e ha righe le derivate desiderate. Sono sicuro che un comune funziona con KFAS , ma usando NAs potrebbe essere possibile avere anche un tempo che varia . t k y k Z k o k o > 1 ook>1tkykZkoko>1o
Yves,

@Yves Ti ho capito bene: Se ho la prima e la seconda derivata nel punto in t_k, poi lo Z_k assomiglia a questo: matrix(c(0,0,0, 0,1,0, 0,0,1), nrow=length(d_k), ncol=m, byrow = T). Quindi, nel complesso, sarebbe un cubo di dimensione "massima derivata" * "grado spline" * "# di passi temporali"
dani,

Sì @dani, quasi: il numero di righe per tutte le matrici è cioè nell'esempio. Questo è l'ordine derivato più elevato più uno. Inoltre, il grado della spline è , non . Nel tuo esempio poiché non osservi la derivata dell'ordine (la funzione stessa) dovrebbe essere impostato su nelle osservazioni e potresti anche eliminare la prima riga. Tuttavia, sospetto che in questo caso specifico il problema non sia corretto, l'MVU potrebbe non essere osservabile . Zkmaxk{dk+1}32m1m0NA
Yves,

5

Puoi fare incredibilmente bene con una routine dei minimi quadrati standard, a patto di avere una ragionevole idea delle dimensioni relative degli errori casuali commessi per ogni derivata. Non vi è alcuna restrizione sul numero di misurazioni effettuate per ciascun valore : è anche possibile misurare simultaneamente derivati ​​diversi su ciascuno di essi. L'unica limitazione nell'uso degli Ordinary Least Squares (OLS) è la solita: si assume che le misurazioni siano indipendenti.x

L'idea di base può essere espressa più chiaramente astraggendo il problema. Il modello utilizza un set di funzioni (come qualsiasi base spline) come base per la previsione dei valori di una funzione sconosciuta in punti Ciò significa che si cerca di stimare i coefficienti per i quali ciascuna delle combinazioni lineari avvicina accettabilmente a Chiamiamo questo spazio (vettoriale) di combinazioni linearipfj:RR, j=1,2,,pyi=f(xi)f(x1,x2,,xn).βjjβjfj(xi)yi.F.

La particolarità di questo problema è che non osservi necessariamenteyi. Invece, esiste un set definito di funzionali lineari associati ai dati. Ricordiamo che una funzione è una "funzione di una funzione:" ogni assegna un numero a qualsiasi funzione Il modello presuppone cheLiLiLi[f]fF.

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

dove sono dati funzionali, sono noti fattori di scala e sono variabili casuali indipendenti e distribuite in modo identico.Liσi>0εi

Due ipotesi aggiuntive rendono OLS applicabile e statisticamente significativo:

  1. La distribuzione comune di ha una varianza finita.εi

  2. Ogni è una funzione lineare . Un funzionale è lineare quando per qualsiasi elemento e numeri corrispondentiLiLfjFαj,

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

(2) consente al modello di essere espresso in modo più esplicito come(1)

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

Il punto centrale di questa riduzione è che, poiché hai stipulato tutti i funzionali tutte le funzioni di base e le deviazioni standard i valori sono tutti numeri - -queste sono solo le solite "variabili" o "caratteristiche" di un problema di regressione - e sono semplicemente pesi (relativi). Pertanto, nel senso ottimale del teorema di Gauss-Markov, OLS è un'ottima procedura da utilizzare.Li,fj,σi,Li[fj]σi

I funzionali coinvolti nella domanda sono i seguenti:

  • Valuta in un punto specificato Questo è ciò che facciamo di solito. Questo è lineare perché, per definizione, le combinazioni lineari di funzioni vengono valutate in modo puntuale.fx: L[f]=f(x).

  • Valuta la derivata in un punto specificato Questo è lineare perché la differenziazione è lineare.fx: L[f]=f(x).

  • Valuta la seconda derivata in un punto specificatofx: L[f]=f(x).


Va bene, come funziona questo approccio? Come al solito, studieremo i residui confrontando i valori adattati con i valori osservati. Poiché posizioni, velocità e accelerazioni sono tutte in unità diverse, dovrebbero essere tracciate su assi separati.y^iyiy^i

figura

La riga superiore utilizza le curve per rappresentare graficamente e le sue prime due derivate. I punti dati rilevanti sono tracciati sopra le curve: valori osservati a sinistra, derivati ​​osservati nel mezzo e secondi derivati ​​osservati a destra.y^

La riga inferiore traccia i residui corrispondenti. Come al solito, stiamo cercando una mancanza di qualsiasi relazione apprezzabile: speriamo che i valori residui (le loro coordinate y) variano casualmente da sinistra a destra, mostrando indipendenza e nessuna tendenza.

I valori di dati sono stati generati esattamente come nella domanda (dopo aver impostato il seme di numero casuale su 17 usando per riproducibilità). Ho esplorato accoppiamenti usando gli spazi B-spline generati dalla funzione , anche come nella domanda, per gradi da 1 a 6. Questa figura mostra i risultati per il grado 2, che è il grado più basso (cioè il modello più semplice) esibendo un basso AIC e un buon comportamento residuo, così come il modello indicato da un ANOVA di tutti e sei i modelli (nidificati).n=23set.seed(17)FRbs

La misura è

y^=27.48993+2.54078f1+2.97679f2

dove e sono le funzioni di base B-spline create da .f1f2bs

I residui si comportano bene. Gli attacchi sono buoni. Inoltre, questo approccio ha trovato il modello corretto : i dati sono stati effettivamente generati da una funzione quadratica (grado 2). Inoltre, le deviazioni standard dei residui sono circa delle giuste dimensioni: 0,11, 0,20 e 0,61 rispetto a 0,1, 0,3 e 0,6 utilizzati per generare gli errori originali. È piuttosto sorprendente dato che queste curve ovviamente estrapolano le osservazioni (che non vanno oltre ) e usano un set di dati così piccolo ( ).x=5n=23

Infine, i residui degli attacchi per spline di grado superiore sono qualitativamente gli stessi; apportano solo lievi miglioramenti a un costo di utilizzo di modelli meno plausibili. Per gradi sufficientemente alti, iniziano ad oscillare selvaggiamente per piccoli valori di tra i valori osservati, per esempio. Per illustrare questo (cattivo) comportamento, ecco la misura di grado 9:x

figura 2

Infine, ecco un esempio in cui sono state fatte più osservazioni di vari funzionali lineari della base. Il codice per generare queste osservazioni è stato modificato da quello della domanda a

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

Figura 3


Il Rcodice per eseguire questi calcoli è piuttosto generale. In particolare, utilizza la differenziazione numerica per trovare le derivate in modo che non dipenda dal tipo di spline utilizzato. Gestisce i diversi valori di ponderando le osservazioni in modo proporzionale a Costruisce e adatta automaticamente una serie di modelli in un ciclo. I funzionali lineari e le deviazioni standard sono codificati. Ce ne sono tre per ciascuno, selezionati in base al valore della variabile nel set di dati.σi1/σi2.Liσitype

Come esempi di come è possibile utilizzare gli adattamenti, la coda stampa i riepiloghi, un elenco dei loro AIC e un ANOVA di tutti.

#
# 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

Prima di tutto, voglio ringraziarti per aver posto questa domanda. È una domanda DAVVERO interessante. Adoro le spline e le cose fantastiche che puoi fare con loro. E questo mi ha dato una scusa per fare qualche ricerca. :-)

BLUF: la risposta breve è no. Non conosco alcuna funzionalità in R che lo farà automaticamente per te. La lunga risposta è ... molto più complicata. Il fatto che le derivate e i valori delle funzioni non siano campionati nello stesso posto rende questo più difficile. E il fatto che non si abbia un valore di funzione vicino all'estremità destra dell'intervallo potrebbe renderlo impossibile.

Cominciamo con la spline cubica. Dati punti e le corrispondenti seconde derivate , la spline cubica che li attraversa è:(xj,yj)zj

Sj(x)=Ayj+Byj+1+Czj+Dzj+1
dove È abbastanza semplice verificare che , , e . Ciò garantisce che la spline e il suo secondo derivato siano continui. Tuttavia, a questo punto, non abbiamo una prima derivata continua . Per forzare la prima derivata a essere continua, abbiamo bisogno del seguente vincolo:
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
Nella classica configurazione della spline cubica, supponi di avere i punti e usi l'equazione (insieme a due vincoli di confine aggiuntivi) per risolvere lo . Una volta che conosci , la spline è completamente specificata e puoi usarla per interpolare in qualsiasi punto arbitrario. Come bonus aggiuntivo, l'equazione si trasforma in una matrice tridiagonale che può essere risolta in tempo lineare!(xj,yj)(1)zjzj(1)

OK, ora supponiamo che, invece di conoscere , tu conosca . Puoi usare l'equazione per risolvere per ? Dal punto di vista dell'algebra pura, sembra fattibile. Ci sono equazioni e incognite, quindi ... perché no? Ma si scopre che non puoi; la matrice sarà singolare. E questo non dovrebbe sorprendere. Come potresti eventualmente interpolare i valori della funzione dati SOLO le seconde derivate? Come minimo, avresti bisogno di un valore iniziale, proprio come un'equazione differenziale.yjzj(1)yjNN

E la tua situazione? Alcuni dei tuoi punti hanno valori di funzione e alcuni dei tuoi punti hanno delle derivate. Per il momento, ignoriamo i primi derivati ​​(sono una specie di pasticcio da affrontare nella base della spline cubica). Formalmente, sia sia l'insieme di punti con valori di funzione e sia l'insieme di punti con seconde derivate. Abbiamo ancora equazioni con incognite. È solo che alcune delle incognite sono e alcune sono . Si scopre che otterrai una soluzione se 0, 1 o 2 E o(xi,yi),iI(xj,zj),jJNNyjzjIN3,N2N1I. In altre parole, uno dei primi tre punti deve essere un valore di funzione E uno degli ultimi tre punti deve essere un valore di funzione. A parte questo vincolo, sei libero di inserire tutti i derivati ​​che desideri.

Che ne dici di quei primi derivati? È certamente possibile includere i primi derivati ​​nella spline. Ma, come ho detto, diventa molto più disordinato. La prima derivata della spline è data da: Naturalmente, siamo davvero interessati alla derivata ai nodi, quindi possiamo semplificare un po 'valutandola in : Puoi aggiungere questi vincoli alla matrice dall'equazione

Sj(x)=yj+1yjhj3A216hjzj+3B216hjzj+1
xj
Sj(xj)=yj+1yjhj13hjzj16hjzj+1
(1)e la spline risultante avrà i primi derivati ​​specificati. Inoltre, questo aiuterà con il problema della matrice singolare. Otterrai una soluzione se hai ORA un valore di funzione o una prima derivata nei primi tre e ultimi tre punti.

Quindi ho messo tutto insieme in un po 'di codice ed ecco l'immagine che ho ottenuto:

Spline è andata terribilmente storto

Come puoi vedere, i risultati non sono eccezionali. Questo perché si tratta di una spline regolare che deve onorare TUTTI i dati. Poiché i dati sono stocastici, abbiamo davvero bisogno di usare una spline di regressione. Questo è un argomento per un altro post. Ma se lavori attraverso la matematica, finirai per ottimizzare una funzione quadratica dell'obiettivo soggetta a vincoli di uguaglianza lineare - e c'è una soluzione a forma chiusa!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.