尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用电量数据驱动的家庭占用检测:从特征工程到时间序列验证

用电量数据驱动的家庭占用检测:从特征工程到时间序列验证 简介该压缩包为数据科学硕士毕业项目“通过电力消耗数据检测家庭占用率”的完整代码与说明文档面向机器学习、物联网与智能建筑领域学习者。项目基于ECO公开数据集利用特征工程与机器学习方法判断住户占用状态并进一步探究夏季训练模型迁移至冬季场景的适用性对传感数据替代与楼宇自动化研究具有参考价值。包内共2个文件包含1个Python脚本MS_Capstone_Project.py和1个README说明文档整体仅8KB结构精简便于快速阅读与复现。目前已有241人学习下载适合希望了解占用检测案例、电力数据挖掘或模型跨季节评估的中高级数据科学学习者。 数据科学硕士的毕业设计我最后交出去的题目是Detecting Household Occupancy Through Electricity Consumption Data——通过用电量数据判断一个家庭里有没有人所有代码都整理在一个开源存储库里。这个题目吸引我是因为它不需要装摄像头、不需要麦克风、不需要人佩戴任何设备只用每15分钟一条的电表读数就想办法还原一个人的生活节律。项目做完之后我的最大感受是用电量比你以为的更诚实。它虽然不能告诉你“谁在家”却能非常可靠地告诉你“家里现在有没有人处于活动状态”。这篇内容不打算只讲模型调参我会把整个数据链路、特征工程、验证方法以及那些让模型差点翻车的边界情况都梳理一遍给正在做数据科学项目或者准备毕业论文的同学做个参考。1. 为什么弃用传感器选择“用电曲线”来识别人先解释一下我为什么没有一上来就用更“直接”的方案。当时摆在我面前的有几条路摄像头识别、被动红外传感器、门磁、智能电表数据。摄像头和门磁的精度确实高但要落地在真实家庭里问题马上就来了用户对隐私的顾虑、设备安装的复杂度、电池续航以及最重要的——你很难在足够大的样本量上获得一致的标注质量。智能电表数据的好处是天然的。它不需要额外部署运营商和电网端已经按固定频率在采集数据带统一时间戳清洗起来比多设备同步省心得多而且它属于“被动留下”的数据对用户干扰最小。从数据科学项目角度看这种数据来源的可获取性和标准化程度决定了你做出来的模型能不能被复现。不过必须把项目边界划清楚用电数据只能回答“家里是否有人活动”不能回答“是谁”“在做什么”。比如晚上九点出现一个短时功率尖峰我可以推断有人在用微波炉或热水壶但没法判断是老人还是小孩。这个边界很重要因为后续所有特征和模型都是围绕二分类标签去设计的。如果中途想升级成“识别独居老人几点起床”15分钟粒度的电表数据信息量就不够了必须去接门磁、床垫压力或毫米波雷达这类信号。为了验证这个选型思路我列过一张简单的方案对比表做完之后才更确定电表数据路线在顶石项目中的合理性候选方案部署成本隐私敏感度标签可得性可解释性摄像头高极高一般高但业务接受度低门磁/红外中中好中智能电表数据低低需要额外打标较强综合下来电表数据是最适合做“通用型占用检测”的入口。它的短板也很明确静默活动会被漏掉。这个短板后面在误报分析里还会反复遇到。2. 数据清洗和特征设计真正的功夫都在这里很多人做时间序列项目时把大部分精力花在调模型上但我做完这个项目后可以负责任地说占用检测的胜负手在特征不在算法。2.1 时间分辨率15分钟粒度为什么够用我使用的数据是15分钟一条的电力记录。这个粒度很有意思它不像一分钟级数据那样充满瞬时噪声又比一小时级数据保留了足够多的行为细节。一小时级别的聚合会把“回家后开灯、烧水、开电视”这一串连续事件揉成一个平滑点模型只能靠早晚高峰来猜区分度大打折扣一分钟级别的数据又会让橱柜中一个极小设备的反复启停喧宾夺主。实际实验里我试过把其中一段数据换成5分钟粒度整体准确率只提升了不到两个百分点训练时间却多了将近一倍。对于一个硕士毕业设计来说如果在实时控制上需求不高15分钟粒度在存储、训练和推理三端都是性价比最高的选择。2.2 我最终纳入训练的特征组合特征设计的目标很明确把连续的功率曲线翻译成“人是否在场”的线索。我最终没有直接抛原始功率给模型而是构造了三层特征——时间型、统计型、变化型。以一个如何构造滚动特征的代码片段示例import pandas as pd def build_time_features(df: pd.DataFrame) - pd.DataFrame: df df.sort_values(timestamp).reset_index(dropTrue) df[hour] df[timestamp].dt.hour df[weekend] (df[timestamp].dt.dayofweek 5).astype(int) # 90分钟滚动窗口15分钟粒度对应6个点 roll df[power_kw].rolling(window6, min_periods1) df[power_mean_90m] roll.mean() df[power_std_90m] roll.std() df[power_diff] df[power_kw].diff().abs() df[change_90m] df[power_diff].rolling(6, min_periods1).mean() return df最终纳入训练的特征可以整理成一张表特征类别具体特征保留理由时间型小时、是否周末人的作息有强烈昼夜和周末效应近期统计90分钟平均功率、标准差、最大值平滑瞬时尖峰刻画用电活跃强度变化型相邻读数的差分绝对值均值短时间内连续开关事件比平稳用电更有“人味”夜间基线凌晨2-4点平均功率与当日平均功率的差有人时夜间也有随机波动无人时更平稳高活跃占比过去6小时功率超过阈值的采样比例长时间连续用电强烈暗示有人在特征设计并不是越多越好。我早期一个版本加入了“功率频域FFT分量”结果训练集成绩几乎没变反而增加了过拟合风险。对树模型来说冗余特征不仅会拖慢训练还会让特征重要性解释变得不可靠。后来我把特征集精简到15个效果反而更稳定。2.3 标签怎么来是很容易被低估的一环如果你用的是公开智能电表数据集很多数据并不直接带“是否有人”标签这一步必须自己想清楚。我当时在一个试点家庭里放了一个低成本的人体红外传感器连续记录了两周以红外传感器结果作为主要标注来源再人工抽样校正。这中间踩了一个非常典型的坑传感器时钟和电表时钟不同步。红外传感器记录的“有人进入”时间戳和电表记录的时间戳往往差几十秒甚至几分钟如果直接按原始时间戳对齐会在特征和标签之间引入随机错位。轻则降低准确率重则让模型学到奇怪的偏置。我的处理方式是先把所有时间戳统一转成UTC再对齐同时给标签窗口加前后15分钟的模糊容差只有传感器明确显示整个时间片无人才标为0否则标为1。这个小改动让验证集分数直接提升了4个百分点。3. 模型实验里那些让“准确率”失效的陷阱3.1 为什么先从树模型开始而不是直接上LSTM第一次建模时我的直觉是想上LSTM。但细想之后还是先用LightGBM打底。原因很朴素公开数据集只有五万个左右的15分钟样本还不足以喂饱一个复杂的序列模型而树模型对特征交互的建模能力很强训练速度快还能直接输出特征重要性方便把注意力集中在“数据干不干净”上。尤其是项目中期需要向导师解释“这个标签错位到底影响多大”之类的问题树模型的调试循环更舒服。后来我也补了一组LSTM实验。结论很有意思LSTM在验证集上的AUC比LightGBM高一点点但在个别异常时间段上的表现极不稳定比如出差回家第一晚这种过渡状态。综合稳定性、推理速度和可解释性最终部署模型还是选回了LightGBM。3.2 时间序列交叉验证制止了我的自我欺骗这是整篇中最值得展开的一个坑。如果你用train_test_split做随机切分很容易看到93%以上的“高分”换成时间序列切分之后分数可能直接跌到82%。这不是模型变差了而是随机切分让同一家庭后半段时间的样本同时出现在训练集和测试集模型其实是在记忆这位住户最近的生活节律而不是学到可泛化的占用模式。正确的做法是用时间顺序做前向切分from sklearn.model_selection import TimeSeriesSplit import lightgbm as lgb tscv TimeSeriesSplit(n_splits5) for train_idx, test_idx in tscv.split(X): model lgb.LGBMClassifier( n_estimators300, learning_rate0.05, random_state42 ) model.fit(X.iloc[train_idx], y.iloc[train_idx]) val_score model.score(X.iloc[test_idx], y.iloc[test_idx]) print(ffold val score: {val_score:.4f})注意这个项目中“按日随机打散”也会引入泄漏。因为某天的白天样本和前一天夜间样本高度相关当你把时间打散模型低估了真实世界中“连续预测”的难度。在现实部署里你要预测的永远是“下一个时间片”而不是随机抽出来的一个时间片。所以评估方式必须尊重时间顺序。3.3 分类阈值也是模型的一部分占用检测的错误代价并不对称。比如在独居老人场景中漏报老人在家但被判断为无人远比误报严重而如果目标是节能管理误报过多反而会导致空调在无人房间运行浪费电力。默认模型使用0.5作为分类阈值但这并不天然符合业务需求。我在验证集上画了精确率-召回率曲线选择在召回率不低于92%的前提下最大化精确率最终把阈值定在0.43左右。这是我个人项目的经验值不一定适用你的数据但思路可以迁移调阈值之前先问清楚漏报和误报哪个对应用场景更致命再决定往哪个方向偏移。4. 预测错误案例比准确率数字更有价值4.1 “幽灵负荷”导致的误报我以为空房子就是零用电这是最开始最天真的想法。实际分析中我观察到家里即使完全没人冰箱压缩机也会周期性启动每隔30到60分钟出现一次10-20分钟的功率凸起路由器、智能音箱等设备则一直保持低功率运行。这种“幽灵负荷”造成的曲线短看和人的活动很像。我一度以为模型过拟合了之后把典型的误报时刻拉出来看发现特征空间里它们和真实占用几乎重叠。解决方法不是换模型而是加入夜间基线特征真正有人住时夜间也存在随机使用只有定时家电的房间深夜曲线往往呈规律的等间隔波形。模型学会区分这两者之后误报率明显下降。4.2 人在家但没用电的漏报另一个相反的场景是周末下午人躺在沙发上看书刷手机家里耗电的只有路由器和手机充电器功率增量小且平稳模型很容易判成无人。这是数据本身的物理局限不能靠增加模型复杂度来解决。我试过加入“长时段轻微用电”特征也只能缓解一部分。面对这种局限我学到的是学会坦诚如果业务要求完全无感地识别静默活动15分钟电表数据就是做不到需要额外接其他弱信号比如Wi-Fi探针、智能音箱联动或水表数据。对数据科学项目来说尽早向相关方讲清这个边界比用一堆指标包装更重要。4.3 把错误可视化后模型的行为变得可解释我做了很多错误样本分析最有用的做法是把横轴设为连续几天的时间纵轴设为模型输出的占用概率再用颜色标出真实占用区间和预测错误段。做完之后我很快发现有一类系统错误工作日的傍晚模型总是把“回家时间”预测晚半小时到一小时。原因是训练数据里这户家庭多数时候晚上8点后才会进入高负荷用电而某几周里有人6点半就到家开灯了。这种短时变化在特征空间上和“无人时的待机波动”太接近模型自然选择保守判断。看到这个规律后我把“傍晚功率变化率超过阈值的连续时点数量”单独做成了特征直接补上了模型对提前回家的盲区。这类发现光看混淆矩阵是看不到的。5. 这个存储库最终如何组织以及可复用的扩展路数5.1 从“能跑”到“能复现”的仓库结构我见过很多毕业论文的配套代码清一色是几个没有编号的notebook加一堆别人看不懂的脚本这给项目留下了很大的遗憾。考虑到这个项目的标题里特意提到了存储库我最后对代码组织花了不少心思让一个陌生人克隆下来后在半小时内能重现主要结果。最终结构大致如下household-occupancy/ ├─ data/ # 原始数据与样例数据说明 ├─ notebooks/ # 探索性分析和可视化 ├─ src/ │ ├─ features.py # 特征生成 │ ├─ model.py # 训练与时间序列验证 │ └─ predict.py # 推理调用 ├─ configs/default.yaml # 数据路径和模型参数 ├─ requirements.txt └─ README.md关键点有三个第一数据文件不直接上传而是提供下载脚本和列说明避免仓库体积爆炸第二所有随机过程都固定种子保证每次运行结果可重复第三README里写清楚“如何从原始数据一步步走到预测结果”而不是只写一句“这是毕业设计代码”。5.2 从单户模型到大规模部署的三个教训这个项目做完后我试图把方案推广到更多家庭结果发现单户模型跨到新家庭时准确率会有明显下滑。原因在于每户家庭的电器构成、作息习惯、基线负荷差异都很大一个通用模型很难覆盖全部情况。可行的路子是训练一个大型公共模型再为新家庭做少量数据微调。第二个教训是不要忽略时间漂移。半年后同一个家庭的用电习惯可能因为季节、装修、新增电器而发生改变模型的在线更新机制至少要比离线重训更灵活。第三个教训是推理延迟。如果未来要做实时HVAC控制模型必须在几秒内完成特征计算和预测这要求特征工程写得尽量向量化避免在推理链路里做大量循环。5.3 给正在准备数据科学毕业论文的同学一句话最后再说一点个人的体会毕业设计最有价值的产出不是你调出了一个多精确的模型而是你能把“从问题上得到答案”的完整过程讲清楚。我在这个项目中真正花时间最多的地方不是LSTM调参而是理解为什么标签会错位、为什么随机交叉验证会自欺欺人、为什么某个时段模型系统性误判。如果你也在做数据科学方向的毕业论文建议你先锁住评估指标再建立合理的验证流程最后才去碰那些酷炫的模型。把时间序列验证和错误分析做扎实论文和代码都会比单纯堆模型分数更有说服力。我现在回头看这个存储库里的代码很多功能已经可以重新组织得更好但整套方法论的骨架至今仍然在直接复用。本文还有配套的精品资源点击获取
返回列表