简介:这是一份面向智能用电与非侵入式负荷监测(NILM)研究者的可直接运行项目包,基于Python与PyCharm环境,内置REDD低频数据集,配套CO与FHMM两种典型分解预测算法,适合入门到进阶阶段学习算法调用、数据预处理与结果评估。压缩包共1046个文件,大小约460.46MB,核心为439个Python脚本及220个编译产物,覆盖数据加载、模型训练与评估全流程;另含122个dat原始/处理数据、87个yaml配置、49个ipynb交互式分析文档,以及少量H5权重、CSV结果和说明文档,各类型分工明确,便于按模块对照研读。资源已有3401人学习,具备较高参考价值。除代码与数据外,包内还提供环境配置脚本、依赖描述文件与项目说明,可帮助节省环境搭建时间,更快复现NILM分解结果并体会两种算法在能耗预测上的差异。
1. NILMTK 环境搭建:从 Python 3.8 到 PyCharm 的版本匹配是关键
很多人第一次接触 NILM(非侵入式负荷监测)时,下载了 NILMTK.zip,然后在 PyCharm 里新建项目、pip install nilmtk、紧接着 import nilmtk 就红了。原因不是包坏了,而是这个工具包对 Python 版本和 pandas、numpy 的依赖版本极其敏感,用新版 Python 或者全局解释器,装完就被版本冲突顶掉。我帮某开发者在模拟项目X 上配过一次完整环境,从 Python 版本到 PyCharm 解释器一路理顺,NILMTK 才能正常读取数据并跑通设备功率统计。这篇安装落地文按“装前准备 → 下载安装 → 配置 → 排错 → 验证”的顺序来写,用 Python 和 PyCharm 跑 NILMTK 的开发者,照着走一遍就能把环境立起来。
2. 安装前准备:Python 3.8、PyCharm 与虚拟环境的取舍
NILMTK 的安装难点不在工具包本身,而在它和现代 Python 生态的兼容性。很多人一上来就直接进入 pip install,结果陷入 pandas 版本泥潭。我建议先花十分钟把 Python 版本、虚拟环境、依赖范围这三个决策定死,后面每一步都会顺畅很多。
2.1 Python 版本:为什么锁定 3.8 而不是 3.10 或 3.11
NILMTK 早期源码是在 Python 2.7 上开发的,后来社区迁移到 Python 3 时,很多内部数据结构还保留着旧式写法,对较新解释器没有系统性的回归测试。实际经验是:Python 3.8 最稳,3.9 基本可用,3.10 以上容易出现 numpy、pandas 低版本装不上的情况,Python 3.11 更是直接跟多数预编译包脱节。
以我踩过的坑为例,某开发者第一次用 Python 3.10 打开 NILMTK 项目,conda 提示没有匹配的 numpy<1.21 预编译包,因为旧版 numpy 没有针对 3.10 的 wheel。后来把环境重建为 Python 3.8,同一个依赖列表一次性装完,前后只差一个解释器版本。
| Python 版本 | NILMTK 兼容性 | 说明 |
|---|---|---|
| 3.6 | 可装但偏旧 | pandas、scikit-learn 版本受限,新版 PyCharm 支持弱 |
| 3.8 | 推荐 | conda-forge 上预编译包覆盖最全 |
| 3.9 | 多数可用 | 需要稍微放宽依赖版本 |
| 3.10+ | 容易冲突 | 旧版 numpy 无预编译 wheel,pip 会自动升级导致崩坏 |
提示:如果条件允许,用 conda 而不是纯 pip 来管理 Python 版本,conda-forge 对旧版本预编译包的覆盖明显更完整。
检查当前环境的 Python 版本,在终端里执行:
python --version conda --version第一行确认解释器版本,第二行确认 conda 是否可用。如果输出不是 conda 而是空白,说明 conda 不在 PATH 里,需要先重新加载 shell 配置或重启终端。没有 conda 的,直接用 Python 官网安装对应版本的 3.8,后续用 venv 建环境也能走通,只是依赖解析会稍微费力。
2.2 PyCharm 虚拟环境:避免全局解释器依赖污染
我一般不用系统自带的全局 Python 跑 NILMTK,原因是老版本 pandas、numpy 会跟全局环境里其他项目的新版依赖互相踩踏。比如某个项目已经装了 pandas 2.x,NILMTK 内部很多接口基于旧版 DataFrame 行为,一旦共用全局解释器,加载数据时会直接报AttributeError: module 'pandas' has no attribute 'Panel'。
所以在 PyCharm 里我建议单独建一个 conda 虚拟环境,把 NILMTK 的依赖锁在环境内部,不污染其他项目。创建命令:
conda create -n nilmtk_env python=3.8 -y conda activate nilmtk_env-n nilmtk_env给环境起名,随意改但别用中文和空格;python=3.8就是上一节反复强调的版本;-y是跳过确认,避免安装中途卡住。环境创建后会提示To activate this environment, use conda activate nilmtk_env,先确认终端行首出现(nilmtk_env)再继续下一步。
PyCharm 连接这个环境的方法是:Settings 或 Preferences 里找到 Project > Python Interpreter,选择 Add Interpreter > Conda Environment > Existing Environment,然后路径指向conda env list里 nilmtk_env 对应的 Python 可执行文件。这里最容易犯的错误是直接选了 base 环境,导致后续所有依赖都装入全局,这是环境隔离失败的高频原因。
2.3 依赖清单:numpy、pandas、scikit-learn 的版本区间
NILMTK 本身是一个工具包框架,核心功能围绕数据导入、事件检测和负荷分解算法展开,因此对数据科学栈的依赖很重。安装时不会限制依赖上限,如果你直接从最新版开始,大概率会遇到 NumPy 二进制接口不兼容或者 pandas API 变更导致的运行时崩溃。
我这里给一份经过实测的依赖组合,适用 Python 3.8:
conda install -n nilmtk_env numpy=1.19.5 pandas=1.1.5 scipy=1.5.4 scikit-learn=0.24.2 matplotlib=3.3.4 -c conda-forgenumpy=1.19.5是 NILMTK 兼容性最好的版本,很大程度上避免 numpy 1.20 之后的 float/double 类型提示变化;pandas=1.1.5是为了保住它依赖的 DataFrame 内部接口;scipy=1.5.4负责 HDF 数据读写和插值计算;scikit-learn=0.24.2给 NILM 算法提供基础评估能力。-c conda-forge指定从 conda-forge 频道拉取预编译包,比默认 channels 对旧版本的覆盖更全。
同时建议顺手安装 jupyter 或 notebook,不是运行必须,但调试阶段看负荷曲线时很有用。注意不要在这个阶段安装 hmmlearn 和 networkx,NILMTK 的 contrib 模块用得到,核心不含这两个包,先不装可以减少依赖冲突面。
3. 下载与安装:从 NILMTK.zip 到 conda 环境落地的完整流程
环境定好后,收尾安装就是把 NILMTK 源码解压、依赖装好、本地可导入。这一步的拦路虎大多是国内网络拉取慢、setup.py 依赖解析失败,以及 pip/conda 混用导致的版本漂移。我用下面的顺序做了几十次,基本不出问题。
3.1 解压 NILMTK.zip 并确认源码结构
拿到 NILMTK.zip 后,先别急着 pip install,把它放到一个干净的目录里解压。通常源码根目录下会有 setup.py、README、LICENSE 和一个叫 nilmtk 的 Python 包目录。看到 setup.py 意味着这是一个需要走本地安装的 Python 项目,而看到 nilmtk/ 目录才是核心代码本体。
mkdir -p /opt/nilmtk-src unzip NILMTK.zip -d /opt/nilmtk-src cd /opt/nilmtk-src ls如果unzip在系统里不存在,Ubuntu/Debian 上用sudo apt install unzip,或者直接用 PyCharm 的终端配合图形界面解压也行。解压后重点检查两件事:一是文件目录里是否有嵌套的NILMTK文件夹,有嵌套时cd需要进入内层;二是确认没有中文路径,Python 包里凡是涉及相对导入的组件,被中文目录套住后容易出现编码异常。
路径选/opt/nilmtk-src只是示例,也可以放/home/xxx/nilmtk。但强烈建议躲开桌面和中文用户名目录,NILMTK 里有部分数据读取逻辑走本地 HDF 文件,路径里的非 ASCII 字符会带来莫名其妙的 I/O 错误。
3.2 在 conda 环境内安装基础依赖包
依赖这一步最好在 conda 环境里完成,激活环境后先安装一组不含 NILMTK 的数据科学基础包,再单独安装 NILMTK 本体。这样如果 NILMTK 安装报错,能确认是环境问题还是包本身问题。
conda activate nilmtk_env conda install -n nilmtk_env numpy=1.19.5 pandas=1.1.5 scipy=1.5.4 scikit-learn=0.24.2 matplotlib=3.3.4 -c conda-forge -y参数说明:-n nilmtk_env和conda activate双重指定,避免有人在终端里没激活环境就把包装进 base;-c conda-forge指定频道,实际上 conda-forge 上有较多针对旧版本的兼容构建;-y跳过安装确认。装完后可以执行conda list | grep numpy查看版本是否严格锁定在 1.19.5,如果显示 2.x,说明 conda 没有按指定版本解析,需要检查是否有其他环境变量覆盖了 channel。
注意:这一步不要同时把 NILMTK 一起
conda install。历史版本的 NILMTK 在 conda 默认频道里要么缺失要么依赖解析冲突,直接 pip 安装源码包反而更容易控制。
3.3 pip install -e . 本地安装与依赖报错处理
在具备 setup.py 的源码目录里,最常见的本地安装命令是:
cd /opt/nilmtk-src pip install -e .-e是 editable 模式,也就是开发模式,安装后修改源码目录里的 Python 文件可以即时生效,不用反复重装。这样调试 NILMTK 内部逻辑或者自定义数据集解析器时,性价比很高。
如果安装中途报错提示依赖缺失,比如error: Setup script exited with error,通常不是源码问题,而是 setuptools 版本太旧或者缺失。解决办法:
python -c "import setuptools; print(setuptools.__version__)" pip install --upgrade setuptools wheel还有一个经验做法:如果 setup.py 自动解析依赖时和当前 pandas/numpy 版本打架,可以用pip install --no-deps -e .先只装 NILMTK 本体,跳过依赖检查,然后手动把缺失的依赖补上。好处是能快速把错误范围缩小到依赖组合本身,缺点是后续缺哪个包 pip 不会提示,需要自己按import报错逐个补。
安装完成后,切到项目目录下验证一下:
cd /opt/nilmtk-src python -c "from nilmtk import DataSet; print('ok')"输出 ok,说明 NILMTK 已经把核心模块注册进当前环境的 site-packages。这一步在 PyCharm 里做的话,注意当前使用 Terminal 的解释器是 conda envnilmtk_env,而不是 PyCharm 默认的 base,否则会看到奇怪的 ModuleNotFoundError。
4. 配置与验证:PyCharm 解释器、数据集路径与首次导入
安装完成的 NILMTK 相当于放在仓库里还没有上膛的子弹,要在 PyCharm 里真正跑起来,需要把解释器、数据集路径、项目结构一次性配置到位。很多人栽在“明明 pip 装好了,PyCharm 里还是报错”这个坎上,根因几乎都指向解释器绑定与数据路径不一致。
4.1 PyCharm 解释器绑定与项目结构
在 PyCharm 的 Settings 或 Preferences 里,找到 Project 下的 Python Interpreter,点击 Add Interpreter,选择 Conda Environment,再选 Existing Environment。路径选择你那个nilmtk_env的 Python 可执行文件。
如何确认路径?终端执行:
conda env list输出里会列出每个环境的存放路径,比如/usr/local/miniconda3/envs/nilmtk_env/bin/python。在 PyCharm 选择这个路径后,左下角会显示当前解释器版本,并且 PyCharm 会自动初始化一个 Run/Debug Configuration。这一步选错是最高频的翻车点:有人选了 base 环境,有人选了系统 Python,还有人选了 PyCharm 自动生成的 venv,最后 import 时全部失败。
建议在项目根目录保留一个requirements-virtual-version.txt文件,把第 2.3 节那一组版本号写死,方便新机器一键重建环境。PyCharm 本身也会索引环境里的第三方包,所以在解释器加载完成后,NILMTK 会出现在 Project Dependencies 列表中,说明 PyCharm 已经在环境里识别到了它。
4.2 数据集路径与文件读取方式
NILMTK 的数据导入依赖DataSet类,它接收一个具体的数据文件路径,通常是 HDF5 格式。路径中我强烈建议不要出现中文、空格、特殊符号,NILMTK 在读取 HDF 文件时涉及 pandas 的 HDFStore,对路径的编码容忍度有限。另外把数据文件单独放到项目根目录下的 data 子目录里,理由有两点:一是保持项目目录结构紧凑,二是避免未来写相对路径时层层递进把脚本搞乱。
mkdir -p /path/to/project/data mv /path/to/sample.h5 /path/to/project/data/把 HDF 文件放进去后,打开 PyCharm,在 Project 工具窗口中确认 data 目录中有对应 .h5 文件。如果用的是一堆 CSV 文件,需要先转成 HDF5。常见做法是先用 NILMTK 自带的数据转换工具在另一个环境里把 csv 转成 h5,转换时注意时间戳格式统一;只保留两列:时间戳和功率。我的习惯是转换完成后顺手用 pandas 读一遍,确认没有 nan 时间戳,因为后续按时间窗口切片遇到连续 nan 会出现静默截断。
4.3 首次导入:from nilmtk import DataSet 的三种写法
配置好解释器和数据路径后,新建一个 Python 文件,写最简导入测试:
from nilmtk import DataSet print(DataSet.__name__)这是第一种写法,也是最应该生效的方式,前提是 PyCharm 解释器已正确指向 nilmtk_env。如果运行后没输出,先在右下角看当前解释器名,确认没切到 base。
第二种情况是你在终端里跑脚本,但终端里的 Python 与 conda 环境不一致。这时可以在脚本最前面主动插入 NILMTK 源码路径,绕开环境变量问题:
import sys sys.path.insert(0, '/opt/nilmtk-src') from nilmtk import DataSet print(DataSet.__name__)sys.path.insert(0, ...)是把源码目录加到模块搜索路径的最前面,避免和其他目录里的同名模块冲突。这种方式只适合临时排查,真正项目运行还是建议把解释器绑定好,而不是每个脚本里都塞这种代码。
第三种是先从依赖层面确认版本对不对:
import numpy import pandas print("numpy", numpy.__version__) print("pandas", pandas.__version__)NILMTK 在 pandas 2.x 下导入会报AttributeError: module 'pandas' has no attribute 'Panel',因为老版本 NILMTK 内部还在引用 pandas 的 Panel 结构,而 pandas 从 1.0 开始逐步移除,2.0 之后彻底删除。所以这一步只要看到 pandas 版本是 1.1.5 左右,基本可以放心导入,如果显示 2.x,马上回第 2.3 节把版本降回来。
导入测试通过后,再读一次数据文件做端到端验证:
from nilmtk import DataSet dataset = DataSet('data/sample.h5') print(dataset)能打印出数据集信息,说明 NILMTK 不仅能 import,还能正确处理 HDF 数据。如果这一步报找不到文件,优先检查 PyCharm 工作目录是不是项目根目录,运行配置里 Working directory 经常默认选到用户目录,路径要么改成绝对路径要么改成项目相对路径。这就是为什么前面把数据放在 data 子目录,因为 writestream 数据,读取路径可以稳定维持data/sample.h5这种干净写法。
5. 避坑与常见问题排查:解释器、版本冲突与导入失败的四个高频现象
NILMTK 的坑大多不在算法层,而在环境层。下面四条是我帮别人和自己排查时遇到频率最高的,每一条都按现象、原因、解决来拆,照着比对就能少走弯路。
5.1 import nilmtk 报 ModuleNotFoundError
现象:在 PyCharm 运行脚本,控制台输出ModuleNotFoundError: No module named 'nilmtk'。
原因:最常见的是解释器选错。PyCharm 不同项目可以绑不同解释器,如果你之前用 base 环境安装的 NILMTK,新建项目后又手动切了一个空环境的解释器,自然找不到模块。另一个次常见原因是终端里处于不同的 conda 环境,前面用 nilmtk_env 安装,后面终端却在 base 环境里运行 Python。
解决:先在终端执行conda activate nilmtk_env,然后运行pip show nilmtk,看输出里的 Location 是否指向 nilmtk_env 的 site-packages。确认环境正确后,再去 PyCharm 里重新选择解释器路径。如果pip show显示没有被安装,回到第 3 章重新执行pip install -e .。还有一种特殊情况是终端能 import,但 PyCharm 的 Run/Debug 配置还是旧解释器,需要在 Run > Edit Configurations 里改 Python interpreter。
5.2 conda 安装依赖时长时间卡在 Solving environment
现象:执行conda install ...后在 Solving environment 上卡了很久,或者提示通道冲突,然后给你一堆不可解的版本列表。
原因:conda 默认 channel 和 conda-forge 混合后,求解器要为 numpy、pandas 等多个包找一个同时满足的版本组合,python 3.8 太新或要求太严格会让求解时间呈指数增长。这个不是网络慢,是 conda 的依赖求解器在硬算。
解决:第一试验区用一个 channel,命令改成-c conda-forge,不要同时挂 default、conda-forge、其他第三频道的混源;第二给 conda 装上 mamba 做加速解析。
conda install -n nilmtk_env mamba -c conda-forge -y mamba install -n nilmtk_env numpy=1.19.5 pandas=1.1.5 scipy=1.5.4 -c conda-forgemamba 的底层依赖求解器比 conda 快得多,实测同样的版本组合,从几分钟降到十几秒。注意 mamba 成功后可以不卸载 conda,两者共存没有冲突。没有 mamba 的情况下,也可以手动删除环境重新建,重建时直接把所有依赖写进一条命令,减少多次求解带来的版本漂移。
5.3 读取数据时内存溢出或进程被系统杀掉
现象:加载整个 HDF 数据文件时,PyCharm 运行面板直接报 MemoryError,或者笔记本风扇狂转、进程消失。
原因:NILMTK 在调用DataSet时会把数据文件的时间索引加载进来,某些公开数据集是秒级采样,单周数据就有几十万行。如果一次性把整个文件导入并构建全屋电表对象,内存消耗能超过几个 GB。不是 NILMTK 有 bug,是加载粒度不对。
解决:读取数据在构建电表对象之前加时间窗口,先只截取一小段验证流程再扩展范围:
from nilmtk import DataSet dataset = DataSet('data/sample.h5') dataset.set_window(end='2013-01-08') elec = dataset.build_meters_dataframe()set_window(end=...)把数据范围限定在前八天内,内存占用骤降;build_meters_dataframe()只构建当前窗口对应的电表聚合数据。如果仍然内存紧张,就把窗口再缩小到两三天。等验证通过后,再逐步延长窗口,直到满足业务需求为止。另外在 PyCharm 里调大 VM 堆内存是这个问题的错觉,因为 NILMTK 跑在 Python 进程里,Python 进程不占用 JVM 堆内存,改的是 IDE 本身,对解决这个问题没有帮助,真正该做的是把数据切小或用 chunked 读取的方式。
5.4 PyCharm 里已经装了包,运行后仍找不到模块
现象:右侧 Project Interpreter 里能看到 nilmtk,在终端pip show nilmtk也有输出,但 PyCharm 运行脚本还是失败。
原因:PyCharm 的 Project Interpreter 展示的是解释器关联的包列表,如果你用的是 pyenv 或 venv 管理环境,很有可能会同时存在多个同名 Python。终端里的pip和 PyCharm 里解释器对应的pip指向不同 site-packages。此时pip install -e .可能装进了系统解释器,而 PyCharm 用的是另一个。
解决:在 PyCharm 里打开 Python Console,先执行:
import sys print(sys.executable)输出真实解释器路径,再在终端执行python -c "import sys; print(sys.executable)"对比两者。路径不一致时以 PyCharm 中的为准,回到终端用同一个路径的python -m pip install -e .重新安装。更稳妥的做法是删掉当前 Run 配置,新建一个,PyCharm 会自动套用项目解释器。这条排查流程对任何第三方库其实都通用,NILMTK 只是其中一个容易触发的案例。
6. 装完怎么验证:用 DataSet 加载数据并完成单设备功率统计
环境是否真正跑通,判断标准是能否用 NILMTK 完成一次“读文件 → 选窗口 → 构建电表 → 统计功率”的完整链路。只停留在 import 成功还不够,因为很多版本问题要在数据处理阶段才暴露。
我建议你在项目根目录新建validate_nilmtk.py,写入下面的代码:
from nilmtk import DataSet # 读取数据文件 dataset = DataSet('data/sample.h5') # 限定时间窗口,避免内存炸掉 dataset.set_window(end='2013-01-02') # 构建电表聚合数据 elec = dataset.build_meters_dataframe() # 取其中一路设备,比如冰箱回路代号 'fridge' appliance = elec['fridge'] power_series = appliance.power() print(power_series.describe()) dataset.close()这段脚本跑起来的标志性结果是 power_series 里能打印 count、mean 和 max 等统计量,说明 NILMTK 已能正确解析 HDF 结构,且时间对齐与插值逻辑没出问题。describe()里如果 count 为 0,多半是时间窗口与实际数据日期对不上,把 set_window 去掉或改成数据集真实覆盖的时间范围即可。
验证过程我一般按三步走。第一步,先要求 import 和 DataSet 构造均无异常输出,这是环境基础。第二步,set_window后构建电表数据,如果这里报内存错误说明窗口太大,缩小为一天。第三步,检查power_series里最大最小功率是否在合理范围,比如冰箱回路出现 1000W 的瞬时值,说明可能是数据对齐错误,需要回到 CSV 转 HDF 的步骤重新检查。
那次帮某开发者配置时,就是卡在第三步,冰箱回路里混入了整屋总功率,后来发现是转换时没有把插头接入点分配正确。从那以后,我每次搭完 NILMTK 环境都强制跑一遍这条验证链路,先看导入,再看窗口切片,最后看设备功率量纲,三步都通过我才放心交付。希望这套过程和坑位清单能帮到你,把你的 NILMTK 环境一次搭稳。
本文还有配套的精品资源,点击获取