传统统计学习方法: naive approach, moving average, Holt linear, exponential smoothing, ARIMA, and Prophet
现代机器学习方法: 树模型等
深度学习方法: LSTM、Seq2seq、Transform-XL等
树模型需要人为构建特征,同时预测值不可超越区间内取值的上限。
深度学习网络,可以发现输入数据之间的交互关系,同时可以发现趋势。
根据数据可以尝试不同的方法,选择较优的方法。下面是树模型的构造特征的方法。
也是时点特征。
年、月、日、时、分、星期等。
由此扩展出来的是否周末(销量等差异)、节假日(销量差异)、白昼(温度差异)、是否发薪日等(月中、月末购买意向)、月份的第几周(上半月、下半月之类)等。
小时0-23特征,0与23的差距并不像数值上的那么大,通过sin,cos处理将小时处理成循环取值。
日期特征当做类别特征还是数值特征?
对于趋势明显的,把其视为数值比类别效果好,这个我在M5上做过验证。解释如下:
以上是时间点特征,这里是时间段特征。
个人解释,时间序列的预测在长期或短期内存在规律包括周期性等,这种规律性通过窗口内统计特征体现。
以上特征就相当于另类编码,或离散化。涉及到平均情况以及离散程度等。
时间序列之所以可以预测,因为我们研究时间序列很重要的一个应用(或者出发点),是希望通过时间序列的历史数据来得到其未来的一些预测。换句话说,我们希望时间序列在历史数据上的一些性质,在将来保持不变,这不就是时间平移的不变性么?反过来想,如果时间序列不是平稳的,由历史数据得到的统计性质对未来毫无意义,那么研究时间序列还有什么意义呢?参考
这也就为滞后特征带来了意义。其实可以这样理解,当前或者未来所处的片段,是过去的一个缩影。
滞后1期、2期、3期。。。其实,这种连续的滞后是没必要的,极可能产生信息冗余,建议不要整太多。可以整一些滞后7、14、28、60、120等这种可以解释的。
通常滞后特征与滚动、差分等一起使用。
shift(14).rolling(7).mean()
(滞后14期的7步移动平均)shift(14).diff(1).
(滞后14期的1阶差分,差分主要是去趋势)延伸。滞后、差分等特征会带来缺失值,处理:原文或以下原话
# 原文
# There are few options to work
# with NaNs in train set
## 1. drop it train_df[train_df['d']>MAX_LAG_DAY]
## 1.1 in our case we already dropped some lines by release date
## so you have find d.min() for each id
## and drop train_df[train_df['d']>(train_df['d_min']+MAX_LAG_DAY)]
## 2. If you want to keep it you can
## fill with '-1' to be able to convert to int
## 3. Leave as it is
## 4. Fill with mean -> not recommended
下面说一说个人对滞后局限的理解:
做STFT之类。频域特征最大的问题就是对时间的不敏感,而且还存在边缘效应,所以在预测未来时间点的场景下,基本没有什么作用。参考
这里是对类别特征进行聚合统计信息,相当于另类编码。
# 历史信息提取
data_df['dt'] = data_df['day'].values + (data_df['month'].values - 3) * 31 # 有了大小的可比较概念
for f in ['outdoorTemp','outdoorHum','outdoorAtmo','indoorHum','indoorAtmo', 'temperature']:
tmp_df = pd.DataFrame()
for t in tqdm(range(15, 45)):
# 类似Catboost的TS编码,有一个时间顺序的概念
tmp = data_df[data_df['dt']<t].groupby(['hour'])[f].agg({'mean'}).reset_index()
tmp.columns = ['hour','hit_{}_mean'.format(f)]
tmp['dt'] = t
tmp_df = tmp_df.append(tmp)
data_df = data_df.merge(tmp_df, on=['dt','hour'], how='left')
上面都已经提到了组合特征,这里再强调一下,多个特征组合也是非常重要。LGBM中内含互斥特征捆绑EFB策略,即EFB算法利用特征和特征间的关系构造一个加权无向图,并将其转换为图着色的问题来求解,求解过程中采用的贪心策略。说白了就是对于稀疏特征,将特征与特征之间共同取值为非0的较少的特征进行合并。这里其实主要是减少特征数量,从而减少耗时。
我们构造的交叉特征可以反应不同特征组合,从而可能发现惊喜。
以下是科大讯飞温室温度预测中的交叉特征处理方式,源于【Coggle数据科学】
# 基本交叉特征
for f1 in tqdm(['outdoorTemp','outdoorHum','outdoorAtmo','indoorHum','indoorAtmo']+group_feats):
for f2 in ['outdoorTemp','outdoorHum','outdoorAtmo','indoorHum','indoorAtmo']+group_feats:
if f1 != f2:
colname = '{}_{}_ratio'.format(f1, f2)
data_df[colname] = data_df[f1].values / data_df[f2].values
以下源于M5的id交叉信息的统计特征。
########################### Apply on grid_df
#################################################################################
# lets read grid from
# https://www.kaggle.com/kyakovlev/m5-simple-fe
# to be sure that our grids are aligned by index
grid_df = pd.read_pickle('../data/output/grid_part_1.pkl')
grid_df[TARGET][grid_df['d']>(1941-28)] = np.nan
base_cols = list(grid_df)
icols = [
['state_id'],
['store_id'],
['cat_id'],
['dept_id'],
['state_id', 'cat_id'],
['state_id', 'dept_id'],
['store_id', 'cat_id'],
['store_id', 'dept_id'],
['item_id'],
['item_id', 'state_id'],
['item_id', 'store_id']
]
for col in icols:
print('Encoding', col)
col_name = '_'+'_'.join(col)+'_'
grid_df['enc'+col_name+'mean'] = grid_df.groupby(col)[TARGET].transform('mean').astype(np.float16)
grid_df['enc'+col_name+'std'] = grid_df.groupby(col)[TARGET].transform('std').astype(np.float16)
keep_cols = [col for col in list(grid_df) if col not in base_cols]
grid_df = grid_df[['id','d']+keep_cols]
先写到这里,后期想到再补充。