赞
踩
绝大部分行业场景,尤其是互联网、量化行业,每天都会产生大量的数据。金融领域股票价格随时间的走势;电商行业每日的销售额;旅游行业随着节假日周期变化的机票酒店价格等;
我们称这种不同时间收到的,描述一个或多种特征随着时间发生变化的数据,为时间序列数据(Time Series Data)。
而时间序列预测做的就是通过多种维度的数据本身内在与时间的关联特性,利用历史的数据预测未来这么一件事情。
时序预测从不同角度看有不同分类:
本文接下来会从实现原理的角度切入,大致介绍一下场景的时间序列预测方法的原理以及具体python实现,大部分深度学习的实现依赖于AWS于2019开源的时间序列建模工具包Gluon Time Series(GluonTS)[2]
ARIMA是一种非常流行的时间序列预测统计方法,它是自回归综合移动平均(Auto-Regressive Integrated Moving Averages)的首字母缩写。ARIMA模型建立在以下假设的基础上: 数据序列是平稳的,这意味着均值和方差不应随时间而变化。 通过对数变换或差分可以使序列平稳。
- from gluonts.model.r_forecast import RForecastPredictor
- # build model
- arima_estimator = RForecastPredictor(freq='1D', prediction_length=args.horizon, method_name="arima")
- # Predicting
- forecast_df = pd.DataFrame(columns=['id', 'target_start_date', 'point_fcst_value']) # df_pred
- for entry_, forecast_ in tqdm(zip(training_data, estimator.predict(training_data))):
- id = entry_["id"]
- forecast_df = forecast_df.append(
- pd.DataFrame({"id": id,
- "target_start_date": forecast_.index.map(lambda s: s.strftime('%Y%m%d')),
- "point_fcst_value": forecast_.median}))
实就是一种(三次)指数平滑方法,Holt (1957) 和 Winters (1960) 将Holt方法进行拓展用来捕获季节因素。Holt-Winters季节性方法包括预测方程和三个平滑方程:一个用于水平 ,一个用于趋势 ,另一个用于季节性分量。然后以累加或累乘的方式叠加分量组成预测。
- from statsmodels.tsa.holtwinters import ExponentialSmoothing
- data = pd.Series(data)
- yhat = ExponentialSmoothing(data, seasonal_periods=4, trend='add', seasonal='add').fit(use_boxcox=True)
prophet 算法是基于时间序列分解(同上:seasonal、trend、residual)和机器学习的拟合来做的,它最适用于具有强烈季节性影响和多个季节历史数据的时间序列。Prophet 对缺失数据和趋势变化具有稳健性,并且通常可以很好地处理异常值。
- from gluonts.model.prophet import ProphetPredictor
- # build model
- prophet_estimator = ProphetPredictor(freq='1D',
- prediction_length=args.horizon,
- prophet_params={'daily_seasonality': True,
- 'weekly_seasonality': True,
- 'changepoint_prior_scale': 0.03,
- 'changepoint_range': 0.5,
- 'seasonality_mode': 'multiplicative'
- }
- # Predicting
- # same as above
时间序列的特征工程在之前的文章里讲过了,详见
VoidOc:时间序列异常检测(一)—— 算法综述617 赞同 · 34 评论文章正在上传…重新上传取消
Boosting 是集成学习中非常重要的一类算法,其基本原理是串行生成一系列弱学习器(weak learner),这些弱学习器直接通过组合到一起构成最终的模型。Boosting 算法可以用于解决分类和回归问题,主要的算法包括早期的AdaBoost 和 后续的Gradient Boosting。
而GBDT(Gradient Boosting Decision Tree)是弱学习器使用 CART 回归树的一种 Gradient Boosting,使用决策树作为弱学习器的一个好处是:决策树本身是一种不稳定的学习器(训练数据的一点波动可能给结果带来较大的影响),从统计学的角度单棵决策树的方差比较大。而在集成学习中,弱学习器间方差越大,弱学习器本身泛化性能越好,则集成学习模型的泛化性能就越好。因此使用决策树作为弱学习器通常比使用较稳定的弱学习器(如线性回归等)泛化性能更好。
包括后续演变而出的XGBoost和LightGBM算法等基于GBM的衍生算法,在早年由于泛化性好,训练速度快等优点在Kaggle等比赛中得到广泛使用。
- from xgboost import XGBRegressor
- from sklearn.model_selection import train_test_split
-
- # 重新分割训练和测试数据
- dm_trainDF = dm_allDF[:len(trainDF)]
- dm_testDF = dm_allDF[len(trainDF):]
-
- # 去掉id号
- train_data = dm_trainDF.drop(['Id'],axis=1).values
- train_label = trainDF_label.values
-
- X_test_ids = dm_testDF['Id'].values
- X_test = dm_testDF.drop(['Id'],axis=1).values
-
- # 分割训练集和验证集
- X_train, X_valid, Y_train, Y_valid = train_test_split(train_data, train_label,test_size=0.2)
-
- xgb = XGBRegressor(n_estimators=500, learning_rate=0.05, min_child_weight=5, max_depth=4)
- xgb.fit(X_train,Y_train)
- print "Validation:",xgb.score(X_valid,Y_valid)
-
- predict = xgb.predict(X_test)
NNI (Neural Network Intelligence)是一个轻量但强大的工具包,帮助用户自动的进行特征工程,神经网络架构搜索,超参调优以及模型压缩。
nnictl create --config nni_config.yml
4. 数据看板
5. faild报错查询
如果遇到报错,首先索引到本地log directory后进入-> trials -> CVpHS(具体trial实例名)-> cat stderr 查看具体脚本报错。
6. 停止实验
nnictl stop
DeepAR 是一个自回归循环神经网络,使用递归神经网络 (RNN) 结合自回归 AR 来预测标量(一维)时间序列。可以冷启动预测,直接学习概率分布的参数,但受限于RNN框架,对于较长时间的周期季节等信息则难以补获。
- from gluonts.model.deepar import DeepAREstimator
- # build model
- deepar_estimator = DeepAREstimator(
- freq="1D",
- num_layers=num_layers,
- num_cells=num_cells,
- cell_type=cell_type,
- dropout_rate=dropout_rate,
- prediction_length=args.horizon,
- trainer=Trainer(epochs=80))
-
- # Predicting
- # same as above
确定输入的协变量的参数:
use_feat_dynamic_real:是否启用时变连续变量作为协变量,如果我们调用天气信息作为协变量,需要设置为True
use_feat_static_cat:是否采用时不变类别变量作为协变量,这里我们设置为True,因为我们需要提供观测点的信息。对于上文提到的管网和测点分布,如果合理分析,可以提取更多有用的时不变类别信息
use_feat_static_real:是否启用时不变连续变量作为协变量,这里我们设置为False
lags_seq:显式设置lag参数,否则系统自动计算lag
time_features:显式设置时间特征,否则系统自动计算
输入数据的格式相对简单,因为GluonTS对输入数据格式ListDataset要求比较宽松。多重时间序列用list表示,每个时间序列需要指定一个字典:
详见: 数据如琥珀:多重时序高阶算法-DeepAR(供水管网压力预测Baseline)
对deepAR引入的协变量是“动态cat feature”还是 “静态cat feature”区分的讨论:
https://github.com/awslabs/gluon-ts/issues/392
马东什么:temporal fusion transformer
- import tqdm
- from gluonts.model.deepar import DeepAREstimator
-
- # Building training dataset
- train_data_list = []
- def _split_times_series(df, data_list, dynamic_real_1, dynamic_cat_1, dynamic_cat_2):
- new_df = df.sort_values(by=date_col, ascending=True)
- time_series_dict = {
- "item_id": new_df[id_col].values[0],
- "start": pd.to_datetime(new_df[date_col].min()),
- "target": new_df[target_col].values,
- "dynamic_real_1": [dynamic_real_1.T], # 主要是这行的差别
- "dynamic_cat_1": dynamic_cat_1,
- "dynamic_cat_2": dynamic_cat_2,
- }
- data_list.append(time_series_dict)
-
- tqdm.pandas(desc='progress: ')
- train_df.groupby(train_df[id_col]).progress_apply(_split_times_series,
- data_list=train_data_list,
- dynamic_real_1=camp_df_real_features_for_train,
- dynamic_cat_1=camp_df_cat1_features_for_train,
- dynamic_cat_2=camp_df_cat2_features_for_train)
-
- training_data = ListDataset(train_data_list, freq="1D")
-
- # build model
- rmv_imputation = RollingMeanValueImputation(10)
- estimator = DeepAREstimator(
- freq="1D",
- num_layers=num_layers,
- num_cells=num_cells,
- prediction_length=args.horizon,
- imputation_method=rmv_imputation,
- impute_missing_values=True,
- use_feat_dynamic_real=True,
- trainer=Trainer(epochs=epochs))
-
- # Predicting
- # same as above
https://github.com/aws/amazon-sagemaker-examples/issues/1312
WaveNet是DeepMind于2016年9月提出的一种基于空洞因果卷积式的语音生产模型,后面专家们发现它也可被用于时间序列的预测,他的感受野较大,网络结构可以自动的在不同时间尺度上提取周期信息。
- rom gluonts.model.wavenet import WaveNetEstimator
- # build model
- wavenet_estimator = WaveNetEstimator(
- freq="1D",
- n_residue=n_residue,
- embedding_dimension=embedding_dimension,
- act_type=act_type,
- n_skip=n_skip,
- prediction_length=args.horizon,
- trainer=Trainer(epochs=50, learning_rate=learning_rate)
- )
-
- # Predicting
- # same as above
N-BEATS是Bengio团队于2019年5月提出的用于时间序列预测的深度网络,主要结构包括前向后向残差链接以及不同的模块分解。他的可解释性相较其他深度学习模型会强一些(通过模块分解),但由于其存在复原原序列的过程,因此预测结果的稳定性要差一些。
- from gluonts.model.n_beats import NBEATSEstimator
- # build model
- nbeats_estimator = NBEATSEstimator(
- freq="1D",
- widths=[64, 64],
- num_stacks=2,
- num_blocks=[3],
- num_block_layers=[10],
- stack_types=['T', 'S'],
- prediction_length=args.horizon,
- trainer=Trainer(epochs=30))
-
- # Predicting
- # same as above
2.4.4.1 Transformer
Transformer是Google 在 2017 年提出的一种 用于NLP任务的模型,可以用来做时间序列预测。它可以关注到序列的长期依赖信息,且支持并行化计算,但其本身没有序列的概念,需要增加position embedding是网络学习到序列位置信息。
- from gluonts.model.transformer import TransformerEstimator
- # build model
- transformer_estimator = TransformerEstimator(
- freq="1D",
- embedding_dimension=15,
- model_dim=64,
- num_heads=4,
- prediction_length=args.horizon,
- trainer=Trainer(epochs=50)
- )
-
- # Predicting
- # same as above
2.4.4.2 TFT[4]
来源鱼arxiv上的一篇文章《Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting》,用于可解释多元时间序列预测的时间融合变换器。
- import tqdm
- from gluonts.model.tft import TemporalFusionTransformerEstimator
- # Building training dataset
- train_data_list = []
- def _split_times_series(df, data_list, dynamic_real_1, dynamic_cat_1, dynamic_cat_2):
- new_df = df.sort_values(by=date_col, ascending=True)
- time_series_dict = {
- "item_id": new_df[id_col].values[0],
- "start": pd.to_datetime(new_df[date_col].min()),
- "target": new_df[target_col].values,
- "dynamic_real_1": np.array(dynamic_real_1, ndmin=2),
- "dynamic_cat_1": dynamic_cat_1,
- "dynamic_cat_2": dynamic_cat_2,
- }
- data_list.append(time_series_dict)
- tqdm.pandas(desc='progress: ')
- train_df.groupby(train_df[id_col]).progress_apply(_split_times_series,
- data_list=train_data_list,
- dynamic_real_1=camp_df_real_features_for_train,
- dynamic_cat_1=camp_df_cat1_features_for_train,
- dynamic_cat_2=camp_df_cat2_features_for_train)
-
- training_data = ListDataset(train_data_list, freq="1D")
- # build model
- estimator = TemporalFusionTransformerEstimator(
- freq="1D",
- prediction_length=args.horizon,
- batch_size=batch_size,
- context_length=context_length,
- dropout_rate=dropout_rate,
- trainer=Trainer(batch_size=batch_size, epochs=epochs),
- # 数值型协变量dimension引入
- dynamic_feature_dims={"dynamic_real_1": 1},
- # 非数值型协变量引入
- dynamic_cardinalities={"dynamic_cat_1": cat1_cardinality, "dynamic_cat_2": cat2_cardinality},
- num_heads=num_heads,
- hidden_dim=hidden_dim)
-
- # Predicting
- # same as above
2.4.4.3 Informer
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。