ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于随机森林回归的家庭用电预测:从特征工程到滚动预测的完整实战

基于随机森林回归的家庭用电预测:从特征工程到滚动预测的完整实战 简介这份资源面向具备一定Python与机器学习基础的学习者围绕家庭用电预测这一典型回归任务提供从数据准备到模型评估的完整代码实现。包内共4个文件均为py脚本按编号分步组织压缩包约9KB轻量便于快速运行与二次修改。内容覆盖线性回归、多项式回归、决策树回归、随机森林回归与支持向量回归等主流算法并涉及缺失值处理、异常值检测、标准化归一化、特征工程、时间序列特征构造、交叉验证与参数调优等关键环节评估指标包括MSE、RMSE和R²。已有259人学习下载适合希望系统掌握回归建模流程、理解多模型对比思路的读者参考也可作为课程设计或项目练手的实践素材。1. 家庭用电预测这件事回归算法到底能帮你解决什么夏天晚上七点半你打开手机看到这个月电费又超了三百块但你完全说不清钱花在哪——空调热水器还是那台常年不关的旧冰箱家庭用电预测要回答的就是这个问题给定历史用电数据、时间信息、气象条件预测未来某个时刻或某一天的用电量。这不是分类问题不是让你判断用电高还是低而是回归问题——输出一个连续的千瓦时数值。基于机器学习回归算法实现家庭用电预测核心工作流就四步拿到带时间戳的用电序列构造特征滞后值、滑动窗口统计、时段编码、温度等选回归模型训练最后评估预测误差是否落在可接受范围内。适合谁做想做机器学习入门项目但不想碰手写数字识别这种玩具数据的人做智能家居或能耗管理需要预测模块的开发者以及被机器学习入门四个字劝退过但想找一个完整闭环练手的人。随机森林回归算法在这个场景里是常见起点原因后面会讲清楚。2. 数据拿到手先别急着喂模型家庭用电预测的特征工程怎么做2.1 用电数据的三种典型格式与读取方式家庭用电预测的数据来源通常有三种形态智能电表导出的 CSV每行一个时间戳有功功率、公开数据集如 UCI 的 Individual Household Electric Power Consumption、以及自己用传感器采集的 JSON 日志。不管哪种第一步都是统一成 pandas DataFrame索引设为时间戳值列为用电量。import pandas as pd import numpy as np # 读取智能电表导出的 CSV假设列名为 timestamp 和 power_kwh df pd.read_csv(household_power.csv, parse_dates[timestamp]) df df.set_index(timestamp).sort_index() # 统一重采样到小时级避免原始数据秒级抖动 df_hourly df[power_kwh].resample(1h).mean().to_frame() # 检查缺失情况 print(df_hourly.isna().sum()) print(df_hourly.describe())这段代码做了三件事解析时间戳、按小时重采样、输出缺失统计。参数上resample(1h)里的1h可以改成15min或1D取决于你的预测粒度——预测明天全天用1D预测未来几小时用1h。mean()也可以换成sum()但要注意功率kW取均值电量kWh取求和搞混了预测值会差一个量级。缺失值先别急着填打印出来看看是设备离线还是数据本身就没有前者需要插值后者可能要考虑剔除。2.2 滞后特征和滑动窗口让模型看到过去回归模型本身不知道时间顺序你得手动把过去变成特征列。家庭用电有强周期性——早上和晚上两个高峰、周末和工作日不同、夏天和冬天不同。滞后特征就是把前 N 个小时的用电量平移成当前行的输入。# 构造滞后特征前1小时、前2小时、前24小时、前168小时一周 for lag in [1, 2, 3, 24, 168]: df_hourly[flag_{lag}] df_hourly[power_kwh].shift(lag) # 滑动窗口统计过去6小时均值和标准差 df_hourly[rolling_mean_6] df_hourly[power_kwh].shift(1).rolling(6).mean() df_hourly[rolling_std_6] df_hourly[power_kwh].shift(1).rolling(6).std() # 时间编码小时、星期几、是否周末 df_hourly[hour] df_hourly.index.hour df_hourly[dayofweek] df_hourly.index.dayofweek df_hourly[is_weekend] (df_hourly[dayofweek] 5).astype(int) # 丢弃因 shift 产生的 NaN 行 df_hourly df_hourly.dropna()关键点shift(1)在 rolling 之前执行是为了防止用当前时刻的值预测当前时刻——这是时间序列里最常见的翻车点叫数据泄漏。滞后阶数怎么选先看自相关图ACF如果 24 小时处有明显峰值就加lag_24如果一周周期明显加lag_168。但别贪多每加一个滞后列就多一个维度随机森林虽然对维度不敏感但太多噪声特征会拉低精度。我一般先用lag_1、lag_24、lag_168三个打底再根据残差图补。2.3 外部变量温度、节假日、家庭成员作息纯靠历史用电量模型能学到周期模式但遇到今天突然降温 10 度就抓瞎。温度是最有效的外部变量没有气象站数据的话用公开的日平均温度按城市匹配即可。节假日用布尔列标记家庭成员的作息变化比如暑假孩子在家可以用月份或学期标志近似。# 假设有温度数据按天对齐后前向填充到小时 temp_daily pd.read_csv(temperature.csv, parse_dates[date]) temp_daily temp_daily.set_index(date)[temp_c] df_hourly[temp] temp_daily.reindex(df_hourly.index.date).values df_hourly[temp] df_hourly[temp].ffill() # 节假日标记简化版周末法定假日列表 holidays [2024-01-01, 2024-02-10, 2024-05-01] df_hourly[is_holiday] df_hourly.index.strftime(%Y-%m-%d).isin(holidays).astype(int)温度做前向填充是因为日温度变化平缓小时级插值意义不大。注意reindex那一步用df_hourly.index.date取日期部分再映射回小时索引这是 pandas 里对齐不同频率数据的常用手法。如果温度缺失超过 20%建议直接放弃这个特征用hour和月份做交互项替代。3. 选随机森林回归还是梯度提升模型训练与调参的实操路径3.1 为什么家庭用电预测首选树模型而不是线性回归线性回归假设特征和用电量之间是线性关系但家庭用电和温度的关系是 U 型的——太冷开暖气、太热开空调中间段反而用电少。树模型天然能拟合这种非线性而且对特征缩放不敏感不用做标准化。随机森林回归算法通过 bagging 降低方差比单棵决策树稳定梯度提升如 XGBoost、LightGBM通过 boosting 降低偏差精度通常更高但调参更敏感。入门阶段我建议先用随机森林跑通全流程因为它的n_estimators和max_depth两个参数就够用不容易因为学习率设错而翻车。3.2 训练集/验证集划分时间序列不能随机打乱这是血泪经验用train_test_split随机划分时间序列数据模型会偷看未来。正确做法是按时间切分——前 80% 做训练后 20% 做验证。from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error feature_cols [c for c in df_hourly.columns if c ! power_kwh] X df_hourly[feature_cols] y df_hourly[power_kwh] # 按时间顺序切分前80%训练后20%验证 split_idx int(len(df_hourly) * 0.8) X_train, X_val X.iloc[:split_idx], X.iloc[split_idx:] y_train, y_val y.iloc[:split_idx], y.iloc[split_idx:] model RandomForestRegressor( n_estimators200, max_depth12, min_samples_leaf5, random_state42, n_jobs-1 ) model.fit(X_train, y_train) y_pred model.predict(X_val) mae mean_absolute_error(y_val, y_pred) rmse np.sqrt(mean_squared_error(y_val, y_pred)) print(fMAE: {mae:.3f} kWh, RMSE: {rmse:.3f} kWh)参数说明n_estimators200是树的数量太少欠拟合太多训练慢且收益递减200 到 500 之间通常够用。max_depth12控制每棵树深度家庭用电数据特征维度不高12 层能覆盖大部分交互模式再深容易过拟合。min_samples_leaf5保证叶子节点至少有 5 个样本防止模型记住噪声。n_jobs-1用满所有 CPU 核心加速训练。评估指标上MAE 比 RMSE 更直观——MAE 是平均绝对误差单位是 kWh直接告诉你预测平均偏了多少。3.3 特征重要性排序与调参方向训练完先别急着调参看特征重要性。随机森林的feature_importances_能告诉你哪些特征在起作用。import matplotlib.pyplot as plt importances pd.Series(model.feature_importances_, indexfeature_cols) importances.sort_values(ascendingFalse).head(10).plot(kindbarh) plt.xlabel(Importance) plt.tight_layout() plt.show()如果lag_1和lag_24排最前说明短期惯性和日周期是主要驱动力符合预期。如果某个温度特征重要性接近零检查是不是对齐错了或者填充方式有问题。调参顺序先调max_depth从 8 到 20 试再调min_samples_leaf从 1 到 20 试最后加n_estimators。用GridSearchCV配合TimeSeriesSplit做交叉验证别用默认的 KFold。4. 避坑与排查家庭用电预测里最容易翻车的五个地方4.1 预测值出现负数现象模型预测出 -0.5 kWh 这种物理上不可能的值。原因随机森林回归是各棵树预测值的平均单棵树可能在某些叶子节点上给出负值平均后仍为负。解决训练前对目标值做log1p变换预测后再expm1还原或者训练后直接y_pred np.clip(y_pred, 0, None)。前者更优雅后者更快。4.2 验证集误差远大于训练集现象训练集 MAE 0.1验证集 MAE 1.5。原因过拟合模型记住了训练集的噪声。解决降低max_depth提高min_samples_leaf减少滞后特征数量。如果还不行检查是不是把未来信息泄漏进了特征——比如用了全局均值做填充。4.3 周末和工作日预测一样准但节假日全错现象模型在周末表现正常一到春节、国庆就偏得离谱。原因训练数据里节假日样本太少模型没见过这种模式。解决要么在特征里加is_holiday并确保训练集包含至少两个完整年度的数据要么对节假日单独建模。数据不足时接受节假日误差偏大别硬调。4.4 温度特征重要性为零现象加了温度列但feature_importances_显示它几乎没用。原因温度数据对齐错了——比如把日温度直接赋给小时索引时没有广播导致所有小时拿到同一个值模型无法区分。解决打印df_hourly[[temp, power_kwh]].head(48)肉眼检查温度应该在一天内有小幅波动而不是一条直线。4.5 用未来数据做了标准化现象线下验证很好上线后预测一塌糊涂。原因标准化时用了全量数据的均值和方差相当于把未来信息泄漏给了训练。解决标准化参数只能从训练集计算然后应用到验证集和测试集。树模型不需要标准化但如果你用了神经网络或 SVR这条必须遵守。5. 把预测误差再压一压残差分析与滚动预测的进阶技巧模型跑通之后想再提升精度别急着换更复杂的模型先做残差分析。把验证集的残差真实值减预测值按小时画出来你会看到某些时段系统性偏高或偏低。比如晚上六到九点残差普遍为正说明模型低估了晚高峰——这时候加一个is_evening_peak的布尔特征或者对晚高峰时段单独训练一个模型往往比调参有效。另一个实用技巧是滚动预测。上面的做法是一次性预测未来 20% 的所有点但实际部署时你只能拿到当前时刻之前的数据。滚动预测模拟真实场景每次预测下一个小时然后把真实值加入历史再预测下下个小时。# 滚动预测每次预测1步用真实值更新滞后特征 history df_hourly.iloc[:split_idx].copy() predictions [] for i in range(split_idx, len(df_hourly)): # 用当前 history 构造最新一行的特征 row df_hourly.iloc[[i]].copy() for lag in [1, 2, 3, 24, 168]: row[flag_{lag}] history[power_kwh].iloc[-lag] row[rolling_mean_6] history[power_kwh].iloc[-6:].mean() row[rolling_std_6] history[power_kwh].iloc[-6:].std() pred model.predict(row[feature_cols])[0] predictions.append(pred) # 把真实值追加进 history实际部署时这里用真实观测值 history pd.concat([history, df_hourly.iloc[[i]]]) rolling_mae mean_absolute_error(df_hourly[power_kwh].iloc[split_idx:], predictions) print(fRolling MAE: {rolling_mae:.3f} kWh)滚动预测的 MAE 通常比一次性预测高一些因为它更接近真实部署条件。如果滚动 MAE 和一次性 MAE 差距超过 30%说明模型对滞后特征依赖过重一旦历史值有偏差就会累积。这时候考虑加入更多外部变量或者改用 LightGBM 这类对特征交互捕捉更强的模型。最后说一个我自己的习惯每次调完参把验证集最后一周的预测曲线和真实曲线叠在一起画出来肉眼过一遍。指标好看不代表曲线合理——如果模型在每天凌晨都预测出一个尖峰而真实数据是平的那指标再好也不能上线。这个项目适合作为机器学习回归算法的完整练手从特征工程到模型评估到滚动预测每一步都有可复现的代码和可解释的参数。希望帮到你。本文还有配套的精品资源点击获取
返回列表