攻克时间序列预测难题:Time-Series-Library输入处理与损失函数全解析
你是否还在为时间序列预测模型的输入格式混乱而头疼?是否因损失函数选择不当导致预测结果偏差?本文将系统解析Time-Series-Library中的数据输入处理流程与核心损失函数设计,帮助你快速掌握模型调优关键技巧。读完本文,你将能够:理解4种主流数据加载器的适用场景、掌握3类损失函数的数学原理与代码实现、通过实际案例优化模型输入输出策略。
数据输入处理:从原始数据到模型输入的完整流程
时间序列预测的准确性首先取决于数据输入的质量。Time-Series-Library提供了多套数据加载方案,覆盖不同时间粒度和应用场景。
数据集加载架构概览
项目采用模块化设计将原始数据转换为模型可接受的张量格式,核心代码位于data_provider/data_loader.py。该模块实现了从数据读取、标准化到时间特征编码的全流程处理,支持小时级、分钟级等多粒度时间序列数据。
主流数据加载器解析
库中实现了5种核心数据加载器,分别适用于不同场景:
- 高频时间序列加载器:Dataset_ETT_hour与Dataset_ETT_minute分别针对小时级和分钟级数据设计,支持电力负荷等高频监测数据。代码通过设置seq_len(序列长度)、label_len(标签长度)和pred_len(预测长度)三个参数控制输入输出窗口大小。
# 小时级数据加载示例 [data_provider/data_loader.py#L19]
class Dataset_ETT_hour(Dataset):
def __init__(self, args, root_path, flag='train', size=None,
features='S', data_path='ETTh1.csv',
target='OT', scale=True, timeenc=0, freq='h'):
# size参数格式: [seq_len, label_len, pred_len]
self.seq_len = size[0] # 输入序列长度
self.label_len = size[1] # 标签序列长度
self.pred_len = size[2] # 预测序列长度
-
通用数据加载器:Dataset_Custom支持自定义格式数据,通过features参数控制单变量('S')或多变量('M')输入,满足个性化数据处理需求。
-
M4竞赛数据集加载器:Dataset_M4专为M4时间序列预测竞赛设计,支持年度、季度等多种周期性数据,代码位于[data_provider/data_loader.py#L310]。
-
异常检测专用加载器:包括PSMSegLoader、MSLSegLoader等,针对工业设备异常检测场景优化,支持滑动窗口采样和标签对齐。
时间特征编码策略
时间特征编码是提升模型性能的关键步骤。库中实现了两种编码方式:
- 数值编码(timeenc=0):将日期转换为月、日、小时等数值特征
- 时间嵌入(timeenc=1):通过utils/timefeatures.py实现三角函数编码,更好地捕捉周期性模式
# 时间特征编码示例 [data_provider/data_loader.py#L74]
if self.timeenc == 0:
df_stamp['month'] = df_stamp.date.apply(lambda row: row.month)
df_stamp['day'] = df_stamp.date.apply(lambda row: row.day)
df_stamp['hour'] = df_stamp.date.apply(lambda row: row.hour)
data_stamp = df_stamp.drop(['date'], 1).values
elif self.timeenc == 1:
data_stamp = time_features(pd.to_datetime(df_stamp['date'].values), freq=self.freq)
损失函数设计:预测精度的核心保障
损失函数直接影响模型的学习方向和预测性能。Time-Series-Library在utils/losses.py中实现了多种专为时间序列预测优化的损失函数。
三大核心损失函数解析
- MAPE损失(平均绝对百分比误差)
- 适用场景:需关注相对误差的预测任务
- 数学公式:$MAPE = \frac{1}{n}\sum|\frac{y-\hat{y}}{y}|$
- 代码实现:
class mape_loss(nn.Module):
def forward(self, insample: t.Tensor, freq: int,
forecast: t.Tensor, target: t.Tensor, mask: t.Tensor) -> t.float:
weights = divide_no_nan(mask, target)
return t.mean(t.abs((forecast - target) * weights))
-
sMAPE损失(对称平均绝对百分比误差)
- 解决MAPE在目标值接近0时的不稳定性问题
- 数学公式:$sMAPE = \frac{200}{n}\sum\frac{|y-\hat{y}|}{|y|+|\hat{y}|}$
-
MASE损失(平均绝对标度误差)
- 基于历史数据波动性进行归一化,适合非平稳时间序列
- 代码关键实现:
def forward(self, insample: t.Tensor, freq: int, ...) -> t.float:
# 计算历史平均绝对误差作为基准
masep = t.mean(t.abs(insample[:, freq:] - insample[:, :-freq]), dim=1)
masked_masep_inv = divide_no_nan(mask, masep[:, None])
return t.mean(t.abs(target - forecast) * masked_masep_inv)
损失函数选择策略
不同模型和数据集需要匹配不同的损失函数:
- 短期预测:优先使用sMAPE,对极端值更稳健
- 长期预测:MASE表现更优,考虑时间序列的动态波动性
- 异常检测:结合mask机制忽略异常值对损失的影响
模型输入与损失函数协同优化案例
以电力负荷预测为例,展示如何组合使用数据加载器和损失函数:
步骤1:配置ETT小时级数据加载器
data_loader = Dataset_ETT_hour(
args, root_path='./data', data_path='ETTh1.csv',
size=[96, 48, 96], # seq_len=96, label_len=48, pred_len=96
features='M', target='OT', timeenc=1, freq='h'
)
步骤2:选择合适的损失函数
对于电力负荷数据,推荐使用sMAPE损失函数:
from utils.losses import smape_loss
criterion = smape_loss()
步骤3:模型训练与评估
通过exp/exp_long_term_forecasting.py实现完整训练流程,代码会自动将数据加载器的输出与损失函数对接。
实战技巧与最佳实践
输入窗口优化
- 短期预测(<24小时):seq_len = 3-5倍pred_len
- 长期预测(>7天):seq_len至少包含一个完整周期
- 代码参考:scripts/long_term_forecast/ETT_script/Autoformer_ETTh1.sh
损失函数调优建议
- 当数据存在极端值时,优先使用sMAPE替代MAPE
- 多步预测任务中,可对不同预测步采用加权损失
- 结合utils/metrics.py中的评估指标选择损失函数
总结与展望
本文详细解析了Time-Series-Library的数据输入处理机制和损失函数设计。通过合理配置数据加载参数和选择适当的损失函数,可以显著提升时间序列预测模型的性能。项目后续将增加更多异常值鲁棒的损失函数,并优化多变量时间序列的特征选择机制。
建议结合官方提供的TimesNet_tutorial.ipynb教程进行实践,同时参考README.md获取最新的模型支持信息。如有疑问,可查阅CONTRIBUTING.md参与社区讨论。
点赞收藏本文,关注项目更新,不错过时间序列预测的最新技术进展!下一篇我们将深入探讨Transformer类模型在时间序列预测中的应用优化。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




