循环编码:时间序列中周期性特征的一种常用编码方式

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 循环编码是深度学习中处理周期性数据的一种技术,常用于时间序列预测。它将周期性特征(如小时、日、月)转换为网络可理解的形式,帮助模型识别周期性变化。传统的one-hot编码将时间特征转换为分类特征,而循环编码利用正弦和余弦转换,保持时间顺序信息。通过将时间戳转换为弧度并应用sin和cos,每个原始特征只映射到两个新特征,减少了特征数量。这种方法在神经网络中有效,但在树模型中可能需谨慎使用。

在深度学习或神经网络中,"循环编码"(Cyclical Encoding)是一种编码技术,其特点是能够捕捉输入或特征中的周期性或循环模式。这种编码方法常用于处理具有周期性行为的任务,比如时间序列预测或理解展示周期性特征的序列。

循环编码的核心思想是将数据的周期性特征转化为网络能够理解的形式。例如,在处理时间数据时,比如小时、日、月等的循环模式,可以使用循环编码来帮助模型识别和利用这些周期性的变化。

当涉及到训练时间序列模型时,通常会使用以下时间特征:

小时、星期、月、周或年中的一天

将时间戳列转换为这些类型的特性是相当容易的。在确保将时间列转换为datetime对象(使用pd.to_datetime)之后,可以使用.dt提取一系列时间序列特征。

 df['Hour']=df['Datetime'].dt.hour
 df['Month']=df['Datetime'].dt.month
 df['Dayofweek']=df['Datetime'].dt.dayofweek

能源消耗数据集通常是时间序列,其最终目标是使用过去的数据预测未来的消耗,因此这是一个很好的用例。虽然其他外部特征,如温度、湿度和风速也会影响能耗,但本文将重点关注时间序列特征的提取和转换。

在能源消耗方面,一天中有一定的高峰时段,更有可能出现更高的消耗。也有一些特定的时间往往消耗较少。从某种意义上说,每个小时都有自己的范畴。

放大该数据集的特定部分就可以展示这一点。全天都有明确的消费模式——使用量在同一时间(下午5 - 6点)达到峰值,在早上5 - 7点达到最低。

这些模式与其他特征有复杂的交互,例如一年中的时间/月份和一周中的一天,这就是为什么我们希望在模型中包含尽可能多的信息的原因。

传统编码的问题

那么我们怎么做呢?如果你像大多数人一样,你早就知道分类特征需要以其他格式编码,以便模型正确地理解它们是什么。最著名的方法是one-hot编码。

One-hot编码简单且易于实现。对于一天(或一个月、一天等)中的任何一个小时,“它是小时/天/月n吗?”然后用二进制0或1来回答这个问题。它对每种类别都这样做。因此,对于1 day_of_week原始特征,您将有7个编码特征(表示一周中的7天):

  • is_day_1
  • is_day_2
  • is_day_3
  • is_day_4
  • is_day_5
  • is_day_6
  • is_day_7

在Python中,最简单的方法是使用pd.get_dummies:

 columns_to_encode = ['Hour', 'Month', 'Dayofweek']

 df = pd.get_dummies(df, columns=columns_to_encode)

这将产生新的特性集。

我们从3个特征(小时、月、日)得到了40多个特征。随着添加越来越多需要编码的时间序列特征,这会变得越来越混乱。

循环编码

这时候就可以到我们提到的循环编码,因为时间序列特征本质上是周期性的。以时间为例当时钟敲响24:00(凌晨12点),新的一天开始,下一个小时是1:00(凌晨1点)。虽然数字1和24实际上是距离最远的数字,但1和23一样接近24,因为它们在一个循环中。

另一种用数字表示时间序列特征的方法是将时间戳转换成正弦和余弦变换。这种方式会告诉你一天中的时间,一周中的时间,或者一年中的时间。

我们需要的编码不是将日期时间值转换为分类特征(就像我们使用one-hot编码一样),而是将它们转换为数值特征,其中一些值更接近(例如12AM和1AM),而其他值则更远(例如12AM和12PM)。但当我们用One-hot编码时,这种信息就丢失了。

正弦和余弦来自单位圆,可以映射时间戳在这个圆上的位置,用正弦和余弦坐标表示。将圆圈的右侧视为起点(在下面的图表中以0表示)或真正的24小时时间刻度上的00:00 (12AM),我们将其划分为4个6小时的地标,以便能够将小时映射到圆上。

当你在单位圆上逆时针移动时,它增加到/2(或90度),这相当于6:00AM,(180度)或12:00PM, 3 /2或6:00PM,最后在12:00 am回到0。这些时间点都有自己独特的坐标。这样就可以用正弦和余弦表示24小时的每日周期。

其他周期也可以这样做,比如一周或一年的时间,一般的公式如下:

要在Python中完成此操作,需要首先将datetime(在我的示例中是小时时间戳)转换为数值变量。通过将该列转换为pd.Timestamp.timestamp对象,将每个时间戳转换为unix时间(自1970年1月1日以来经过的秒数)。然后把这个数值列变换成正弦和余弦的特征。

 # Convert datetime into a numerical seconds timestamp object 
 # (tells you the date/time in seconds)
 timestamp_s = df['Datetime'].map(pd.Timestamp.timestamp)

 # Get the number of seconds for each time period
 day = 24*60*60
 week = day*7
 year = day*(365.2425)

 # Transform using sin and cos
 # Time of day
 df['Day_sin'] = np.sin(timestamp_s * (2 * np.pi / day))
 df['Day_cos'] = np.cos(timestamp_s * (2 * np.pi / day))

 # Time of week
 df['Week_sin'] = np.sin(timestamp_s * (2 * np.pi / week))
 df['Week_cos'] = np.cos(timestamp_s * (2 * np.pi / week))

 # Time of year
 df['Year_sin'] = np.sin(timestamp_s * (2 * np.pi / year))
 df['Year_cos'] = np.cos(timestamp_s * (2 * np.pi / year))

上面的代码解释如下:首先将时间戳从秒转换为弧度。2 * np.pi 是因为一个完整的圆/周期有2pi的弧度。转换后除以的周期持续时间(以秒为单位)(日、周或年)。然后就可以将每个时间戳映射到一个唯一的角度,该角度通过乘以弧度数来表示它在周期中的位置。

如果周期是day,那么一天开始的时间戳将被映射到0弧度,一天中间的时间戳将被映射到np.pi,一天结束时的时间戳将被映射为2 * np.pi 。

最后对计算结果进行sin和cos,得到单位圆上实际的x和y坐标值。这些值总是在-1到1之间。

通过这种方法,每个原始时间序列特征(例如一天中的小时,一周中的一天,一年中的月份)现在只映射到2个新特征(原始特征的sin和cos),而不是24,7,12等。

缺点和注意事项

使用这种方法时一定要小心。虽然它非常方便和高效,但也有一些缺点和注意事项:

1、One-hot编码可以更好地用于基于特定时间、月份等具有更一致的不同值的数据集-例如,数据集在中午12点或某个月份达到峰值。而在时间范围更大的数据集(12PM-2PM)中,循环编码等方法一般会更准确。

2、这种类型的编码适用于深度学习/神经网络,但可能不适用于随机森林这样的树分割算法。因为通常表示一个特征的单个时间戳被分割成两个特征,而基于树的算法每次只分割一个特征。这两个特征是对应于一个原始特征的坐标对,而树形模型可能将它们分开处理。

但是这并不是说你永远不能对基于树的算法使用循环编码。我实际上在随机森林模型中使用了这种类型的编码,并取得了很好的效果。还是我们的老生常谈,这将取决于数据集,所以在交叉验证和最终hold out测试集上运行测试是很重要的。

这种编码方式在各种应用中都非常有用,尤其是在预测和分析涉及明确周期或重复模式的数据时。但是在决定使用哪种编码之前,将编码结果进行比较是非常重要的。

本文的数据集:

https://avoid.overfit.cn/post/99a2cd8d7acb46afa36ead49b53b2dd1

作者:Haden P

目录
相关文章
|
机器学习/深度学习
使用LSTM预测结果为一条直线原因总结
使用LSTM预测结果为一条直线原因总结
4123 1
使用LSTM预测结果为一条直线原因总结
|
监控 算法
偏最小二乘(Partial Least Squares,PLS)原理及模型建立
偏最小二乘(Partial Least Squares,PLS)原理及模型建立
偏最小二乘(Partial Least Squares,PLS)原理及模型建立
|
机器学习/深度学习 人工智能 达摩院
[ICML'22] 阿里巴巴达摩院FEDformer,长程时序预测全面超越SOTA
本文介绍阿里巴巴达摩院决策智能实验室时间序列预测方向的最新(ICML 2022 accepted)工作:FEDformer: Frequency Enhanced Decomposed Transformer for Long-term Series Forecasting论文链接:https://arxiv.org/abs/2201.12740代码链接:https://github.com/DA
3300 0
[ICML'22] 阿里巴巴达摩院FEDformer,长程时序预测全面超越SOTA
|
大数据 数据挖掘
大数据中配对删除(Pairwise Deletion)
【10月更文挑战第22天】
511 6
|
机器学习/深度学习 资源调度 自然语言处理
长短时记忆网络(LSTM)完整实战:从理论到PyTorch实战演示
长短时记忆网络(LSTM)完整实战:从理论到PyTorch实战演示
18056 0
|
存储 关系型数据库 MySQL
【阿里规约】阿里开发手册解读——数据库和ORM篇
从命名规范、建表规范、查询规范、索引规范、操作规范等角度出发,详细阐述MySQL数据库使用过程中所需要遵循的各种规范。
【阿里规约】阿里开发手册解读——数据库和ORM篇
|
机器学习/深度学习 数据采集 数据挖掘
【第十届“泰迪杯”数据挖掘挑战赛】B题:电力系统负荷预测分析 ARIMA、AutoARIMA、LSTM、Prophet、多元Prophet 实现
详细介绍了在第十届“泰迪杯”数据挖掘挑战赛B题中对电力系统负荷进行预测分析的方法,包括数据预处理、特征工程、平稳性检验、数据转换以及使用ARIMA、AutoARIMA、LSTM、Prophet和多元Prophet模型进行建模和预测,并提供了完整代码的下载链接。
623 0
|
机器学习/深度学习 人工智能 PyTorch
基于torch.nn.Dropout通过实例说明Dropout丢弃法(附代码)
基于torch.nn.Dropout通过实例说明Dropout丢弃法(附代码)
780 0
|
机器学习/深度学习 算法
LSTM时间序列预测中的一个常见错误以及如何修正
在使用LSTM进行时间序列预测时,常见错误是混淆回归和预测问题。LSTM需将时间序列转化为回归问题,通常使用窗口或多步方法。然而,窗口方法中,模型在预测未来值时依赖已知的未来值,导致误差累积。为解决此问题,应采用迭代预测和替换输入值的方法,或者在多步骤方法中选择合适的样本数量和训练大小以保持时间结构。编码器/解码器模型能更好地处理时间数据。
841 1
|
存储 算法 PyTorch
pytorch 给定概率分布的张量,如何利用这个概率进行重复\不重复采样?
在 PyTorch 中,可以使用 torch.distributions.Categorical 来基于给定的概率分布进行采样。
1357 0