def setUp(self): self.init_probs = [0.5, 0.5] self.transition_probs = [ [0.9, 0.1], [0.1, 0.9], ] self.emission_probs = [ [0.7, 0.3], [0.3, 0.7], ] self.decoder = viterbi.SimpleViterbiDecoder( init_probs=self.init_probs, transition_probs=self.transition_probs, emission_probs=self.emission_probs)
def _compute_flight(self): """Adds boolean flag .flying to self.fixes.""" emissions = self._flying_emissions() decoder = viterbi.SimpleViterbiDecoder( # More likely to start the log standing, i.e. not in flight init_probs=[0.80, 0.20], transition_probs=[ [0.9926, 0.0074], # transitions from standing [0.0003, 0.9997], # transitions from flying ], emission_probs=[ [0.974, 0.026], # emissions from standing [0.031, 0.969], # emissions from flying ]) output = decoder.decode(emissions) for fix, output in zip(self.fixes, output): fix.flying = (output == 1)
def _compute_circling(self): """Adds .circling to self.fixes.""" emissions = self._circling_emissions() decoder = viterbi.SimpleViterbiDecoder( # More likely to start in straight flight than in circling init_probs=[0.80, 0.20], transition_probs=[ [0.982, 0.018], # transitions from straight flight [0.030, 0.970], # transitions from circling ], emission_probs=[ [0.942, 0.058], # emissions from straight flight [0.093, 0.907], # emissions from circling ]) output = decoder.decode(emissions) for i in range(len(self.fixes)): self.fixes[i].circling = (output[i] == 1)
def _compute_flight(self): """Adds boolean flag .flying to self.fixes. Two pass: 1. Viterbi decoder 2. Only emit landings (0) if the downtime is more than _config.min_landing_time (or it's the end of the log). """ # Step 1: the Viterbi decoder emissions = self._flying_emissions() decoder = viterbi.SimpleViterbiDecoder( # More likely to start the log standing, i.e. not in flight init_probs=[0.80, 0.20], transition_probs=[ [0.9995, 0.0005], # transitions from standing [0.0005, 0.9995], # transitions from flying ], emission_probs=[ [0.8, 0.2], # emissions from standing [0.2, 0.8], # emissions from flying ]) outputs = decoder.decode(emissions) # Step 2: apply _config.min_landing_time. ignore_next_downtime = False apply_next_downtime = False for i, (fix, output) in enumerate(zip(self.fixes, outputs)): if output == 1: fix.flying = True # We're in flying mode, therefore reset all expectations # about what's happening in the next down mode. ignore_next_downtime = False apply_next_downtime = False else: if apply_next_downtime or ignore_next_downtime: if apply_next_downtime: fix.flying = False else: fix.flying = True else: # We need to determine whether to apply_next_downtime # or to ignore_next_downtime. This requires a scan into # upcoming fixes. Find the next fix on which # the Viterbi decoder said "flying". j = i + 1 while j < len(self.fixes): upcoming_fix_decoded = outputs[j] if upcoming_fix_decoded == 1: break j += 1 if j == len(self.fixes): # No such fix, end of log. Then apply. apply_next_downtime = True fix.flying = False else: # Found next flying fix. upcoming_fix = self.fixes[j] upcoming_fix_time_ahead = upcoming_fix.rawtime - fix.rawtime # If it's far enough into the future of then apply. if upcoming_fix_time_ahead >= self._config.min_landing_time: apply_next_downtime = True fix.flying = False else: ignore_next_downtime = True fix.flying = True