Prognozy z modelu BSTS (w R) zawodzą całkowicie

15

Po przeczytaniu tego postu na blogu o Bayesowskich modelach strukturalnych szeregów czasowych, chciałem spojrzeć na wdrożenie tego w kontekście problemu, w którym wcześniej korzystałem z ARIMA.

Mam pewne dane z niektórymi znanymi (ale hałaśliwymi) komponentami sezonowymi - z pewnością są to komponenty roczne, miesięczne i tygodniowe, a także pewne efekty ze względu na specjalne dni (takie jak święta federalne lub religijne).

Użyłem tego bstspakietu, aby to zaimplementować i, o ile mogę stwierdzić, nie zrobiłem nic złego, chociaż komponenty i przewidywania po prostu nie wyglądają tak, jak się spodziewałem. Nie jest dla mnie jasne, czy moja implementacja jest błędna, niekompletna lub ma jakiś inny problem.

Cały szereg czasowy wygląda następująco:

Pełne dane

Mogę trenować model na pewnym podzbiorze danych, a model ogólnie wygląda dobrze pod względem dopasowania (wykres poniżej). Kod, którego używam do tego celu, znajduje się tutaj:

library(bsts)

predict_length = 90
training_cut_date <- '2015-05-01'
test_cut_date <- as.Date(training_cut_date) + predict_length

df = read.csv('input.tsv', sep ='\t')

df$date <- as.Date(as.character(df$date),format="%Y-%m-%d")
df_train = df[df$date < training_cut_date,]

yts <- xts(log10(df_train$count), order.by=df_train$date)

ss <- AddLocalLinearTrend(list(), yts)
ss <- AddSeasonal(ss, yts, nseasons = 7)
ss <- AddSeasonal(ss, yts, nseasons = 12)
ss <- AddNamedHolidays(ss, named.holidays = NamedHolidays(), yts)

model <- bsts(yts, state.specification = ss, niter = 500, seed=2016)

Model wygląda rozsądnie:

Działka modelowa

Ale jeśli wykreślę prognozę, to po pierwsze trend będzie całkowicie błędny, a po drugie niepewność rośnie BARDZO szybko - do tego stopnia, że ​​nie mogę pokazać pasma niepewności na tym samym wykresie, co prognozy bez wykonania osi y na log- skala. Kod tej części znajduje się tutaj:

burn <- SuggestBurn(0.1, model)
pred <- predict(model, horizon = predict_length, burn = burn, quantiles = c(.025, .975))

Czysta prognoza wygląda następująco:

czysta prognoza

A potem, gdy przeskalowano z powrotem do rozkładu początkowego (z kropkowaną linią pokazującą przejście od treningu do przewidywania, problemy są oczywiste:

pełna dystrybucja

Próbowałem dodać więcej trendów sezonowych, usunąć trendy sezonowe, dodać termin AR, zmienić AddLocalLinearModel na AddGeneralizedLocalLinearTrend i kilka innych rzeczy dotyczących ulepszenia modelu, ale nic nie rozwiązało problemów i nie uczyniło prognoz bardziej sensownymi. W niektórych przypadkach kierunek zmienia się, więc zamiast spadać do zera, prognoza nadal rośnie w funkcji czasu. Zdecydowanie nie rozumiem, dlaczego model tak się psuje. Wszelkie sugestie byłyby bardzo mile widziane.

anthr
źródło
2
Dlaczego nie opublikujesz swoich danych, a ja postaram się pomóc ... Nie będę w stanie odpowiedzieć, dlaczego model się psuje, ponieważ nie stosuję tego podejścia, ponieważ ma zbyt wiele założeń. precyzyjne co do tego, ile wartości zostało zatrzymanych, datę początkową i kraj pochodzenia.
IrishStat,
Dziękuję bardzo za komentarz. Przesłałem tutaj nieprzetworzone dane na wypadek, gdybyś miał czas na sprawdzenie. Dane wahają się od początku 2013 r. Do końca tego roku. Próbowałem też prognozować za pomocą modelu ARIMA, ale przewidywania z tego nie pasowały również do danych wstrzymania. Dane wstrzymujące to w zasadzie tylko ułamek roku 2015 lub 2016, w zależności od tego, ile danych treningowych chciałem wykorzystać.
anrr
Mam problem z pobraniem. Wyślij plik csv na mój adres e-mail
IrishStat,

Odpowiedzi:

26

Steve Scott tutaj. Napisałem pakiet bsts. Mam dla ciebie kilka sugestii. Po pierwsze, twoje składniki sezonowe nie działają tak, jak myślisz. Myślę, że masz codzienne dane, ponieważ próbujesz dodać składnik na 7 sezonów, który powinien działać poprawnie. Ale powiedziałeś, aby twój roczny składnik sezonowy powtarzał się co 12 dni. Uzyskiwanie miesięcznego komponentu sezonowego z danymi dziennymi jest dość trudne, ale możesz zrobić 52 tygodniowy sezon do AddSeasonal(..., nseasons = 52, season.duration = 7) .

seasonal.durationArgumentem opowiada modelu jak wskazuje wiele czasu w każdym sezonie powinien trwać. nseasonsArgumentem informuje go, ilu sezonów są w cyklu. Łączna liczba punktów czasowych w cyklu wynosiseason.duration * nseasons .

Druga sugestia jest taka, że ​​możesz pomyśleć o innym modelu trendu. LocalLinearTrendModel jest bardzo elastyczne, ale elastyczność ta może pojawić się jako niepożądane odchylenia w długości prognoz krótkoterminowych. Istnieje kilka innych modeli trendów, które zawierają nieco więcej struktury. GeneralizedLocalLinearTrend(przepraszam za nieopisową nazwę) zakłada, że ​​„nachylenie” komponentu trendu jest procesem AR1 zamiast losowego marszu. Jest to moja domyślna opcja, jeśli chcę prognozować w dalekiej przyszłości. Większość zmian w szeregu czasowym wydaje się wynikać z sezonowości, więc możesz spróbować, AddLocalLevela nawetAddAr zamiast tegoAddLocalLinearTrend .

Wreszcie, ogólnie rzecz biorąc, jeśli otrzymujesz dziwne prognozy i chcesz dowiedzieć się, która część modelu jest winna, spróbuj plot(model, "components")zobaczyć, jak model rozkłada się na poszczególne elementy, o które prosiłeś.

Steve Scott
źródło
FYI: Mam bardzo podobne problemy z moimi danymi, które są również codzienne. Wdrożyłem wszystkie wymienione tutaj sugestie i żadna z nich nie wydaje się pomocna.
ZakJ
1
@ Steve Scott Przepraszam, że przeszkadzam, Steve, chcę cię o to zapytać: jeśli próbuję modelować wiele szeregów czasowych i jestem w hierarchicznej strukturze modeli mieszanych, czy mogę to modelować za pomocą pakietu? Przy okazji: bardzo dziękuję za paczkę!
Tommaso Guerrini
4

Myślę, że możesz także zmienić domyślne nagranie. Kiedy użyłem bsts, stworzyłem siatkę wartości wypalenia i niterowania z MAPE jako moją statystyką w okresie wstrzymania. Spróbuj również użyć AddStudentLocalLinearTrend zamiast tego, jeśli dane mają duże zróżnicowanie, aby model mógł oczekiwać takich zmian

Elderkm2012
źródło
1
Byłem pomocny w moim przypadku, gdy miałem kilka punktów danych (20)
SCallan