Skip to content

Commit 4dab5d0

Browse files
committed
feat: AFHMM & AFHMM+SAC: implement chunkwise training.
Fixes #42
1 parent 5de20f7 commit 4dab5d0

File tree

2 files changed

+36
-123
lines changed

2 files changed

+36
-123
lines changed

nilmtk_contrib/disaggregate/afhmm.py

Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ class AFHMM(Disaggregator):
1818
def __init__(self, params):
1919
self.MODEL_NAME = 'AFHMM'
2020
self.models = []
21-
self.num_appliances = 0
22-
self.appliances = []
21+
self.means_vector = OrderedDict()
22+
self.pi_s_vector = OrderedDict()
23+
self.transmat_vector = OrderedDict()
2324
self.signal_aggregates = OrderedDict()
2425
self.time_period = params.get("time_period", 720)
2526
self.default_num_states = params.get("default_num_states", 2)
@@ -29,62 +30,41 @@ def __init__(self, params):
2930
if self.load_model_path:
3031
self.load_model(self.load_model_path)
3132

33+
@nilmtk.docinherit.doc_inherit
3234
def partial_fit(self, train_main, train_appliances, **load_kwargs):
33-
self.models = []
34-
self.num_appliances = 0
35-
self.appliances = []
36-
train_main = pd.concat(train_main, axis=0)
37-
train_app_tmp = []
38-
for app_name, df_list in train_appliances:
39-
df_list = pd.concat(df_list, axis=0)
40-
train_app_tmp.append((app_name,df_list))
41-
42-
# All the initializations required by the model
43-
train_appliances = train_app_tmp
44-
learnt_model = OrderedDict()
45-
means_vector = []
46-
one_hot_states_vector = []
47-
pi_s_vector = []
48-
transmat_vector = []
49-
states_vector = []
50-
train_main = train_main.values.flatten().reshape((-1,1))
51-
52-
for appliance_name, power in train_appliances:
53-
# Learning the pi's and transistion probablities for each appliance using a simple HMM
54-
self.appliances.append(appliance_name)
55-
X = power.values.reshape((-1,1))
56-
learnt_model[appliance_name] = hmm.GaussianHMM(self.default_num_states, "full")
57-
# Fit
58-
learnt_model[appliance_name].fit(X)
59-
means = learnt_model[appliance_name].means_.flatten().reshape((-1,1))
60-
states = learnt_model[appliance_name].predict(X)
61-
transmat = learnt_model[appliance_name].transmat_
35+
"""
36+
train_main: pd.DataFrame It will contain the mains reading.
37+
train_appliances: list of tuples [('appliance1', [ df1 ]),('appliance2', [ df2 ]),...]
38+
"""
39+
for appli_name, df_list in train_appliances:
40+
# Compute model parameters for this chunk.
41+
app_df = pd.concat(df_list, axis=0)
42+
X = app_df.values.reshape(( -1, 1 ))
43+
learnt_model = hmm.GaussianHMM(self.default_num_states, "full")
44+
learnt_model.fit(X)
45+
means = learnt_model.means_.flatten().reshape(( -1, 1 ))
46+
states = learnt_model.predict(X)
47+
transmat = learnt_model.transmat_.T
6248
counter = Counter(states.flatten())
63-
total = 0
64-
keys = list(counter.keys())
65-
keys.sort()
66-
67-
for i in keys:
68-
total+=counter[i]
69-
pi = []
70-
71-
for i in keys:
72-
pi.append(counter[i]/total)
73-
pi = np.array(pi)
74-
nb_classes = self.default_num_states
75-
targets = states.reshape(-1)
76-
means_vector.append(means)
77-
pi_s_vector.append(pi)
78-
transmat_vector.append(transmat.T)
79-
states_vector.append(states)
80-
self.num_appliances+=1
81-
self.signal_aggregates[appliance_name] = (np.mean(X)*self.time_period).reshape((-1,))
82-
83-
self.means_vector = means_vector
84-
self.pi_s_vector = pi_s_vector
85-
self.means_vector = means_vector
86-
self.transmat_vector = transmat_vector
87-
print ("Finished Training")
49+
total = sum(counter.values())
50+
pi = np.array([ v/total for v in counter.values() ])
51+
sigagg = (np.mean(X) * self.time_period).reshape(( -1, ))
52+
# Merge with previous values.
53+
# Hypothesis 1: chunk size is constant. (mean of means)
54+
# Hypothesis 2: if the appliance is already registered in
55+
# self.means_vector, then it is also known in all other dicts.
56+
if appli_name in self.means_vector:
57+
self.means_vector[appli_name] = (self.means_vector[appli_name] + means) / 2
58+
self.pi_s_vector[appli_name] = (self.pi_s_vector[appli_name] + pi) / 2
59+
self.transmat_vector[appli_name] = (self.transmat_vector[appli_name] + transmat) / 2
60+
self.signal_aggregates[appli_name] = (self.signal_aggregates[appli_name] + sigagg) / 2
61+
else:
62+
self.means_vector[appli_name] = means
63+
self.pi_s_vector[appli_name] = pi
64+
self.transmat_vector[appli_name] = transmat
65+
self.signal_aggregates[appli_name] = sigagg
66+
67+
print ("{}: Finished training".format(self.MODEL_NAME))
8868

8969
def disaggregate_thread(self, test_mains,index,d):
9070
means_vector = self.means_vector

nilmtk_contrib/disaggregate/afhmm_sac.py

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import numpy as np
33
import pandas as pd
44

5-
from collections import Counter, OrderedDict
6-
from hmmlearn import hmm
75
from nilmtk_contrib.disaggregate import AFHMM
86

97

@@ -16,71 +14,6 @@ def __init__(self, params):
1614
super().__init__(params)
1715
self.MODEL_NAME = 'AFHMM_SAC'
1816

19-
def partial_fit(self, train_main, train_appliances, **load_kwargs):
20-
self.models = []
21-
self.num_appliances = 0
22-
self.appliances = []
23-
'''
24-
train_main :- pd.DataFrame It will contain the mains reading.
25-
train_appliances :- list of tuples [('appliance1',df1),('appliance2',df2),...]
26-
'''
27-
train_main = pd.concat(train_main, axis=0)
28-
train_app_tmp = []
29-
30-
for app_name, df_list in train_appliances:
31-
df_list = pd.concat(df_list, axis=0)
32-
train_app_tmp.append((app_name,df_list))
33-
34-
train_appliances = train_app_tmp
35-
learnt_model = OrderedDict()
36-
means_vector = []
37-
one_hot_states_vector = []
38-
pi_s_vector = []
39-
transmat_vector = []
40-
states_vector = []
41-
42-
train_main = train_main.values.flatten().reshape((-1,1))
43-
44-
for appliance_name, power in train_appliances:
45-
#print (appliance_name)
46-
self.appliances.append(appliance_name)
47-
X = power.values.reshape((-1,1))
48-
learnt_model[appliance_name] = hmm.GaussianHMM(self.default_num_states, "full")
49-
# Fit
50-
learnt_model[appliance_name].fit(X)
51-
means = learnt_model[appliance_name].means_.flatten().reshape((-1,1))
52-
states = learnt_model[appliance_name].predict(X)
53-
transmat = learnt_model[appliance_name].transmat_
54-
counter = Counter(states.flatten())
55-
total = 0
56-
keys = list(counter.keys())
57-
keys.sort()
58-
59-
for i in keys:
60-
total+=counter[i]
61-
62-
pi = []
63-
for i in keys:
64-
pi.append(counter[i]/total)
65-
66-
pi = np.array(pi)
67-
68-
nb_classes = self.default_num_states
69-
targets = states.reshape(-1)
70-
71-
means_vector.append(means)
72-
pi_s_vector.append(pi)
73-
transmat_vector.append(transmat.T)
74-
states_vector.append(states)
75-
self.num_appliances+=1
76-
self.signal_aggregates[appliance_name] = (np.mean(X)*self.time_period).reshape((-1,))
77-
78-
self.means_vector = means_vector
79-
self.pi_s_vector = pi_s_vector
80-
self.means_vector = means_vector
81-
self.transmat_vector = transmat_vector
82-
print ("Finished Training")
83-
8417
def disaggregate_thread(self, test_mains,index,d):
8518
means_vector = self.means_vector
8619
pi_s_vector = self.pi_s_vector

0 commit comments

Comments
 (0)