Localizando o ponto de mudança nos dados a partir de uma função linear por partes

10

Saudações,

Estou realizando pesquisas que ajudarão a determinar o tamanho do espaço observado e o tempo decorrido desde o big bang. Espero que você possa ajudar!

Eu tenho dados em conformidade com uma função linear por partes na qual desejo executar duas regressões lineares. Há um ponto em que a inclinação e a interceptação mudam, e eu preciso (escrever um programa para) encontrar esse ponto.

Pensamentos?

rhombidodecahedron
fonte
3
Qual é a política de postagem cruzada? A mesma pergunta foi feita exatamente em math.stackexchange.com: math.stackexchange.com/questions/15214/…
mpiktas
O que há de errado em fazer mínimos quadrados não lineares simples neste caso? Estou perdendo algo óbvio?
grg s
Eu diria que a derivada da função objetivo com relação ao parâmetro de ponto de mudança é bastante un-alisar
Andre Holzner
A inclinação mudaria tanto que os mínimos quadrados não lineares não seriam concisos e precisos. O que sabemos é que temos dois ou mais modelos lineares; portanto, devemos atacar para extrair esses dois modelos.
HelloWorld

Respostas:

1

O mcppacote pode fazer isso. Digamos que seus dados sejam

Primeiro, vamos simular alguns dados:

df = data.frame(x = 1:100,
                y = c(rnorm(40, 10 + (1:40)*0.5),
                      rnorm(60, 10 + 40*0.5 -8 + (1:60)*0.2)))

Agora vamos ver se podemos recuperar o ponto de mudança em 40 (e os valores dos parâmetros) usando mcp:

model = list(
  y ~ 1 + x,  # linear segment
  ~ 1 + x  # another linear segment
)
library(mcp)
fit = mcp(model, df)

Traçar. As linhas cinza são desenhos aleatórios do ajuste, mostrando que ele captura a tendência. A curva azul é o local estimado do ponto de mudança:

insira a descrição da imagem aqui

Vamos ver as estimativas de parâmetros individuais. int_são interceptações, x_são inclinações em x e cp_são pontos de mudança:

summary(fit)

Population-level parameters:
    name  mean lower upper Rhat n.eff
    cp_1 40.48 40.02 41.00    1  2888
   int_1 11.12  9.11 13.17    1   778
   int_2 21.72 20.09 23.49    1   717
 sigma_1  3.23  2.76  3.69    1  5343
     x_1  0.46  0.36  0.54    1   724
     x_2  0.21  0.16  0.26    1   754

Disclaimer: Eu sou o desenvolvedor de mcp.

Jonas Lindeløv
fonte
8

A distribuição de pacotes R pode ajudá-lo. Veja a vinheta, ela tem uma boa visão geral de como resolver problemas semelhantes.

mpiktas
fonte
6

XEu=(xEu,yEu)Eu=1 1,..,Nj2N-2{X1 1,...,Xj}{X(j+1 1),...,XN}j


fonte
Publiquei uma resposta com base em sua sugestão simples, mas eficaz.
HelloWorld 7/11
5

Este é um problema de detecção de ponto de mudança (offline). Nossa discussão anterior fornece referências a artigos de periódicos e código R. Veja primeiro o "modelo de partição de produtos" de Barry e Hartigan , porque ele lida com mudanças na inclinação e possui implementações eficientes.

whuber
fonte
3

Além disso, o pacote segmentado me ajudou com problemas semelhantes no passado.

Misha
fonte
Infelizmente, o pacote precisa de um valor inicial para o ponto de interrupção.
HelloWorld
Além disso, segmentednão é possível modelar alterações de interceptação entre segmentos - apenas uma interceptação para o primeiro segmento.
Jonas Lindeløv
2

Eu desenvolvi a resposta do mbq que procurava por todas as possibilidades. Além disso, faço isso:

  • Verifique a significância dos dois modelos por partes para garantir que os coeficientes sejam significativos
  • Verifique a diferença na soma dos resíduos quadráticos para o modelo completo
  • Confirmar visualmente meu modelo (verifique se não é algo sem sentido)

Por que verificar o significado? Isso ocorre porque o ponto com o SSE mínimo não faz sentido se um dos dois modelos se encaixa muito mal nos dados. Isso pode acontecer para duas variáveis ​​altamente correlacionadas sem um ponto de interrupção claro, onde as inclinações mudam.

Vamos verificar essa abordagem simples com um caso de teste fácil:

x <- c(-50:50)
y <- abs(x)
plot(x,y,pch=19)

insira a descrição da imagem aqui

O ponto de interrupção é obviamente zero. Use o seguinte script R:

f <- function(x, y)
{
    d <- data.frame(x=x, y=y)
    d <- d[order(x),]
    r <- data.frame(k=rep(0,length(x)-4), sums=rep(0,length(x)-4))

    plm <- function(i)
    {
        d1 <- head(d,i)
        d2 <- tail(d,-i)

        # Make sure we've divided the region perfectly        
        stopifnot(nrow(d1)+nrow(d2) == nrow(d))

        m1 <- lm(y~x, data=d1)
        m2 <- lm(y~x, data=d2)

        r <- list(m1, m2)
        r
    }

    lapply(2:(nrow(d)-3), function(i)
    {
        r$k[i-2] <<- d[i,]$x

        # Fit two piecewise linear models
        m <- plm(i)

        # Add up the sum of squares for residuals
        r$sums[i-2] <<- sum((m[[1]]$residuals)^2) + sum((m[[2]]$residuals)^2)
    })

    b <- r[which.min(r$sums),]    
    b
}

Ajuste modelos lineares por partes para todas as combinações possíveis:

f(x,y)
   k sums
   0    0

Se verificarmos os coeficientes para os dois modelos ótimos, eles serão altamente significativos. O R2 deles também será muito alto.

Olá Mundo
fonte