应用Python依据汇总统计信息增加新个性,本文将通知你如何计算几个工夫序列中的滚动统计信息。将这些信息增加到解释变量中通常会取得更好的预测性能。
简介
自回归
多变量工夫序列蕴含两个或多个变量,钻研这些数据集的目标是预测一个或多个变量,参见上面的示例。
上图是蕴含9个变量的多变量工夫序列。这些是智能浮标捕捉到的陆地情况。
大多数预测模型都是基于自回归的。这相当于解决了一个监督学习回归工作。该序列的将来值是指标变量。输出的解释变量是每个变量最近的过来值。
自回归在一个次要假如下工作。最近的过来值蕴含了对于将来的足够信息。但这可能不肯定是真的。咱们能够尝试从最近的数据中提取更多的信息。例如,滚动汇总统计信息有助于形容最近的动静。
自动化特色工程
特色工程包含提取和生成解释变量,这是任何数据迷信我的项目的要害。特色的品质是模型性能的一个外围方面,所以数据科学家在这个过程中破费了大量的工夫。
个性工程通常是一个特地的过程:数据科学家基于他们的畛域常识和专业知识创立个性,如果该过程的可能自动化化解决将会为咱们节俭很多的工夫。让咱们看看如何在多元工夫序列中做到这一点。
基线模型
读取数据
咱们将应用从智能浮标收集的多元工夫序列作为本文的数据集 [1]。 这个浮标位于爱尔兰海岸。 它捕捉了 9 个与陆地条件相干的变量。 其中包含淡水温度、波浪高度和淡水流速等。 下面的图 1 显示了 2022 年第一个月的状况。
以下是应用 pandas 读取这些数据的办法:
import pandas as pd # skipping second row, setting time column as a datetime column # dataset available here: https://github.com/vcerqueira/blog/tree/main/data buoy = pd.read_csv('data/smart_buoy.csv', skiprows=[1], parse_dates=['time']) # setting time as index buoy.set_index('time', inplace=True) # resampling to hourly data buoy = buoy.resample('H').mean() # simplifying column names buoy.columns = [ 'PeakP', 'PeakD', 'Upcross', 'SWH', 'SeaTemp', 'Hmax', 'THmax', 'MCurDir', 'MCurSpd' ]
这个数据集钻研的指标是预测SWH(显著波高)变量的将来值。这个变量常被用来量化海浪的高度。这个问题的一个用例是预计海浪发电的大小,因为这种能源是一种越来越受欢迎的代替不可再生能源。
自回归模型
工夫序列是多元的,所以能够应用ARDL(Auto-regressive distributed lags)办法来解决这个工作。咱们在之前也介绍过则个办法。上面是这个办法的实现:
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_percentage_error as mape from sklearn.multioutput import MultiOutputRegressor from lightgbm import LGBMRegressor # https://github.com/vcerqueira/blog/blob/main/src/tde.py from src.tde import time_delay_embedding target_var = 'SWH' colnames = buoy.columns.tolist() # create data set with lagged features using time delay embedding buoy_ds = [] for col in buoy: col_df = time_delay_embedding(buoy[col], n_lags=24, horizon=12) buoy_ds.append(col_df) # concatenating all variables buoy_df = pd.concat(buoy_ds, axis=1).dropna() # defining target (Y) and explanatory variables (X) predictor_variables = buoy_df.columns.str.contains('\(t\-') target_variables = buoy_df.columns.str.contains(f'{target_var}\(t\+') X = buoy_df.iloc[:, predictor_variables] Y = buoy_df.iloc[:, target_variables] # train/test split X_tr, X_ts, Y_tr, Y_ts = train_test_split(X, Y, test_size=0.3, shuffle=False) # fitting a lgbm model without feature engineering model_wo_fe = MultiOutputRegressor(LGBMRegressor()) model_wo_fe.fit(X_tr, Y_tr) # getting forecasts for the test set preds_wo_fe = model_wo_fe.predict(X_ts) # computing the MAPE error mape(Y_ts, preds_wo_fe) # 0.238
首先将工夫序列转化为一个自回归问题。这是通过函数time_delay_embedding实现的。预测的指标是预测将来12个SWH值(horizon=12)。解释变量是序列中每个变量的过来的24个值(n_lag =24)。
咱们这里间接应用LightGBM对每个预测层位进行训练。这种办法法是一种罕用的多步超前预测办法。它在scikit-learn中也有实现,名为MultiOutputRegressor。
下面的代码构建和测试一个自回归模型。解释变量只包含每个变量最近的过来值。后果的均匀相对百分比误差为0.238。
咱们把这个后果作为基类比照,让咱们看看是否能够通过个性工程来进步。
多元工夫序列的特色工程
本文本将介绍两种从多元工夫序列中提取特色的办法:
- 单变量特征提取。计算各变量的滚动统计。例如,滚动均匀能够用来打消虚伪的观测;
- 二元特征提取。计算变量对的滚动统计,以总结它们的相互作用。例如,两个变量之间的滚动协方差。
单变量特征提取
咱们能够总结每个变量最近的过来值。例如,计算滚动均匀来总结最近的状况。或者滚动差量来理解最近的扩散水平。
import numpy as np SUMMARY_STATS = { 'mean': np.mean, 'sdev': np.std, } univariate_features = {} # for each column in the data for col in colnames: # get lags for that column X_col = X.iloc[:, X.columns.str.startswith(col)] # for each summary stat for feat, func in SUMMARY_STATS.items(): # compute that stat along the rows univariate_features[f'{col}_{feat}'] = X_col.apply(func, axis=1) # concatenate features into a pd.DF univariate_features_df = pd.concat(univariate_features, axis=1)
如果能须要增加更多的统计数据。能够向SUMMARY_STATS字典增加函数来实现这一点。将这些函数放在一个字典中能够放弃代码整洁。
二元特征提取
单变量统计漏掉了不同变量之间潜在的相互作用。所以咱们能够应用二元特征提取过程捕捉这些信息。
这个想法是为不同的变量对计算特色。能够应用二元统计总结了这些对的联结动静。
有两种办法能够做到这一点:
- 滚动二元统计。计算以变量对作为输出的统计信息。例如,滚动协方差或滚动相关性滚动二元统计的例子包含协方差、相关性或绝对熵。
- 滚动二元变换,而后单变量统计。这将一对变量转换为一个变量,并对该变量进行统计。例如,计算元素互相关系,而后取其平均值。有许多二元转换的办法。例如,百分比差别、互相关联或成对变量之间的线性卷积。通过第一步操作后,用平均值或标准偏差等统计数据对这些转换进行汇总。
上面是用于性实现这两个过程的代码:
import itertools import pandas as pd from scipy.spatial.distance import jensenshannon from scipy import signal from scipy.special import rel_entr from src.feature_extraction import covariance, co_integration BIVARIATE_STATS = { 'covariance': covariance, 'co_integration': co_integration, 'js_div': jensenshannon, } BIVARIATE_TRANSFORMATIONS = { 'corr': signal.correlate, 'conv': signal.convolve, 'rel_entr': rel_entr, } # get all pairs of variables col_combs = list(itertools.combinations(colnames, 2)) bivariate_features = [] # for each row for i, _ in X.iterrows(): # feature set in the i-th time-step feature_set_i = {} for col1, col2 in col_combs: # features for pair of columns col1, col2 # getting the i-th instance for each column x1 = X.loc[i, X.columns.str.startswith(col1)] x2 = X.loc[i, X.columns.str.startswith(col2)] # compute each summary stat for feat, func in BIVARIATE_SUMMARY_STATS.items(): feature_set_i[f'{col1}|{col2}_{feat}'] = func(x1, x2) # for each transformation for trans_f, t_func in BIVARIATE_TRANSFORMATIONS.items(): # apply transformation xt = t_func(x1, x2) # compute summary stat for feat, s_func in SUMMARY_STATS.items(): feature_set_i[f'{col1}|{col2}_{trans_f}_{feat}'] = s_func(xt) bivariate_features.append(feature_set_i) bivariate_features_df = pd.DataFrame(bivariate_features, index=X.index)
字典bivariate_transforms或BIVARIATE_STATS中增加其余的函数,能够增加额定的转换或统计信息。
在提取所有特色之后,咱们将将它们连贯到原始解释变量。训练和测试的过程和之前的是一样的,只不过咱们减少了一些人工生成的变量。
# concatenating all features with lags X_with_features = pd.concat([X, univariate_features_df, bivariate_features_df], axis=1) # train/test split X_tr, X_ts, Y_tr, Y_ts = train_test_split(X_with_features, Y, test_size=0.3, shuffle=False) # fitting a lgbm model with feature engineering model_w_fe = MultiOutputRegressor(LGBMRegressor()) model_w_fe.fit(X_tr, Y_tr) # getting forecasts for the test set preds_w_fe = model_w_fe.predict(X_ts) # computing MAPE error print(mape(Y_ts, preds_w_fe)) # 0.227
失去了0.227的均匀相对百分比误差,这是一个小小的进步,因为咱们的基线是0.238。
特征选择
以上提取过程共失去了558个解释变量。依据变量和汇总统计信息的数量,这可能会产生高维问题。因而,从数据集中删除蹩脚或冗余的特色是很重要的。
咱们将找到一些重要特色并从新训练
# getting the importance of each feature in each horizon avg_imp = pd.DataFrame([x.feature_importances_ for x in model_w_fe.estimators_]).mean() # getting the top 100 features n_top_features = 100 importance_scores = pd.Series(dict(zip(X_tr.columns, avg_imp))) top_features = importance_scores.sort_values(ascending=False)[:n_top_features] top_features_nm = top_features.index # subsetting training and testing sets by those features X_tr_top = X_tr[top_features_nm] X_ts_top = X_ts[top_features_nm] # re-fitting the lgbm model model_top_features = MultiOutputRegressor(LGBMRegressor()) model_top_features.fit(X_tr_top, Y_tr) # getting forecasts for the test set preds_top_feats = model_top_features.predict(X_ts_top) # computing MAE error mape(Y_ts, preds_top_feats) # 0.229
能够看到前100个个性与残缺的558个个性的性能类似。以下是前15个特色的重要性(为了简洁起见省略了其余特色):
能够看到最重要的特色是指标变量的第一个滞后值。一些提取的特色也呈现在前15名中。例如第三个特色SWH|Hmax_js_div。这示意指标变量的滞后与Hmax的滞后之间的Jensen-Shannon散度。第五个个性是SeaTemp_sdev,示意陆地温度的标准偏差滞后。
另一种去除冗余特色的办法是利用相关性过滤器。删除高度相干的特色以缩小数据的维数,这里咱们就不进行演示了。
总结
本文侧重于多变量工夫序列的预测问题。特征提取过程利用于工夫序列的多个子序列,在每个工夫步骤中,都要用一组统计数据总结过来24小时的数据。
咱们也能够用这些统计来一次性形容整个工夫序列。如果咱们指标是将一组工夫序列聚类,那么这可能是很有用。用特征提取总结每个工夫序列。而后对失去的特色利用聚类算法。
用几句话总结本文的关键点:
- 多变量工夫序列预测通常是一个自回归过程
- 特色工程是数据迷信我的项目中的一个关键步骤。
- 能够用特色工程改良多元工夫序列数据。这包含计算单变量和双变量转换和汇总统计信息。
- 提取过多的特色会导致高维问题。能够应用特征选择办法来删除不须要的特色。
本文的数据集在这里下载:
https://avoid.overfit.cn/post/dcb4ca4d223e4e728fb778739b69f136
作者:Vitor Cerqueira