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 bsts
pakietu, 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:
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:
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:
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:
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.
Odpowiedzi:
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.duration
Argumentem opowiada modelu jak wskazuje wiele czasu w każdym sezonie powinien trwać.nseasons
Argumentem 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.
LocalLinearTrend
Model 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ć,AddLocalLevel
a 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ś.źródło
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
źródło