在时间序列预测领域,近年来出现了机器学习算法,如梯度提升树框架(XGBoost、LightGBM)、深度学习(LSTM、GRU、TCN)算法。 在进行时间序列建模时,机器学习算法与深度学习的区别在于是否预处理特征。 例如,在我们获得包含“日期时间”时间戳的原始数据后,机器学习算法通常会对时间戳进行细粒度的时间特征提取,以帮助模型更好地理解时间模式和趋势。 一般的深度学习模型不会对原始数据的时间特征进行预处理,而是依靠模型自身对时间特征的理解来进行特征提取和变换。
数据处理
- 检查数据:
预测分为首先,我们必须观察提供/收集的时间序列数据。 检查它是否是按时间顺序排列的连续观察序列。 因为时间序列模型的假设即是连续时间数据,所以如果所得到的时间序列数据过于离散,需要对时间单位进行细粒度化,以提高数据的连续性。
2、数据清洗:
- 重复数据:去除重复信息,删除不相关的数据,删除例如 order_id 或 row_id,等只代表序列含义的列,无法对预测做出贡献。
- 处理缺失值:数据缺失在一定阈值内需要删除或估算。 一般来讲,从技术人员角度,缺失数据超过40-50%即可界定为缺失大部分有效信息。但如果项目有业务人员参与,缺失百分比也取决于先验知识。如果数据缺失比例少于既定阈值,需要考虑填充,一般可以通过0、均值、众数、中位数等填充缺失值。在必要时也可以考虑少样本分类、回归模型预测出改缺失特征的缺失值,进而完成填充。
- 纠正格式错误:确保输入数据格式正确。比如数据集中的“日期”数据可能是“object”格式,而对于建模来说,日期数据应该是应为“datetime”格式。
- 检测和处理异常值数据:通常模型对于异常值的敏感度会显著影响模型性能。例如决策树对异常值较为敏感,因为在构建树的过程中,异常值可能导致节点的划分发生变化,进而导致建模失败。但适当的构建模型结构可以提高鲁棒性。诸如决策树的集成模型(随机森林、梯度提升树)则相对不容易受到异常值的干扰。因此请识别异常值并确定适当的操作来处理它们。
- 标准化:不同的特征可能有不同的尺度和单位。例如,在数据集中,一个特征的范围可能是从 0 到 1,而另一个特征的范围可能是从 1 到100。如果模型不适应这种差异,则可能会导致训练不稳定或某些特征可能产生过大的影响。标准化,例如对数变换、归一化等是考虑稳定数据方差的好方法
3、数据分析:
分析数据集的特征,例如季节性、趋势、周期性等,因为它有助于进行进一步的特征工程(如果有必要)。
具体代码
通常细粒度的时间特征可以通过以下方式抽取,具体取决于业务需求:
- 细粒度时序特征
import pandas as pd
def get_season(month):
if 3 <= month <= 5:
return 'Spring'
elif 6 <= month <= 8:
return 'Summer'
elif 9 <= month <= 11:
return 'Fall'
else:
return 'Winter'
def create_data_features(data):
'''📊Create features for main data (test or train) set📊'''
# To datetime
data['datetime'] = pd.to_datetime(data['datetime'])
# Time period features
data['date'] = data['datetime'].dt.normalize()
data['year'] = data['datetime'].dt.year
data['quarter'] = data['datetime'].dt.quarter
data['month'] = data['datetime'].dt.month
data['week'] = data['datetime'].dt.isocalendar().week
data['hour'] = data['datetime'].dt.hour
# Day features
data['day_of_year'] = data['datetime'].dt.day_of_year
data['day_of_month'] = data['datetime'].dt.day
data['day_of_week'] = data['datetime'].dt.day_of_week
# Season features
data['season'] = data['month'].apply(get_season)
# Weekday/Weekend features
data['is_weekend'] = data['day_of_year'].isin([5, 6]).astype(int)
return data
- 节假日时间特征
def create_holiday_features(df, country_code='GR'):
"""
Creates holiday features from datetime index
"""
year_range = list(range(min(df.datetime.dt.year), max(df.datetime.dt.year) + 1))
country_holidays = holidays.country_holidays(
country_code,
years=year_range,
observed=False
)
df['holiday'] = df['datetime'].apply(lambda datetime: int(datetime.date() in country_holidays))
return df
- 滞后特征
时滞效应是指过去的观测值对当前和未来的观测值有延迟的影响。通过引入滞后时间特征,可以更好地处理这种时滞效应。滞后特征是将过去时间点的观测值作为输入特征,用于预测未来时间点的目标值,因此滞后时间特征可以帮助建立因果关系。例如,在销售预测中,过去的销售量可能与未来的销售量存在一定的因果关系。并且在机器学习中,之后时间特征可以帮助理解和捕捉序列相关性,周期性,及潜在数据模式。
在实际应用中,通常会考虑不同滞后时间步长的特征,比如过去一天、过去一周、过去一个月等,以适应不同的时序模式。使用这些滞后时间特征,可以改善模型的性能,提高对未来观测值的准确性。
def create_lag_features(df, column, lags):
for lag in lags:
df[f'{column}_lag_{lag}'] = df[column].shift(lag)
# Usage
create_lag_features(df, 'value', [1, 3, 7])
深度学习中是否需要特征工程?
在本文中,我们介绍了可以考虑用于机器学习建模的时间特征工程。 在深度学习中,模型通常具有强大的特征提取能力,其设计目的是直接从原始数据中学习特征表示。 因此,在深度学习中通常不需要显式特征提取,因为模型可以自主学习相关特征。
然而,根据问题的性质和数据的特征,特征提取可能仍然在深度学习管道中发挥作用。 以下是一些可以考虑特征提取的场景:
- 有限数据集:
当可用数据相对较小时,预训练的特征提取器(例如,使用在大型数据集上预训练的神经网络的卷积层)可能有助于提取通用特征,增加特征信息量,从而减少对大量注释数据的需求。
- 特定领域的知识:
如果您拥有特定领域的专业知识,手动选择和提取特定特征可能有助于模型更好地理解问题。
- 资源限制:
在资源受限的情况下,例如在移动设备上部署模型,在训练期间使用预先训练的特征提取器,然后在顶部添加额外的层进行微调可能是有益的。
在大多数情况下,深度学习模型可以直接从原始数据中学习足够的特征表示。 然而,根据问题的不同,特定的特征工程技术仍然可以提供帮助,而不是仅仅依赖于端到端的深度学习方法。并且在实际建模中,在深度学习建模前进行特征工程已被证实可以部分提高模型对于数据集的理解。
在下一篇文章中,我们将根据几个案例,展示几个简单的在时域的时间序列特征提取及建模demo。