на одну точку вперед. Как сделать циклом- придумал, но он работает очень медленно. Можно это как-то векторизовать?
slide.arima <- function(x, window=36) {
result <- rep(-999, length(x))
result[1:window] <- NA
for (i in (window+1):length(x)){
result[i] <- (x[(i-window):(i-1)] %>% ts(frequency = 12) %>% auto.arima() %>% forecast(h=1))$mean[1]
}
return(result)
}
x <- sin(1:100)
system.time(slide.arima(x))
пользователь система прошло
122.63 0.01 122.73
И второй вопрос: выражение ( %>% … %>%...)$mean[1] выглядит как-то неправильно. Можно ли вместо скобок и $mean[1] сделать что-то более читаемое или и так считается норм?
Завтра вам постараюсь дать пример. Я тоже строю десятки моделей (был кейс с сотнями и т.д.) с помощью подбора порядка модели в рамках auto.arima. Вещь нужная, но тяжелая. Тут векторизация может быть, если её писать на пониженном уровне абстракции. В самой либе такого нет... Векторизация работает на более примитивных операциях, где, просто, циклы написаны на более низком уровне (C, например, который в базе). Я использую параллельное исполнение (multi core). И ещё, есть нюансы с ограничениями по порядку модели, их надо указать, если хочется побыстрее. По поводу 2). Надо проверить (я не у компа) , но, выглядит так, что %>%$('mean') %>%[(1) подобное должно работать.
Попробуйте это: https://cran.r-project.org/web/packages/greybox/vignettes/ro.html
arima - это по сути регрессия на лагах... хотя алгоритм простой, выявление лучшей модели требует перебора всех вариантов. По умолчанию, стоит параметр nmodels = 94. Это значит, что строится 94 модели и выбирается лучшая. Поэтому на циклах вы много не оптимизируете. Придется либо уменьшать количество перебираемых моделей, либо смотреть другие реализации arima, либо использовать параллельные вычисления. Для красивого выбора элемента используйте purrr::pluck(), далее код: x <- sin(1:100) #оригинальная функция с pluck() для читаемости slide.arima <- function(x, window = 36) { #x <- sin(1:100) result <- rep(-999, length(x)) result[1:window] <- NA for (i in (window + 1):length(x)){ result[i] <- x[(i-window):(i-1)] %>% ts(frequency = 12) %>% forecast::auto.arima() %>% forecast::forecast(h=1) %>% purrr::pluck("mean") } return(result) } system.time(res1 <- slide.arima(x)) # пользователь система прошло # 98.916 9.435 112.950 #функция на векторизованными циклами и параллельными вычислениями future::plan(future::multisession, workers = 2) slide_arima <- function(x, window = 36){ window_begin <- 1:(length(x) - window) window_end <- window:(length(x) - 1) get_forecast <- function(vec){ ts(x[vec], frequency = 12) %>% forecast::auto.arima() %>% forecast::forecast(., h = 1) %>% purrr::pluck("mean") } res <- map2(.x = window_begin, .y = window_end, ~.x:.y) %>% furrr::future_map_dbl(~get_forecast(.)) rep(NA, window) %>% append(res) } system.time(res2 <- slide_arima(x)) # пользователь система прошло # 0.406 0.053 59.573 res1 == res2
Регрессия на лагах — это AR, ARIMA сложнее описывается
Да, конечно, там ещё регрессия на остатках и сезонность, но в любом случае это OLS
Обсуждают сегодня