goruck/nilm

Energy Management Using Real-Time Non-Intrusive Load Monitoring

Python

104

104 commits

updated Sep 8, 2025

See the code
deep-learning
edge-computing
energy-disaggregation
energy-management
nilm
tensorflow2
tensorflow-lite

See what people are saying (1)

README

Energy Management Using Real-Time Non-Intrusive Load Monitoring

Introduction

The goal of non-intrusive load monitoring (NILM) is to recover the energy consumption of individual appliances from the aggregate mains signal, which is a measure of the total electricity consumption of a building or house. NILM is also known as energy disaggregation and both terms will be used interchangeably throughout.

R. Gopinath, et al., nicely summarizes the rational behind NILM in the paper Energy management using non-intrusive load monitoring techniques — State- of-the-art and future research directions¹:

In recent years, the development of smart sustainable cities has become the primary focus among urban planners and policy makers to make responsible use of resources, conserve the environment and improve the well-being of the society. Energy management is an integral part of the smart sustainable cities development programme which involves conscious and efficient use of available energy resources towards attaining sustainability and self-reliance on energy systems. Building sector is one of the key sectors that utilize more energy. Therefore, efforts are being made to monitor and manage energy consumption effectively in residential and commercial buildings. In recent years, non-intrusive load monitoring (NILM) technique has become a popular and emerging approach to monitor events (on/off) and energy consumption of appliances/electrical utilities in buildings using single energy meter. The information about the energy consumption at the appliance level would help consumers to understand their appliance usage behavior and take necessary steps for reducing energy consumption.

By using deep learning models trained on publicly available datasets it is now feasible to enable NILM in very cost effective ways by leveraging commodity hardware and open source software. Deploying the trained models at the edge of the power grid, i.e. the building level, results in additional cost savings since it obviates the need for always connected internet cloud services which can be expensive at scale and running the algorithms in real-time provides for low latency operation.

This Project will show you how NILM works by taking you through the steps I used to implement a prototype system at my house.

Architecture

The following first two diagrams illustrate the NILM concept and process steps at a high level. The last diagram shows my prototype system which is based on these concepts and is implemented using Arduino- and Raspberry Pi-based compute.

Alt text

Alt text

Alt text

NILM Algorithm Selection and Models

Algorithm Selection

Energy disaggregation is a highly underdetermined and a single-channel Blind Source Separation (BSS) problem² which makes it difficult to obtain accurate predictions. Let $M$ be the number of household appliances and $i$ be the index referring to the $i$-th appliance. The aggregate power consumption $x$ at a given time $t$ is the sum of the power consumption of all appliances $M$, denoted by $y_i\forall{i=1,...,M}$. Therefore, the total power consumption $x$ at a given time $t$ can expressed by the equation below.

$$ x(t)=\sum_{i=1}^{M} y_i(t) + \epsilon_{\text{noise}}(t) $$

(1)

Where $\epsilon_{noise}$ is a noise term. The goal of this project is to solve the inverse problem and estimate the appliance power consumption $y_i$, given the aggregate power signal $x$, and to do so in a manner suitable for deployment at the edge.

Past approaches have included factorial hidden Markov models (FHMM)¹ and various event-based methods with some success⁶. You can also solve the single-channel BSS problem can by using sequence-to-sequence (seq2seq) learning with neural networks, and it can applied to the NILM problem using transformers, convolutional and recurrent neural networks³. Seq2seq learning involves training a neural network to map between an input time series, such as the aggregate power readings the case of NILM, and a output sequence, such as the estimated energy consumption of a single appliance. A sliding input window is typically used to training the network which generates a corresponding window of the output. This method produces multiple predictions for each appliance in the output so an average of the predictions is used for the final result. Some of the predictions will be more accurate than others, especially those near the midpoint of the input sliding window. The averaging will tend to lower the overall accuracy of the predictions.

Some of the disadvantages of of seq2seq leaning can mitigated by sequence-to-point learning (seq2point) for single-channel BSS⁴. You also use a sliding input signal window in this approach, however the network is trained to predict the output signal only at the midpoint of the window which makes the prediction problem easier on the network, leading to more accurate results.

I selected the seq2point learning approach for my prototype system and my implementation was inspired and guided by work described by Michele D'Incecco, Stefano Squartini and Mingjun Zhong⁵. I developed a variety of seq2point learning models using Tensorflow as shown in the Python module define_models.py but focussed my work on the models transformer and cnn.

Neural Network Models

The cnn model is depicted below for an input sequence length of 599 samples. The model generally follows traditional cnn concepts from vision use cases where several convolutional layers are used to extract features from the input power sequence at gradually finer details as the input traverses through the network. These features are the on-off patterns of the appliances as well as their power consumption levels. Max pooling is used to manage the complexity of the model after each convolutional layer. Finally, dense layers are used to output the final single point power consumption estimate for the window which is de-normalized before using in downstream processing. There are about 40 million parameters in this model using the default values.

Alt text

The transformer model is depicted below for an input sequence length of 599 samples where the transformer block is a Bert-style encoder. The input sequence is first passed through a convolutional layer to expand it into a latent space which is analogous to the feature extraction in the cnn model case. These features are pooled and L2 normalized to reduce model complexity and to mitigate the effects of outliers. Next, the sequence features are processed by a Bert-style transformer lineup which includes positional embedding and transformer blocks that applies importance weighting. The output of the encoder is decoded by several layers which are comprised of relative position embedding which applies symmetric weights around the mid-point of the signal, average pooling which reduces the sequence to a single value per feature and then finally dense layers that output the final single point estimated power value for the window which again is de-normalized for downstream processing. There are about six million parameters in this model using the default values.

Alt text

The Bert-style transformer encoder is depicted below.

Alt text

NILM Datasets

There are a number of large-scale publicly available datasets specifically designed to address the NILM problem which were captured in household buildings from various countries. The table⁷ below shows several of the most widely used.

Alt text

The datasets generally include many 10’s of millions of active power, reactive power, current, and voltage samples but with different sampling frequencies which requires you to pre-process the data before use. Most NILM algorithms utilize only real (aka active or true) power data. Five appliances are usually considered for energy disaggregation research which are kettle, microwave, fridge, dish washer and washing machine. These are the appliances I considered for my prototype and following the work of Michele DIncecco, et al.⁵, I mainly focused on the REFIT⁸ dataset but will eventually include UK-DALE and REDD.

Note that these datasets are typically very imbalanced because the majority of the time an appliance is in the off state.

Model Training and Results

I used TensorFlow to train and test the model. All code associated with this section can be found on the Machine Learning section of the project’s GitHub, NILM⁹. The seq2point learning models for the appliances were trained individually on z-score standardized REFIT data or normalized to $[0, P_m]$, where $P_m$ is the maximum power consumption of an appliance in its active state. Using normalized data tended to give the best model performance so it is used by default.

I used the following metrics to evaluate the model’s performance. You can view the code that calculates these metrics here.

  • Mean absolute error ($MAE$), which evaluates the absolute difference between the prediction and the ground truth power at every time point and calculates the mean value, as defined by the equation below.

$$ \mathrm{MAE}=\frac{1}{N}\sum_{i=1}^{N}\lvert \hat{x}_i - x_i\rvert $$

(2)

  • Normalized signal aggregate error ($SAE$), which indicates the relative error of the total energy. Denote $r$ as the total energy consumption of the appliance and $\hat{r}$ as the predicted total energy, then SAE is defined per the equation below.

$$ \mathrm{SAE}=\frac{\lvert \hat{r} - r\rvert}{r} $$

(3)

  • Energy per Day ($EpD$) which measures the predicted energy used in a day, useful when the household users are interested in the total energy consumed in a period. Denote $D$ as the total number of days and $e=\sum_{t}e_t$ as the appliance energy consumed in a day, then EpD is defined per the equation below.

$$ \mathrm{EpD}=\frac{1}{D}\sum_{n=1}^{D} e_n $$

(4)

  • Normalized disaggregation error ($NDE$) which measures the normalized error of the squared difference between the prediction and the ground truth power of the appliances, as defined by the equation below.

$$ \mathrm{NDE}=\frac{\sum_{i,t}\bigl(x_{i,t}-\hat{x}{i,t}\bigr)^2}{\sum{i,t} x_{i,t}^2} $$

(5)

I also used accuracy ($ACC$), F1-score ($F1$) and Matthew’s correlation coefficient ($MCC$) to assess if the model can perform well with the severely imbalanced datasets used to train and test the model. These metrics depend on the on-off status of the device and are computed using the parameters in the common.py module. $ACC$ is equal to the number of correctly predicted time points over the test dataset. $F1$ and $MCC$ are computed according to the equations below where $TP$ stands for true positives, $TN$ stands for true negatives, $FP$ stands for false positives and $FN$ stands for false negatives.

$$ F_1=\frac{TP}{TP+\frac{1}{2}(FP+FN)} $$

(6)

$$ \mathrm{MCC}=\frac{TN\cdot TP - FN\cdot FP}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}} $$

(7)

$MAE$, $SAE$, $NDE$ and $EpD_e$ (defined as $ 100% \times (EpD_{predicted} - EpD_{ground_truth}) / EpD_{ground_truth}$) reflect the model's ability to correctly predict the appliance energy consumption levels. $F1$ and $MCC$ indicates the model's ability to correctly predict appliance activations using imbalanced classes. $ACC$ is less useful in this application because most of the time the model will correctly predict the appliance is off which dominates the dataset.

A sliding window of 599 samples of the aggregate real power consumption signal is used as inputs to seq2point model and the midpoints of the corresponding windows of the appliances are used as targets. You can see how the samples and targets are generated by an instance of the WindowGenerator Class defined in the window_generator.py module.

You can see the code I used to train the model in train.py which uses the tf.distribute.MirroredStrategy() distributed training strategy. I used the Keras Adam optimizer and to reduce over-fitting, early stopping is used. The training code can be configured to train the seq2point model from scratch, or given a fitted model, prune it or fine tune it with quantization aware training (QAT), both of which can improve inference performance especially on edge hardware.

The key hyper-parameters for training and the optimizer are summarized below.

  • Input Window Size: 599 samples
  • Global Batch size: 1024 samples.
  • From scratch Learning Rate: 1e-04
  • QAT and Prune Learning Rate: 1e-05
  • Adam Optimizer: beta_1=0.9, beta_2=0.999, epsilon=1e-08.
  • Early Stopping Criteria: 6 epochs.

The loss function11 shown in the equation below is used to compute training gradients and to evaluate validation loss on a per-batch basis. It consists of a combination of Mean Squared Error, Binary Cross-Entropy and Mean Absolute Error losses, averaged over distributed model replica batches.

$$ L(x,s) = (\hat{x}-x)^{2} - [\hat{s}\log s + (1-\hat{s})\log(1-s)] + \lambda,|\hat{x}-x| $$

for $\hat{x} \in \mathcal{O}$. (8)

Where $x, \hat{x}\in[0, 1]$ are the ground truth and predicted power usage single point values divided by the maximum power limit per appliance and $s, \hat{s}\in\set{0, 1}$ are the appliance state label and prediction, and $O$ is the set of predictions when either the status label is on or the prediction is incorrect. The hyperparameter $\lambda$ tunes the absolute loss term on an a per-appliance basis.

You can find the training results for each appliance in the models folder. Typical performance metrics for the cnn model are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e\thinspace(%)\downarrow$
kettle0.73090.73460.99608.7880.22840.4696-22.85
microwave0.56710.56670.99337.5640.04600.8845-4.661
fridge0.79290.69420.864512.330.03730.41113.733
dishwasher0.60690.64830.98015.3670.03470.3742-3.473
washingmachine0.84780.84410.989314.750.29290.3470-29.29

Typical performance metrics for the transformer model are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e\thinspace(%)\downarrow$
kettle0.81770.81760.99677.2640.13480.376013.48
microwave0.65300.65060.99526.4280.14540.7496-14.54
fridge0.81380.72620.879911.020.05590.37435.590
dishwasher0.69140.71190.98735.3730.06900.3906-6.904
washingmachine0.84350.84200.988614.190.24400.2440-24.40

Average metrics across all appliances for both model architectures are compared in the table below.

Architecture$\overline{F1}\uparrow$$\overline{MCC}\uparrow$$\overline{ACC}\uparrow$$\overline{MAE}$ $(W)$ $\downarrow$$\overline{SAE}\downarrow$$\overline{NDE}\downarrow$$\overline{|EpD_e|}\thinspace(%)\downarrow$
cnn0.71610.70650.96439.8520.19570.452819.57
transformer0.76390.74970.96958.8550.12980.378112.98

You can see that the cnn and transformer models have similar performance even though the latter has about six times fewer parameters than the former. However, each transformer training step takes about seven times longer than cnn due to the transformer model's use of self-attention which has $O(n^2)$ complexity as compared to the cnn model's $O(n)$, where $n$ is the input sequence length. On the basis on training (and inference) efficiency, you can see that cnn is preferable with little loss in model performance.

You can find a variety of performance metrics in the literature to compare these results against, here are two examples. The middle column in the table5 below shows another cnn-based model's performance. You can see the results of this project compare very favorably.

Alt text

The table12 below shows the results from two transformer-based models (BERT4NILM and ELECTRIcity) and three other architectures. Although the data is incomplete, again this project's transformer-based model results compare favorably.

Alt text

Model Quantization

I performed Post-training quantization on the cnn and transformer models using the TensorFlow Lite converter API with various quantization modes to improve inference speed on edge hardware, including the Raspberry Pi and the Google Edge TPU, while mitigating the impact on accuracy. You can see the quantization modes I used in the table below.

ModeDescription
convert_onlyConvert to tflite but keep all parameters in Float32 (no quantization).
w8Quantize weights from float32 to int8 and biases to int64. Leave activations in Float32.
w8_a8_fallbackSame as w8 but quantize activations from float32 to int8. Fallback to float if an operator does not have an integer implementation.
w8_a8Same as w8 but quantize activations from float32 to int8. Enforce full int8 quantization for all operators.
w8_a16Same as w8 but quantize activations to int16.

The cnn model was quantized using all modes to understand the best tradeoff between latency and accuracy. Only the weights for the transformer model were quantized to int8 using mode w8, the activations needed to be kept in Float32 to maintain acceptable accuracy. See convert_keras_to_tflite.py for the code that does this quantization which also uses TensorFlow Lite's quantization debugger to check how well each layer in the model was quantized. I also profiled the converted models using the TensorFlow Lite Model Benchmark Tool to quantify inference latencies.

The quantized inference results are shown in the tables below, where $L_{x86}$ is the average inference latency on a 3.8 GHz x86 machine using eight tflite interpreter threads and $L_{arm}$ is the average inference latency on the ARM aarch-64-based Raspberry Pi 4 using four threads with both computers using the TensorFlow Lite XNNPACK CPU delegate. $L_{tpu}$ is the average inference latency on the Google Coral Edge TPU. Model inputs and outputs were keep in float32 to maximize inference speed for the x86- and ARM-based machines but were set to int8 for the edge tpu.

CNN Model Results and Discussion

The quantized results for the cnn models are shown in the table below for quantization mode w8.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.74280.74540.99667.3710.20130.4500-20.13743.9103809.41
microwave0.64000.63730.99337.9710.15780.7194-15.78736.5493586.55
fridge0.64910.50400.793517.780.09070.7000-8.971731.3713520.54
dishwasher0.51430.57870.97195.39550.05690.3647-5.694742.2793519.52
washingmachine0.88380.87910.991915.330.29300.3811-29.30751.8013515.68

The quantized results for the cnn kettle model are shown below for the other quantization modes.

Mode$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)$L_{tpu}$ (${\mu}s$)
convert_only0.71190.71990.99647.8120.28620.4780-28.65309.53112890.10NA
w8_a8_fallback0.65840.67360.99598.6770.37000.5448-36.70186.4833435.56NA
w8_a80.65840.67360.99608.7680.36700.5447-36.70185.4033258.1927777.8
w8_a160.74740.74790.99667.4310.15310.4516-15.315095.3824065.3NA

The quantized results for the cnn microwave model are shown below for the other quantization modes.

Mode$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)$L_{tpu}$ (${\mu}s$)
convert_only0.64100.63840.99337.9760.16300.7195-18.30302.75013055.3NA
w8_a8_fallback0.62680.62380.99318.0060.17960.7206-17.96187.2323458.30NA
w8_a80.62680.62380.99318.0050.17960.7206-17.96183.9103466.65100000
w8_a160.63910.63650.99337.9680.15900.7172-15.895100.7624052.0NA

Results for the other appliance models are omitted for brevity but show similar characteristics as a function of quantization mode.

You can see the negative impact of activation quantization but weight quantization, because of regularization effects, has a moderate benefit on some model performance metrics. As expected, the full quantization modes lead to the lowest latencies. Quantizing activations to int16 by the w8_a16 mode results in the highest latencies because only non-optimized reference kernel implementations are presently available in TensorFlow Lite but this scheme leads to the best model metrics given the regularization benefits from weight quantization and better preservation of activation numerics.

You can also see that inference latency of the modes follows w8 ${>}$ convert_only ${>}$ w8_a8 for the x86 machine but convert_only ${>}$ w8 ${>}$ w8_a8 for the aarch64 machine, although the variation is larger for x86. To better understand this, I profiled the converted models using the TFLite Model Benchmark Tool. A summary of the profiling results for the cnn microwave model are shown below which are representative of the other models.

Model Profiling on x86 (slowest to fastest)

You can see that the Fully Connected and Convolution operations are taking the longest to execute in all cases but are much faster in the fully quantized mode of w8_a8.

w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED20.39756.5527%56.5527%02
CONV_2D40.20429.0598%85.6125%04
Copy (NC X32)20.0517.26496%92.8775%09
Max Pooling (NHWC F32)10.0385.41311%98.2906%04
Convolution (NHWC F32) IGEMM10.0121.7094%100%01
Fully Connected (NC F32) GEMM100%100%01
EXPAND_DIMS900%100%09
convert_only node typecountavg_msavg %cdf %mem KBtimes called
Fully Connected (NC F32) GEMM30.15153.3569%53.3569%03
Convolution (NHWC F32) IGEMM10.06221.9081%75.265%05
Max Pooling (NHWC F32)10.03713.0742%88.3392%04
Copy (NC X32)10.03311.6608%100%09
EXPAND_DIMS900%100%09
w8_a8 node typecountavg_msavg %cdf %mem KBtimes called
Convolution (NHWC QC8) IGEMM10.06137.1951%37.1951%05
Fully Connected (NC QS8) GEMM30.03722.561%59.7561%03
Max Pooling (NHWC S8)10.03420.7317%80.4878%04
Copy (NC X8)10.03219.5122%100%09
EXPAND_DIMS900%100%09
Convert (NC QS8 F32)100%100%01
Convert (NC F32 QS8)100%100%01

Model Profiling on aarch64 (slowest to fastest)

You can see the copy and Max Pooling operations in particular are relatively slower on x86 than on aarch64 which is probably due to memory bandwidth and micro-architecture differences.

convert_only node typecountavg_msavg %cdf %mem KBtimes called
Copy (NC X32)134.83530.9136%30.9136%09
Convolution (NHWC F32) IGEMM132.41428.7651%59.6787%05
Max Pooling (NHWC F32)123.00820.418%80.0967%04
Fully Connected (NC F32) GEMM322.42519.9006%99.9973%03
EXPAND_DIMS90.0030.00266229%100%09
w8 node typecountavg_msavg %cdf %mem KBtimes called
Max Pooling (NHWC F32)142.28146.9085%46.9085%04
CONV_2D417.46119.3721%66.2806%04
Copy (NC X32)216.87718.7241%85.0047%09
Convolution (NHWC F32) IGEMM110.65811.8245%96.8292%01
FULLY_CONNECTED22.8473.1586%99.9878%02
Fully Connected (NC F32) GEMM10.0070.00776613%99.9956%01
EXPAND_DIMS90.0040.00443779%100%09
w8_a8 node typecountavg_msavg %cdf %mem KBtimes called
Copy (NC X8)134.68630.9647%30.9647%09
Convolution (NHWC QC8) IGEMM133.25929.6908%60.6554%05
Max Pooling (NHWC S8)123.92221.3555%82.0109%04
Fully Connected (NC QS8) GEMM320.14617.9846%99.9955%03
EXPAND_DIMS90.0020.00178543%99.9973%09
Convert (NC F32 QS8)10.0020.00178543%99.9991%01
Convert (NC QS8 F32)10.0010.000892714%100%01

Quantization Efficacy

The RMSE / scale is close to $1 / sqrt(12)$ (~ 0.289) when quantized distribution is similar to the original float distribution, indicating a well-quantized model. The larger the value is, it's more likely for the layer not being quantized well. The tables below show the RMSE / Scale metric for the cnn kettle and cnn washingmachine models and the Suspected? column indicates a layer that significantly exceeds 0.289. Other models are omitted for brevity but show similar results. These layers can remain in float to generate a selectively quantized model that increases accuracy at the expense of inference performance but doing so for the cnn models did not materially improve accuracy. See Inspecting Quantization Errors with Quantization Debugger.

Layer quantization efficacy metrics for the cnn kettle model using mode w8_a8 are shown below.

layerop_namerangermse/scaleSuspected?
0EXPAND_DIMS23.9299752.75E-01
1CONV_2D5.5180122.22E-01
2RESHAPE5.5180122.38E-06
3EXPAND_DIMS5.5180122.38E-06
4MAX_POOL_2D5.5180122.42E-06
5RESHAPE5.5180122.42E-06
6EXPAND_DIMS5.5180122.42E-06
7CONV_2D3.4945751.79E-01
8RESHAPE3.4945751.44E-06
9EXPAND_DIMS3.4945751.44E-06
10MAX_POOL_2D3.4945751.49E-06
11RESHAPE3.4945751.49E-06
12EXPAND_DIMS3.4945751.49E-06
13CONV_2D5.9109111.22E-01
14RESHAPE5.9109111.09E-06
15EXPAND_DIMS5.9109111.09E-06
16MAX_POOL_2D5.9109111.18E-06
17RESHAPE5.9109111.18E-06
18EXPAND_DIMS5.9109111.18E-06
19CONV_2D10.826711.00E-01
20RESHAPE10.826711.00E-06
21EXPAND_DIMS10.826711.00E-06
22MAX_POOL_2D10.826711.08E-06
23RESHAPE10.826711.08E-06
24EXPAND_DIMS10.826711.08E-06
25CONV_2D2.9876645.77E-02
26RESHAPE2.9876643.82E-07
27FULLY_CONNECTED1.7250321.20E+00Yes
28FULLY_CONNECTED1.5123426.19E-01
29FULLY_CONNECTED0.9908332.03E+00Yes

Layer quantization efficacy metrics for the cnn washingmachine model using mode w8_a8 are shown below.

layerop_namerangermse/scaleSuspected?
0EXPAND_DIMS30.9545473.00E-01
1CONV_2D12.6207011.81E-01
2RESHAPE12.6207011.56E-06
3EXPAND_DIMS12.6207011.56E-06
4MAX_POOL_2D12.6207011.67E-06
5RESHAPE12.6207011.67E-06
6EXPAND_DIMS12.6207011.67E-06
7CONV_2D15.0307761.94E-01
8RESHAPE15.0307761.94E-07
9EXPAND_DIMS15.0307761.94E-07
10MAX_POOL_2D15.0307762.36E-07
11RESHAPE15.0307762.36E-07
12EXPAND_DIMS15.0307762.36E-07
13CONV_2D10.1322361.68E-01
14RESHAPE10.1322361.83E-06
15EXPAND_DIMS10.1322361.83E-06
16MAX_POOL_2D10.1322362.06E-06
17RESHAPE10.1322362.06E-06
18EXPAND_DIMS10.1322362.06E-06
19CONV_2D9.0384371.45E-01
20RESHAPE9.0384371.90E-06
21EXPAND_DIMS9.0384371.90E-06
22MAX_POOL_2D9.0384372.20E-06
23RESHAPE9.0384372.20E-06
24EXPAND_DIMS9.0384372.20E-06
25CONV_2D5.1519329.58E-02
26RESHAPE5.1519321.08E-06
27FULLY_CONNECTED7.2693781.13E-01
28FULLY_CONNECTED3.791721.75E-01
29FULLY_CONNECTED1.1023789.51E-01Yes

Model Memory Footprint

I used the TFLite Model Benchmark Tool to get the approximate RAM consumption of the TFLite cnn microwave model at runtime which is shown in the table below for each quantization mode as well as the TFLite model disk space. The other cnn models show similar characteristics. The findings for the x86 architecture were identical to the arm architecture. Note that the Keras model consumes about 42.49 (MB) on disk. You can see that there is about a four times reduction in disk storage space due to the float32 to int8 weight conversions. Interestingly, RAM runtime usage varies considerably due to the TFLite algorithms that that optimize intermediate tensors usage. These are pre-allocated to reduce inference latency at the cost of memory space. See Optimizing TensorFlow Lite Runtime Memory.

Quant ModeDisk (MB)RAM (MB)
convert_only42.48504484.957
w810.64204012.7109
w8_a810.64801623.3633
w8_a1610.66098410.1836

Transformer Model Results and Discussion

Note that even though the XNNPACK delagate was enabled during transformer model inference evaluation nothing was actually accelerated because the transformer model contains dynamic tensors. The following warning is shown when using the TFLite interpreter for inference:

Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors (tensor#94 is a dynamic-sized tensor).

This means that all operators are unsupported by XNNPACK and will fall back to the default CPU kernel implementations. A future effort will involve refactoring the transformer model use only static-size tensors. Note that a tensor could be marked dynamic at TFLite runtime when there is a control-flow operation (e.g., if, while etc.) prepared. In other words, even when the model graph itself doesn't have any tensors of dynamic shapes statically, at runtime a model could have dynamic tensors. The current transformer model uses if control-flow operations.

The quantized results for the transformer model are shown in the table below for quantization mode w8.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.84600.84830.99775.1170.17610.2760-17.612052061939
microwave0.73750.73550.99526.9690.34350.6049-34.352090560823
fridge0.74370.62610.838114.520.08380.5518-8.5602098661862
dishwasher0.66710.69050.98606.2140.11170.4521-11.172098363432
washingmachine0.89100.88720.992615.080.37960.3442-37.962142660901

The quantized results for the transformer kettle and microwave models are shown in the table below for quantization mode convert_only.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.84600.84830.99775.1170.17610.2760-17.61710069746
microwave0.67190.67360.99487.0540.39300.6518-39.30705068667

Model Profiling on x86 (slowest to fastest)

w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1416.24379.5485%79.5485%014
ADD410.6673.26657%82.815%041
MUL420.6613.23718%86.0522%042
BATCH_MATMUL40.5822.85029%88.9025%04
TRANSPOSE200.5512.69847%91.601%020
RESHAPE480.3841.8806%93.4816%048
POW20.3711.81694%95.2985%02
SOFTMAX20.2020.989275%96.2878%02
MEAN130.1770.86684%97.1546%013
CONV_2D10.1520.744405%97.899%01
SQUARED_DIFFERENCE60.1190.582791%98.4818%06
TANH20.110.538714%99.0205%02
AVERAGE_POOL_2D10.0860.421176%99.4417%01
FILL140.0590.288947%99.7306%014
SQUARE10.0360.176306%99.9069%01
SQRT10.0190.0930506%100%01
SUB600%100%06
STRIDED_SLICE1400%100%014
SHAPE2400%100%024
RSQRT600%100%06
REDUCE_PROD1600%100%016
PACK2200%100%022
GATHER1600%100%016
EXPAND_DIMS200%100%02
CONCATENATION800%100%08
convert_only node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED142.21131.0447%31.0447%014
ADD411.34418.8711%49.9158%041
MUL420.6939.73041%59.6462%042
RESHAPE480.6198.69138%68.3375%048
BATCH_MATMUL40.5297.42769%75.7652%04
TRANSPOSE200.45.6164%81.3816%020
POW20.3945.53215%86.9138%02
MEAN130.2163.03286%89.9466%013
SOFTMAX20.1552.17636%92.123%02
SQUARED_DIFFERENCE60.1281.79725%93.9202%06
TANH20.1191.67088%95.5911%02
AVERAGE_POOL_2D10.1021.43218%97.0233%01
FILL140.0991.39006%98.4134%014
CONV_2D10.0510.716091%99.1294%01
SQUARE10.0370.519517%99.649%01
SQRT10.0250.351025%100%01
SUB600%100%06
STRIDED_SLICE1400%100%014
SHAPE2400%100%024
RSQRT600%100%06
REDUCE_PROD1600%100%016
PACK2200%100%022
GATHER1600%100%016
EXPAND_DIMS200%100%02
CONCATENATION800%100%08

Model Profiling on aarch64 (slowest to fastest)

convert_only node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1430.77744.8716%44.8716%014
MUL428.57112.4962%57.3678%042
ADD417.42510.8254%68.1931%041
POW25.3087.73885%75.932%02
BATCH_MATMUL43.825.56941%81.5014%04
TRANSPOSE203.3524.88708%86.3885%020
RESHAPE482.9274.26745%90.6559%048
TANH22.022.94508%93.601%02
SOFTMAX21.1821.72331%95.3243%02
MEAN130.9271.35153%96.6758%013
SQUARED_DIFFERENCE60.7611.10951%97.7854%06
AVERAGE_POOL_2D10.5170.753765%98.5391%01
SQUARE10.3260.475295%99.0144%01
CONV_2D10.2810.409687%99.4241%01
SQRT10.1480.215778%99.6399%01
PACK220.1050.153086%99.793%022
FILL140.0770.112263%99.9052%014
SUB60.0220.0320751%99.9373%06
RSQRT60.0220.0320751%99.9694%06
STRIDED_SLICE140.0120.0174955%99.9869%014
SHAPE240.0050.0072898%99.9942%024
EXPAND_DIMS20.0030.00437388%99.9985%02
CONCATENATION80.0010.00145796%100%08
REDUCE_PROD1600%100%016
GATHER1600%100%016
w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1422.75938.6283%38.6283%014
MUL427.71813.0996%51.7278%042
ADD416.95211.7994%63.5273%041
POW25.0748.61197%72.1392%02
BATCH_MATMUL43.7736.40382%78.5431%04
TRANSPOSE202.9825.06127%83.6043%020
RESHAPE482.9024.92549%88.5298%048
TANH21.953.30968%91.8395%02
SOFTMAX21.2222.07407%93.9136%02
MEAN130.911.54452%95.4581%013
SQUARED_DIFFERENCE60.791.34085%96.7989%06
CONV_2D10.6591.1185%97.9174%01
AVERAGE_POOL_2D10.480.814692%98.7321%01
SQUARE10.3590.609321%99.3414%01
SQRT10.1260.213857%99.5553%01
PACK220.1070.181608%99.7369%022
FILL140.0820.139176%99.8761%014
SUB60.0250.0424319%99.9185%06
RSQRT60.0230.0390373%99.9576%06
STRIDED_SLICE140.0130.0220646%99.9796%014
EXPAND_DIMS20.0050.00848637%99.9881%02
SHAPE240.0040.0067891%99.9949%024
GATHER160.0020.00339455%99.9983%016
CONCATENATION80.0010.00169727%100%08
REDUCE_PROD1600%100%016

Quantization Efficacy

Layer quantization efficacy metrics for the transformer kettle model using mode w8_a8 are shown in the table below, although as noted above quantizing the transformer model's activations results in very poor model performance. You can see the RSQRT operator in particular does not quantize well, these operators are used in the Gaussian error linear activation functions which helps explain the poor performance of the model. The other transformer appliance models show similar efficacy metrics.

layerop_namerangermse/scaleSuspect?
0EXPAND_DIMS23.9299750.2751951
1CONV_2D6.7934230.2952648
2RESHAPE12.0805460.1608947
3EXPAND_DIMS12.0805460
4AVERAGE_POOL_2D12.0805460
5ADD11.5981160.03801457
6RESHAPE3.4056010.0580239
7FILL10
8MUL0.4899790.2888043
9ADD3.727090.2890081
10FILL10
11FILL2E-060
12RESHAPE3.727090
13TRANSPOSE3.727090
14MEAN1.3714330.3178885
15SQUARED_DIFFERENCE4.452920.2296307
16MEAN0.5470540.2962779
17ADD0.5480540.4589049
18RSQRT15.74584841.5733Yes
19MUL15.7458480
20MUL9.6065490.3037147
21MUL2.3841170.2467738
22SUB2.3841171.428423E-06
23ADD8.7926540.3326802
24TRANSPOSE8.7926540
25RESHAPE8.7926540
26MUL8.6060960.2844383
27ADD8.6824710.2893911
28RESHAPE8.6824710
29FULLY_CONNECTED13.5893970.337322
30RESHAPE13.5893970
31ADD13.666590.2940356
32RESHAPE13.666590
33TRANSPOSE13.666590
34FULLY_CONNECTED16.0618660.3192651
35RESHAPE16.0618660
36ADD16.148240.2843503
37RESHAPE16.148240
38TRANSPOSE16.148240
39BATCH_MATMUL791.0610.2887679
40MUL69.9205721.274111E-06
41SOFTMAX0.9960940.1901133
42FULLY_CONNECTED15.3700910.3185204
43RESHAPE15.3700910
44ADD15.4205750.273666
45RESHAPE15.4205750
46TRANSPOSE15.4205750
47BATCH_MATMUL13.7882380.2886845
48TRANSPOSE13.7882380
49RESHAPE13.7882380
50RESHAPE13.7882380
51FULLY_CONNECTED13.1031680.3028338
52RESHAPE13.1031680
53ADD13.2293180.2886953
54ADD15.801880.288787
55FILL10
56FILL2E-060
57RESHAPE15.801880
58TRANSPOSE15.801880
59MEAN0.3454990.4923606
60SQUARED_DIFFERENCE63.2240750.2779759
61MEAN4.9313160.3027504
62ADD4.9323160.0311987
63RSQRT1.1958380.304619
64MUL1.1958380
65MUL10.5555070.2823485
66MUL0.2194670.4081438
67SUB0.2194672.18255E-06
68ADD10.5139150.2897937
69TRANSPOSE10.5139150
70RESHAPE10.5139150
71MUL11.1647260.2816773
72ADD11.1913460.2954707
73RESHAPE11.1913460
74FULLY_CONNECTED20.6551380.3090305
75RESHAPE20.6551380
76ADD20.6503910.3390533
77MUL99.8711660.2299994
78ADD120.5215530.2948375
79MUL96.1622759.767714E-07
80TANH1.9921880.2440195
81ADD20.2198295
82MUL10.3251960
83MUL9.7768290.4144
84RESHAPE9.7768290
85FULLY_CONNECTED83.5733430.2907445
86RESHAPE83.5733430
87ADD83.5955790.08025211
88ADD85.8043380.2887958
89FILL10
90FILL2E-060
91RESHAPE85.8043380
92TRANSPOSE85.8043380
93MEAN0.6711320.3675501
94SQUARED_DIFFERENCE2199.590730.2545643
95MEAN175.2618570.2906021
96ADD175.2628590.001332498
97RSQRT0.985917infYes
98MUL0.9859170
99MUL10.029120.2857049
100MUL0.1436550.2965899
101SUB0.1436551.620293E-06
102ADD10.0168860.273117
103TRANSPOSE10.0168860
104RESHAPE10.0168860
105MUL10.0616650.2678465
106ADD10.076550.2902205
107RESHAPE10.076550
108FULLY_CONNECTED24.4527020.305032
109RESHAPE24.4527020
110ADD24.4717230.2637686
111RESHAPE24.4717230
112TRANSPOSE24.4717230
113FULLY_CONNECTED24.6025280.3068753
114RESHAPE24.6025280
115ADD24.5248950.2782782
116RESHAPE24.5248950
117TRANSPOSE24.5248950
118BATCH_MATMUL2375.913540.2896734
119MUL210.0030572.292973E-06
120SOFTMAX0.9960940.05637038
121FULLY_CONNECTED20.0751730.3076454
122RESHAPE20.0751730
123ADD20.0757060.263613
124RESHAPE20.0757060
125TRANSPOSE20.0757060
126BATCH_MATMUL19.7015350.2828629
127TRANSPOSE19.7015350
128RESHAPE19.7015350
129RESHAPE19.7015350
130FULLY_CONNECTED93.7410010.2932989
131RESHAPE93.7410010
132ADD93.7548040.07540143
133ADD98.0717430.2887844
134FILL10
135FILL2E-060
136RESHAPE98.0717430
137TRANSPOSE98.0717430
138MEAN0.7337640.2978907
139SQUARED_DIFFERENCE2799.432840.2259659
140MEAN47.0610990.3333294
141ADD47.0620960.00378661
142RSQRT0.8873590.932645Yes
143MUL0.8873590
144MUL17.2518030.2807441
145MUL0.2723830.2891514
146SUB0.2723831.761181E-06
147ADD17.3112720.3122337
148TRANSPOSE17.3112720
149RESHAPE17.3112720
150MUL17.3474510.2828182
151ADD17.3474510.2636831
152RESHAPE17.3474510
153FULLY_CONNECTED18.3242110.3175219
154RESHAPE18.3242110
155ADD18.3434220.3259408
156MUL69.1358550.2440944
157ADD87.479280.2834869
158MUL69.7983634.807578E-07
159TANH1.9921880.3179474
160ADD20.2156563
161MUL9.1717110
162MUL9.5787540.2946312
163RESHAPE9.5787540
164FULLY_CONNECTED364.4675730.2889795
165RESHAPE364.4675730
166ADD364.4068580.01272385
167ADD371.9008480.2615761
168FILL10
169FILL2E-060
170RESHAPE371.9008480
171TRANSPOSE371.9008480
172MEAN5.6726590.3749806
173SQUARED_DIFFERENCE37128.262650.1978192
174MEAN2799.735270.2974154
175ADD2799.736297.520764E-05
176RSQRT0.991143infYes
177MUL0.9911430
178MUL14.4559022.44185Yes
179MUL0.35215714.605Yes
180SUB0.3521572.75764E-06
181ADD14.4789330.3361114
182TRANSPOSE14.4789330
183RESHAPE14.4789330
184MUL16.6851170.2978353
185ADD16.7037110.2075399
186FILL10
187MUL0.4242910.2876463
188ADD16.9331830.2892929
189FILL10
190FILL2E-060
191RESHAPE16.9331830
192TRANSPOSE16.9331830
193MEAN0.06233548.13572Yes
194SQUARED_DIFFERENCE85.6101050.2268296
195MEAN1.226184381.2859Yes
196ADD1.2271840.01558558
197RSQRT1.0944140.3163588
198MUL1.0944140
199MUL15.9616330.2128369
200MUL0.067050.2904581
201SUB0.067052.78254E-06
202ADD15.9498230.2522852
203TRANSPOSE15.9498230
204RESHAPE15.9498230
205MUL13.8851220.2597474
206ADD13.7800750.3595855
207MEAN4.1983990.3065109
208FULLY_CONNECTED2.4345570.3960356
209FULLY_CONNECTED0.7335579.714286Yes

Model Memory Footprint

Identical to the cnn case, I used the TFLite Model Benchmark Tool to get the approximate RAM consumption of the TFLite microwave model at runtime which is shown in the table below for each relevant quantization mode as well as the TFLite model disk space. The other transformer models show similar characteristics. Note that the Keras model consumes about 6.02 (MB) on disk. You can see that there is about a three times reduction in model size due to the weights being quantized from float32 to int8 which is less than the four times reduction seen in the cnn case likely because there are fewer layers with weights. You can also see that the x86 TFLite runtime is more memory efficient than its aarch64 counterpart for this model.

Quant ModeDisk (MB)aarch64 RAM (MB)x86 RAM (MB)
convert_only6.21727620.824216.8438
w82.08831216.425813.3789

NILM Prototype System Components

I built a NILM prototype at my home to test the energy disaggregation algorithms in real-world conditions and to understand where they can be improved. The prototype is comprised of the following main subsystems. You can see a photograph of the prototype in the Appendix.

Analog Signal Conditioning

I used two clip-on current transformers in one of the home’s sub-panels to sense the current flowing through each of split voltage phases and a voltage transformer plugged into an outlet near the circuit breaker panel that provides the voltage of one of the phases. These signals are level-shifted, amplified and low-passed filtered by this subsystem before being passed on to the analog-to-digital converters inside an Arduino MEGA 2560 that performs aggregate metrics computation. You can see a schematic for the Analog Signal Conditioning Subsystem in the Appendix and find more details in the Panel to Arduino section.

Aggregate Metrics Computation

I used an Arduino MEGA 2560 to host the signal processing algorithms that takes the voltage signals from the Analog Signal Conditioning Subsystem and generates aggregate RMS voltage, RMS current, Real Power and Apparent Power metrics in real-time. Presently, only Real Power is used in downstream processing. I leveraged emonLibCM10 for these signal processing algorithms. emonLibCM runs continuously in the background and digitizes the analog input channels of the Arduino, calculates these metrics and then informs the Arduino sketch that the measurements are available and should be read and processed by downstream processing. The sketch is configured to update the metrics every eight seconds and can be found in ard.ino

Disaggregated Energy Consumption Computation

The actual energy disaggregation computations are hosted on a Raspberry Pi 4 which is connected over USB to the Arduino to fetch the aggregate metrics. The computations are comprised of running the tflite appliance inference models, trained and quantized per the steps described above, with pre- and post-processing steps. See the infer.py module for the code that performs these computations. The inference models output predicted energy for each appliance from 599-sample sized windows of the aggregate real power input signal. These predictions and aggregate mains power are stored in a local CSV file and made available for downstream reporting and analysis.

Typical disaggregated energy prediction results from my home are shown in the plots and tables below using tflite models trained on another machine from the dataset as described above and quantized using mode 'w8'. Two sets of results are shown, the first is with no fine-tuning and second, with fine-tuning using local data via the program fine_tune.

In the plots below, the horizontal axis is datetime. The vertical axis is energy consumption in Watts. The first plot shows the aggregate mains power with each appliance in separate sub-plots. Ground truth power was obtained by logging appliance power data in real-time at the outlet. The second plat shows aggregate mains power and appliance power plotted together and the last plot is a zoomed-in area of the second plot. These plots and the metrics that follow are generated by the program predict.

Alt text

Alt text

Alt text

NILM metrics were computed for the Float32 predictions on aggregate mains data that was captured in real-time and for the quantized model real-time predictions, both vs ground truth.

The Float32 model trained on the default dataset predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.0NaN0.99181.659INF0.9999INF
microwave0.53190.54060.99614.2610.03020.8198-3.018
fridge0.68750.46720.741436.590.24580.7494-24.56
dishwasher0.23720.21650.959612.740.95860.9615-95.62
washingmachine0.66610.66960.97497.5960.22131.407-23.97

The corresponding quantized model real-time predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.0NaN0.99862.873INF1.594INF
microwave0.52580.53530.99614.2370.01880.8208-1.880
fridge0.62570.40020.712539.520.36680.8189-36.65
dishwasher0.25710.23540.946914.700.95570.9558-95.57
washingmachine0.67600.68270.97587.5600.24011.393-24.01

You can see that model performance is comparable between the Float32 and real-time quantized results but overall they are poor with microwave being the exception. This indicates that the models can benefit from fine tuning with the ground truth data.

The Float32 model fine-tuned with local data predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.62050.66720.99587.8080.57160.5555-57.16
microwave0.49890.51290.991210.5080.65430.6795-65.43
fridge0.82860.66650.831224.7050.25020.3717-25.02
dishwasher0.76070.74910.954421.9110.46020.3957-46.02
washingmachine0.91550.91380.99053.2880.11560.3535-11.56

The corresponding quantized model real-time predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.58450.63450.99558.1990.59180.5954-59.18
microwave0.52210.51960.990410.7220.57810.6574-57.81
fridge0.83510.67580.836726.1370.24770.3603-24.27
dishwasher0.61880.62300.908323.5060.23130.3414-23.13
washingmachine0.71030.72570.95853.9100.24540.340924.54

You can see that fine-tuning the model with local data greatly improves its performance.

Amazon Alexa

I plan to use Amazon Alexa as the user interface to the appliance energy data, however this work is not yet started.

Conclusion

By using large publicly available datasets to train seq2point learning models it is very feasible to perform energy disaggregation that is fairly accurate without fine-tuning the models with local data. These models are modest in size and with little loss in accuracy can be quantized to run efficiently on commodity edge hardware such as the Raspberry Pi 4. More work needs to be done to further improve the accuracy of the models and to test with more appliance types. This project demonstrates that a key component of a sustainable and scalable power grid is within reach of the mass consumer market.

References

  1. Sustainable Cities and Society 62 (2020) 102411 | Energy management using non-intrusive load monitoring techniques — State- of-the-art and future research directions by R. Gopinath, Mukesh Kumar, C. Prakash Chandra Joshua and Kota Srinivas.
  2. Wikipedia | Signal Separation.
  3. arXiv:1507.06594 | Neural NILM: Deep Neural Networks Applied to Energy Disaggregation by Jack Kelly and William Knottenbelt.
  4. arXiv:1612.09106 | Sequence-to-point learning with neural networks for non-intrusive load monitoring by Chaoyun Zhang, Mingjun Zhong, Zongzuo Wang, Nigel Goddard and Charles Sutton.
  5. arXiv:1902.08835 | Transfer Learning for Non-Intrusive Load Monitoring by Michele D'Incecco, Stefano Squartini and Mingjun Zhong.
  6. Artificial Intelligence Techniques for a Scalable Energy Transition pp 109–131 | A Review on Non-intrusive Load Monitoring Approaches Based on Machine Learning by Hajer Salem, Moamar Sayed-Mouchaweh and Moncef Tagina.
  7. 1st International Symposium on Signal Processing Applications in Smart Buildings at 3rd IEEE Global Conference on Signal & Information Processing | Dataport and NILMTK: A Building Data Set Designed for Non-intrusive Load Monitoring by Oliver Parson, Grant Fisher, April Hersey, Nipun Batra, Jack Kelly, Amarjeet Singh, William Knottenbelt and Alex Rogers.
  8. Proceedings of the 8th International Conference on Energy Efficiency in Domestic Appliances and Lighting | A data management platform for personalised real-time energy feedback by David Murray and Jing Liao and Lina Stankovic and Vladimir Stankovic and Richard Hauxwell-Baldwin and Charlie Wilson and Michael Coleman and Tom Kane and Steven Firth. The REFIT dataset used in this project is is licensed under the Creative Commons Attribution 4.0 International Public License.
  9. GitHub | NILM by Lindo St. Angel
  10. GitHub | EmonLibCM by Trystan Lea, Glyn Hudson, Brian Orpin and Ivan Kravets.
  11. BERT4NILM: A Bidirectional Transformer Model for Non-Intrusive Load Monitoring by Zhenrui Yue, et. al.
  12. ELECTRIcity: An Efficient Transformer for Non-Intrusive Load Monitoring by Stavros Sykiotis, Maria Kaselimi ,Anastasios Doulamis and Nikolaos Doulamis.

Please also see this project's companion Medium article Energy Management Using Real-Time Non-Intrusive Load Monitoring.

Appendix

Photograph of Prototype

A photograph of an early version of my prototype system is shown below.

Alt text

Analog Signal Conditioning Schematic

The schematic for the Analog Signal Conditioning circuitry is shown below.

Alt text

Contributors

goruck

104 commits

goruck/nilm

Energy Management Using Real-Time Non-Intrusive Load Monitoring

Python

104

104 commits

updated Sep 8, 2025

See the code
deep-learning
edge-computing
energy-disaggregation
energy-management
nilm
tensorflow2
tensorflow-lite

See what people are saying (1)

README

Energy Management Using Real-Time Non-Intrusive Load Monitoring

Introduction

The goal of non-intrusive load monitoring (NILM) is to recover the energy consumption of individual appliances from the aggregate mains signal, which is a measure of the total electricity consumption of a building or house. NILM is also known as energy disaggregation and both terms will be used interchangeably throughout.

R. Gopinath, et al., nicely summarizes the rational behind NILM in the paper Energy management using non-intrusive load monitoring techniques — State- of-the-art and future research directions¹:

In recent years, the development of smart sustainable cities has become the primary focus among urban planners and policy makers to make responsible use of resources, conserve the environment and improve the well-being of the society. Energy management is an integral part of the smart sustainable cities development programme which involves conscious and efficient use of available energy resources towards attaining sustainability and self-reliance on energy systems. Building sector is one of the key sectors that utilize more energy. Therefore, efforts are being made to monitor and manage energy consumption effectively in residential and commercial buildings. In recent years, non-intrusive load monitoring (NILM) technique has become a popular and emerging approach to monitor events (on/off) and energy consumption of appliances/electrical utilities in buildings using single energy meter. The information about the energy consumption at the appliance level would help consumers to understand their appliance usage behavior and take necessary steps for reducing energy consumption.

By using deep learning models trained on publicly available datasets it is now feasible to enable NILM in very cost effective ways by leveraging commodity hardware and open source software. Deploying the trained models at the edge of the power grid, i.e. the building level, results in additional cost savings since it obviates the need for always connected internet cloud services which can be expensive at scale and running the algorithms in real-time provides for low latency operation.

This Project will show you how NILM works by taking you through the steps I used to implement a prototype system at my house.

Architecture

The following first two diagrams illustrate the NILM concept and process steps at a high level. The last diagram shows my prototype system which is based on these concepts and is implemented using Arduino- and Raspberry Pi-based compute.

Alt text

Alt text

Alt text

NILM Algorithm Selection and Models

Algorithm Selection

Energy disaggregation is a highly underdetermined and a single-channel Blind Source Separation (BSS) problem² which makes it difficult to obtain accurate predictions. Let $M$ be the number of household appliances and $i$ be the index referring to the $i$-th appliance. The aggregate power consumption $x$ at a given time $t$ is the sum of the power consumption of all appliances $M$, denoted by $y_i\forall{i=1,...,M}$. Therefore, the total power consumption $x$ at a given time $t$ can expressed by the equation below.

$$ x(t)=\sum_{i=1}^{M} y_i(t) + \epsilon_{\text{noise}}(t) $$

(1)

Where $\epsilon_{noise}$ is a noise term. The goal of this project is to solve the inverse problem and estimate the appliance power consumption $y_i$, given the aggregate power signal $x$, and to do so in a manner suitable for deployment at the edge.

Past approaches have included factorial hidden Markov models (FHMM)¹ and various event-based methods with some success⁶. You can also solve the single-channel BSS problem can by using sequence-to-sequence (seq2seq) learning with neural networks, and it can applied to the NILM problem using transformers, convolutional and recurrent neural networks³. Seq2seq learning involves training a neural network to map between an input time series, such as the aggregate power readings the case of NILM, and a output sequence, such as the estimated energy consumption of a single appliance. A sliding input window is typically used to training the network which generates a corresponding window of the output. This method produces multiple predictions for each appliance in the output so an average of the predictions is used for the final result. Some of the predictions will be more accurate than others, especially those near the midpoint of the input sliding window. The averaging will tend to lower the overall accuracy of the predictions.

Some of the disadvantages of of seq2seq leaning can mitigated by sequence-to-point learning (seq2point) for single-channel BSS⁴. You also use a sliding input signal window in this approach, however the network is trained to predict the output signal only at the midpoint of the window which makes the prediction problem easier on the network, leading to more accurate results.

I selected the seq2point learning approach for my prototype system and my implementation was inspired and guided by work described by Michele D'Incecco, Stefano Squartini and Mingjun Zhong⁵. I developed a variety of seq2point learning models using Tensorflow as shown in the Python module define_models.py but focussed my work on the models transformer and cnn.

Neural Network Models

The cnn model is depicted below for an input sequence length of 599 samples. The model generally follows traditional cnn concepts from vision use cases where several convolutional layers are used to extract features from the input power sequence at gradually finer details as the input traverses through the network. These features are the on-off patterns of the appliances as well as their power consumption levels. Max pooling is used to manage the complexity of the model after each convolutional layer. Finally, dense layers are used to output the final single point power consumption estimate for the window which is de-normalized before using in downstream processing. There are about 40 million parameters in this model using the default values.

Alt text

The transformer model is depicted below for an input sequence length of 599 samples where the transformer block is a Bert-style encoder. The input sequence is first passed through a convolutional layer to expand it into a latent space which is analogous to the feature extraction in the cnn model case. These features are pooled and L2 normalized to reduce model complexity and to mitigate the effects of outliers. Next, the sequence features are processed by a Bert-style transformer lineup which includes positional embedding and transformer blocks that applies importance weighting. The output of the encoder is decoded by several layers which are comprised of relative position embedding which applies symmetric weights around the mid-point of the signal, average pooling which reduces the sequence to a single value per feature and then finally dense layers that output the final single point estimated power value for the window which again is de-normalized for downstream processing. There are about six million parameters in this model using the default values.

Alt text

The Bert-style transformer encoder is depicted below.

Alt text

NILM Datasets

There are a number of large-scale publicly available datasets specifically designed to address the NILM problem which were captured in household buildings from various countries. The table⁷ below shows several of the most widely used.

Alt text

The datasets generally include many 10’s of millions of active power, reactive power, current, and voltage samples but with different sampling frequencies which requires you to pre-process the data before use. Most NILM algorithms utilize only real (aka active or true) power data. Five appliances are usually considered for energy disaggregation research which are kettle, microwave, fridge, dish washer and washing machine. These are the appliances I considered for my prototype and following the work of Michele DIncecco, et al.⁵, I mainly focused on the REFIT⁸ dataset but will eventually include UK-DALE and REDD.

Note that these datasets are typically very imbalanced because the majority of the time an appliance is in the off state.

Model Training and Results

I used TensorFlow to train and test the model. All code associated with this section can be found on the Machine Learning section of the project’s GitHub, NILM⁹. The seq2point learning models for the appliances were trained individually on z-score standardized REFIT data or normalized to $[0, P_m]$, where $P_m$ is the maximum power consumption of an appliance in its active state. Using normalized data tended to give the best model performance so it is used by default.

I used the following metrics to evaluate the model’s performance. You can view the code that calculates these metrics here.

  • Mean absolute error ($MAE$), which evaluates the absolute difference between the prediction and the ground truth power at every time point and calculates the mean value, as defined by the equation below.

$$ \mathrm{MAE}=\frac{1}{N}\sum_{i=1}^{N}\lvert \hat{x}_i - x_i\rvert $$

(2)

  • Normalized signal aggregate error ($SAE$), which indicates the relative error of the total energy. Denote $r$ as the total energy consumption of the appliance and $\hat{r}$ as the predicted total energy, then SAE is defined per the equation below.

$$ \mathrm{SAE}=\frac{\lvert \hat{r} - r\rvert}{r} $$

(3)

  • Energy per Day ($EpD$) which measures the predicted energy used in a day, useful when the household users are interested in the total energy consumed in a period. Denote $D$ as the total number of days and $e=\sum_{t}e_t$ as the appliance energy consumed in a day, then EpD is defined per the equation below.

$$ \mathrm{EpD}=\frac{1}{D}\sum_{n=1}^{D} e_n $$

(4)

  • Normalized disaggregation error ($NDE$) which measures the normalized error of the squared difference between the prediction and the ground truth power of the appliances, as defined by the equation below.

$$ \mathrm{NDE}=\frac{\sum_{i,t}\bigl(x_{i,t}-\hat{x}{i,t}\bigr)^2}{\sum{i,t} x_{i,t}^2} $$

(5)

I also used accuracy ($ACC$), F1-score ($F1$) and Matthew’s correlation coefficient ($MCC$) to assess if the model can perform well with the severely imbalanced datasets used to train and test the model. These metrics depend on the on-off status of the device and are computed using the parameters in the common.py module. $ACC$ is equal to the number of correctly predicted time points over the test dataset. $F1$ and $MCC$ are computed according to the equations below where $TP$ stands for true positives, $TN$ stands for true negatives, $FP$ stands for false positives and $FN$ stands for false negatives.

$$ F_1=\frac{TP}{TP+\frac{1}{2}(FP+FN)} $$

(6)

$$ \mathrm{MCC}=\frac{TN\cdot TP - FN\cdot FP}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}} $$

(7)

$MAE$, $SAE$, $NDE$ and $EpD_e$ (defined as $ 100% \times (EpD_{predicted} - EpD_{ground_truth}) / EpD_{ground_truth}$) reflect the model's ability to correctly predict the appliance energy consumption levels. $F1$ and $MCC$ indicates the model's ability to correctly predict appliance activations using imbalanced classes. $ACC$ is less useful in this application because most of the time the model will correctly predict the appliance is off which dominates the dataset.

A sliding window of 599 samples of the aggregate real power consumption signal is used as inputs to seq2point model and the midpoints of the corresponding windows of the appliances are used as targets. You can see how the samples and targets are generated by an instance of the WindowGenerator Class defined in the window_generator.py module.

You can see the code I used to train the model in train.py which uses the tf.distribute.MirroredStrategy() distributed training strategy. I used the Keras Adam optimizer and to reduce over-fitting, early stopping is used. The training code can be configured to train the seq2point model from scratch, or given a fitted model, prune it or fine tune it with quantization aware training (QAT), both of which can improve inference performance especially on edge hardware.

The key hyper-parameters for training and the optimizer are summarized below.

  • Input Window Size: 599 samples
  • Global Batch size: 1024 samples.
  • From scratch Learning Rate: 1e-04
  • QAT and Prune Learning Rate: 1e-05
  • Adam Optimizer: beta_1=0.9, beta_2=0.999, epsilon=1e-08.
  • Early Stopping Criteria: 6 epochs.

The loss function11 shown in the equation below is used to compute training gradients and to evaluate validation loss on a per-batch basis. It consists of a combination of Mean Squared Error, Binary Cross-Entropy and Mean Absolute Error losses, averaged over distributed model replica batches.

$$ L(x,s) = (\hat{x}-x)^{2} - [\hat{s}\log s + (1-\hat{s})\log(1-s)] + \lambda,|\hat{x}-x| $$

for $\hat{x} \in \mathcal{O}$. (8)

Where $x, \hat{x}\in[0, 1]$ are the ground truth and predicted power usage single point values divided by the maximum power limit per appliance and $s, \hat{s}\in\set{0, 1}$ are the appliance state label and prediction, and $O$ is the set of predictions when either the status label is on or the prediction is incorrect. The hyperparameter $\lambda$ tunes the absolute loss term on an a per-appliance basis.

You can find the training results for each appliance in the models folder. Typical performance metrics for the cnn model are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e\thinspace(%)\downarrow$
kettle0.73090.73460.99608.7880.22840.4696-22.85
microwave0.56710.56670.99337.5640.04600.8845-4.661
fridge0.79290.69420.864512.330.03730.41113.733
dishwasher0.60690.64830.98015.3670.03470.3742-3.473
washingmachine0.84780.84410.989314.750.29290.3470-29.29

Typical performance metrics for the transformer model are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e\thinspace(%)\downarrow$
kettle0.81770.81760.99677.2640.13480.376013.48
microwave0.65300.65060.99526.4280.14540.7496-14.54
fridge0.81380.72620.879911.020.05590.37435.590
dishwasher0.69140.71190.98735.3730.06900.3906-6.904
washingmachine0.84350.84200.988614.190.24400.2440-24.40

Average metrics across all appliances for both model architectures are compared in the table below.

Architecture$\overline{F1}\uparrow$$\overline{MCC}\uparrow$$\overline{ACC}\uparrow$$\overline{MAE}$ $(W)$ $\downarrow$$\overline{SAE}\downarrow$$\overline{NDE}\downarrow$$\overline{|EpD_e|}\thinspace(%)\downarrow$
cnn0.71610.70650.96439.8520.19570.452819.57
transformer0.76390.74970.96958.8550.12980.378112.98

You can see that the cnn and transformer models have similar performance even though the latter has about six times fewer parameters than the former. However, each transformer training step takes about seven times longer than cnn due to the transformer model's use of self-attention which has $O(n^2)$ complexity as compared to the cnn model's $O(n)$, where $n$ is the input sequence length. On the basis on training (and inference) efficiency, you can see that cnn is preferable with little loss in model performance.

You can find a variety of performance metrics in the literature to compare these results against, here are two examples. The middle column in the table5 below shows another cnn-based model's performance. You can see the results of this project compare very favorably.

Alt text

The table12 below shows the results from two transformer-based models (BERT4NILM and ELECTRIcity) and three other architectures. Although the data is incomplete, again this project's transformer-based model results compare favorably.

Alt text

Model Quantization

I performed Post-training quantization on the cnn and transformer models using the TensorFlow Lite converter API with various quantization modes to improve inference speed on edge hardware, including the Raspberry Pi and the Google Edge TPU, while mitigating the impact on accuracy. You can see the quantization modes I used in the table below.

ModeDescription
convert_onlyConvert to tflite but keep all parameters in Float32 (no quantization).
w8Quantize weights from float32 to int8 and biases to int64. Leave activations in Float32.
w8_a8_fallbackSame as w8 but quantize activations from float32 to int8. Fallback to float if an operator does not have an integer implementation.
w8_a8Same as w8 but quantize activations from float32 to int8. Enforce full int8 quantization for all operators.
w8_a16Same as w8 but quantize activations to int16.

The cnn model was quantized using all modes to understand the best tradeoff between latency and accuracy. Only the weights for the transformer model were quantized to int8 using mode w8, the activations needed to be kept in Float32 to maintain acceptable accuracy. See convert_keras_to_tflite.py for the code that does this quantization which also uses TensorFlow Lite's quantization debugger to check how well each layer in the model was quantized. I also profiled the converted models using the TensorFlow Lite Model Benchmark Tool to quantify inference latencies.

The quantized inference results are shown in the tables below, where $L_{x86}$ is the average inference latency on a 3.8 GHz x86 machine using eight tflite interpreter threads and $L_{arm}$ is the average inference latency on the ARM aarch-64-based Raspberry Pi 4 using four threads with both computers using the TensorFlow Lite XNNPACK CPU delegate. $L_{tpu}$ is the average inference latency on the Google Coral Edge TPU. Model inputs and outputs were keep in float32 to maximize inference speed for the x86- and ARM-based machines but were set to int8 for the edge tpu.

CNN Model Results and Discussion

The quantized results for the cnn models are shown in the table below for quantization mode w8.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.74280.74540.99667.3710.20130.4500-20.13743.9103809.41
microwave0.64000.63730.99337.9710.15780.7194-15.78736.5493586.55
fridge0.64910.50400.793517.780.09070.7000-8.971731.3713520.54
dishwasher0.51430.57870.97195.39550.05690.3647-5.694742.2793519.52
washingmachine0.88380.87910.991915.330.29300.3811-29.30751.8013515.68

The quantized results for the cnn kettle model are shown below for the other quantization modes.

Mode$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)$L_{tpu}$ (${\mu}s$)
convert_only0.71190.71990.99647.8120.28620.4780-28.65309.53112890.10NA
w8_a8_fallback0.65840.67360.99598.6770.37000.5448-36.70186.4833435.56NA
w8_a80.65840.67360.99608.7680.36700.5447-36.70185.4033258.1927777.8
w8_a160.74740.74790.99667.4310.15310.4516-15.315095.3824065.3NA

The quantized results for the cnn microwave model are shown below for the other quantization modes.

Mode$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)$L_{tpu}$ (${\mu}s$)
convert_only0.64100.63840.99337.9760.16300.7195-18.30302.75013055.3NA
w8_a8_fallback0.62680.62380.99318.0060.17960.7206-17.96187.2323458.30NA
w8_a80.62680.62380.99318.0050.17960.7206-17.96183.9103466.65100000
w8_a160.63910.63650.99337.9680.15900.7172-15.895100.7624052.0NA

Results for the other appliance models are omitted for brevity but show similar characteristics as a function of quantization mode.

You can see the negative impact of activation quantization but weight quantization, because of regularization effects, has a moderate benefit on some model performance metrics. As expected, the full quantization modes lead to the lowest latencies. Quantizing activations to int16 by the w8_a16 mode results in the highest latencies because only non-optimized reference kernel implementations are presently available in TensorFlow Lite but this scheme leads to the best model metrics given the regularization benefits from weight quantization and better preservation of activation numerics.

You can also see that inference latency of the modes follows w8 ${>}$ convert_only ${>}$ w8_a8 for the x86 machine but convert_only ${>}$ w8 ${>}$ w8_a8 for the aarch64 machine, although the variation is larger for x86. To better understand this, I profiled the converted models using the TFLite Model Benchmark Tool. A summary of the profiling results for the cnn microwave model are shown below which are representative of the other models.

Model Profiling on x86 (slowest to fastest)

You can see that the Fully Connected and Convolution operations are taking the longest to execute in all cases but are much faster in the fully quantized mode of w8_a8.

w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED20.39756.5527%56.5527%02
CONV_2D40.20429.0598%85.6125%04
Copy (NC X32)20.0517.26496%92.8775%09
Max Pooling (NHWC F32)10.0385.41311%98.2906%04
Convolution (NHWC F32) IGEMM10.0121.7094%100%01
Fully Connected (NC F32) GEMM100%100%01
EXPAND_DIMS900%100%09
convert_only node typecountavg_msavg %cdf %mem KBtimes called
Fully Connected (NC F32) GEMM30.15153.3569%53.3569%03
Convolution (NHWC F32) IGEMM10.06221.9081%75.265%05
Max Pooling (NHWC F32)10.03713.0742%88.3392%04
Copy (NC X32)10.03311.6608%100%09
EXPAND_DIMS900%100%09
w8_a8 node typecountavg_msavg %cdf %mem KBtimes called
Convolution (NHWC QC8) IGEMM10.06137.1951%37.1951%05
Fully Connected (NC QS8) GEMM30.03722.561%59.7561%03
Max Pooling (NHWC S8)10.03420.7317%80.4878%04
Copy (NC X8)10.03219.5122%100%09
EXPAND_DIMS900%100%09
Convert (NC QS8 F32)100%100%01
Convert (NC F32 QS8)100%100%01

Model Profiling on aarch64 (slowest to fastest)

You can see the copy and Max Pooling operations in particular are relatively slower on x86 than on aarch64 which is probably due to memory bandwidth and micro-architecture differences.

convert_only node typecountavg_msavg %cdf %mem KBtimes called
Copy (NC X32)134.83530.9136%30.9136%09
Convolution (NHWC F32) IGEMM132.41428.7651%59.6787%05
Max Pooling (NHWC F32)123.00820.418%80.0967%04
Fully Connected (NC F32) GEMM322.42519.9006%99.9973%03
EXPAND_DIMS90.0030.00266229%100%09
w8 node typecountavg_msavg %cdf %mem KBtimes called
Max Pooling (NHWC F32)142.28146.9085%46.9085%04
CONV_2D417.46119.3721%66.2806%04
Copy (NC X32)216.87718.7241%85.0047%09
Convolution (NHWC F32) IGEMM110.65811.8245%96.8292%01
FULLY_CONNECTED22.8473.1586%99.9878%02
Fully Connected (NC F32) GEMM10.0070.00776613%99.9956%01
EXPAND_DIMS90.0040.00443779%100%09
w8_a8 node typecountavg_msavg %cdf %mem KBtimes called
Copy (NC X8)134.68630.9647%30.9647%09
Convolution (NHWC QC8) IGEMM133.25929.6908%60.6554%05
Max Pooling (NHWC S8)123.92221.3555%82.0109%04
Fully Connected (NC QS8) GEMM320.14617.9846%99.9955%03
EXPAND_DIMS90.0020.00178543%99.9973%09
Convert (NC F32 QS8)10.0020.00178543%99.9991%01
Convert (NC QS8 F32)10.0010.000892714%100%01

Quantization Efficacy

The RMSE / scale is close to $1 / sqrt(12)$ (~ 0.289) when quantized distribution is similar to the original float distribution, indicating a well-quantized model. The larger the value is, it's more likely for the layer not being quantized well. The tables below show the RMSE / Scale metric for the cnn kettle and cnn washingmachine models and the Suspected? column indicates a layer that significantly exceeds 0.289. Other models are omitted for brevity but show similar results. These layers can remain in float to generate a selectively quantized model that increases accuracy at the expense of inference performance but doing so for the cnn models did not materially improve accuracy. See Inspecting Quantization Errors with Quantization Debugger.

Layer quantization efficacy metrics for the cnn kettle model using mode w8_a8 are shown below.

layerop_namerangermse/scaleSuspected?
0EXPAND_DIMS23.9299752.75E-01
1CONV_2D5.5180122.22E-01
2RESHAPE5.5180122.38E-06
3EXPAND_DIMS5.5180122.38E-06
4MAX_POOL_2D5.5180122.42E-06
5RESHAPE5.5180122.42E-06
6EXPAND_DIMS5.5180122.42E-06
7CONV_2D3.4945751.79E-01
8RESHAPE3.4945751.44E-06
9EXPAND_DIMS3.4945751.44E-06
10MAX_POOL_2D3.4945751.49E-06
11RESHAPE3.4945751.49E-06
12EXPAND_DIMS3.4945751.49E-06
13CONV_2D5.9109111.22E-01
14RESHAPE5.9109111.09E-06
15EXPAND_DIMS5.9109111.09E-06
16MAX_POOL_2D5.9109111.18E-06
17RESHAPE5.9109111.18E-06
18EXPAND_DIMS5.9109111.18E-06
19CONV_2D10.826711.00E-01
20RESHAPE10.826711.00E-06
21EXPAND_DIMS10.826711.00E-06
22MAX_POOL_2D10.826711.08E-06
23RESHAPE10.826711.08E-06
24EXPAND_DIMS10.826711.08E-06
25CONV_2D2.9876645.77E-02
26RESHAPE2.9876643.82E-07
27FULLY_CONNECTED1.7250321.20E+00Yes
28FULLY_CONNECTED1.5123426.19E-01
29FULLY_CONNECTED0.9908332.03E+00Yes

Layer quantization efficacy metrics for the cnn washingmachine model using mode w8_a8 are shown below.

layerop_namerangermse/scaleSuspected?
0EXPAND_DIMS30.9545473.00E-01
1CONV_2D12.6207011.81E-01
2RESHAPE12.6207011.56E-06
3EXPAND_DIMS12.6207011.56E-06
4MAX_POOL_2D12.6207011.67E-06
5RESHAPE12.6207011.67E-06
6EXPAND_DIMS12.6207011.67E-06
7CONV_2D15.0307761.94E-01
8RESHAPE15.0307761.94E-07
9EXPAND_DIMS15.0307761.94E-07
10MAX_POOL_2D15.0307762.36E-07
11RESHAPE15.0307762.36E-07
12EXPAND_DIMS15.0307762.36E-07
13CONV_2D10.1322361.68E-01
14RESHAPE10.1322361.83E-06
15EXPAND_DIMS10.1322361.83E-06
16MAX_POOL_2D10.1322362.06E-06
17RESHAPE10.1322362.06E-06
18EXPAND_DIMS10.1322362.06E-06
19CONV_2D9.0384371.45E-01
20RESHAPE9.0384371.90E-06
21EXPAND_DIMS9.0384371.90E-06
22MAX_POOL_2D9.0384372.20E-06
23RESHAPE9.0384372.20E-06
24EXPAND_DIMS9.0384372.20E-06
25CONV_2D5.1519329.58E-02
26RESHAPE5.1519321.08E-06
27FULLY_CONNECTED7.2693781.13E-01
28FULLY_CONNECTED3.791721.75E-01
29FULLY_CONNECTED1.1023789.51E-01Yes

Model Memory Footprint

I used the TFLite Model Benchmark Tool to get the approximate RAM consumption of the TFLite cnn microwave model at runtime which is shown in the table below for each quantization mode as well as the TFLite model disk space. The other cnn models show similar characteristics. The findings for the x86 architecture were identical to the arm architecture. Note that the Keras model consumes about 42.49 (MB) on disk. You can see that there is about a four times reduction in disk storage space due to the float32 to int8 weight conversions. Interestingly, RAM runtime usage varies considerably due to the TFLite algorithms that that optimize intermediate tensors usage. These are pre-allocated to reduce inference latency at the cost of memory space. See Optimizing TensorFlow Lite Runtime Memory.

Quant ModeDisk (MB)RAM (MB)
convert_only42.48504484.957
w810.64204012.7109
w8_a810.64801623.3633
w8_a1610.66098410.1836

Transformer Model Results and Discussion

Note that even though the XNNPACK delagate was enabled during transformer model inference evaluation nothing was actually accelerated because the transformer model contains dynamic tensors. The following warning is shown when using the TFLite interpreter for inference:

Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors (tensor#94 is a dynamic-sized tensor).

This means that all operators are unsupported by XNNPACK and will fall back to the default CPU kernel implementations. A future effort will involve refactoring the transformer model use only static-size tensors. Note that a tensor could be marked dynamic at TFLite runtime when there is a control-flow operation (e.g., if, while etc.) prepared. In other words, even when the model graph itself doesn't have any tensors of dynamic shapes statically, at runtime a model could have dynamic tensors. The current transformer model uses if control-flow operations.

The quantized results for the transformer model are shown in the table below for quantization mode w8.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.84600.84830.99775.1170.17610.2760-17.612052061939
microwave0.73750.73550.99526.9690.34350.6049-34.352090560823
fridge0.74370.62610.838114.520.08380.5518-8.5602098661862
dishwasher0.66710.69050.98606.2140.11170.4521-11.172098363432
washingmachine0.89100.88720.992615.080.37960.3442-37.962142660901

The quantized results for the transformer kettle and microwave models are shown in the table below for quantization mode convert_only.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)$L_{x86}$ (${\mu}s$)$L_{arm}$ (${\mu}s$)
kettle0.84600.84830.99775.1170.17610.2760-17.61710069746
microwave0.67190.67360.99487.0540.39300.6518-39.30705068667

Model Profiling on x86 (slowest to fastest)

w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1416.24379.5485%79.5485%014
ADD410.6673.26657%82.815%041
MUL420.6613.23718%86.0522%042
BATCH_MATMUL40.5822.85029%88.9025%04
TRANSPOSE200.5512.69847%91.601%020
RESHAPE480.3841.8806%93.4816%048
POW20.3711.81694%95.2985%02
SOFTMAX20.2020.989275%96.2878%02
MEAN130.1770.86684%97.1546%013
CONV_2D10.1520.744405%97.899%01
SQUARED_DIFFERENCE60.1190.582791%98.4818%06
TANH20.110.538714%99.0205%02
AVERAGE_POOL_2D10.0860.421176%99.4417%01
FILL140.0590.288947%99.7306%014
SQUARE10.0360.176306%99.9069%01
SQRT10.0190.0930506%100%01
SUB600%100%06
STRIDED_SLICE1400%100%014
SHAPE2400%100%024
RSQRT600%100%06
REDUCE_PROD1600%100%016
PACK2200%100%022
GATHER1600%100%016
EXPAND_DIMS200%100%02
CONCATENATION800%100%08
convert_only node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED142.21131.0447%31.0447%014
ADD411.34418.8711%49.9158%041
MUL420.6939.73041%59.6462%042
RESHAPE480.6198.69138%68.3375%048
BATCH_MATMUL40.5297.42769%75.7652%04
TRANSPOSE200.45.6164%81.3816%020
POW20.3945.53215%86.9138%02
MEAN130.2163.03286%89.9466%013
SOFTMAX20.1552.17636%92.123%02
SQUARED_DIFFERENCE60.1281.79725%93.9202%06
TANH20.1191.67088%95.5911%02
AVERAGE_POOL_2D10.1021.43218%97.0233%01
FILL140.0991.39006%98.4134%014
CONV_2D10.0510.716091%99.1294%01
SQUARE10.0370.519517%99.649%01
SQRT10.0250.351025%100%01
SUB600%100%06
STRIDED_SLICE1400%100%014
SHAPE2400%100%024
RSQRT600%100%06
REDUCE_PROD1600%100%016
PACK2200%100%022
GATHER1600%100%016
EXPAND_DIMS200%100%02
CONCATENATION800%100%08

Model Profiling on aarch64 (slowest to fastest)

convert_only node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1430.77744.8716%44.8716%014
MUL428.57112.4962%57.3678%042
ADD417.42510.8254%68.1931%041
POW25.3087.73885%75.932%02
BATCH_MATMUL43.825.56941%81.5014%04
TRANSPOSE203.3524.88708%86.3885%020
RESHAPE482.9274.26745%90.6559%048
TANH22.022.94508%93.601%02
SOFTMAX21.1821.72331%95.3243%02
MEAN130.9271.35153%96.6758%013
SQUARED_DIFFERENCE60.7611.10951%97.7854%06
AVERAGE_POOL_2D10.5170.753765%98.5391%01
SQUARE10.3260.475295%99.0144%01
CONV_2D10.2810.409687%99.4241%01
SQRT10.1480.215778%99.6399%01
PACK220.1050.153086%99.793%022
FILL140.0770.112263%99.9052%014
SUB60.0220.0320751%99.9373%06
RSQRT60.0220.0320751%99.9694%06
STRIDED_SLICE140.0120.0174955%99.9869%014
SHAPE240.0050.0072898%99.9942%024
EXPAND_DIMS20.0030.00437388%99.9985%02
CONCATENATION80.0010.00145796%100%08
REDUCE_PROD1600%100%016
GATHER1600%100%016
w8 node typecountavg_msavg %cdf %mem KBtimes called
FULLY_CONNECTED1422.75938.6283%38.6283%014
MUL427.71813.0996%51.7278%042
ADD416.95211.7994%63.5273%041
POW25.0748.61197%72.1392%02
BATCH_MATMUL43.7736.40382%78.5431%04
TRANSPOSE202.9825.06127%83.6043%020
RESHAPE482.9024.92549%88.5298%048
TANH21.953.30968%91.8395%02
SOFTMAX21.2222.07407%93.9136%02
MEAN130.911.54452%95.4581%013
SQUARED_DIFFERENCE60.791.34085%96.7989%06
CONV_2D10.6591.1185%97.9174%01
AVERAGE_POOL_2D10.480.814692%98.7321%01
SQUARE10.3590.609321%99.3414%01
SQRT10.1260.213857%99.5553%01
PACK220.1070.181608%99.7369%022
FILL140.0820.139176%99.8761%014
SUB60.0250.0424319%99.9185%06
RSQRT60.0230.0390373%99.9576%06
STRIDED_SLICE140.0130.0220646%99.9796%014
EXPAND_DIMS20.0050.00848637%99.9881%02
SHAPE240.0040.0067891%99.9949%024
GATHER160.0020.00339455%99.9983%016
CONCATENATION80.0010.00169727%100%08
REDUCE_PROD1600%100%016

Quantization Efficacy

Layer quantization efficacy metrics for the transformer kettle model using mode w8_a8 are shown in the table below, although as noted above quantizing the transformer model's activations results in very poor model performance. You can see the RSQRT operator in particular does not quantize well, these operators are used in the Gaussian error linear activation functions which helps explain the poor performance of the model. The other transformer appliance models show similar efficacy metrics.

layerop_namerangermse/scaleSuspect?
0EXPAND_DIMS23.9299750.2751951
1CONV_2D6.7934230.2952648
2RESHAPE12.0805460.1608947
3EXPAND_DIMS12.0805460
4AVERAGE_POOL_2D12.0805460
5ADD11.5981160.03801457
6RESHAPE3.4056010.0580239
7FILL10
8MUL0.4899790.2888043
9ADD3.727090.2890081
10FILL10
11FILL2E-060
12RESHAPE3.727090
13TRANSPOSE3.727090
14MEAN1.3714330.3178885
15SQUARED_DIFFERENCE4.452920.2296307
16MEAN0.5470540.2962779
17ADD0.5480540.4589049
18RSQRT15.74584841.5733Yes
19MUL15.7458480
20MUL9.6065490.3037147
21MUL2.3841170.2467738
22SUB2.3841171.428423E-06
23ADD8.7926540.3326802
24TRANSPOSE8.7926540
25RESHAPE8.7926540
26MUL8.6060960.2844383
27ADD8.6824710.2893911
28RESHAPE8.6824710
29FULLY_CONNECTED13.5893970.337322
30RESHAPE13.5893970
31ADD13.666590.2940356
32RESHAPE13.666590
33TRANSPOSE13.666590
34FULLY_CONNECTED16.0618660.3192651
35RESHAPE16.0618660
36ADD16.148240.2843503
37RESHAPE16.148240
38TRANSPOSE16.148240
39BATCH_MATMUL791.0610.2887679
40MUL69.9205721.274111E-06
41SOFTMAX0.9960940.1901133
42FULLY_CONNECTED15.3700910.3185204
43RESHAPE15.3700910
44ADD15.4205750.273666
45RESHAPE15.4205750
46TRANSPOSE15.4205750
47BATCH_MATMUL13.7882380.2886845
48TRANSPOSE13.7882380
49RESHAPE13.7882380
50RESHAPE13.7882380
51FULLY_CONNECTED13.1031680.3028338
52RESHAPE13.1031680
53ADD13.2293180.2886953
54ADD15.801880.288787
55FILL10
56FILL2E-060
57RESHAPE15.801880
58TRANSPOSE15.801880
59MEAN0.3454990.4923606
60SQUARED_DIFFERENCE63.2240750.2779759
61MEAN4.9313160.3027504
62ADD4.9323160.0311987
63RSQRT1.1958380.304619
64MUL1.1958380
65MUL10.5555070.2823485
66MUL0.2194670.4081438
67SUB0.2194672.18255E-06
68ADD10.5139150.2897937
69TRANSPOSE10.5139150
70RESHAPE10.5139150
71MUL11.1647260.2816773
72ADD11.1913460.2954707
73RESHAPE11.1913460
74FULLY_CONNECTED20.6551380.3090305
75RESHAPE20.6551380
76ADD20.6503910.3390533
77MUL99.8711660.2299994
78ADD120.5215530.2948375
79MUL96.1622759.767714E-07
80TANH1.9921880.2440195
81ADD20.2198295
82MUL10.3251960
83MUL9.7768290.4144
84RESHAPE9.7768290
85FULLY_CONNECTED83.5733430.2907445
86RESHAPE83.5733430
87ADD83.5955790.08025211
88ADD85.8043380.2887958
89FILL10
90FILL2E-060
91RESHAPE85.8043380
92TRANSPOSE85.8043380
93MEAN0.6711320.3675501
94SQUARED_DIFFERENCE2199.590730.2545643
95MEAN175.2618570.2906021
96ADD175.2628590.001332498
97RSQRT0.985917infYes
98MUL0.9859170
99MUL10.029120.2857049
100MUL0.1436550.2965899
101SUB0.1436551.620293E-06
102ADD10.0168860.273117
103TRANSPOSE10.0168860
104RESHAPE10.0168860
105MUL10.0616650.2678465
106ADD10.076550.2902205
107RESHAPE10.076550
108FULLY_CONNECTED24.4527020.305032
109RESHAPE24.4527020
110ADD24.4717230.2637686
111RESHAPE24.4717230
112TRANSPOSE24.4717230
113FULLY_CONNECTED24.6025280.3068753
114RESHAPE24.6025280
115ADD24.5248950.2782782
116RESHAPE24.5248950
117TRANSPOSE24.5248950
118BATCH_MATMUL2375.913540.2896734
119MUL210.0030572.292973E-06
120SOFTMAX0.9960940.05637038
121FULLY_CONNECTED20.0751730.3076454
122RESHAPE20.0751730
123ADD20.0757060.263613
124RESHAPE20.0757060
125TRANSPOSE20.0757060
126BATCH_MATMUL19.7015350.2828629
127TRANSPOSE19.7015350
128RESHAPE19.7015350
129RESHAPE19.7015350
130FULLY_CONNECTED93.7410010.2932989
131RESHAPE93.7410010
132ADD93.7548040.07540143
133ADD98.0717430.2887844
134FILL10
135FILL2E-060
136RESHAPE98.0717430
137TRANSPOSE98.0717430
138MEAN0.7337640.2978907
139SQUARED_DIFFERENCE2799.432840.2259659
140MEAN47.0610990.3333294
141ADD47.0620960.00378661
142RSQRT0.8873590.932645Yes
143MUL0.8873590
144MUL17.2518030.2807441
145MUL0.2723830.2891514
146SUB0.2723831.761181E-06
147ADD17.3112720.3122337
148TRANSPOSE17.3112720
149RESHAPE17.3112720
150MUL17.3474510.2828182
151ADD17.3474510.2636831
152RESHAPE17.3474510
153FULLY_CONNECTED18.3242110.3175219
154RESHAPE18.3242110
155ADD18.3434220.3259408
156MUL69.1358550.2440944
157ADD87.479280.2834869
158MUL69.7983634.807578E-07
159TANH1.9921880.3179474
160ADD20.2156563
161MUL9.1717110
162MUL9.5787540.2946312
163RESHAPE9.5787540
164FULLY_CONNECTED364.4675730.2889795
165RESHAPE364.4675730
166ADD364.4068580.01272385
167ADD371.9008480.2615761
168FILL10
169FILL2E-060
170RESHAPE371.9008480
171TRANSPOSE371.9008480
172MEAN5.6726590.3749806
173SQUARED_DIFFERENCE37128.262650.1978192
174MEAN2799.735270.2974154
175ADD2799.736297.520764E-05
176RSQRT0.991143infYes
177MUL0.9911430
178MUL14.4559022.44185Yes
179MUL0.35215714.605Yes
180SUB0.3521572.75764E-06
181ADD14.4789330.3361114
182TRANSPOSE14.4789330
183RESHAPE14.4789330
184MUL16.6851170.2978353
185ADD16.7037110.2075399
186FILL10
187MUL0.4242910.2876463
188ADD16.9331830.2892929
189FILL10
190FILL2E-060
191RESHAPE16.9331830
192TRANSPOSE16.9331830
193MEAN0.06233548.13572Yes
194SQUARED_DIFFERENCE85.6101050.2268296
195MEAN1.226184381.2859Yes
196ADD1.2271840.01558558
197RSQRT1.0944140.3163588
198MUL1.0944140
199MUL15.9616330.2128369
200MUL0.067050.2904581
201SUB0.067052.78254E-06
202ADD15.9498230.2522852
203TRANSPOSE15.9498230
204RESHAPE15.9498230
205MUL13.8851220.2597474
206ADD13.7800750.3595855
207MEAN4.1983990.3065109
208FULLY_CONNECTED2.4345570.3960356
209FULLY_CONNECTED0.7335579.714286Yes

Model Memory Footprint

Identical to the cnn case, I used the TFLite Model Benchmark Tool to get the approximate RAM consumption of the TFLite microwave model at runtime which is shown in the table below for each relevant quantization mode as well as the TFLite model disk space. The other transformer models show similar characteristics. Note that the Keras model consumes about 6.02 (MB) on disk. You can see that there is about a three times reduction in model size due to the weights being quantized from float32 to int8 which is less than the four times reduction seen in the cnn case likely because there are fewer layers with weights. You can also see that the x86 TFLite runtime is more memory efficient than its aarch64 counterpart for this model.

Quant ModeDisk (MB)aarch64 RAM (MB)x86 RAM (MB)
convert_only6.21727620.824216.8438
w82.08831216.425813.3789

NILM Prototype System Components

I built a NILM prototype at my home to test the energy disaggregation algorithms in real-world conditions and to understand where they can be improved. The prototype is comprised of the following main subsystems. You can see a photograph of the prototype in the Appendix.

Analog Signal Conditioning

I used two clip-on current transformers in one of the home’s sub-panels to sense the current flowing through each of split voltage phases and a voltage transformer plugged into an outlet near the circuit breaker panel that provides the voltage of one of the phases. These signals are level-shifted, amplified and low-passed filtered by this subsystem before being passed on to the analog-to-digital converters inside an Arduino MEGA 2560 that performs aggregate metrics computation. You can see a schematic for the Analog Signal Conditioning Subsystem in the Appendix and find more details in the Panel to Arduino section.

Aggregate Metrics Computation

I used an Arduino MEGA 2560 to host the signal processing algorithms that takes the voltage signals from the Analog Signal Conditioning Subsystem and generates aggregate RMS voltage, RMS current, Real Power and Apparent Power metrics in real-time. Presently, only Real Power is used in downstream processing. I leveraged emonLibCM10 for these signal processing algorithms. emonLibCM runs continuously in the background and digitizes the analog input channels of the Arduino, calculates these metrics and then informs the Arduino sketch that the measurements are available and should be read and processed by downstream processing. The sketch is configured to update the metrics every eight seconds and can be found in ard.ino

Disaggregated Energy Consumption Computation

The actual energy disaggregation computations are hosted on a Raspberry Pi 4 which is connected over USB to the Arduino to fetch the aggregate metrics. The computations are comprised of running the tflite appliance inference models, trained and quantized per the steps described above, with pre- and post-processing steps. See the infer.py module for the code that performs these computations. The inference models output predicted energy for each appliance from 599-sample sized windows of the aggregate real power input signal. These predictions and aggregate mains power are stored in a local CSV file and made available for downstream reporting and analysis.

Typical disaggregated energy prediction results from my home are shown in the plots and tables below using tflite models trained on another machine from the dataset as described above and quantized using mode 'w8'. Two sets of results are shown, the first is with no fine-tuning and second, with fine-tuning using local data via the program fine_tune.

In the plots below, the horizontal axis is datetime. The vertical axis is energy consumption in Watts. The first plot shows the aggregate mains power with each appliance in separate sub-plots. Ground truth power was obtained by logging appliance power data in real-time at the outlet. The second plat shows aggregate mains power and appliance power plotted together and the last plot is a zoomed-in area of the second plot. These plots and the metrics that follow are generated by the program predict.

Alt text

Alt text

Alt text

NILM metrics were computed for the Float32 predictions on aggregate mains data that was captured in real-time and for the quantized model real-time predictions, both vs ground truth.

The Float32 model trained on the default dataset predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.0NaN0.99181.659INF0.9999INF
microwave0.53190.54060.99614.2610.03020.8198-3.018
fridge0.68750.46720.741436.590.24580.7494-24.56
dishwasher0.23720.21650.959612.740.95860.9615-95.62
washingmachine0.66610.66960.97497.5960.22131.407-23.97

The corresponding quantized model real-time predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.0NaN0.99862.873INF1.594INF
microwave0.52580.53530.99614.2370.01880.8208-1.880
fridge0.62570.40020.712539.520.36680.8189-36.65
dishwasher0.25710.23540.946914.700.95570.9558-95.57
washingmachine0.67600.68270.97587.5600.24011.393-24.01

You can see that model performance is comparable between the Float32 and real-time quantized results but overall they are poor with microwave being the exception. This indicates that the models can benefit from fine tuning with the ground truth data.

The Float32 model fine-tuned with local data predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.62050.66720.99587.8080.57160.5555-57.16
microwave0.49890.51290.991210.5080.65430.6795-65.43
fridge0.82860.66650.831224.7050.25020.3717-25.02
dishwasher0.76070.74910.954421.9110.46020.3957-46.02
washingmachine0.91550.91380.99053.2880.11560.3535-11.56

The corresponding quantized model real-time predictions vs ground truth are shown in the table below.

Appliance$F1\uparrow$$MCC\uparrow$$ACC\uparrow$$MAE$ $(W)$ $\downarrow$$SAE\downarrow$$NDE\downarrow$$EpD_e$ ($%$)
kettle0.58450.63450.99558.1990.59180.5954-59.18
microwave0.52210.51960.990410.7220.57810.6574-57.81
fridge0.83510.67580.836726.1370.24770.3603-24.27
dishwasher0.61880.62300.908323.5060.23130.3414-23.13
washingmachine0.71030.72570.95853.9100.24540.340924.54

You can see that fine-tuning the model with local data greatly improves its performance.

Amazon Alexa

I plan to use Amazon Alexa as the user interface to the appliance energy data, however this work is not yet started.

Conclusion

By using large publicly available datasets to train seq2point learning models it is very feasible to perform energy disaggregation that is fairly accurate without fine-tuning the models with local data. These models are modest in size and with little loss in accuracy can be quantized to run efficiently on commodity edge hardware such as the Raspberry Pi 4. More work needs to be done to further improve the accuracy of the models and to test with more appliance types. This project demonstrates that a key component of a sustainable and scalable power grid is within reach of the mass consumer market.

References

  1. Sustainable Cities and Society 62 (2020) 102411 | Energy management using non-intrusive load monitoring techniques — State- of-the-art and future research directions by R. Gopinath, Mukesh Kumar, C. Prakash Chandra Joshua and Kota Srinivas.
  2. Wikipedia | Signal Separation.
  3. arXiv:1507.06594 | Neural NILM: Deep Neural Networks Applied to Energy Disaggregation by Jack Kelly and William Knottenbelt.
  4. arXiv:1612.09106 | Sequence-to-point learning with neural networks for non-intrusive load monitoring by Chaoyun Zhang, Mingjun Zhong, Zongzuo Wang, Nigel Goddard and Charles Sutton.
  5. arXiv:1902.08835 | Transfer Learning for Non-Intrusive Load Monitoring by Michele D'Incecco, Stefano Squartini and Mingjun Zhong.
  6. Artificial Intelligence Techniques for a Scalable Energy Transition pp 109–131 | A Review on Non-intrusive Load Monitoring Approaches Based on Machine Learning by Hajer Salem, Moamar Sayed-Mouchaweh and Moncef Tagina.
  7. 1st International Symposium on Signal Processing Applications in Smart Buildings at 3rd IEEE Global Conference on Signal & Information Processing | Dataport and NILMTK: A Building Data Set Designed for Non-intrusive Load Monitoring by Oliver Parson, Grant Fisher, April Hersey, Nipun Batra, Jack Kelly, Amarjeet Singh, William Knottenbelt and Alex Rogers.
  8. Proceedings of the 8th International Conference on Energy Efficiency in Domestic Appliances and Lighting | A data management platform for personalised real-time energy feedback by David Murray and Jing Liao and Lina Stankovic and Vladimir Stankovic and Richard Hauxwell-Baldwin and Charlie Wilson and Michael Coleman and Tom Kane and Steven Firth. The REFIT dataset used in this project is is licensed under the Creative Commons Attribution 4.0 International Public License.
  9. GitHub | NILM by Lindo St. Angel
  10. GitHub | EmonLibCM by Trystan Lea, Glyn Hudson, Brian Orpin and Ivan Kravets.
  11. BERT4NILM: A Bidirectional Transformer Model for Non-Intrusive Load Monitoring by Zhenrui Yue, et. al.
  12. ELECTRIcity: An Efficient Transformer for Non-Intrusive Load Monitoring by Stavros Sykiotis, Maria Kaselimi ,Anastasios Doulamis and Nikolaos Doulamis.

Please also see this project's companion Medium article Energy Management Using Real-Time Non-Intrusive Load Monitoring.

Appendix

Photograph of Prototype

A photograph of an early version of my prototype system is shown below.

Alt text

Analog Signal Conditioning Schematic

The schematic for the Analog Signal Conditioning circuitry is shown below.

Alt text

Contributors

goruck

104 commits

Languages

Python

96.8%

C++

2.9%