In [1]:
from __future__ import print_function, division
import numpy as np
from os.path import join, expanduser
import matplotlib.pyplot as plt
import yaml # for pretty-printing dict
from neuralnilm.metrics import run_metrics, across_all_appliances
import pandas as pd
# sklearn evokes warnings from numpy
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
In [2]:
TRAIN_HOUSES = {
'microwave': (1, 2),
'fridge': (1, 2, 4),
'dish washer': (1, 2),
'kettle': (1, 2, 4),
'washing machine': (1, 5)
}
TEST_HOUSES = {
'microwave': (5,),
'fridge': (5,),
'dish washer': (5,),
'kettle': (5,),
'washing machine': (2,)
}
APPLIANCES = TRAIN_HOUSES.keys()
ON_POWER_THRESHOLDS = {
'microwave': 200,
'fridge': 30,
'dish washer': 10,
'kettle': 2000,
'washing machine': 20
}
HOUSES = [1, 2, 3, 4, 5]
METRICS = [
'f1_score',
'precision_score',
'recall_score',
'accuracy_score',
'relative_error_in_total_energy',
'total_energy_correctly_assigned',
'mean_absolute_error'
]
ALGORITHMS = ['co', 'fhmm', 'ae', 'rectangles', 'rnn']
full_algorithm_names = [
'Combinatorial Optimisation ', 'Factorial HMM', 'Autoencoder', 'Rectangles', 'LSTM']
ESTIMATES_PATH = expanduser(
"~/PhD/experiments/neural_nilm/data_for_BuildSys2015/disag_estimates")
GROUND_TRUTH_PATH = expanduser(
"~/PhD/experiments/neural_nilm/data_for_BuildSys2015/ground_truth_and_mains")
PLOT_PATH = expanduser("~/PhD/writing/papers/BuildSys_2015_Neural_NILM")
In [3]:
def load(architecture, building_i, appliance):
# load estimates
estimates_fname = "{}_building_{}_estimates_{}.csv".format(
architecture, building_i, appliance)
estimates_fname = join(ESTIMATES_PATH, estimates_fname)
y_pred = np.loadtxt(estimates_fname, delimiter=',')
# load ground truth
y_true_fname = "building_{}_{}.csv".format(building_i, appliance.replace(' ', '_'))
y_true_fname = join(GROUND_TRUTH_PATH, y_true_fname)
y_true = np.loadtxt(y_true_fname, delimiter=',')
# load mains
mains_fname = "building_{}_mains.csv".format(building_i)
mains_fname = join(GROUND_TRUTH_PATH, mains_fname)
mains = np.loadtxt(mains_fname, delimiter=',')
return y_true, y_pred, mains
In [4]:
def plot_all(y_true, y_pred, mains, title=None):
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(y_pred)
axes[0].set_title('y_pred')
axes[1].plot(y_true)
axes[1].set_title('y_true')
axes[2].plot(mains)
axes[2].set_title('mains')
if title:
fig.set_title(title)
plt.show()
return fig, axes
In [5]:
# Run metrics
def calc_metrics(houses):
scores = pd.Panel(
np.NaN,
items=APPLIANCES,
major_axis=METRICS,
minor_axis=ALGORITHMS
)
for appliance in APPLIANCES:
houses_for_appliance = houses[appliance]
on_power_threshold = ON_POWER_THRESHOLDS[appliance]
for algo in ALGORITHMS:
house_scores = pd.DataFrame(
np.NaN, columns=METRICS, index=houses_for_appliance)
for house_i in houses_for_appliance:
y_true, y_pred, mains = load(algo, house_i, appliance)
house_scores_dict = run_metrics(
y_true, y_pred, mains, on_power_threshold)
house_scores_dict.pop('sum_abs_diff')
house_scores.loc[house_i] = house_scores_dict
scores[appliance, :, algo].update(house_scores.dropna().mean())
scores['across all appliances'] = scores.mean(axis=0)
return scores
In [25]:
test_houses_scores = calc_metrics(TEST_HOUSES)
train_houses_scores = calc_metrics(TRAIN_HOUSES)
In [26]:
APPLIANCE = 'washing machine'
test_houses_scores[APPLIANCE]
Out[26]:
In [30]:
train_houses_scores[APPLIANCE]
Out[30]:
In [28]:
train_houses_scores[APPLIANCE]
Out[28]:
In [33]:
y_true, y_pred, mains = load('rectangles', 5, APPLIANCE)
plot_all(y_true, y_pred, mains)
Out[33]:
In [34]:
# plot
COLOR = ['#5F7343', '#99A63C', '#FEC06A', '#F25430', '#E61924']
FONTSIZE = 10
def plot_scores(scores):
appliances = list(scores.items)
metrics = list(scores.major_axis)
algorithms = list(scores.minor_axis)
nrows = len(metrics)
ncols = len(appliances)
n_algorithms = len(algorithms)
x = range(n_algorithms)
fig, axes = plt.subplots(nrows=nrows, ncols=ncols, sharey='row', figsize=(8.1, 8.7))
fig.patch.set_facecolor('white')
for row_i, metric in enumerate(metrics):
for col_i, appliance in enumerate(appliances):
ax = axes[row_i, col_i]
scores_for_algorithms = scores[appliance, metric]
rects = ax.bar(
x, scores_for_algorithms, color=COLOR, edgecolor=COLOR, zorder=3)
# Numbers on the plot
if row_i == 6: # mean absolute error (watts)
text_y = 90
text_format = '{:3.0f}'
elif row_i == 4: # relative error in total energy
text_y = 0
else:
text_y = 0.5
text_format = '{:.2f}'
# Draw text
for i, rect in enumerate(rects):
ax.text(
rect.get_x() + (1/6),
text_y,
text_format.format(scores_for_algorithms[i]),
va='center', rotation=90, fontsize=FONTSIZE)
# Formatting
ax.set_xticks([])
ax.tick_params(direction='out')
ax.yaxis.grid(
b=True, which='major', color='white', linestyle='-', zorder=0)
ax.patch.set_facecolor((0.85, 0.85, 0.85))
if row_i == 4: # relative error in total energy
ax.set_ylim((-1, 1))
for spine in ['top', 'right', 'left', 'bottom']:
ax.spines[spine].set_visible(False)
if row_i == 0:
if appliance == 'across all appliances':
label = 'Across all\nappliances'
else:
label = appliance.replace(' ', '\n')
label = label[0].capitalize() + label[1:]
ax.set_title(label, fontsize=FONTSIZE)
if col_i == 0:
label = metric.replace('_', '\n')
if label == 'mean\nabsolute\nerror':
label = label + '\n(watts)'
elif label == 'total\nenergy\ncorrectly\nassigned':
label = 'prop. of\n' + label
elif label == 'relative\nerror\nin\ntotal\nenergy':
label = 'relative\nerror in\ntotal\nenergy'
label = label[0].capitalize() + label[1:]
ylabel = ax.set_ylabel(label, fontsize=FONTSIZE)
ylabel.set_rotation('horizontal')
ylabel.set_verticalalignment('center')
ylabel.set_horizontalalignment('center')
ax.yaxis.labelpad = 25
ax.tick_params(axis='y', left='on', right='off')
else:
ax.tick_params(axis='y', left='off', right='off')
plt.subplots_adjust(hspace=0.3, top=0.96, bottom=0.07, left=0.13, right=0.99)
plt.legend(rects, full_algorithm_names, ncol=n_algorithms, loc=(-7, -0.6),
frameon=False, fontsize=FONTSIZE)
return fig, axes
In [35]:
fig, axes = plot_scores(test_houses_scores)
#fig.suptitle('Unseen houses', fontsize=16)
plt.savefig(join(PLOT_PATH, 'unseen_houses.eps'))
plt.show()
In [36]:
fig, axes = plot_scores(train_houses_scores)
#fig.suptitle('Train houses', fontsize=16)
plt.savefig(join(PLOT_PATH, 'train_houses.eps'))
plt.show()
In [ ]: