working(with(real(time(data...
TRANSCRIPT
Working with Real Time Data Streams for IoT Devices
Lachlan Blackhall (@lblackhall) PyconAU, 2016
Smart Homes
Smart CiJes
Data!!!
Stream Processing
A Typical IoT Device
What you hope your data looks like
What it actually looks like
Filtering to the Rescue
A Simple Example
Noisy Temperature Data
Moving Average Filter class MovingAverageFilter(object): def __init__(self, window): self.window = window self.data = [] def step(self, measurement): self.data.append(measurement) if len(self.data) > self.window: self.data.pop(0) def current_state(self): return sum(self.data) / len(self.data)
Kalman Filter class SingleStateKalmanFilter(object): def __init__(self, A, B, C, x, P, Q, R): self.A = A # Process dynamics self.B = B # Control dynamics self.C = C # Measurement dynamics self.current_state_esJmate = x # Current state esJmate self.current_prob_esJmate = P # Current probability of state esJmate self.Q = Q # Process covariance self.R = R # Measurement covariance
Kalman Filter cont. def current_state(self): return self.current_state_esJmate def step(self, control_input, measurement): # PredicJon step predicted_state_esJmate = self.A * self.current_state_esJmate + self.B * control_input predicted_prob_esJmate = (self.A * self.current_prob_esJmate) * self.A + self.Q # ObservaJon step innovaJon = measurement -‐ self.C * predicted_state_esJmate innovaJon_covariance = self.C * predicted_prob_esJmate * self.C + self.R # Update step kalman_gain = predicted_prob_esJmate * self.C * 1 / float(innovaJon_covariance) self.current_state_esJmate = predicted_state_esJmate + kalman_gain * innovaJon # eye(n) = nxn idenJty matrix. self.current_prob_esJmate = (1 -‐ kalman_gain * self.C) * predicted_prob_esJmate
IniJalising the Filters # IniJalise the Kalman Filter A = 1 # No process innovaJon C = 1 # Measurement B = 0 # No control input Q = 0.005 # Process covariance R = 1 # Measurement covariance x = 18 # IniJal esJmate P = 1 # IniJal covariance filter = SingleStateKalmanFilter(A, B, C, x, P, Q, R) # IniJalise two moving average filters with different window lengths ma5 = MovingAverageFilter(5) ma50 = MovingAverageFilter(50)
SimulaJng a Data Stream # Empty lists for capturing filter esJmates predicJons = [] wavg5 = [] wavg50 = [] # Simulate the data arriving sequenJally for data in random_data: ma5.step(data) wavg5.append(ma5.current_state()) ma50.step(data) wavg50.append(ma50.current_state()) filter.step(0, data) predicJons.append(filter.current_state())
Noisy Data
Moving Average (5 samples)
Moving Average (50 Samples)
Kalman Filter
Resources • hjp://www.bzarg.com/p/how-‐a-‐kalman-‐filter-‐works-‐in-‐
pictures/ • hjps://en.wikipedia.org/wiki/Kalman_filter • hjps://en.wikipedia.org/wiki/Moving_average
Thanks
• [email protected] • @lblackhall • hjps://github.com/lblackhall/pyconau2016