
简介本资源是一份面向能源数据分析、电力系统智能运维及机器学习实践者的伦敦智能电表负荷聚类完整项目包聚焦于从真实时间序列数据中挖掘用户用电行为模式。项目综合运用KMeans、DBSCAN与AutoEncoder三种主流聚类方法覆盖特征工程、降维表示、密度识别与可视化全流程适用于负荷分类、需求侧管理、异常用户识别等典型电力AI应用场景适合具备Python基础与机器学习入门知识的中级学习者。压缩包共27个文件4.97MB含6个核心Python脚本如data_process.py、clustering_autoencoder.py、7个CSV数据集含预处理后的日/周/月特征集与标签、5个PNG/JPEG图表聚类结果热力图、轮廓系数对比等及1份README说明文档结构清晰、模块解耦便于复现与二次开发。已有1263人学习下载读者可直接运行代码完成端到端聚类分析获取可解释的用户分群结果、算法性能对比报告及可视化输出显著降低智能电表时序聚类的实践门槛。 刚拿到伦敦智能电表数据聚类.zip这个包的时候我第一反应是解压、跑起来、看结果。结果解压第一步就弹了个file is not a zip file的报错折腾了十几分钟才发现是下载到的其实是个HTML错误页面。顺着这个思路把这套数据完整做下来之后我意识到这个zip包背后真正有价值的东西不是那几行聚类代码而是从拿到一个用电数据压缩包到形成可解释的用户分群这条完整链路。这篇内容围绕智能电表数据聚类展开覆盖数据文件解压与校验、时间序列清洗与特征工程、聚类算法选型、分群结果解读以及打包交付时的工程化细节。适合刚开始接触用电数据挖掘的同学们做参考也适合给那些已经跑通了K-Means但觉得结果没法解释的读者解决具体的卡点。1. 伦敦智能电表数据集到底长什么样拿到zip之后的第一件事1.1 数据来源与整体构成伦敦智能电表数据London Smart Meter Data是英国配电公司UK Power Networks公开的一个真实住户用电数据集。数据范围大概是2011年底到2014年初覆盖约5600个住宅用户每个用户的电表每半小时记录一次有功功率或电量读数。也就是说一个用户一天最多有48个采样点一个用户一年就是17520个点两年下来接近35000个点。全部用户加起来数据量级在GB级别。这个数据集之所以在社区里受欢迎是因为它包含的不只是一个用户一条平均功耗这种粗粒度信息而是完整保留了时间序列形态。你可以看到每个家庭一天之内用电的起伏这种形态信息是后续做负荷曲线聚类、用户行为分群的核心输入。zip包里的文件通常是这样的meter_readings.csv用户ID、时间戳、读数单位通常是kWh或kWinformations.csv用户ID对应的电表ID、区域信息、住户类型等标签acorn.csv用户所属的Acorn分类英国一种住户画像分群体系有时还附带天气数据、节假日标记等辅助特征1.2 文件结构里那些容易忽略的细节真正打开CSV之后要注意几个细节。第一是时间戳格式这个数据集里常见的是2013-04-15 00:00:00这种带日期的字符串但有些版本的导出会把日期和时间拆成两列。第二是读数的含义有些列存的是当前表底读数有些列存的是本半小时内的用电量如果不区分直接拿来做分析结果会完全偏掉。我通常的做法是先不急着写聚类脚本而是先对每个CSV做一次快速checklist文件编码是不是UTF-8有没有BOM头列名大小写是否一致有没有隐藏空格时间戳是否单调递增有没有重复采样点每个用户ID对应的记录数是否均匀是否有的用户缺了大段时间这一步花不了多少时间但能省掉后面无数返工。很多人拿过来就直接pd.read_csv然后开始聚类最后发现某个用户的数据只有别人的一半长度怎么办都不知道。1.3 解压这个zip时踩过的坑这个zip包本身的处理也有一些常见问题我在帮同事处理类似压缩包时经常看到报错file is not a zip file或could not find EOCD。EOCD是zip文件末尾的结束目录标记解压工具找不到它说明文件不是完整有效的zip归档。最常见的原因是下载中断、网络传输不完整或者服务器返回了一个错误页面但浏览器保存成了zip后缀。处理方法很简单先看文件大小是否和发布页面一致再用十六进制编辑器或命令行xxd看文件开头zip文件应该以PK0x50 0x4B开头。如果开头是或者!DOCTYPE那基本就是HTML错误页。分段压缩包z01、z02。如果发布方用了分段压缩下载到的可能是一堆xxx.z01、xxx.z02和最后的xxx.zip。这时候不要单独去解压任何一个分片要把所有分片放在同一个目录下用7-Zip或WinRAR选中主zip文件解压工具会自动找齐其他分片。有的人只下载了最后一个分片解压失败其实不是文件坏了是前面的分片没下全。zip密码问题。有些数据包发布时会加密码readme或下载页面会写明。先检查发布方的说明文档不要急着用工具去恢复密码。如果是自己加密后忘了密码想找回可以尝试一些专业的密码恢复软件但成功率取决于密码强度和机器性能。如果是别人加密的包、又没授权那就别碰尊重数据版权和隐私边界。提示解压后的第一件事不是看数据而是先记录文件的MD5或SHA256值和发布方提供的校验值对比。这个习惯在传输大数据包时非常有用能快速确认文件是否完整。2. 数据清洗与特征工程聚类质量的地基真正决定聚类效果的不是算法本身而是你喂给算法的是什么特征。原始用电序列里掺杂了大量噪声和缺失直接丢进聚类模型得到的结果往往是一堆无法解释的碎片簇。所以我在拿到干净的时间序列之后会先做一轮系统的清洗再把它压缩成有业务含义的特征。2.1 时间戳对齐与缺失值处理智能电表数据有一个特点理论上每半小时一个点但实际采集时会有跳采、重复采、延迟上报。我在这个数据集上统计过大概有4%到8%的用户会缺某些时段。如果某个用户某天只有30个点而不是48个点不能简单跳过因为后面聚类的输入是日负荷曲线天数不齐会导致特征矩阵维度不一致。处理策略是这样先用pivot把原始长表转成时间 x 用户的宽表缺失位置自然变成NaN按标准的半小时时间轴重采样缺失比例低于10%的用户用前后值线性插值补全缺失比例高于30%的用户直接整段剔除因为这些样本的特征不可靠连续缺失超过6小时的片段不插值标记为异常日在特征提取时用正常日平均替代代码大概长这样import pandas as pd df pd.read_csv(meter_readings.csv, parse_dates[timestamp]) pivot df.pivot_table(indextimestamp, columnsid, valuesreading, aggfuncmean) pivot pivot.sort_index().resample(30min).mean() # 统计每个用户的缺失比例 missing_ratio pivot.isnull().mean() valid_users missing_ratio[missing_ratio 0.3].index pivot pivot[valid_users].interpolate(limit12)2.2 日与周负荷特征把时间序列压缩成可聚类的向量原始48维日负荷曲线做聚类也不是不行问题是维度高、噪声大而且每个用户不同日期的曲线形态差异很大。我在实际项目中更常用的是先提取日级统计特征再对特征聚类。这样做的优势是稳定性和可解释性都更好。我常用的日级特征包括日总用电量kWh日峰值功率kW和出现时刻日最低功率与夜间基础负荷通常是凌晨2点到5点的平均功率峰期用电占比如晚上17点到21点的用电占总用电的比例负荷率 平均功率 / 峰值功率变异系数 标准差 / 均值衡量一天内用电波动程度如果要保留曲线形态我会做归一化后的日负荷曲线聚类先把每天48个点除以该天总用电量这样所有曲线变成形状的表示然后对工作日和周末分别聚类再合并成工作日模式 周末模式标签。2.3 为什么要标准化聚类距离对尺度极其敏感这是新手最容易忽略的地方。假设用电量高的用户平均每天30kWh用电量低的用户只有5kWh如果直接用欧氏距离聚类距离几乎完全由用电量大小决定两个白天不用电、晚上集中用电的用户仅仅因为总量不同就会被分到完全不同的簇。这样不是不行但往往不是我们想要的业务分群。所以聚类之前必须认真做特征缩放。常见做法是StandardScaler或MinMaxScaler。from sklearn.preprocessing import StandardScaler features [daily_total, peak_power, night_base_load, peak_ratio, load_factor, cv] X df[features].values scaler StandardScaler() X_scaled scaler.fit_transform(X)关于要不要降维我的经验是如果只是十几个特征做不做PCA影响不大规范化之后直接聚类即可。但如果把48维日负荷曲线整个喂进去可以考虑先做PCA降到10维左右再聚类能过滤掉一部分高频噪声。不过PCA以后簇中心的可解释性会下降这个要自己权衡。提示聚类结果里如果有一个簇的中心是各项特征都很小的用户另一个簇是各项特征都很大的用户先别急着下结论大用户簇检查一下是不是没做标准化。3. 聚类算法选型从K-Means到高斯混合模型的取舍聚类算法选哪个取决于你对结果的期望。是要一个快速可解释的基线还是要能表达用户可能同时具备多个属性的软分群我在这个项目里的做法是先用K-Means跑通再用高斯混合模型GMM做细化两者结合判断。3.1 K-Means作为基线先看管路通不通K-Means最大的优点就是快、简单、簇中心直观可读。对5600个用户、十几个特征跑几百次迭代都是毫秒级完全不是性能瓶颈。我用它当基线是为了先确认数据流程没问题、可视化结果有区分度。核心代码很简单from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score K range(2, 11) sil_scores [] for k in K: model KMeans(n_clustersk, random_state42, n_init10) labels model.fit_predict(X_scaled) sil_scores.append(silhouette_score(X_scaled, labels)) # 取轮廓系数开始下降之前的K作为候选轮廓系数只是一个参考不是越大越好。有些数据集K2时轮廓系数最高但分出来的两个簇可能就是用电多和用电少业务上一文不值。所以我还会看肘部法则的SSE曲线以及每个簇的用户数是否过于失衡。3.2 GMM的软聚类优势电力用户本来就不是非黑即白一个家庭里的用电行为是多个成员叠加的结果——有人白天在家办公有人晚上回来做饭还有电器在凌晨定时运行。硬聚类要求每个用户只能属于一个簇这不太符合现实。GMM的好处是输出每个用户属于每个簇的后验概率你可以说这个用户有60%像夜间储能型30%像白天双峰型这对后续精细化运营非常有价值。GMM实现也很方便from sklearn.mixture import GaussianMixture gmm GaussianMixture(n_components6, covariance_typefull, random_state42) gmm_labels gmm.fit_predict(X_scaled) gmm_proba gmm.predict_proba(X_scaled)协方差类型的选择需要看特征数量特征少用full特征多或者样本少改成diag或tied能避免过拟合。GMM在n_components选择上可以看BIC或AIC但和K-Means一样指标只做参考最终还是看业务解释性。3.3 聚类数K结合指标和业务形态一起定我见过不少人在这一步死磕指标尝试各种聚类评价指标最后选了一个轮廓系数最高的K但画出来的簇中心曲线几乎完全重叠。这样做的根源问题是评价指标只度量分离度不度量业务可解释性。我的做法是三步走用轮廓系数和SSE曲线圈定一个粗略范围比如K在4到8之间对每个候选K把簇中心对应的日负荷曲线画出来肉眼检查是否可分观察每个簇的用户占比避免出现某个簇只有几十个用户的极端情况实际上我在这个数据集上最终选的是6个簇。K6时每个簇中心曲线形态差异明显用户分布也相对均匀业务上每个簇都能给出一段说得通的描述。这个数字不是这个数据集唯一的答案但如果你的目标就是给用户做可解释分群这个方法方向是对的。4. 聚类结果解读与用户分群画像聚类结果不是画一张散点图就结束。真正有价值的产出是把每个簇翻译成一段可以让非技术同事看懂的用户画像。这一步做得好的话后续的营销策略、电价套餐设计、需求响应目标群体选择全部可以落地。4.1 典型负荷曲线簇长什么样我这套数据聚出的6个簇如果按日负荷曲线形态描述大致是这样簇编号日用电形态典型占比可能的用户特征A白天低位晚高峰骤升约28%上班族白天家里没人晚归做饭娱乐B全天平稳夜间略低约18%老年人或全天居家用电习惯稳定C白天双峰午间晚间约16%混合家庭有人中午回家D夜间用电显著偏高约14%使用储热式电暖器或夜间优惠电价E整体电量高峰形不明显约15%大户型或用电设备多F整体电量低波动剧烈约9%单身上班族仅少量必用电注意这个表是根据我在类似用电数据上的经验做的示意不是这个数据集的唯一标准答案。不同版本数据、不同特征组合簇的形态会有差异。但查看结果的方法是一致的取每个簇所有用户的平均日负荷曲线画在同一张图上对比形态。4.2 结合住户属性做交叉验证这个数据集自带acorn标签和部分用户属性可以用来交叉验证聚类结果有没有业务意义。比如簇D夜间高用电是否集中分布在某个特定区域或某类住宅类型簇A晚高峰骤升是否和住户人数有关联交叉验证的做法很简单cross pd.crosstab(cluster_labels, df[acorn_group], normalizeindex)看每个簇里不同属性用户的占比。如果某个簇和某个属性标签高度相关比如簇D里80%都是某种储热供暖型住宅说明聚类捕获了真实的物理差异而不是随机分组。如果交叉验证发现所有簇的属性分布都差不多说明聚类依赖的特征可能与属性无关或者是特征工程质量不够好需要回炉。4.3 聚类结果能用来做什么从应用角度看用户分群至少有三个方向能用上一是需求响应。夜间用电高的簇D用户天然适合参与夜间谷段电量激励或储热设备调控因为他们的用电行为本身就有弹性。晚高峰骤升的簇A用户更适合分时电价引导错峰。分群之后可以分别设计补贴策略而不是一刀切。二是预测和异常检测。每个簇的负荷曲线就是该用户的基准画像。如果某个原本属于A簇的用户连续一周出现夜间用电异常升高可能说明设备故障或行为突变可以触发告警。三是低压电网规划。稳定用电的簇B和波动剧烈的簇F接入同一台区时对变压器容量的要求不同。聚类结果可以辅助台区负载管理识别哪些台区需要扩容或调整三相平衡。这些应用不是这个数据集本身包含的但做聚类项目如果不思考结果怎么用后期很难产生实际价值。5. 从jupyter到生产zip交付背后的工程教训数据项目的最终交付往往不是一个模型文件而是一个包含数据、代码、文档的压缩包。这个zip就是别人复现你工作的唯一入口能否顺畅解压、跑通、复现直接决定项目的可信度。结合这个项目我整理了三个工程化经验。5.1 环境复现requirements.txt要写死版本我收到过很多项目zip包解压之后没有环境说明或者requirements.txt里全是pandas1.0这种松散的版本范围。这种1.0的写法在半年后极可能装出和你完全不同的版本然后行为差异导致结果对不上。正确做法是python3.10.12 pandas2.0.3 numpy1.24.3 scikit-learn1.3.0 matplotlib3.7.1 jupyter1.0.0如果你用conda建议把environment.yml一并打进去里面写死python版本和所有依赖版本。有人会觉得这样太死板但如果你需要别人无缝复现死板恰恰是最大的省心。5.2 大文件处理内存优化与增量读取这个数据集全量展开后CSV可能有几个GB直接用pandas读进内存可能撑爆普通笔记本。我常用的办法是读CSV时指定dtype和usecols只保留必要的列把数值列指定为更紧凑的类型。import pandas as pd dtype_dict {id: int32, reading: float32} df pd.read_csv(meter_readings.csv, dtypedtype_dict, parse_dates[timestamp])如果文件实在太大用chunksize分段读取chunk_list [] for chunk in pd.read_csv(meter_readings.csv, dtypedtype_dict, chunksize500000): # 在chunk上做清洗和聚合减小体积 chunk_agg chunk.groupby([id, date]).agg({reading: [sum, max, min]}) chunk_list.append(chunk_agg) df_agg pd.concat(chunk_list).groupby(level[0, 1]).mean()核心思路是不要把所有原始数据同时放在内存里而是先把几十万行数据压缩成日级统计量再做后续分析。这样内存占用能从GB级降到几十MB聚类速度也快一大截。5.3 交付zip前的自查清单项目收尾准备打包时我会有个自查清单对照检查一遍再发出去压缩包内是否包含README写明数据来源、脚本运行顺序、输出文件说明解压后是否能按README的顺序从零复现整个流程是否包含环境依赖文件requirements.txt或environment.yml是否有校验值MD5/SHA256供下载方核对文件完整性是否清理了缓存文件、.ipynb_checkpoints、临时目录是否明确标注了数据文件的许可协议和使用限制我在实际中遇到过最典型的情况是压缩包里的jupyter notebook是带输出状态的别人打开直接看到了我的运行结果但一运行就报错因为中间的某个变量是在之前的cell里定义却没保存。这在交付时务必避免要么清空输出重新run一遍要么确保能一键执行。还有一次同事把数据文件放到网盘共享下载下来一直报EOCD错误最后发现是网盘下载链接被服务商压缩成了另一个格式。所以发布大文件时如果允许建议同时提供SHA256校验值下载方拿到后先校验再解压能省掉很多来回沟通的成本。另外关于zip包的密码保护如果是敏感数据加密后再传输是正确的做法。但密码一定要通过可靠渠道单独告知接收方不要写在README里一起打包。这一条在数据项目交付时尤其重要——你要防护的是传输途中泄露而不是接收方内部的知情权。这个项目做下来我最大的体会是聚类本身不是难点难点在于从一份原始zip到稳定、可解释、可复用的分析结果之间有无数个细节容易翻车。解压报错、时间戳错位、特征没标准化、K选得没道理、交付的包别人跑不起来——每一步都会消耗大量时间。把这些环节都理顺之后聚类反而变得简单了。最后再分享一个小技巧我会把解压校验、数据清洗、特征提取、聚类评估这四段逻辑分别封装成独立函数中间用CSV或pickle缓存中间结果。这样每次调整聚类参数时不用重新跑一遍数据清洗直接从特征文件开始迭代速度快了好几倍。如果你也在处理类似的用电数据分析项目建议从第一天就按这个思路组织代码后面会感谢自己。本文还有配套的精品资源点击获取