3
$\begingroup$

I have a question about breakpoints test, that is to select which variables to put in the model ?

enter image description here

Example:

Y = C(constant) + Ut , Ut ~ N(0,1) ....first model

Y = C(constant) + Trend + Ut , Ut ~ N(0,1) ....second model

Y = C(constant) + AR(1) + Trend + Ut , Ut ~ N(0,1) ....third model

Y = C(constant) + AR(1) + AR(2) + Trend + Ut , Ut ~ N(0,1) ....fourth model

In the picture(1) I simulate two time series and combine them , each of them are AR(1) Model , one has trend and another no trend. Assumption I don't know components of this series , to detect break in this time series , which model should I use (1、2、3、4 model,or neither of them) ?

I know if I want to see the constant change i put C in model to detect change , want to see trend change then put C + trend in model , but I want to know a better way to select model detect break , not use eyes.

$\endgroup$
2
$\begingroup$

The simplest way of dealing with changepoints is to iterate through your data points (maybe like the middle 80% of them) and fit each each segment with each of your models and choose the changepoint based on whichever minimizes some criteria like rmse or something simple. Then take your residuals and do the same process again but then add your two 'rounds' of fitted values to get the new residuals. Do this again and again until you minimize a global criteria like some modified version of the AICC/BIC to take into account the number of changepoints so K + n_changepoints in the formula.

If you use python you can try out a package I am messing around with ThymeBoost:

pip install ThymeBoost

A simple example like what you have done but with a linear estimator:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
                              split_cost = 'mse',
                              global_cost = 'maicc',
                              fit_type = 'local',
                              seasonal_period = 0,
                              verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()

enter image description here

But we really can use whatever base estimator for trend so lets use arima:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'ar',
                              arima_order = (2,1,2),
                              split_cost = 'mse',
                              global_cost = 'maicc',
                              fit_type = 'local',
                              seasonal_period = 0,
                              verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results() 

enter image description here

Using verbose the model prints results from each round:

Round 0 cost: -1344.0438903501597
Using Split: 101
Round 1 cost: -1971.2578426717146
Using Split: 151
Round 2 cost: -1953.8696120415427
Boosting Terminated 
Using round 1

So it found a changepoint at 101 where the coefficients of the arima will be different. That is close enough to the true changepoint at 100 if you ask me! Round 0 is always fit with with the median of the data since this approach is heavily influenced by gradient boosting and it has a nice interpretation of saying 'there is no trend'. Although for your case you may just want to fit all your different models globally for the first round.

Now let's try with 3 changepoints to see what happens:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
                              split_cost = 'mse',
                              global_cost = 'maicc',
                              fit_type = 'local',
                              seasonal_period = 0,
                              verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()

enter image description here

Oof, that's pretty bad. Looks like it is a problem with how I propose the segments since I don't want to exhaustively try every data point, so let's increase the number of proposals (and you will see I commented out approximate_splits = True if set to False it will try every point):

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
                              split_cost = 'mse',
                              global_cost = 'maicc',
                              fit_type = 'local',
                              seasonal_period = 0,
                              #approximate_splits = True,
                              n_split_proposals = 25,
                              verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()

enter image description here

Looks a lot better but it is slow to react to the third changepoint at x = 200.

The only real change you would need from what is done here is that ThymeBoost won't cycle through model configurations at each segment, it will just refit for the ar coefficients or linear coefficients or whatever base trend estimator you are using. So in your loop of fitting each split you would just need to add another loop to try each model configuration. Just be careful about how different configurations effect whatever global cost you choose.

$\endgroup$
1
  • $\begingroup$ Many thanks for your assistance , It's very helpful ! $\endgroup$
    – Ivan
    May 7 at 3:21
1
$\begingroup$

Generally, it is a good strategy to use a model so that - after accounting for any structural breaks - the model fits well in each of the segments. Thus, in your case the linear trend plus AR(1) effect would be appropriate because this model will fit well in both parts even if the slope of the trend will be zero in the second segment.

Of course, this is a bit of a chicken-and-egg problem because for finding the breaks you need a model that fits well after accounting for the breaks. But possibly some guidance for the model is known from the literature or prior data etc.

Finally, if you hadn't mentioned that you simulated trend-stationary time series with AR(1) effects my first intuition would have been that this is a non-stationary series. So I probably would have modeled the first differences $\Delta Y$ rather than original levels $Y$. Then you don't need to include the trend as a regressor. The change in slope for $Y$ will correspond to a change in intercept for $\Delta Y$.

$\endgroup$
1
  • $\begingroup$ Thank you for your suggestion about after differences find change in intercept, I try this solutions to deal data, then saw a significant change, It's very interesting and helpful. $\endgroup$
    – Ivan
    May 7 at 3:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.