时间序列预测首先要确定预测的内容。
install.packages("modeltime")
library(tidymodels)
library(modeltime)
library(timetk)
library(lubridate)
library(tidyverse)
library(forecast)
我们研究的数据集为共享自行车的租用量,我们将数据集简化为具有“日期”和“值”列的单变量时间序列。
df_bike = bike_sharing_daily %>%
select(dteday, cnt) %>%
set_names(c("date", "value"))
glimpse(df_bike)
## Rows: 731
## Columns: 2
## $ date 2011-01-01, 2011-01-02, 2011-01-03, 2011-01-04, 2011-01-05, 201…
## $ value 985, 801, 1349, 1562, 1600, 1606, 1510, 959, 822, 1321, 1263, 11…
接下来,使用 plot_time_series() 函数可视化数据集。调参 .interactive = TRUE 以获得可交互的绘图,若为FALSE 返回 ggplot2 静态图,默认为TRUE。
df_bike %>%
plot_time_series(date, value, .interactive = F) +
xlab("Date") +
ylab("Count of total rent bikes")
数据的时间跨度为2011-01-11至2013-01-01,共计731个数据,从图中可以看出数据量较大,不易于分析,为更好地观察趋势,应该将数据再划分为更小的时间跨度,具体根据结果确定。可以看出,这张图没有特别明显的趋势,是否有很强的季节性(每周/每月)?
df_bike %>%
plot_seasonal_diagnostics(date, value, .interactive = FALSE)
可以看到共享单车租用量具有月度季节性,在第2、3季度租用量大于第1、4季度。这很可能是因为第1、4季度是冬天。
使用函数time_series_split() 去创建训练集和测试集
splits = df_bike %>%
time_series_split(assess = "3 months", cumulative = T)
## Using date_var: date
接下来可视化训练/测试集
splits %>%
tk_time_series_cv_plan() %>%
plot_time_series_cv_plan(date, value, .interactive = F)
处理并观察为数据之后,现在就可以建模了。 我们主要用modeltime和parsnip函数建模。
自动模型通常是已经自动化的建模方法。这包括来自forecast包的“Auto ARIMA”和“Auto ETS”功能以及来自prophet包的“Prophet”算法。这些算法已集成到modeltime包中中。设置过程很简单:
接下来先拟合自动ARIMA模型:
model_arima = arima_reg() %>%
set_engine("auto_arima") %>%
fit(value ~ date, training(splits))
## frequency = 7 observations per 1 week
model_arima
## parsnip model object
##
## Fit time: 382ms
## Series: outcome
## ARIMA(0,1,3) with drift
##
## Coefficients:
## ma1 ma2 ma3 drift
## -0.6106 -0.1868 -0.0673 9.3169
## s.e. 0.0396 0.0466 0.0398 4.6225
##
## sigma^2 estimated as 730568: log likelihood=-5227.22
## AIC=10464.44 AICc=10464.53 BIC=10486.74
类似于 Auto Arima模型,同理我们训练 Prophet模型如下:
model_prophet = prophet_reg(seasonality_yearly = TRUE) %>%
set_engine("prophet") %>%
fit(value ~ date, training(splits))
model_prophet
首先,我将使用 **recipe()**函数 创建一个预处理配方并添加时间序列步骤。该过程使用“日期”列来创建我想要建模的 45 个新特征。其中包括时间序列特征和傅立叶级数。
recipe_spec = recipe(value ~ date, training(splits)) %>%
step_timeseries_signature(date) %>%
step_rm(contains("am.pm"), contains("hour"), contains("minute"),
contains("second"), contains("xts")) %>%
step_fourier(date, period = 365, K =5) %>%
step_dummy(all_nominal())
recipe_spec %>% prep() %>% juice()
训练 Elastic NET 模型很容易。只需使用 linear_reg() 和 set_engine(“glmnet”) 设置模型。请注意,我们还没有拟合模型(正如我们在前面的步骤中所做的那样)。
model_spec_glmnet <- linear_reg(penalty = 0.01, mixture = 0.5) %>%
set_engine("glmnet")
接下来,制作一个适合的工作流程:
workflow_fit_glmnet <- workflow() %>%
add_model(model_spec_glmnet) %>%
add_recipe(recipe_spec %>% step_rm(date)) %>%
fit(training(splits))
同理类似于 Elastic Net模型
model_spec_rf <- rand_forest(trees = 500, min_n = 50) %>%
set_engine("randomForest")
workflow_fit_rf <- workflow() %>%
add_model(model_spec_rf) %>%
add_recipe(recipe_spec %>% step_rm(date)) %>%
fit(training(splits))
我已经包含了几个混合模型(例如 arima_boost() 和 prophet_boost()),它们将两种自动化算法与机器学习相结合。接下来我将展示prophet_boost()!
Prophet Boost 算法将 Prophet 与 XGBoost 相结合,以实现两全其美(即 Prophet 自动化 + 机器学习)。该算法的工作原理是:
我们可以像使用机器学习算法一样使用工作流来设置模型。
model_spec_prophet_boost <- prophet_boost(seasonality_yearly = TRUE) %>%
set_engine("prophet_xgboost")
workflow_fit_prophet_boost <- workflow() %>%
add_model(model_spec_prophet_boost) %>%
add_recipe(recipe_spec) %>%
fit(training(splits))
通过modeltime包加速模型评估和模型选择
modeltime 工作流旨在加快模型评估和选择。现在我们有几个时间序列模型,让我们分析它们并使用 modeltime 工作流来进行预测。
Modeltime Table 用 ID 组织模型并创建通用描述以帮助我们跟踪我们的模型。让我们将模型添加到 modeltime_table() 中。
model_table <- modeltime_table(
model_arima,
model_prophet,
workflow_fit_glmnet,
workflow_fit_rf,
workflow_fit_prophet_boost
)
model_table
模型校准用于量化误差和估计置信区间。我们将使用 modeltime_calibrate() 函数对样本外数据(又名测试集)执行模型校准。生成了两个新列(“.type”和“.calibration_data”),其中最重要的是“.calibration_data”。这包括测试集的实际值、拟合值和残差。
calibration_table = model_table %>%
modeltime_calibrate(testing(splits))
calibration_table
使用校准数据,我们可以可视化测试预测(预测)。
calibration_table %>%
modeltime_forecast(actual_data = df_bike) %>%
plot_modeltime_forecast(.interactive = FALSE)
## Using '.calibration_data' to forecast.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning -
## Inf
接下来,计算测试精度以比较模型。
calibration_table %>%
modeltime_accuracy() %>%
table_modeltime_accuracy(.interactive = FALSE)
从准确度度量和预测结果中,我们看到:
我们从最终模型中排除 Auto ARIMA,然后使用其余模型进行未来的预测。
calibration_table %>%
# Remove ARIMA model with low accuracy
filter(.model_id != 1) %>%
# Refit and Forecast Forward
modeltime_refit(df_bike) %>%
modeltime_forecast(h = "12 months", actual_data = df_bike) %>%
plot_modeltime_forecast(.interactive = FALSE)
本文只是触及了表面,modeltime 包的功能比这里介绍的要丰富得多,以下是没有涵盖的内容:
特征工程:时间序列分析的艺术是特征工程。 Modeltime 与尖端的时间序列预处理工具配合使用,包括recipes和 timetk 包中的工具。
超参数调整:可以调整 ARIMA 模型和机器学习模型。有对与错的方式(两种类型都不一样)。
可扩展性:训练多个时间序列组和自动化是组织中一个巨大的需求领域。您需要知道如何将分析扩展到数千个时间序列。
优势和劣势:您是否知道某些机器学习模型更适合趋势、季节性,但不是两者兼而有之?为什么 ARIMA 对于某些数据集更好?随机森林和 XGBoost 什么时候会失败?
深度学习:循环神经网络 (RRN) 一直在压制时间序列竞赛。它们会用于业务数据吗?你如何实施它们?