Encontrar el punto de cambio en los datos de una función lineal por partes

10

Saludos,

Estoy realizando una investigación que ayudará a determinar el tamaño del espacio observado y el tiempo transcurrido desde el Big Bang. ¡Ojalá puedas ayudar!

Tengo datos que se ajustan a una función lineal por partes en la que quiero realizar dos regresiones lineales. Hay un punto en el que la pendiente y la intersección cambian, y necesito (escribir un programa para) encontrar este punto.

Pensamientos?

romdodecaedro
fuente
3
¿Cuál es la política de publicación cruzada? Se hizo exactamente la misma pregunta en math.stackexchange.com: math.stackexchange.com/questions/15214/…
mpiktas
¿Qué tiene de malo hacer mínimos cuadrados no lineales simples en este caso? ¿Me estoy perdiendo algo obvio?
grg s
Yo diría que la derivada de la función de objetivo con respecto al parámetro del punto de cambio es bastante irregular
Andre Holzner
La pendiente cambiaría tanto que los mínimos cuadrados no lineales no serían concisos y precisos. Lo que sabemos es que tenemos dos o más modelos lineales, por lo tanto, debemos atacar para extraer esos dos modelos.
HelloWorld

Respuestas:

1

El mcppaquete puede hacer esto. Digamos que sus datos son

Primero, simulemos algunos datos:

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

Ahora veamos si podemos recuperar el punto de cambio en 40 (y los valores de los parámetros) usando mcp:

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

Tramalo. Las líneas grises son dibujos aleatorios del ajuste, lo que muestra que captura la tendencia. La curva azul es la ubicación estimada del punto de cambio:

ingrese la descripción de la imagen aquí

Veamos las estimaciones de los parámetros individuales. int_son intersecciones, x_son pendientes en xy cp_son puntos de cambio:

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

Descargo de responsabilidad: soy el desarrollador de mcp.

Jonas Lindeløv
fuente
8

R strucchange de paquete puede ayudarlo. Mire la viñeta, tiene una buena visión general de cómo resolver problemas similares.

mpiktas
fuente
6

Si el número de puntos no es demasiado grande, puede probar todas las posibilidades. Vamos a suponer que los puntos son , donde . Entonces, puede hacer un bucle con de a y ajustar dos líneas a ambos y . Finalmente, elige para el cual la suma de la suma de los residuos al cuadrado para ambas líneas es mínima.i = 1 , . . , N j 2 N - 2 { X 1 , . . . , X j } { X ( j + 1 ) , . . . , X N } jXyo=(Xyo,yyo)yo=1,..,nortej2norte-2{X1,...,Xj}{X(j+1),...,Xnorte}j


fuente
He publicado una respuesta basada en su sugerencia simple pero efectiva.
HolaMundo
5

Este es un problema de detección de punto de cambio (fuera de línea). Nuestra discusión anterior proporciona referencias a artículos de revistas y código R. Mire primero el "modelo de partición del producto" de Barry y Hartigan , porque maneja los cambios en la pendiente y tiene implementaciones eficientes.

whuber
fuente
3

También el paquete segmentado me ha ayudado con problemas similares en el pasado.

Misha
fuente
Desafortunadamente, el paquete necesita un valor inicial para el punto de ruptura.
HelloWorld
Además, segmentedno puede modelar cambios de intercepción entre segmentos, solo una intercepción para el primer segmento.
Jonas Lindeløv
2

Me basé en la respuesta de mbq que busca todas las posibilidades. Además, hago esto:

  • Verifique la importancia de los dos modelos por partes para asegurarse de que los coeficientes sean significativos
  • Verifique la diferencia con la suma de los residuos cuadrados para el modelo completo
  • Confirmar mi modelo visualmente (asegúrese de que no sea una tontería)

¿Por qué verificar la importancia? Esto se debe a que el punto con el SSE mínimo no tiene sentido si alguno de los modelos por partes se ajusta muy mal a los datos. Esto puede suceder para dos variables altamente correlacionadas sin un punto de ruptura claro donde cambian las pendientes.

Veamos este enfoque simple con un caso de prueba fácil:

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

ingrese la descripción de la imagen aquí

El punto de ruptura es obviamente cero. Use el siguiente 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 lineales por partes para todas las combinaciones posibles:

f(x,y)
   k sums
   0    0

Si verificamos los coeficientes para los dos modelos óptimos, serán altamente significativos. Su R2 también será muy alto.

Hola Mundo
fuente