Como posso ajustar um spline aos dados que contêm valores e derivações da 1ª / 2ª?


13

Eu tenho um conjunto de dados que contém, digamos, algumas medidas de posição, velocidade e aceleração. Todos vêm da mesma "corrida". Eu poderia construir um sistema linear e ajustar um polinômio a todas essas medidas.

Mas posso fazer o mesmo com splines? O que é uma maneira 'R' de fazer isso?

Aqui estão alguns dados simulados que eu gostaria de ajustar:

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?

insira a descrição da imagem aqui


Não sei a resposta para sua pergunta, mas splinefunposso calcular derivativos e, presumivelmente, você pode usar isso como ponto de partida para ajustar os dados usando alguns métodos inversos? Estou interessado em aprender a solução para isso.
David LeBauer 27/09/19

1
Este problema foi resolvido por Maurice Cox em seu artigo de 1972. Não sei se R suporta, mas o termo de pesquisa é "Hermite splines".
user14717

@DavidLeBauer é isso que estou fazendo atualmente. Eu formalizei um problema de otimização que se encaixa em vários pontos, de modo que o spline e seus derivados se aproximem dos dados. Mas um método mais direto seria ótimo.
dani

3
Uma abordagem bastante padrão é através da filtragem Kalman. O estado (não observável) contém as derivadas exatas e as observações são versões ruidosas delas. Por exemplo, o modelo para uma spline cúbica informa aproximadamente que a derivada de segunda ordem é um ruído branco (tempo contínuo), mas um modelo de ordem superior também pode ser usado. Você terá que descrever o ruído de medição, dependendo da ordem de derivação da observação atual. Três variações de ruído (a serem estimadas) podem ser suficientes em uma primeira abordagem.
Yves

2
o que é erro de medição em derivativos? é muito maior que a posição? Também na sua trama, por que os pontos não estão alinhados? o que é o eixo x?
Aksakal

Respostas:


8

Descreveremos como um spline pode ser usado através das técnicas de Kalman Filtering (KF) em relação a um modelo de espaço de estado (SSM). O fato de que alguns modelos de splines podem ser representados por SSM e computados com KF foi revelado por CF Ansley e R. Kohn nos anos 1980-1990. A função estimada e seus derivados são as expectativas do estado, condicionadas às observações. Essas estimativas são calculadas usando uma suavização de intervalo fixo , uma tarefa de rotina ao usar um SSM.

Por uma questão de simplicidade, suponha que as observações sejam feitas às vezes e que o número de observação em envolva apenas uma derivada com a ordem em . A parte de observação do modelo escreve como que indica a função verdadeira não observada e é um erro gaussiano com variação dependendo da ordem de derivação . A equação de transição (tempo contínuo) assume a forma geral 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 dε(tk)H(tk)dk
(T1)ddtα(t)=Aα(t)+η(t)
onde é o vetor de estado não observado e é um ruído branco gaussiano com covariância , considerado independente da ruído de observação r.vs . Para descrever um spline, consideramos um estado obtido empilhando as primeiras derivadas, ou seja, . A transição é α(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)]
e, em seguida, obtemos um spline polinomial com a ordem (e o grau ). Enquanto corresponde ao spline cúbico usual,2m2m-1m=2>1 ano ( t k ) 2m2m1m=2>1. Para manter um formalismo clássico do SSM, podemos reescrever (O1) como onde a matriz de observação seleciona a derivada adequada em e a variação de é escolhida dependendo de . Então onde , e . Da mesma forma,
(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 3para três variações , e . H1H2H3

Embora a transição seja em tempo contínuo, o KF é realmente um tempo discreto padrão . Na verdade, nós o faremos na prática foco em tempos onde temos uma observação, ou onde queremos estimar os derivados. Podemos considerar o conjunto como a união desses dois conjuntos de tempos e assumir que a observação em pode estar ausente: isso permite estimar as derivadas a qualquer momento independentemente da existência de uma observação. Resta derivar o SSM discreto.t{tk}tkmtk

Usaremos índices para tempos discretos, escrevendo para e assim por diante. O SSM em tempo discreto assume o formato onde as matrizes e são derivados de (T1) e (O2) enquanto a variação de é dada por desde queαkα(tk)

(DT)αk+1=Tkαk+ηkyk=Zkαk+εk
TkQk:=Var(ηk)εkHk=Hdk+1yknão está faltando. Usando alguma álgebra, podemos encontrar a matriz de transição para o SSM onde para . Da mesma forma, a matriz de covariância para o SSM em tempo discreto pode ser fornecida como
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
onde os índices e são entre e .ij1m

Agora, para continuar a computação em R, precisamos de um pacote dedicado ao KF e aceitar modelos que variam no tempo; o pacote CRAN KFAS parece uma boa opção. Podemos escrever funções R para calcular as matrizes e partir do vetor de tempos para codificar o SSM (DT). Nas notações usadas pelo pacote, uma matriz vem para multiplicar o ruído na equação de transição de (DT): consideramos aqui a identidade . Observe também que uma covariância inicial difusa deve ser usada aqui.TkQktkRkηkIm

EDIT A como inicialmente escrita estava errada. Corrigido (também no código R e imagem).Q

CF Ansley e R. Kohn (1986) "Sobre a equivalência de duas abordagens estocásticas para suavização de estrias" J. Appl. Probab. , 23, pp. 391-405

R. Kohn e CF Ansley (1987) "Um Novo Algoritmo para Suavização de Spline Baseado no Suavização de um Processo Estocástico" SIAM J. Sci. e Stat. Comput. , 8 (1), pp. 33–48

J. Helske (2017). "KFAS: Modelos exponenciais de espaço de estado da família em R" J. Stat. Suave. , 78 (10), p. 1-39

alisamento com derivados

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

Obrigado pela sua resposta. Estou muito interessado nisso. Atualmente, você não permite que o valor fe sua derivada sejam utilizados de alguma maneira t. Como é possível usar todas as informações? Mais uma vez, busque sua resposta.
dani

Minha leitura é que tudo abaixo de T1 é sobre o uso de múltiplas derivadas no mesmo procedimento de inferência. Yves pode confirmar.
Eric_kernfeld 03/10/19

De fato, você pode usar dizer derivadas para um : a observação é então um vetor e tem linhas escolhendo as derivadas desejadas. Estou certo de que um comum trabalhos com KFAS , mas usando AN pode ser possível ter um tempo variando bem. t k y k Z k o k o > 1 ook>1tkykZkoko>1o
Yves

@Yves Eu entendi corretamente: Se eu tiver a primeira e segunda derivada no ponto em t_k, então o Z_k parece com isso: matrix(c(0,0,0, 0,1,0, 0,0,1), nrow=length(d_k), ncol=m, byrow = T). Assim, em geral, seria um cubo de dimensão 'maior derivada' * 'grau spline' * '# de passos de tempo'
dani

Sim @dani, quase: o número de linhas para todas as matrizes é ou seja, no exemplo. Essa é a ordem derivada mais alta mais uma. Além disso, o grau do spline é , não . No seu exemplo, como você não observa a derivada da ordem (a própria função), ela deve ser configurada nas observações e você também pode descartar a primeira linha. No entanto, suspeito que, neste caso específico, o problema esteja incorreto, o SSM pode não ser observável . max k { d k +1}32m-1m0Zkmaxk{dk+1}32m1m0NA
Yves

4

Você pode se sair espetacularmente bem com uma rotina padrão de mínimos quadrados, desde que tenha uma idéia razoável dos tamanhos relativos dos erros aleatórios cometidos para cada derivada. Não há restrição quanto ao número de medições que você faz para cada valor - você pode até medir simultaneamente diferentes derivadas em cada uma. A única limitação no uso dos mínimos quadrados ordinários (OLS) é a usual: você assume que as medidas são independentes.x

A idéia básica pode ser expressa com mais clareza abstraindo o problema. Seu modelo usa um conjunto de funções (como qualquer base de spline) como base para prever os valores de uma função desconhecida nos pontos Isso significa que você procura estimar os coeficientes para os quais cada uma das combinações lineares aproxima de maneira aceitável de Vamos chamar esse espaço (vetor) de combinações linearespfj:RR, j=1,2,,pyi=f(xi)f(x1,x2,,xn).βjjβjfj(xi)yi.F.

O que há de especial nesse problema é que você não observa necessariamente oyi. Em vez disso, existe um conjunto definido de funcionais lineares associado aos dados. Lembre-se de que uma funcional é uma "função de uma função:" cada atribui um número a qualquer função O modelo postula queLiLiLi[f]fF.

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

onde os recebem funcionais, os são fatores de escala conhecidos e são variáveis ​​aleatórias independentes e identicamente distribuídas.Liσi>0εi

Duas suposições adicionais tornam o OLS aplicável e estatisticamente significativo:

  1. A distribuição comum do tem uma variação finita.εi

  2. Todo é uma funcionalidade linear . Um funcional é linear quando, para qualquer elemento e números correspondentesLiLfjFαj,

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

(2) permite que o modelo seja expresso mais explicitamente como(1)

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

O ponto principal dessa redução é que, como você estipulou todos os funcionais todas as funções e os desvios padrão os valores são todos números - - essas são apenas as "variáveis" ou "características" usuais de um problema de regressão - e o são meros pesos (relativos). Assim, no sentido ideal do teorema de Gauss-Markov, o OLS é um ótimo procedimento para usar.Li,fj,σi,Li[fj]σi

Os funcionais envolvidos na pergunta são os seguintes:

  • Avalie em um ponto especificado É o que costumamos fazer. Isso é linear porque, por definição, combinações lineares de funções são avaliadas pontualmente.fx: L[f]=f(x).

  • Avalie a derivada em um ponto especificado Isso é linear porque a diferenciação é linear.fx: L[f]=f(x).

  • Avalie a segunda derivada em um ponto especificadofx: L[f]=f(x).


Ok, quão bem essa abordagem funciona? Como sempre, estudaremos os resíduos comparando os valores ajustados com os valores observados. Como posições, velocidades e acelerações estão todas em unidades diferentes, elas devem ser plotadas em eixos separados.y^iyiy^i

Figura

A linha superior usa curvas para representar graficamente e suas duas primeiras derivadas. Os pontos de dados relevantes são plotados sobre as curvas: valores observados à esquerda, derivadas observadas no meio e segundas derivadas observadas à direita.y^

A linha inferior plota os resíduos correspondentes. Como sempre, estamos procurando uma falta de relação apreciável: esperamos que os valores residuais (suas coordenadas y) variem aleatoriamente da esquerda para a direita, mostrando independência e sem tendências.

Os valores de dados foram gerados exatamente como na pergunta (depois de definir a semente do número aleatório para 17 usando para reprodutibilidade). Eu explorei ajustes usando os espaços B-spline gerados pela função , também como na pergunta, para os graus 1 a 6. Esta figura mostra os resultados do grau 2, que é o grau mais baixo (ou seja, modelo mais simples) exibindo um baixo AIC e bom comportamento residual, bem como o modelo indicado por uma ANOVA de todos os seis modelos (aninhados).n=23set.seed(17)FRbs

O ajuste é

y^=27.48993+2.54078f1+2.97679f2

onde e são as funções do spline B criadas por .f1f2bs

Os resíduos se comportam bem. Os ataques são bons. Além disso, essa abordagem encontrou o modelo correto : os dados foram realmente gerados a partir de uma função quadrática (grau 2). Além disso, os desvios padrão dos resíduos são aproximadamente os tamanhos corretos: 0,11, 0,20 e 0,61 em comparação com 0,1, 0,3 e 0,6 usados ​​para gerar os erros originais. Isso é bastante surpreendente, dado que essas curvas obviamente extrapolam as observações (que não vão além de ) e usam um conjunto de dados tão pequeno ( ).x=5n=23

Finalmente, os resíduos dos ajustes para splines de alto grau são qualitativamente os mesmos; eles fazem apenas pequenas melhorias a um custo de usar modelos menos plausíveis. Para graus suficientemente altos, eles começam a oscilar descontroladamente para pequenos valores de entre os valores observados, por exemplo. Para ilustrar esse comportamento (ruim), eis o ajuste de grau 9:x

Figura 2

Finalmente, aqui está um exemplo em que várias observações de vários funcionais lineares da base foram feitas. O código para gerar essas observações foi alterado a partir da pergunta para

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


O Rcódigo para realizar esses cálculos é bastante geral. Em particular, ele usa diferenciação numérica para encontrar as derivadas, para que não dependa do tipo de spline usado. Ele lida com os diferentes valores de ponderando as observações proporcionalmente a Ele constrói e ajusta automaticamente um conjunto de modelos em um loop. Os funcionais lineares e os desvios padrão são codificados. Existem três de cada, selecionados de acordo com o valor da variável no conjunto de dados.σi1/σi2.Liσitype

Como exemplos de como você pode usar os ajustes, a coda imprime resumos, uma lista de seus AICs e uma ANOVA de todos eles.

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

Antes de mais nada, quero agradecer a você por fazer esta pergunta. É uma pergunta realmente interessante. Eu amo splines e as coisas legais que você pode fazer com elas. E isso me deu uma desculpa para fazer alguma pesquisa. :-)

BLUF: A resposta curta é não. Não conheço nenhuma funcionalidade no R que faça isso automaticamente para você. A resposta longa é ... muito mais complicada. O fato de os valores das derivadas e da função não serem amostrados no mesmo local torna isso mais difícil. E o fato de você não ter um valor de função próximo à extremidade direita do intervalo pode tornar isso impossível.

Vamos começar com o spline cúbico. Dados os pontos e as segundas derivadas correspondentes , o spline cúbico que passa por eles é:(xj,yj)zj

Sj(x)=Ayj+Byj+1+Czj+Dzj+1
onde É bem simples verificar se , , e . Isso garante que o spline e sua segunda derivada sejam contínuos. No entanto, neste momento, não temos uma primeira derivada contínua . Para forçar a primeira derivada a ser contínua, precisamos da seguinte restrição:
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
Na configuração clássica de spline cúbico, você assume que possui os pontos e usa a equação (junto com duas restrições adicionais de limite) para resolver o . Depois de conhecer o , o spline é totalmente especificado e você pode usá-lo para interpolar em qualquer ponto arbitrário. Como um bônus adicional, a equação transforma em uma matriz tridiagonal que pode ser resolvida em tempo linear!(xj,yj)(1)zjzj(1)

OK, agora suponha que, em vez de conhecer , você conheça . Você pode usar a equação para resolver o ? Do ponto de vista da álgebra pura, parece viável. Existem equações e incógnitas, então ... por que não? Mas acontece que você não pode; a matriz será singular. E isso não deve surpreender. Como você poderia interpolar os valores das funções dadas APENAS as segundas derivadas? No mínimo, você precisaria de um valor inicial, assim como uma equação diferencial.yjzj(1)yjNN

E a sua situação? Alguns de seus pontos têm valores de função e alguns de seus pontos têm derivadas. Por enquanto, vamos ignorar os primeiros derivativos (eles são uma bagunça para lidar com a base de spline cúbico). Formalmente, seja o conjunto de pontos com valores de função e o conjunto de pontos com segundas derivadas. Ainda temos equações com incógnitas. Só que algumas das incógnitas são e outras são . Acontece que você obterá uma solução se 0, 1 ou 2 AND ou(xi,yi),iI(xj,zj),jJNNyjzjIN3,N2N1I. Em outras palavras, um dos três primeiros pontos deve ser um valor de função E um dos últimos três pontos deve ser um valor de função. Além dessa restrição, você pode liberar quantos derivados quiser.

E os primeiros derivados? Certamente é possível incluir as primeiras derivadas em seu spline. Mas, como eu disse, fica muito mais confuso. A primeira derivada do spline é dada por: É claro que só estamos realmente interessados ​​na derivada em nós, para que possamos simplificar isso um pouco avaliando-a em : Você pode adicioná-los restrições à matriz que você obtém da equação

Sj(x)=yj+1yjhj3A216hjzj+3B216hjzj+1
xj
Sj(xj)=yj+1yjhj13hjzj16hjzj+1
(1)e o spline resultante terá as primeiras derivadas especificadas. Além disso, isso ajudará no problema da matriz singular. Você obterá uma solução se tiver um valor de função ou uma primeira derivada nos três primeiros e nos últimos três pontos.

Então, juntei tudo isso em algum código e aqui está a imagem que eu tenho:

Spline deu horrível errado

Como você pode ver, os resultados não são ótimos. Isso ocorre porque esse é um spline regular que deve respeitar TODOS os dados. Como os dados são estocásticos, precisamos realmente usar um spline de regressão. Esse é um tópico para outro post. Mas se você trabalhar com a matemática, acabará otimizando uma função objetiva quadrática sujeita a restrições lineares de igualdade - e há uma solução de formulário fechado!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.