Comment ajuster une spline à des données contenant des valeurs et des dérivées 1/2?


14

J'ai un ensemble de données qui contient, disons, des mesures de position, de vitesse et d'accélération. Tous viennent du même "run". Je pourrais construire un système linéaire et adapter un polynôme à toutes ces mesures.

Mais puis-je faire de même avec les splines? Qu'est-ce qu'une façon «R» de procéder?

Voici quelques données simulées que j'aimerais intégrer:

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?

entrez la description de l'image ici


Je ne connais pas la réponse à votre question, mais splinefunpouvez-vous calculer des dérivées et vous pourriez probablement l'utiliser comme point de départ pour ajuster les données en utilisant des méthodes inverses? Je suis intéressé d'apprendre la solution à cela.
David LeBauer

1
Ce problème a été résolu par Maurice Cox dans son article de 1972. Je ne sais pas si R le supporte, mais le terme de recherche est "splines Hermite".
user14717

@DavidLeBauer c'est ce que je fais actuellement. J'ai formalisé un problème d'optimisation qui correspond à un certain nombre de points tels que la spline et ses dérivés se rapprochent des données. Mais une méthode plus directe serait formidable.
dani

3
Une approche assez standard est le filtrage de Kalman. L'état (non observable) contient les dérivées exactes et les observations en sont des versions bruyantes. Par exemple, le modèle d'une spline cubique indique à peu près que la dérivée de second ordre est un bruit blanc (en temps continu), mais un modèle d'ordre supérieur peut également être utilisé. Vous devrez décrire le bruit de mesure en fonction de l'ordre de dérivation pour l'observation en cours. Trois variances de bruit (à estimer) peuvent suffire dans une première approche.
Yves

2
qu'est-ce qu'une erreur de mesure sur les dérivés? est-il beaucoup plus élevé que la position? aussi dans votre intrigue pourquoi les points ne sont-ils pas alignés? qu'est-ce que l'axe x?
Aksakal

Réponses:


9

Nous décrirons comment une spline peut être utilisée par des techniques de filtrage de Kalman (KF) en relation avec un modèle d'état-espace (SSM). Le fait que certains modèles de splines puissent être représentés par SSM et calculés avec KF a été révélé par CF Ansley et R. Kohn dans les années 1980-1990. La fonction estimée et ses dérivées sont les attentes de l'état conditionnées par les observations. Ces estimations sont calculées en utilisant un lissage à intervalle fixe , une tâche de routine lors de l'utilisation d'un SSM.

Par souci de simplicité, supposons que les observations soient faites aux instants et que le nombre d'observation à n'implique qu'une seule dérivée d'ordre dans . La partie observation du modèle s'écrit comme où dénote la fonction vraie non observée et est une erreur gaussienne de variance fonction de l'ordre de dérivation . L'équation de transition (temps continu) prend la forme générale t1<t2<<tnktkd k { 0 ,dk{0,1,2}

(O1)y(tk)=f[dk](tk)+ε(tk)
f(t)ε ( t k ) H ( t k ) d kε(tk)H(tk)dk
(T1)ddtα(t)=Aα(t)+η(t)
α(t)η(t)Qε(tk)mα(t):=[f(t), où est le vecteur d'état non observé et est un bruit blanc gaussien de covariance , supposé indépendant du bruit d'observation r.vs . Pour décrire une spline, nous considérons un état obtenu en empilant les premières dérivées, à savoir . La transition est α(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 ) et on obtient alors une spline polynomiale d'ordre (et degré ). Alors que correspond à la spline cubique habituelle,2m2m1m=2>1. Afin de nous en tenir au formalisme SSM classique, nous pouvons réécrire (O1) sous la forme où la matrice d'observation sélectionne la dérivée appropriée dans et la variance de est choisie en fonction de . Donc où , et . De même
(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 3pour trois variances , et . H1H2H3

Bien que la transition soit en temps continu, le KF est en fait un temps discret standard . En effet, nous nous concentrerons en pratique sur les moments où nous avons une observation, ou où nous voulons estimer les dérivées. On peut prendre l'ensemble comme l'union de ces deux ensembles de temps et supposer que l'observation à peut être manquante: cela permet d'estimer les dérivées à tout instant quelle que soit l'existence d'une observation. Il reste à dériver le SSM discret.t{tk}tkmtk

Nous utiliserons des indices pour les temps discrets, en écrivant pour et ainsi de suite. Le SSM à temps discret prend la forme où les matrices et sont dérivés de (T1) et (O2) tandis que la variance de est donnée par condition queαkα(tk)

(DT)αk+1=Tkαk+ηkyk=Zkαk+εk
TkQk:=Var(ηk)εkHk=Hdk+1ykTk=exp{δkA}=[ 1 δ 1 kne manque pas. En utilisant une algèbre, nous pouvons trouver la matrice de transition pour le SSM à temps discret où pour . De même, la matrice de covariance pour le SSM à temps discret peut être donnée comme
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
où les indices et sont compris entre et .ij1m

Maintenant, pour reporter le calcul dans R, nous avons besoin d'un package dédié à KF et acceptant des modèles variant dans le temps; le package CRAN KFAS semble une bonne option. Nous pouvons écrire des fonctions R pour calculer les matrices et partir du vecteur de temps afin de coder le SSM (DT). Dans les notations utilisées par le package, une matrice vient multiplier le bruit dans l'équation de transition de (DT): on la prend ici pour être l'identité . Notez également qu'une covariance initiale diffuse doit être utilisée ici.TkQktkRkηkIm

EDIT L' telle qu'écrite initialement était incorrecte. Fixe (également dans le code R et l'image).Q

CF Ansley et R. Kohn (1986) "Sur l'équivalence de deux approches stochastiques du lissage des splines" J. Appl. Probab. , 23, pp. 391–405

R. Kohn et CF Ansley (1987) "Un nouvel algorithme pour le lissage de spline basé sur le lissage d'un processus stochastique" SIAM J. Sci. et Stat. Comput. , 8 (1), pp. 33–48

J.Helske (2017). "KFAS: Modèles d'espace d'états familiaux exponentiels dans R" J. Stat. Doux. , 78 (10), pp. 1-39

lissage avec dérivés

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

Merci pour votre réponse. Ça m'intéresse beaucoup. Actuellement, vous ne permettez pas que la valeur fet son dérivé soient utilisés à un certain degré t. Comment est-il possible d'utiliser toutes les informations? Encore une fois, merci pour votre réponse.
dani

Ma lecture est que tout en dessous de T1 concerne l'utilisation de plusieurs dérivés dans la même procédure d'inférence. Yves peut cependant confirmer.
eric_kernfeld

En effet, vous pouvez utiliser disons dérivées pour un : l'observation est alors un vecteur et a lignes choisissant les dérivées désirées. Je suis sûr qu'un commun fonctionne avec KFAS , mais en utilisant les NA, il peut également être possible d'avoir un temps variant . ok>1tkykZkoko>1o
Yves

@Yves Est - ce que je vous comprends bien: Si je le premier et le deuxième dérivé au point t_k, le Z_k ressemble à ceci: matrix(c(0,0,0, 0,1,0, 0,0,1), nrow=length(d_k), ncol=m, byrow = T). Donc, dans l'ensemble, ce serait un cube de dimension 'dérivée la plus élevée' * 'degré de spline' * '# de pas de temps'
dani

Oui @dani, presque: le nombre de lignes pour toutes les matrices est soit dans l'exemple. Il s'agit de l'ordre dérivé le plus élevé plus un. De plus, le degré de la spline est de , pas de . Dans votre exemple, puisque vous n'observez pas la dérivée d'ordre (la fonction elle-même), elle doit être définie dans les observations et vous pouvez également supprimer la première ligne. Cependant, je soupçonne que dans ce cas spécifique, le problème est mal posé, le SSM peut ne pas être observable . Zkmaxk{dk+1}32m1m0NA
Yves

5

Vous pouvez très bien faire avec une routine des moindres carrés standard, à condition d'avoir une idée raisonnable de la taille relative des erreurs aléatoires commises pour chaque dérivée. Il n'y a aucune restriction sur le nombre de mesures que vous effectuez pour chaque valeur - vous pouvez même mesurer simultanément différentes dérivées sur chacune. La seule limitation dans l'utilisation des moindres carrés ordinaires (OLS) est l'ordinaire: vous supposez que les mesures sont indépendantes.x

L'idée de base peut être exprimée le plus clairement en faisant abstraction du problème. Votre modèle utilise un ensemble de fonctions (comme toute base spline) comme base pour prédire les valeurs d'une fonction inconnue aux points Cela signifie que vous cherchez à estimer les coefficients pour lesquels chacune des combinaisons linéaires approximativement à Appelons cet espace (vectoriel) de combinaisons linéairespfj:RR, j=1,2,,pyi=f(xi)f(x1,x2,,xn).βjjβjfj(xi)yi.F.

La particularité de ce problème est que vous n'observez pas nécessairement leyi. Au lieu de cela, un ensemble défini de fonctionnelles linéaires associé aux données. Rappelons qu'une fonction est une "fonction d'une fonction:" chaque attribue un nombre à n'importe quelle fonction Le modèle postule queLiLiLi[f]fF.

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

où les reçoivent des fonctionnelles, les sont des facteurs d'échelle connus et les sont des variables aléatoires indépendantes et identiquement distribuées.Liσi>0εi

Deux hypothèses supplémentaires rendent l'OLS applicable et statistiquement significatif:

  1. La distribution commune de a une variance finie.εi

  2. Chaque est une fonction linéaire . Un est linéaire lorsque pour tout élément et les nombres correspondantsLiLfjFαj,

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

(2) permet au modèle d'être exprimé plus explicitement sous la forme(1)

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

L'intérêt de cette réduction est que parce que vous avez spécifié toutes les fonctionnelles toutes les fonctions de base et les écarts-types les valeurs sont tous des nombres - - ce ne sont que les "variables" ou "caractéristiques" habituelles d'un problème de régression - et les ne sont que des poids (relatifs). Ainsi, dans le sens optimal du théorème de Gauss-Markov, OLS est une excellente procédure à utiliser.Li,fj,σi,Li[fj]σi

Les fonctionnels impliqués dans la question sont les suivants:

  • Évaluez à un point spécifié C'est ce que nous faisons habituellement. Ceci est linéaire car, par définition, les combinaisons linéaires de fonctions sont évaluées ponctuellement.fx: L[f]=f(x).

  • Évaluez la dérivée à un point spécifié C'est linéaire car la différenciation est linéaire.fx: L[f]=f(x).

  • Évaluez la dérivée seconde à un point spécifiéfx: L[f]=f(x).


D'accord, comment fonctionne cette approche? Comme d'habitude, nous étudierons les résidus comparant les valeurs ajustées aux valeurs observées. Comme les positions, les vitesses et les accélérations sont toutes dans des unités différentes, elles doivent être tracées sur des axes séparés.y^iyiy^i

Figure

La ligne du haut utilise des courbes pour représenter graphiquement et ses deux premières dérivées. Les points de données pertinents sont tracés sur les courbes: valeurs observées à gauche, dérivées observées au milieu et dérivées secondes observées à droite.y^

La ligne du bas représente les résidus correspondants. Comme d'habitude, nous recherchons un manque de toute relation appréciable: nous espérons que les valeurs résiduelles (leurs coordonnées y) varient aléatoirement de gauche à droite, montrant une indépendance et aucune tendance.

Les valeurs de données ont été générées exactement comme dans la question (après avoir défini la valeur de départ aléatoire à 17 en utilisant pour la reproductibilité). J'ai exploré les ajustements en utilisant les espaces B-spline générés par la fonction , également comme dans la question, pour les degrés 1 à 6. Cette figure montre les résultats pour le degré 2, qui est le degré le plus bas (c'est-à-dire le modèle le plus simple) présentant un faible AIC et un bon comportement résiduel, ainsi que le modèle indiqué par une ANOVA des six modèles (imbriqués).n=23set.seed(17)FRbs

L'ajustement est

y^=27.48993+2.54078f1+2.97679f2

où et sont les fonctions de base B-spline créées par .f1f2bs

Les résidus se comportent bien. Les ajustements sont bons. De plus, cette approche a trouvé le bon modèle: les données étaient en effet générées à partir d'une fonction quadratique (degré 2). De plus, les écarts-types des résidus sont à peu près de la bonne taille: 0,11, 0,20 et 0,61 par rapport à 0,1, 0,3 et 0,6 utilisés pour générer les erreurs d'origine. C'est assez étonnant étant donné que ces courbes extrapolent évidemment les observations (qui ne vont pas au-delà de ) et utilisent un si petit ensemble de données ( ).x=5n=23

Enfin, les résidus aux ajustements pour les splines de degré supérieur sont qualitativement les mêmes; ils n'apportent que de légères améliorations au prix de l'utilisation de modèles moins plausibles. Pour des degrés suffisamment élevés, ils commencent à osciller énormément pour de petites valeurs de entre les valeurs observées, par exemple. Pour illustrer ce (mauvais) comportement, voici l'ajustement de degré 9:x

Figure 2

Enfin, voici un exemple où plusieurs observations de diverses fonctions linéaires de la base ont été faites. Le code pour générer ces observations a été changé de celui de la question à

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

figure 3


Le Rcode pour effectuer ces calculs est assez général. En particulier, il utilise la différenciation numérique pour trouver les dérivées afin qu'il ne dépende pas du type de spline utilisé. Il gère les valeurs différentes de en pondérant les observations proportionnellement à Il construit et ajuste automatiquement un ensemble de modèles dans une boucle. Les fonctionnelles linéaires et les écarts-types sont codés en dur. Il y en a trois de chaque, sélectionnés en fonction de la valeur de la variable dans l'ensemble de données.σi1/σi2.Liσitype

Comme exemples de la façon dont vous pouvez utiliser les ajustements, la coda imprime des résumés, une liste de leurs AIC et une ANOVA de tous.

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

Tout d'abord, je tiens à vous remercier d'avoir posé cette question. C'est une question vraiment intéressante. J'adore les splines et les choses sympas que vous pouvez en faire. Et cela m'a donné une excuse pour faire des recherches. :-)

BLUF: La réponse courte est non. Je ne connais aucune fonctionnalité de R qui le fera automatiquement pour vous. La réponse longue est ... beaucoup plus compliquée. Le fait que les dérivées et les valeurs des fonctions ne soient pas échantillonnées au même endroit rend cela plus difficile. Et le fait que vous n'ayez pas de valeur de fonction près de l'extrémité droite de l'intervalle peut le rendre impossible.

Commençons par la spline cubique. Étant donné les points et les dérivées secondes correspondantes , la spline cubique les traversant est:(xj,yj)zj

Sj(x)=Ayj+Byj+1+Czj+Dzj+1
où Il est assez simple de vérifier que , , et . Cela garantit que la spline et sa dérivée seconde sont continues. Cependant, à ce stade, nous n'avons pas de dérivée première continue . Pour forcer la dérivée première à être continue, nous avons besoin de la contrainte suivante:
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
Dans la configuration de spline cubique classique, vous supposez que vous avez les points et utilisez l'équation (avec deux contraintes de frontière supplémentaires) pour résoudre le . Une fois que vous connaissez le , la spline est entièrement spécifiée et vous pouvez l'utiliser pour interpoler à n'importe quel point arbitraire. En prime, l'équation se transforme en une matrice tridiagonale qui peut être résolue en temps linéaire!(xj,yj)(1)zjzj(1)

OK, supposons maintenant qu'au lieu de connaître le , vous connaissez le . Pouvez-vous utiliser l'équation pour résoudre le ? Du point de vue de l'algèbre pure, cela semble faisable. Il y a équations et inconnues, alors ... pourquoi pas? Mais il s'avère que vous ne pouvez pas; la matrice sera singulière. Et cela ne devrait pas surprendre. Comment pourriez-vous éventuellement interpoler les valeurs des fonctions étant donné JUSTE les dérivées secondes? À tout le moins, vous auriez besoin d'une valeur initiale, tout comme une équation différentielle.yjzj(1)yjNN

Et ta situation? Certains de vos points ont des valeurs de fonction et certains de vos points ont des dérivés. Pour le moment, ignorons les premières dérivées (elles sont en quelque sorte un gâchis à gérer dans la base de la spline cubique). Formellement, soit soit l'ensemble de points avec des valeurs de fonction et soit l'ensemble de points avec des dérivées secondes. Nous avons encore équations avec inconnues. C'est juste que certaines des inconnues sont et certaines sont . Il s'avère que vous obtiendrez une solution si 0, 1 ou 2 ET ou(xi,yi),iI(xj,zj),jJNNyjzjIN3,N2N1I. En d'autres termes, l'un des trois premiers points doit être une valeur de fonction ET l'un des trois derniers points doit être une valeur de fonction. En dehors de cette contrainte, vous êtes libre de lancer autant de dérivés que vous le souhaitez.

Et ces premiers dérivés? Il est certainement possible d'inclure des dérivés premiers dans votre spline. Mais, comme je l'ai dit, cela devient beaucoup plus compliqué. La dérivée première de la spline est donnée par: Bien sûr, nous ne sommes vraiment intéressés par la dérivée qu'aux nœuds, donc nous pouvons simplifier un peu cela en l'évaluant à : Vous pouvez ajouter ces contraintes à la matrice que vous obtenez de l'équation

Sj(x)=yj+1yjhj3A216hjzj+3B216hjzj+1
xj
Sj(xj)=yj+1yjhj13hjzj16hjzj+1
(1)et la spline résultante aura les premières dérivées spécifiées. De plus, cela aidera avec le problème de la matrice singulière. Vous obtiendrez une solution si vous avez SOIT une valeur de fonction ou une dérivée première dans les trois premiers et les trois derniers points.

J'ai donc mis tout cela ensemble dans du code et voici l'image que j'ai obtenue:

La spline a mal tourné

Comme vous pouvez le voir, les résultats ne sont pas excellents. C'est parce que c'est une spline régulière qui doit honorer TOUTES les données. Comme les données sont stochastiques, nous devons vraiment utiliser une spline de régression. C'est un sujet pour un autre article. Mais si vous travaillez à travers les mathématiques, vous finirez par optimiser une fonction d'objectif quadratique soumise à des contraintes d'égalité linéaires - et il existe une solution de forme fermée!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.