排名网站优化培训微信企业平台开发
2026/6/28 15:04:06 网站建设 项目流程
排名网站优化培训,微信企业平台开发,微信开发者工具概述,网页制作作业成品做过电力负荷预测或者交通预测朋友#xff0c;大概率都处理过时间特征。这里最直接的做法通常是把时间#xff08;比如分钟或小时#xff09;直接扔进模型里。这看起来逻辑自洽#xff0c;但存在这一个大坑#xff0c;就是“午夜悖论”。 比如说你的模型面对两个时间点大概率都处理过时间特征。这里最直接的做法通常是把时间比如分钟或小时直接扔进模型里。这看起来逻辑自洽但存在这一个大坑就是“午夜悖论”。比如说你的模型面对两个时间点23:59一天的第1439分钟 和 00:01一天的第1分钟。在我们的认知里这俩只差两分钟但在模型的逻辑里1439 和 1 可是不一样的。大多数机器学习算法线性回归、KNN、SVM 甚至神经网络在处理数值时默认遵循线性逻辑数值越大代表的量级越高。它们理解不了“时间是循环的”这个概念。对它们来说午夜不是终点回到起点的闭环而是一个断崖。这就是为什么你加了时间特征模型却在日期变更线附近表现拉胯的根本原因。传统编码方式的局限性处理时间特征最常见的路数无非两种但这两种都有硬伤。整数编码Integer Encoding把 0 到 23 点编码成数字 0-23。这就人为制造了一个断层23 到 0 的跳跃被模型视作全天最大的波动。但实际上晚上 11 点到午夜的变化跟晚上 9 点到 10 点有什么本质区别吗完全没有。下面是这种线性模式下时间特征在数据层面的表现。# Generate data date_today pd.to_datetime(today).normalize() datetime_24_hours pd.date_range(startdate_today, periods24, freqh) df pd.DataFrame({dt: datetime_24_hours}) df[hour] df[dt].dt.hour # Calculate Sin and Cosine df[hour_sin] np.sin(2 * np.pi * df[hour] / 24) df[hour_cos] np.cos(2 * np.pi * df[hour] / 24) # Plot the Hours in Linear mode plt.figure(figsize(15, 5)) plt.plot(df[hour], [1]*24, linewidth3) plt.title(Hours in Linear Mode) plt.xlabel(Hour) plt.xticks(np.arange(0, 24, 1)) plt.ylabel(Value) plt.show()线性模式下的小时表示。独热编码One-hot Encoding既然连续数字有问题那拆成 24 个独立的列呢断层是没了但丢失了更重要的东西:邻近性Proximity。在独热编码下凌晨 2 点和 3 点的距离跟它和晚上 10 点的距离是一样的。模型失去了“时间相邻”这个上下文信息,更别提这会让特征维度爆炸树模型处理起来效率低线性模型跑起来也费劲。解决方案三角函数映射Trigonometric Mapping解决这个问题的核心在于思维视角的转换不要把时间看作一条直线而要看作一个圆。24小时是一个闭环,我们的编码方式也得闭环。把每一个小时想象成圆周上均匀分布的点,要确定圆上一个点的位置单靠一个数值是不够的我们需要两个坐标xand y这就是正弦Sine和余弦Cosine发挥作用的地方。几何原理圆周上的任意角度都可以通过正弦和余弦映射到一个唯一的坐标点。这种映射赋予了模型一个平滑、连续的时间表示。plt.figure(figsize(5, 5)) plt.scatter(df[hour_sin], df[hour_cos], linewidth3) plt.title(Hours in Cyclical Mode) plt.xlabel(Hour)经过正弦和余弦转换后的循环模式。计算公式非常简单2 * π * hour / 24先把小时数值转化成弧度角度。在这个体系下午夜和晚上 11 点的角度非常接近通过sin和cos将角度投影到两个坐标轴上。这两个值结合在一起唯一确定了当前的小时23:00 和 00:00 在特征空间里的距离就被拉得很近了这正是我们想要的效果。这套逻辑同样适用于分钟、星期、月份等任何具有周期性的特征。代码实战我们拿 UCI 的Appliances Energy Prediction数据集来跑个对比实验。模型选用随机森林回归器Random Forest Regressor。Candanedo, L. (2017). Appliances Energy Prediction [Dataset]. UCI Machine Learning Repository. https://doi.org/10.24432/C5VC8G. Creative Commons 4.0 License.# Imports 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获取数据# fetch dataset appliances_energy_prediction fetch_ucirepo(id374) # data (as pandas dataframes) X appliances_energy_prediction.data.features y appliances_energy_prediction.data.targets # To Pandas df pd.concat([X, y], axis1) 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)先建立一个基准模型Baseline使用未处理的线性时间特征。# X and y # X df.drop([Appliances, rv1, rv2, date], axis1) X df[[hour, day, T1, RH_1, T_out, Press_mm_hg, RH_out, Windspeed, Visibility, Tdewpoint]] y df[Appliances] # Train Test Split X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # Fit the model lr RandomForestRegressor().fit(X_train, y_train) # Score print(fScore: {lr.score(X_train, y_train)}) # Test RMSE y_pred lr.predict(X_test) rmse root_mean_squared_error(y_test, y_pred) print(fRMSE: {rmse})基准结果如下Score: 0.9395797670166536 RMSE: 63.60964667197874接下来我们对hour和day进行循环编码替换掉原来的线性特征然后重新训练模型。# Add cyclical hours sin and cosine 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 and 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] # Train Test Split X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # Fit the model lr_cycle RandomForestRegressor().fit(X_train, y_train) # Score print(fScore: {lr_cycle.score(X_train, y_train)}) # Test RMSE y_pred lr_cycle.predict(X_test) rmse root_mean_squared_error(y_test, y_pred) print(fRMSE: {rmse})结果显示Score 提升了约 1%RMSE 下降了 1 个点。Score: 0.9416365489096074 RMSE: 62.87008070927842看着提升不大这只是一个简单的 Toy Example也没做任何精细的数据清洗。但这里的提升完全来自于正弦和余弦变换带来的特征表达能力的增强。本质上这让模型“看懂”了现实世界中电力需求的连续性,它并不会因为时钟跳过 0 点就突然归零。为什么 Sin 和 Cos 缺一不可很多人可能会想只用 Sin 这一列行不行还能省点特征维度。答案是不行。这会破坏对称性。在一个 24 小时的圆周上早上 6 点和晚上 6 点的 Sine 值可能是一样的。如果只给模型一个值它就会混淆这两个截然不同的时间段比如早高峰和晚高峰。必须同时使用 Sin 和 Cos就像定位必须要有经度和纬度一样。只有这样圆上的每一个小时才能拥有唯一的“特征指纹”。实际应用中的收益这套方法在不同模型下的收益是不一样的基于距离的模型KNN, SVMs这是最大的受益者。循环编码消除了边界上的伪“长距离”让数据点之间的距离计算回归真实。神经网络Neural Networks平滑的特征空间有助于网络更快的收敛和更稳定的训练表现消除了午夜那种剧烈的数值跳变。树模型Tree-based models虽然像 XGBoost 或 LightGBM 这种强力模型最终也能通过不断分裂学到这种模式但提供循环编码特征相当于给了它们一个极佳的先验知识Inductive Bias在追求极致性能和解释性时非常有用。适用场景使用这套方法的判断标准很简单问自己一个问题**这个特征是循环往复的吗**如果是那就试试。常见的例子包括一天中的小时0-23一周中的星期1-7一年中的月份1-12风向0-360度总结时间在数据科学里不应该只是一个冰冷的数字它本质上是圆周上的坐标。如果你执意把它当直线处理模型在周期边界处跌倒是迟早的事。使用正弦和余弦进行循环编码是一种优雅且低成本的修正手段。它保留了数据的邻近性消除了人工伪影能让模型学得更快、更准。下次如果你的模型预测曲线在日期交界处出现诡异的跳变不妨试试这个方法。https://avoid.overfit.cn/post/5fea3ffcb7ac4b27a3a0d7bb55b9bd39作者Gustavo Santos

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询