回归算法实现家庭用电预测:特征工程与避坑指南

发布时间:2026/10/10 16:49:45
回归算法实现家庭用电预测:特征工程与避坑指南 简介这是一份机器学习回归算法实战资源面向数据科学初学者与需要完成课程项目的学生旨在解决家庭用电量预测问题。资源系统覆盖线性回归、多项式回归、决策树回归、随机森林回归与支持向量回归等主流算法并涉及缺失值处理、异常值检测、标准化、特征工程及时间序列分析同时展示MSE、RMSE、R²等评估指标的使用。压缩包共4个Python脚本0205家庭用电预测.py按算法难度递进编排适合对照调试、对比不同模型效果整体大小仅9KB轻量无依赖负担。已有262人下载学习适合用于入门实践、作业参考或算法原理验证可帮助读者快速跑通回归建模全流程并理解各模型在实际数据中的适用场景与调参思路。1. 家庭用电预测一个被低估的回归问题切入点月初看到电费单才后悔上月空调没节制这是绝大多数家庭的常态。但如果你手里有一套智能电表或者能读到家庭总闸的功率数据完全可以把「后悔」变成「预判」用机器学习回归算法基于过去一段时间的用电曲线、时间戳和天气特征预测未来一小时甚至未来一天的家庭用电量。这背后就是典型的回归任务——输入是时间、历史负荷、温度等特征输出是一个连续数值未来某个时刻的用电功率。这个 zip 包标题里的「回归算法实现家庭用电预测」拆开看就是三件事把家庭用电数据整理成监督学习样本、构建能拟合用电曲线的回归模型、以及把预测结果落到能用的场景里。适合谁去做手里有计量数据、想给自家或某栋楼做用电分析的开发者以及刚入门机器学习、想找一个不涉及图像和文本的干净回归案例来练手的人。这类问题的好处是数据容易理解、特征可以自己构造、评估指标直观翻车点却不少下面按我实际做过的路线来讲。2. 为什么家庭用电预测适合用回归算法问题定义与特征构造2.1 先定性这是回归任务不是分类任务家庭用电预测的目标是给出未来时刻的功率数值比如「15 分钟后这栋房子大概用 1.8 kW」。这会让人犹豫能不能把用电量分成「高/中/低」三档做成分类能做但代价很大——分类会丢掉用电强度的连续信息当你需要判断「要不要开热水器、会不会超容量」时分类结果没法给出精确参考。回归输出的是一个连续值能直接和电表读数、电网容量、电费单价做算术运算这是它在用电场景里的根本优势。另外一类选择是时序模型LSTM、GRU它们确实能捕捉长距离依赖但对数据量和训练调参的要求高得多家庭用电数据往往只有几个月到一两年的粒度样本量不大树模型和线性模型在这种规模下更容易稳定出效果。我见过某开发者用一万多条小时级记录去训 LSTM结果比随机森林还差问题就出在样本太少、特征时序没构造好而不是模型不够先进。回归算法在这个规模下是性价比最高的起点。2.2 特征设计用电预测的胜负手在特征不在模型用电曲线的规律性很强晚上高、白天低、工作日和周末不一样、夏天开空调和冬天开暖气也不一样。这些规律没法直接喂给模型必须转成特征。我一般把特征拆成三组。第一组是时间特征。小时数0~23、星期几0~6、是否周末、是否节假日这几列能帮模型区分不同时段的用电模式。时间特征要用数值编码小时可以同时用周期编码sin/cos因为 23 点和 0 点其实相邻直接喂「23」和「0」两个数字线性模型会以为它们差得很远。第二组是滞后特征过去 1 小时、24 小时、168 小时即一周前同一时刻的用电量。家庭用电有很强的日周期和周周期滞后特征是预测准确率的最大贡献者。第三组是滚动统计特征过去 6 小时均值、过去 24 小时最大值、用电量标准差这些能刻画最近的用电趋势和波动水平。外部环境特征也不能忽略温度和湿度对空调/暖气负荷影响很大。常见做法是把气象站发布的逐小时温度、湿度按时间戳 join 进来同时把体感温度或「当日最高温」这类衍生变量一起放进去。如果拿不到气象数据就退而求其次用「日期序号」从数据集起点算起的天数让模型自己学季节性趋势——效果会差一点但至少能捕捉大方向。2.3 评估指标看 MAE、RMSE更要把误差换算成「度电」回归模型的评估不能用准确率常用的是 MAE、RMSE、MAPE。MAE 是平均绝对误差单位是 kW直接解释为「平均每次预测偏了多少千瓦」RMSE 对大误差惩罚更重适合你特别在意峰值预测不准的场景MAPE 把误差归一化成百分比方便和不同用电量级别的家庭对比。我自己会额外算一个「误差电量」如果预测值比实际值平均高 0.2 kW持续一小时就是 0.2 度电乘以电费单价就能估算预测误差带来的经济损失。这对说服别人接受你的模型很有用——用「误差造成的电费偏差」比单纯报 RMSE 更直观。需要留意的是MAPE 在用电量接近 0 的深夜时段会爆炸因为分母太小所以评估时要么把深夜样本单独看要么在 MAPE 计算公式里给分母加一个平滑项。3. 把用电数据转成回归样本从原始表到可训练数据集3.1 数据清洗与重采样先用对粒度再谈模型家庭用电原始数据通常是一条条功率记录来自智能插座或电表间隔可能是秒级也可能不均匀。训练回归模型前要先把数据重采样成统一粒度我一般用小时粒度——预测未来 1~24 小时的需求小时级足够分钟级反而会让训练集膨胀、收益却很小。重采样时注意用电量在 15 分钟内的均值比瞬时值稳定得多所以优先用均值聚合而不是直接取某一条记录。import pandas as pd df pd.read_csv(household_power.csv, parse_dates[timestamp]) df.set_index(timestamp, inplaceTrue) # 统一成小时粒度用电功率取均值缺失值用前向填充 hourly df[power].resample(1h).mean() hourly hourly.fillna(methodffill) # 只保留连续且完整的时间范围去掉头部和尾部不完整的片段 hourly hourly.loc[2022-01-01:2023-12-31] print(hourly.describe())这段代码的用途是把任意间隔的原始记录转成时间索引对齐的小时序列。前向填充能处理短时间缺失但如果某段连续缺失超过数小时前向填充会让模型学到「用电量一直不变」的假规律所以我在代码里限制了时间范围把不完整的首尾切掉。resample 的规则里1h是按小时对齐如果你的数据来自不同时区先统一转成当地时间再重采样避免早晨和晚上的用电高峰被整体平移一个小时。3.2 构造监督学习样本滞后特征必须放在同一条样本里模型需要的是「特征矩阵 X 目标值 y」的监督学习格式这一步核心是shift()操作。预测未来 1 小时的样本长这样X 是当前时刻的时间特征、过去 N 小时的用电量、天气数据y 是未来 1 小时的用电量。构造时最容易犯的错是把滞后特征算到未来去了——比如用 t1 时刻的用电量去预测 t1这在训练时看起来准确率极高上线后立刻崩掉。import numpy as np def make_features(hourly: pd.Series, temp: pd.Series None, lags[1, 2, 24, 168]): data pd.DataFrame({power: hourly}) data[hour] hourly.index.hour data[dayofweek] hourly.index.dayofweek data[is_weekend] (data[dayofweek] 5).astype(int) # 周期编码小时保留“23点和0点相邻”这个信息 data[hour_sin] np.sin(2 * np.pi * data[hour] / 24) data[hour_cos] np.cos(2 * np.pi * data[hour] / 24) for lag in lags: data[flag_{lag}h] hourly.shift(lag) # 滚动统计特征过去6小时的均值和过去24小时的最大值 data[roll_mean_6h] hourly.rolling(6).mean() data[roll_max_24h] hourly.rolling(24).max() if temp is not None: data[temp] temp return data data make_features(hourly) data[target] data[power].shift(-1) # 预测未来1小时 data data.dropna()代码里每一列的含义都在名字里。滞后特征lag_1h是上一小时用电量lag_24h是昨天同一时刻的用电量lag_168h是上周同一时刻的用电量分别对应短时惯性、日周期和周周期。滚动窗口特征用rolling().mean()和rolling().max()做出来它们对捕捉「空调刚开机还在爬坡」这类状态很有帮助。target用shift(-1)表示把未来一小时的用电量拉到当前行——这一步是监督学习样本构造的核心滞后特征和 target 的 shift 方向一定不能搞反。dropna 去掉构造滞后特征时产生的前几行空值。3.3 时序切分随机打乱是回归预测里最隐蔽的死法分类任务里随机划分训练集和验证集是常规操作但时间序列不行。用电数据有强自相关性上周四的用电模式和这周四接近如果随机打乱模型会直接记住「这个时间段的用电量大概是多少」验证集里全是它见过的邻近样本看起来效果极好部署后立刻现原形。正确做法是按时间顺序切分前 80% 的时间段做训练后 20% 做验证。train_size int(len(data) * 0.8) train, val data.iloc[:train_size], data.iloc[train_size:] feature_cols [c for c in data.columns if c ! target] X_train, y_train train[feature_cols], train[target] X_val, y_val val[feature_cols], val[target]3.4 三个基线模型先线性后树模型一步一个脚印先把线性回归跑通拿到一个基线分数再上随机森林和梯度提升树。线性回归的好处是能快速验证特征构造有没有硬伤如果线性回归的 RMSE 大得离谱多半是特征里混进了非数值类型或者有大量缺失值没处理如果线性回归表现还行但树模型提升不明显说明特征和目标之间主要是线性关系不必盲目堆模型复杂度。这种先基线后增强的顺序能帮你定位问题是出在特征还是出在模型。from sklearn.ensemble import RandomForestRegressor from sklearn.linear_model import LinearRegression from sklearn.ensemble import GradientBoostingRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error models { linear: LinearRegression(), random_forest: RandomForestRegressor(n_estimators200, max_depth12, random_state42, n_jobs-1), gbr: GradientBoostingRegressor(n_estimators300, max_depth6, learning_rate0.05, random_state42) } for name, model in models.items(): model.fit(X_train, y_train) pred model.predict(X_val) mae mean_absolute_error(y_val, pred) rmse mean_squared_error(y_val, pred, squaredFalse) print(f{name}: MAE{mae:.3f} kW, RMSE{rmse:.3f} kW)参数不是拍脑袋定的随机森林的max_depth12是让树有足够深度去拟合复杂的交互关系但又不至于深到过拟合n_estimators200在这个样本量下已经是稳健区间再加大收益很小、耗时翻倍。梯度提升树的学习率设成0.05配合 300 棵树这个组合在小时级用电数据上通常是省心的默认值。跑完以后对比三个数字线性回归如果 MAE 在 0.3 kW 左右说明特征已经抓住了主要规律随机森林和 GBR 如果能压到 0.2 kW 以下就算入门了。4. 必调参数与多步预测策略从预测 1 小时到预测 24 小时4.1 滞后窗口的选择预测步长不同特征配置完全不同上面 3.2 的例子默认预测未来 1 小时滞后特征是[1, 2, 24, 168]。如果要预测未来 24 小时即明天的用电曲线特征配置就要变当天 0 点去预测 24 小时后时lag_1h是昨天 23 点的用电量它和明天 0 点的用电量相关性已经弱了很多此时lag_24h昨天 0 点和lag_168h上周 0 点反而更有参考价值。经验法则是预测步长越长短时滞后特征1~2 小时的权重越低周期滞后特征24 小时、168 小时的权重越高。我一般会把滞后特征设成几组并排对比[1, 2, 3]、[24, 48]、[168, 336]分别覆盖超短期惯性、日周期、周周期。如果预测目标改成未来 24 小时的平均用电量还可以把滚动窗口调大到rolling(24).mean()把「过去一天的总用电量」这个强特征直接暴露给模型。用树模型的特征重要性去看如果lag_24h始终排第一说明日周期性是你这户用电数据里最强的规律。参数调整节奏建议这样走固定预测目标为未来 1 小时 → 只调滞后特征 → 只看验证集 MAE → 找到滞后特征组合后 → 再调树模型深度和学习率。不要同时调整所有旋钮不然根本分不清效果变化来自哪个参数。4.2 树模型参数小心 max_depth 和 min_samples_leaf 的配合在家庭用电这种上千到上万样本的规模里随机森林和梯度提升树最容易翻车的参数不是n_estimators而是让单棵树长得过深。max_depth太大比如 30时单棵树会记住训练集里的个别极端用电日验证集上一旦出现没见过的峰值预测就会跑偏。min_samples_leaf 是另一个常被忽略的参数它控制叶子节点的最少样本数设得大一点能防止树去拟合那些只出现一次的深夜低用电量样本。一个省心的检查方式是看训练集和验证集的 MAE 差距如果训练 MAE 是 0.05 而验证 MAE 是 0.25说明严重过拟合优先调大min_samples_leaf到 5~10同时把max_depth往下压如果两边都高到 0.3 以上说明欠拟合先回去加滞后特征而不是继续加深模型。以下是一组我在小时级用电数据上常用的参数范围。参数常见范围调整方向说明n_estimators100~400不动优先调其他参数超过 200 后收益急剧变小只在最终训练时加大max_depth6~15过拟合时减小家庭用电数据量不大没必要超过 15min_samples_leaf3~10过拟合时增大比 max_depth 更平滑地控制过拟合learning_rateGBR0.03~0.1欠拟合时调大过拟合时调小配合 n_estimators先定 learning_rate 再定树数量max_featuresauto/sqrt树之间相关性高时调小让每棵树更“独立”提升集成效果参数说明n_estimators在这个规模下 200 和 400 的差距基本在 0.01 kW 以内没必要用 GridSearch 去扫max_features用默认的 sqrt随机森林/ 1.0GBR起步如果发现树之间的预测结果非常一致、像一个模型在重复投票就调小到 0.6 左右让树更具多样性。调参的终点不是验证集 MAE 最低而是训练集和验证集的误差差距在一个可接受的范围内。4.3 多步预测单步模型怎么滚动预测未来 24 小时模型输出的是「未来 1 小时的用电量」要预测未来 24 小时有三种常见做法多输出回归、递归预测、直接训练 24 个模型。递归预测是先用当前特征预测 t1再把 t1 的预测值当作滞后特征去预测 t2不断滚动到 t24。它实现简单但误差会累积第 1 小时预测偏了 0.1第 2 小时把偏了的 0.1 当输入后面越错越多通常到第 8 小时以后预测基本失去参考价值。多输出回归是让模型直接输出 24 个值对应未来 24 小时sklearn 里用MultiOutputRegressor包装任意回归模型每个预测头单独训练。它的好处是 24 小时的误差相互独立不会滚动累积坏处是样本量没有增加24 个模型共享同一份训练数据模型容量不够时反而拟合不好。我自己实际用的方案是混合策略用多输出模型预测未来 1~6 小时的曲线从第 7 小时开始切到递归预测——先用多输出的第 6 小时预测结果刷新滞后特征再递归往后推。这样既避开了短期的误差累积又减少了需要训练的全天模型数量。做多步预测时验证集必须按「预测第 N 小时的误差」分别报告不能只报全时段平均否则你会以为全天预测都很准实际是前面几小时拉低了整体误差。5. 家庭用电预测避坑清单五条血泪经验5.1 时序泄漏验证集结果好得离谱先查 shuffle 和 feature 方向现象模型在验证集上 MAE 只有 0.05 kW比训练集还好或者 RMSE 小到不真实。 原因一是用了train_test_split的默认随机切分验证集里全是训练集时间段的邻近样本二是构造滞后特征或 target 时 shift 方向写反了导致未来信息泄漏进了特征。 解决切分改成按时间顺序参考 3.3 的代码并逐个检查shift(1)到底是把过去的值拉到现在还是把未来的值拉到现在。检查方法很简单打印一条样本看lag_1h是不是样本 timestamp 前一小时的用电量target是不是样本后一小时的用电量。5.2 节假日和社会事件模型把节假日当天当成普通工作日现象春节、国庆这些天预测值比实际值高出 30%~50%因为模型学到的规律是「工作日用电低、周末略高」长假里人在家待着用电曲线更像周末但又有做饭和取暖的高峰。 原因只用「星期几」做特征模型没见过长假这种长尾场景。 解决构造is_holiday布尔特征把本地法定节假日按日期生成一列 0/1 加进特征矩阵。长假前后的几天也要单独处理放假前一天晚上用电量会异常升高这可以做成is_day_before_holiday。没有官方节假日表时退而求其次把日期序号做成特征让树模型自己学着分开「正常日」和「异常日」。5.3 温度滞后今天的气温不会立刻影响今天的用电现象加入温度特征后模型效果反而变差或者特征重要性里温度排第一但预测依旧不准。 原因空调和暖气对气温变化的响应有滞后性人体对温度的感受也不光是当前小时的温度连续几个小时的累积热效应影响更大。 解决不要只加入当前小时的温度改用「过去 24 小时平均温度」「过去 48 小时平均温度」以及「当日最高温」这些滑动平均温度特征。我一般会构造temp_avg_24h和temp_max_1d再判断滞后温度特征的重要性如果temp_avg_24h远高于temp说明这户用电明显受到累积热效应影响。5.4 峰值预测平均误差好看关键时刻的尖峰全偏现象验证集 MAE 不错但你去看每天 18:00~21:00 的晚高峰预测值普遍偏低 0.5 kW 甚至更多刚好是做饭热水器同时工作的时段。 原因家庭用电的峰谷差异极大峰值样本在训练集里占比少回归模型为了降低整体误差会把预测值往中位数方向收缩峰值被牺牲了。 解决训练时给高峰时段样本加权比如对 17:00~22:00 的样本在损失函数里乘 1.5 或 2.0 的权重或者单独训练一个「高峰时段模型」只用高峰时段的数据训练预测时先判断当前时间是否在高峰窗口内。如果目标是电网侧的容量管理峰值预测的准确率比全天平均误差重要得多评估时建议分组报告高峰时段的 MAE。5.5 特征管道不一致训练时好好的部署后预测全乱现象模型在验证回归脚本里表现正常你把特征构造代码复制到线上服务后预测值普遍偏移。 原因最常见的两个一是线上构造滞后特征时历史数据库的时间没对齐lag_24h取到的不一定是 24 小时前那条记录二是训练时做了fillna(0)或归一化但线上推理时没有做同样的处理尤其是新用户没有足够历史数据时滞后特征全是空值。 解决把特征构造封装成一个函数训练和推理共用同一份代码不要在两个地方各写一份。线上推理时如果滞后特征为空不要填 0用前向填充最近的可用值并在模型侧记录哪些样本是「冷启动」样本——它们天然预测不准单独标记出来比硬塞一个好结果更重要。6. 小步快跑的进阶技巧从预测到可解释的用电顾问回归模型跑通后的下一个层面不是换更大的模型而是把预测结果变成能指导行动的信息。我最常用的技巧是特征重要性分析拿训练好的随机森林或梯度提升树输出feature_importances_你会看到lag_24h和hour几乎总是排在最前面这能反过来帮你理解这户人家的用电习惯——是晚上固定时间高还是空调连续运行几天不关。带交互作用的 SHAP 值分析能进一步看出「高温 傍晚」这两个特征组合时预测会跳升这比单看重要性的信息量大得多。另一个可以做的小工具是把预测结果和实时功率做差值监控当实际用电量连续 30 分钟显著高于预测值比如超过 1 个标准差就推送一条消息提醒「家里可能有大功率设备运行异常或忘关空调」。这类应用不要求预测绝对精准更看重趋势偏离的灵敏度和误报率控制。做完这一层你手里的东西就不只是「一个预测模型」而是一个有输入有输出、能被家人信任的用电顾问。建议你先从自己家的数据跑通第 3 章的最小流程随机森林拿到 0.2 kW 以内的 MAE 后再考虑往多步预测和部署走。我自己的习惯是每周跑一次预测并复盘误差最大的三个时段基本上一两周下来就能总结出这户人家独有的用电规律比盲目调参有用得多。希望帮到你。本文还有配套的精品资源点击获取