Recherche du point de changement dans les données à partir d'une fonction linéaire par morceaux

10

Salutations,

J'effectue des recherches qui aideront à déterminer la taille de l'espace observé et le temps écoulé depuis le big bang. J'espère que vous pourrez aider!

J'ai des données conformes à une fonction linéaire par morceaux sur laquelle je veux effectuer deux régressions linéaires. Il y a un point où la pente et l'interception changent, et je dois (écrire un programme pour) trouver ce point.

Pensées?

rhombidodécaèdre
la source
3
Quelle est la politique en matière de publication croisée? On a demandé exactement la même question sur math.stackexchange.com: math.stackexchange.com/questions/15214/...
mpiktas
Quel est le problème de faire des moindres carrés non linéaires simples dans ce cas? Suis-je en train de manquer quelque chose d'évident?
grg s
Je dirais que la dérivée de la fonction objectif par rapport au paramètre de point de changement est plutôt
Andre Holzner
La pente changerait tellement qu'un moindre carré non linéaire ne serait pas concis et précis. Ce que nous savons, c'est que nous avons deux modèles linéaires ou plus, donc nous devons frapper pour extraire ces deux modèles.
HelloWorld

Réponses:

1

Le mcppackage peut le faire. Dites que vos données sont

Tout d'abord, simulons quelques données:

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

Voyons maintenant si nous pouvons récupérer le point de changement à 40 (et les valeurs des paramètres) en utilisant mcp:

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

Tracez-le. Les lignes grises sont des tirages aléatoires de l'ajustement, montrant qu'il capture la tendance. La courbe bleue est l'emplacement estimé du point de changement:

entrez la description de l'image ici

Voyons les estimations des paramètres individuels. int_sont des interceptions, des x_pentes sur x et des cp_points de changement:

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

Avertissement: je suis le développeur de mcp.

Jonas Lindeløv
la source
8

Strucchange du package R peut vous aider. Regardez la vignette, elle a un bon aperçu de la façon de résoudre des problèmes similaires.

mpiktas
la source
6

Xje=(Xje,yje)je=1,..,Nj2N-2{X1,...,Xj}{X(j+1),...,XN}j


la source
J'ai posté une réponse basée sur votre suggestion simple mais efficace.
HelloWorld
5

Il s'agit d'un problème de détection de point de changement (hors ligne). Notre discussion précédente fournit des références aux articles de revues et au code R. Regardez d'abord le «modèle de partition de produit» de Barry et Hartigan , car il gère les changements de pente et a des implémentations efficaces.

whuber
la source
3

De plus, le package segmenté m'a aidé avec des problèmes similaires dans le passé.

Misha
la source
Malheureusement, le package a besoin d'une valeur de départ pour le point d'arrêt.
HelloWorld
En outre, segmentedne peut pas modéliser les changements d'interception entre les segments - uniquement une interception pour le premier segment.
Jonas Lindeløv
2

J'ai construit sur la réponse de mbq que la recherche de toutes les possibilités. De plus, je fais ceci:

  • Vérifiez la signification des deux modèles par morceaux pour vous assurer que les coefficients sont significatifs
  • Vérifier la différence avec la somme des résidus au carré pour le modèle complet
  • Confirmer visuellement mon modèle (assurez-vous que ce n'est pas quelque chose de non-sens)

Pourquoi vérifier la signification? C'est parce que le point avec le SSE minimum n'a aucun sens si l'un des modèles par morceaux correspond très mal aux données. Cela peut se produire pour deux variables hautement corrélées sans point d'arrêt clair où les pentes changent.

Vérifions cette approche simple avec un cas de test simple:

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

entrez la description de l'image ici

Le point d'arrêt est évidemment nul. Utilisez le script R suivant:

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
}

Adaptez les modèles linéaires par morceaux pour toutes les combinaisons possibles:

f(x,y)
   k sums
   0    0

Si nous vérifions les coefficients des deux modèles optimaux, ils seront très significatifs. Leur R2 sera également très élevé.

Bonjour le monde
la source