前途科技
  • 科技
  • AI
    • AI 前沿技术
    • Agent生态
    • AI应用场景
    • AI 行业应用
  • 初创
  • 报告
  • 学习中心
    • 编程与工具
    • 数据科学与工程
我的兴趣
前途科技前途科技
Font ResizerAa
站内搜索
Have an existing account? Sign In
Follow US
Copyright © 2024 AccessPath.com, 前途国际科技咨询(北京)有限公司,版权所有。 | 京ICP备17045010号-1 | 京公网安备 11010502033860号
未分类

你的模型是否“时间失明”?揭秘周期性特征编码的必要性与实践

NEXTECH
Last updated: 2025年12月25日 上午7:28
By NEXTECH
Share
41 Min Read
SHARE

午夜悖论

设想这样一个场景:正在构建一个用于预测电力需求或出租车订单量的模型。于是,将时间(例如分钟数)从午夜开始作为特征输入模型。这看起来清晰简单,对吗?

Contents
午夜悖论标准编码方法的失效背后的几何原理代码实践为何需要同时使用正弦和余弦实际影响与结果何时应该使用此方法总结参考资料与延伸阅读

现在,模型看到了23:59(一天中的第1439分钟)和00:01(一天中的第1分钟)。对人类而言,这两者仅相隔两分钟。但对于模型来说,它们却相距甚远。这就是“午夜悖论”。是的,模型很可能处于“时间失明”状态。

为何会出现这种情况?

因为大多数机器学习模型将数字视为直线,而非循环的圆。

线性回归、K近邻、支持向量机甚至神经网络都会以线性逻辑处理数字,认为较大的数字“多于”较小的数字。它们无法理解时间是循环往复的。午夜成为了模型无法处理的边界情况。

如果在模型中加入小时信息后效果不佳,并且模型在日期边界附近表现挣扎,这很可能就是原因所在。

You Might Also Like

强化学习深度解析:从基础概念到核心算法的全面指南
掌握机器学习系统设计面试:成功通关的关键策略与实战指南
重思AI Native:人、AI与环境共生下的产品设计之道
打造吸睛机器学习作品集:不可或缺的四大项目类型

标准编码方法的失效

接下来探讨几种常见的处理方法,其中至少有一种可能被使用过。

  • 整数编码法

将小时编码为0到23的数字。这种方法在23点和0点之间制造了一个人为的“悬崖”。因此,模型会认为午夜是一天中变化最大的时刻。然而,午夜与晚上11点的差异,真的比晚上10点与9点的差异更大吗?

当然不是。但模型对此一无所知。

下图展示了小时在“线性”模式下的表示。

# 生成数据
date_today = pd.to_datetime('today').normalize()
datetime_24_hours = pd.date_range(start=date_today, periods=24, freq='h')
df = pd.DataFrame({'dt': datetime_24_hours})
df['hour'] = df['dt'].dt.hour    

# 计算正弦和余弦
df["hour_sin"] = np.sin(2 * np.pi * df["hour"] / 24)
df["hour_cos"] = np.cos(2 * np.pi * df["hour"] / 24)

# 绘制线性模式下的小时
plt.figure(figsize=(15, 5))
plt.plot(df['hour'], [1]*24, linewidth=3)
plt.title('线性模式下的小时表示')
plt.xlabel('小时')
plt.xticks(np.arange(0, 24, 1))
plt.ylabel('值')
plt.show()

线性模式下的小时表示图

线性模式下的小时表示。作者供图。

  • 独热编码法

如果对小时进行独热编码呢?创建24个二进制列。问题解决了吗?某种程度上是的。这种方法修复了人为的间隔,但丢失了邻近性。凌晨2点不再比晚上10点更接近凌晨3点。

同时,维度也急剧膨胀。对于树模型而言,这令人烦恼。对于线性模型,则可能效率低下。

因此,需要寻找一种可行的替代方案。

  • 解决方案:三角映射

关键在于思维模式的转变:

停止将时间视为一条直线,而应将其视为一个圆。

24小时制的一天是循环往复的。因此,编码方式也应循环起来,以圆形思维处理。每个小时都是圆环上均匀分布的一个点。要表示圆上的一个点,不能仅用一个数字,而需要使用两个坐标:x 和 y。

这正是正弦和余弦函数的用武之地。

背后的几何原理

圆上的每个角度都可以通过正弦和余弦映射到一个唯一的点。这为模型提供了平滑、连续的时间表示。

plt.figure(figsize=(5, 5))
plt.scatter(df['hour_sin'], df['hour_cos'], linewidth=3)
plt.title('循环模式下的小时表示')
plt.xlabel('小时')

正弦余弦变换后的小时循环模式图

经过正弦和余弦变换后的小时循环模式。作者供图。

以下是计算一天中小时周期的数学公式:

周期性编码数学公式

  • 首先,2 * π * hour / 24 将每个小时转换为一个角度。午夜和晚上11点最终在圆上几乎处于相同位置。
  • 然后,正弦和余弦将该角度投影到两个坐标上。
  • 这两个值共同唯一地定义了该小时。现在,23:00和00:00在特征空间中变得接近。这正是期望达到的效果。

同样的思路适用于分钟、星期几或一年中的月份。

代码实践

以家用电器能耗预测数据集 [4] 为例进行实验。尝试使用随机森林回归模型(一种树模型)来改进预测效果。

Candanedo, L. (2017). Appliances Energy Prediction [Dataset]. UCI Machine Learning Repository. https://doi.org/10.24432/C5VC8G. Creative Commons 4.0 License.

# 导入库
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import root_mean_squared_error
from ucimlrepo import fetch_ucirepo

获取数据。

# 获取数据集 
appliances_energy_prediction = fetch_ucirepo(id=374) 

# 数据(作为pandas数据框) 
X = appliances_energy_prediction.data.features 
y = appliances_energy_prediction.data.targets 

# 转换为Pandas
df = pd.concat([X, y], axis=1)
df['date'] = df['date'].apply(lambda x: x[:10] + ' ' + x[11:])
df['date'] = pd.to_datetime(df['date'])
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['hour'] = df['date'].dt.hour
df.head(3)

首先使用线性时间创建一个快速模型,作为比较的基线。

# 定义X和y
# X = df.drop(['Appliances', 'rv1', 'rv2', 'date'], axis=1)
X = df[['hour', 'day', 'T1', 'RH_1', 'T_out', 'Press_mm_hg', 'RH_out', 'Windspeed', 'Visibility', 'Tdewpoint']]
y = df['Appliances']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 拟合模型
lr = RandomForestRegressor().fit(X_train, y_train)

# 评分
print(f'评分: {lr.score(X_train, y_train)}')

# 测试集RMSE
y_pred = lr.predict(X_test)
rmse = root_mean_squared_error(y_test, y_pred)
print(f'RMSE: {rmse}')

结果如下。

评分: 0.9395797670166536
RMSE: 63.60964667197874

接下来,对周期性时间成分(day和hour)进行编码,并重新训练模型。

# 添加周期性小时的正弦和余弦
df['hour_sin'] = np.sin(2 * np.pi * df['hour'] / 24)
df['hour_cos'] = np.cos(2 * np.pi * df['hour'] / 24)
df['day_sin'] = np.sin(2 * np.pi * df['day'] / 31)
df['day_cos'] = np.cos(2 * np.pi * df['day'] / 31)

# 定义X和y
X = df[['hour_sin', 'hour_cos', 'day_sin', 'day_cos','T1', 'RH_1', 'T_out', 'Press_mm_hg', 'RH_out', 'Windspeed', 'Visibility', 'Tdewpoint']]
y = df['Appliances']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 拟合模型
lr_cycle = RandomForestRegressor().fit(X_train, y_train)

# 评分
print(f'评分: {lr_cycle.score(X_train, y_train)}')

# 测试集RMSE
y_pred = lr_cycle.predict(X_test)
rmse = root_mean_squared_error(y_test, y_pred)
print(f'RMSE: {rmse}')

结果如下。可以看到评分提高了1%,RMSE降低了约1个点。

评分: 0.9416365489096074
RMSE: 62.87008070927842

这个提升看似微小,但需要记住,这个示例仅使用了一个未经任何数据清洗或调优的简单模型。所观察到的效果主要源于正弦和余弦变换。

实际情况是,现实世界中的电力需求并不会在午夜重置。现在,模型终于能够捕捉到这种连续性了。

为何需要同时使用正弦和余弦

切勿陷入仅使用正弦的诱惑,因为感觉一个特征似乎就够了。用一个列代替两个列,更简洁,对吗?

遗憾的是,这会破坏对称性。在24小时制中,早上6点和下午6点可能产生相同的正弦值。不同时间具有相同编码是糟糕的,因为模型现在会混淆早高峰和晚高峰。因此,除非乐于见到混乱的预测结果,否则这并非理想选择。

同时使用正弦和余弦可以解决这个问题。两者共同为每个小时在圆上提供了一个唯一的“指纹”。可以将其想象为纬度和经度,两者缺一不可。

实际影响与结果

那么,这种方法真的对模型有帮助吗?是的,尤其对某些特定模型。

基于距离的模型

K近邻和支持向量机严重依赖距离计算。周期性编码可以防止在边界处产生虚假的“长距离”。相邻的点在特征空间中真正成为邻居。

神经网络

神经网络在平滑的特征空间中学习得更快。周期性编码消除了午夜处的尖锐不连续性。这通常意味着更快的收敛速度和更好的稳定性。

树模型

像XGBoost或LightGBM这样的梯度提升树最终可以学习到这些模式。周期性编码为它们提供了一个良好的起点。如果关注性能和可解释性,这是值得的。

何时应该使用此方法

始终要问自己一个问题:这个特征是否以周期循环的方式重复? 如果是,则考虑使用周期性编码。

常见的例子包括:

  • 一天中的小时
  • 一周中的星期几
  • 一年中的月份
  • 风向(角度)
  • 任何具有循环特性的变量,都可以尝试将其编码为循环。

总结

时间不仅仅是一个数字。它是圆环上的一个坐标。

如果将其视为一条直线,模型可能会在边界处出错,并且难以理解该变量作为一个循环、重复且有规律的模式。

使用正弦和余弦进行周期性编码可以优雅地解决这个问题,它保留了邻近性,减少了人为干扰,并帮助模型更快地学习。

因此,当下次发现模型在日期变更点附近的预测表现奇怪时,可以尝试应用这个新学到的工具,让模型发挥出应有的水平。

GitHub仓库

以下是本次练习的完整代码。

https://github.com/gurezende/Time-Series/tree/main/Sine%20Cosine%20Time%20Encode

参考资料与延伸阅读

[1. 编码小时 Stack Exchange]:https://stats.stackexchange.com/questions/451295/encoding-cyclical-feature-minutes-and-hours

[2. NumPy三角函数]:https://numpy.org/doc/stable/reference/routines.math.html

[3. 关于周期性特征的实用讨论]:

https://www.kaggle.com/code/avanwyk/encoding-cyclical-features-for-deep-learning

TAGGED:Python时间序列机器学习模型优化特征工程
Share This Article
Email Copy Link Print
Previous Article 安克笔记本充电宝优惠信息图 安克大容量笔记本充电宝重回黑五史低价,仅售87.99美元
Next Article 索尼PS5 Pro主机特写 索尼PS5 Pro限时直降100美元!圣诞前入手性能怪兽的最佳时机
Leave a Comment

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

最新内容
图6:👉
提升4倍效率:AI编程助手的四大实战技巧
编程与工具
索尼PS5 Pro主机特写
索尼PS5 Pro限时直降100美元!圣诞前入手性能怪兽的最佳时机
科技
安克笔记本充电宝优惠信息图
安克大容量笔记本充电宝重回黑五史低价,仅售87.99美元
科技
图1:两个包含‘mouse’的不同句子示例
Transformer自注意力机制详解:如何在Excel中理解文本的上下文建模
大模型与工程化

相关内容

图1:线性关系的示例数据
未分类

深入浅出:皮尔逊相关系数的原理、应用与Python实现

2025年11月2日
图1:AI知识探索日历
未分类

机器学习模型揭秘:用Excel亲手实现,告别“黑箱”时代

2025年12月1日
未分类

营销人员为何转向准地理提升实验?深度解析与规划指南

2025年9月24日
蓝天白云湖泊景观
编程与工具

Python随机模块完全指南:从基础到实战应用

2025年11月25日
Show More
前途科技

前途科技是一个致力于提供全球最新科技资讯的专业网站。我们以实时更新的方式,为用户呈现来自世界各地的科技新闻和深度分析,涵盖从技术创新到企业发展等多方面内容。专注于为用户提供高质量的科技创业新闻和行业动态。

分类

  • AI
  • 初创
  • 学习中心

快速链接

  • 阅读历史
  • 我的关注
  • 我的收藏

Copyright © 2025 AccessPath.com, 前途国际科技咨询(北京)有限公司,版权所有。 | 京ICP备17045010号-1 | 京公网安备 11010502033860号

前途科技
Username or Email Address
Password

Lost your password?

Not a member? Sign Up