时间序列特征工程:从基础到实战
1. 时间序列数据特征工程基础时间序列分析是数据科学领域的重要分支广泛应用于金融、气象、工业监测等多个领域。与传统的监督学习不同时间序列数据具有明显的时序依赖性这使得我们需要采用特殊的方法来构建特征。关键认知时间序列预测本质上是通过历史数据预测未来值这要求我们将时间序列重构为监督学习问题。1.1 时间序列的特殊性时间序列数据与普通表格数据的根本区别在于数据点之间存在时间上的先后顺序相邻观测值通常具有相关性自相关可能包含趋势、季节性和周期性等模式没有天然的输入/输出特征划分1.2 监督学习的重构方法要将时间序列转化为监督学习问题我们需要确定预测目标如t1时刻的值设计能够反映时序关系的特征构建包含特征和目标的数据集基本转换形式如下时间序列形式 时间1, 值1 时间2, 值2 时间3, 值3 监督学习形式 特征1, 目标值 特征2, 目标值 特征3, 目标值2. 日期时间特征构建2.1 基础日期特征日期时间信息是最直接可用的特征。对于每日温度数据我们可以提取月份1-12日期1-31星期几0-6是否为周末季度1-4import pandas as pd # 加载数据 series pd.read_csv(daily-min-temperatures.csv, header0, index_col0, parse_datesTrue) # 创建特征DataFrame features pd.DataFrame() features[month] series.index.month features[day] series.index.day features[day_of_week] series.index.dayofweek features[is_weekend] features[day_of_week].isin([5,6]).astype(int)2.2 高级时间特征根据领域知识可以构建更有意义的特征季节特征春夏秋冬是否节假日距特定日期的天数日照时长结合地理位置温度的季节性基准值# 添加季节特征 def get_season(month): if month in [12,1,2]: return 0 # 冬季 elif month in [3,4,5]: return 1 # 春季 elif month in [6,7,8]: return 2 # 夏季 else: return 3 # 秋季 features[season] series.index.month.map(get_season)3. 滞后特征构建3.1 基础滞后特征滞后特征是最常用的时间序列特征直接使用历史观测值作为预测依据# 创建滞后特征 lags pd.concat([ series.shift(1).rename(lag_1), series.shift(2).rename(lag_2), series.shift(3).rename(lag_3), series.shift(7).rename(lag_7), # 一周前 series.shift(30).rename(lag_30) # 一月前 ], axis1) # 合并所有特征 all_features pd.concat([features, lags, series.rename(target)], axis1)3.2 滞后特征选择策略选择滞后特征时需要考虑近期滞后t-1, t-2捕捉短期依赖季节性滞后t-7, t-30捕捉周期性模式长期滞后t-365捕捉年度趋势基于自相关分析选择最优滞后实践经验开始时可以包含多个滞后然后使用特征重要性分析筛选最有价值的滞后项。4. 窗口统计特征4.1 滚动窗口统计滚动窗口计算固定大小窗口内的统计量# 滚动窗口特征 window_size 7 rolling_stats series.rolling(windowwindow_size) window_features pd.concat([ rolling_stats.mean().rename(rolling_mean), rolling_stats.std().rename(rolling_std), rolling_stats.min().rename(rolling_min), rolling_stats.max().rename(rolling_max), rolling_stats.median().rename(rolling_median) ], axis1) # 需要调整窗口起始点 window_features window_features.shift(1)4.2 扩展窗口统计扩展窗口包含所有历史数据expanding_stats series.expanding() expanding_features pd.concat([ expanding_stats.mean().rename(expanding_mean), expanding_stats.std().rename(expanding_std), expanding_stats.min().rename(expanding_min), expanding_stats.max().rename(expanding_max) ], axis1) expanding_features expanding_features.shift(1)5. 特征工程实战技巧5.1 特征组合与变换除了原始特征还可以创建滞后特征的变化率窗口统计的比值温度的季节性差分标准化/归一化值# 温度变化率 all_features[temp_change_1] all_features[lag_1] - all_features[lag_2] all_features[temp_change_7] all_features[lag_1] - all_features[lag_7] # 季节性差分 all_features[seasonal_diff] all_features[lag_1] - all_features[lag_365]5.2 特征选择与评估特征工程后需要评估特征重要性计算特征与目标的相关性使用模型的特征重要性评分递归特征消除基于性能的特征选择from sklearn.ensemble import RandomForestRegressor # 删除缺失值 clean_data all_features.dropna() # 分离特征和目标 X clean_data.drop(target, axis1) y clean_data[target] # 训练模型获取特征重要性 model RandomForestRegressor() model.fit(X, y) # 特征重要性 importance pd.Series(model.feature_importances_, indexX.columns) print(importance.sort_values(ascendingFalse))6. 常见问题与解决方案6.1 数据缺失处理时间序列常见缺失问题节假日数据缺失传感器故障记录错误处理方法前向填充ffill后向填充bfill插值法线性、样条基于模型的填充# 多种填充方法比较 filled_data { ffill: series.fillna(methodffill), bfill: series.fillna(methodbfill), linear: series.interpolate(methodlinear), spline: series.interpolate(methodspline, order3) }6.2 特征缩放策略不同特征的缩放方法标准化Z-score适用于大多数数值特征归一化MinMax适用于有界特征Robust Scaling适用于有异常值的数据分位数变换适用于非正态分布from sklearn.preprocessing import StandardScaler, MinMaxScaler # 对数值特征进行标准化 numeric_features [lag_1, lag_7, rolling_mean] scaler StandardScaler() all_features[numeric_features] scaler.fit_transform(all_features[numeric_features]) # 对月份等循环特征使用正弦/余弦变换 all_features[month_sin] np.sin(2*np.pi*all_features[month]/12) all_features[month_cos] np.cos(2*np.pi*all_features[month]/12)7. 高级特征工程技术7.1 傅里叶变换特征对于周期性明显的时间序列傅里叶变换可以提取频率特征from scipy.fft import fft # 计算傅里叶变换 n len(series) yf fft(series.values) xf np.linspace(0.0, 1.0/(2.0*1.0), n//2) # 提取主要频率成分 dominant_freq xf[np.argmax(np.abs(yf[:n//2]))] all_features[dominant_frequency] dominant_freq7.2 小波变换特征小波变换可以同时捕捉时域和频域信息import pywt # 进行小波分解 coeffs pywt.wavedec(series.values, db1, level3) # 提取小波系数作为特征 for i, coeff in enumerate(coeffs): all_features[fwavelet_coeff_{i}_mean] np.mean(coeff) all_features[fwavelet_coeff_{i}_std] np.std(coeff)7.3 基于模型的特征使用简单模型提取特征线性回归残差移动平均残差季节性分解成分from statsmodels.tsa.seasonal import seasonal_decompose # 季节性分解 result seasonal_decompose(series, modeladditive, period365) # 提取分解成分 all_features[trend] result.trend all_features[seasonal] result.seasonal all_features[residual] result.resid8. 特征工程实战建议领域知识优先温度预测中考虑地理位置、季节、天气系统等专业因素可视化分析绘制特征与目标的关系图发现非线性关系迭代优化从简单特征开始逐步添加复杂特征验证策略使用时间序列交叉验证评估特征效果避免泄漏确保特征构建不会使用未来信息# 时间序列交叉验证示例 from sklearn.model_selection import TimeSeriesSplit tscv TimeSeriesSplit(n_splits5) for train_index, test_index in tscv.split(X): X_train, X_test X.iloc[train_index], X.iloc[test_index] y_train, y_test y.iloc[train_index], y.iloc[test_index] # 训练和评估模型 model.fit(X_train, y_train) score model.score(X_test, y_test) print(fFold score: {score:.3f})在实际项目中我发现温度预测的特征工程有几个关键点季节性特征比想象中更重要特别是年度和季度周期近期的温度变化率导数是非常有预测力的特征天气系统的移动速度决定了最优的滞后窗口大小节假日效应在温度预测中表现明显最后一个小技巧当处理长时间序列时可以先将数据按季节分组分别计算统计特征这样能更好地捕捉季节性模式。