Exemple #1
0
    def test_kalman_filter_without_prior_predict(self):
        t0 = dt.datetime(2017, 5, 12, 16, 18, 25, 204000)

        process = proc.WienerProcess.create_from_cov(mean=3., cov=25.)

        kf = kalman.KalmanFilter(t0,
                                 state_distr=N(mean=100., cov=250.),
                                 process=process)

        observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(1.), process)

        t1 = t0 + dt.timedelta(hours=1)

        observable.observe(time=t1, obs=N(mean=100.35, cov=100.0))

        posterior_predicted_obs1 = observable.predict(t1)
        npt.assert_almost_equal(posterior_predicted_obs1.distr.mean,
                                100.28590504)
        npt.assert_almost_equal(posterior_predicted_obs1.distr.cov,
                                71.513353115)
        npt.assert_almost_equal(posterior_predicted_obs1.cross_cov,
                                posterior_predicted_obs1.distr.cov)

        t2 = t1 + dt.timedelta(hours=2)

        observable.observe(time=t2, obs=N(mean=100.35, cov=100.0))

        posterior_predicted_obs2 = observable.predict(t2)
        npt.assert_almost_equal(posterior_predicted_obs2.distr.mean,
                                100.45709020)
        npt.assert_almost_equal(posterior_predicted_obs2.distr.cov,
                                42.395213845)
        npt.assert_almost_equal(posterior_predicted_obs2.cross_cov,
                                posterior_predicted_obs2.distr.cov)
Exemple #2
0
 def predict(self, time, true_value=None):
     if time < self._time:
         raise ValueError(
             'Predicting the past (current time=%s, prediction time=%s)' %
             (self._time, time))
     if true_value is not None and filtering.FilterPypeOptions.TRUE_VALUE in self._pype_options:
         self._pype.send(filtering.TrueValue(self, self._time, true_value))
     if time == self._time: return
     state_distrs = []
     row = 0
     for p in self._processes:
         process_dim = p.process_dim
         m = self._state_distr.mean[row:row + process_dim, 0:1]
         c = self._state_distr.cov[row:row + process_dim,
                                   row:row + process_dim]
         state_distrs.append(
             p.propagate_distr(time, self._time, N(mean=m, cov=c)))
         row += process_dim
     state_mean = np.vstack([d.mean for d in state_distrs])
     state_cov = block_diag(*[d.cov for d in state_distrs])
     self._state_distr = N(mean=state_mean, cov=state_cov, copy=False)
     self._is_posterior = False
     self._time = time
     if filtering.FilterPypeOptions.PRIOR_STATE in self._pype_options:
         self._pype.send(self.state)
Exemple #3
0
    def process_run_df(self, df):
        auto_refresh = self._auto_refresh
        self._auto_refresh = False

        try:
            for i in range(len(df)):
                time = df.iloc[i]['time']
                observable_name = df.iloc[i]['observable_name']
                accepted = df.iloc[i]['accepted']
                obs_mean = df.iloc[i]['obs_mean']
                obs_cov = df.iloc[i]['obs_cov']
                predicted_obs_mean = df.iloc[i]['predicted_obs_mean']
                predicted_obs_cov = df.iloc[i]['predicted_obs_cov']
                cross_cov = df.iloc[i]['cross_cov']
                innov_mean = df.iloc[i]['innov_mean']
                innov_cov = df.iloc[i]['innov_cov']
                prior_state_mean = df.iloc[i]['prior_state_mean']
                prior_state_cov = df.iloc[i]['prior_state_cov']
                posterior_state_mean = df.iloc[i]['posterior_state_mean']
                posterior_state_cov = df.iloc[i]['posterior_state_cov']
                true_value = df.iloc[i]['true_value']
                log_likelihood = df.iloc[i]['log_likelihood']
                gain = df.iloc[i]['gain']

                # TODO Use an appropriate FilterState, it doesn't have to be KalmanFilterState
                prior_filter_state_object = kalman.KalmanFilterState(
                    None, time, False, N(prior_state_mean, prior_state_cov),
                    self._filter_name)
                # TODO Use an appropriate FilterState, it doesn't have to be KalmanFilterState
                posterior_filter_state_object = kalman.KalmanFilterState(
                    None, time, True,
                    N(posterior_state_mean, posterior_state_cov),
                    self._filter_name)

                self.process_filter_object(prior_filter_state_object)
                self.process_filter_object(posterior_filter_state_object)

                # Need the following check to skip the initial state row, which
                # may be present in the DataFrame:
                if not (i == 0 and observable_name is None):
                    true_value_object = filtering.TrueValue(
                        None, time, true_value, self._filter_name)
                    obs = filtering.Obs(None, time, N(obs_mean, obs_cov),
                                        observable_name)
                    predicted_obs = filtering.PredictedObs(
                        None, time, N(predicted_obs_mean, predicted_obs_cov),
                        cross_cov, observable_name)
                    innov_distr = N(innov_mean, innov_cov)
                    # TODO Use an appropriate ObsResult, it doesn't have to be KalmanObsResult
                    obs_result_object = kalman.KalmanObsResult(
                        accepted, obs, predicted_obs, innov_distr,
                        log_likelihood, gain)
                    if true_value is not None:
                        self.process_filter_object(true_value_object)
                    if obs_mean is not None:
                        self.process_filter_object(obs_result_object)
        finally:
            self.refresh()
            self._auto_refresh = auto_refresh
Exemple #4
0
    def observe(self, obs_distr, predicted_obs, true_value):
        if true_value is not None and filtering.FilterPypeOptions.TRUE_VALUE in self._pype_options:
            self._pype.send(filtering.TrueValue(self, self._time, true_value))
        innov = obs_distr.mean - predicted_obs.distr.mean
        innov_cov = predicted_obs.distr.cov + obs_distr.cov
        innov_cov_inv = np.linalg.inv(innov_cov)
        gain = np.dot(predicted_obs.cross_cov.T, innov_cov_inv)
        m = self._state_distr.mean + np.dot(gain, innov)
        c = self._state_distr.cov - np.dot(gain, predicted_obs.cross_cov)
        self._state_distr = N(mean=m, cov=c, copy=False)
        self._is_posterior = True
        if filtering.FilterPypeOptions.POSTERIOR_STATE in self._pype_options: self._pype.send(self.state)

        log_likelihood = -.5 * (obs_distr.dim * KalmanFilter.LN_2PI + np.log(np.linalg.det(innov_cov)) + \
                np.dot(np.dot(innov.T, innov_cov_inv), innov))
        obs = filtering.Obs(predicted_obs.observable, self._time, obs_distr)
        obs_result = KalmanObsResult(True, obs, predicted_obs, N(mean=innov, cov=innov_cov, copy=False), log_likelihood, gain)
        if filtering.FilterPypeOptions.OBS_RESULT in self._pype_options: self._pype.send(obs_result)
        return obs_result
Exemple #5
0
    def testkalmanfilterwithlowvarianceobs(self):
        t0 = dt.datetime(2017, 5, 12, 16, 18, 25, 204000)

        process = proc.WienerProcess.create_from_cov(mean=3., cov=25.)

        kf = kalman.KalmanFilter(t0,
                                 state_distr=N(mean=100., cov=250.),
                                 process=process)

        observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(1.), process)

        t1 = t0 + dt.timedelta(hours=1)

        observable.observe(time=t1, obs=N(mean=200., cov=0.0))

        posterior_predicted_obs1 = observable.predict(t1)
        npt.assert_almost_equal(posterior_predicted_obs1.distr.mean, 200.0)
        npt.assert_almost_equal(posterior_predicted_obs1.distr.cov,
                                2.8421709430404007E-14)
        npt.assert_almost_equal(posterior_predicted_obs1.cross_cov,
                                posterior_predicted_obs1.distr.cov)
Exemple #6
0
 def predict(self, time, true_value=None):
     if time < self._time:
         raise ValueError(
             'Predicting the past (current time=%s, prediction time=%s)' %
             (self._time, time))
     if true_value is not None and filtering.FilterPypeOptions.TRUE_VALUE in self._pype_options:
         self._pype.send(filtering.TrueValue(self, self._time, true_value))
     if time == self._time: return
     state_distrs = []
     row = 0
     for p in self._processes:
         process_dim = p.process_dim
         m = self._state_distr.mean[row:row + process_dim, 0:1]
         c = self._state_distr.cov[row:row + process_dim,
                                   row:row + process_dim]
         state_distr = p.propagate_distr(
             self._time,
             N(mean=m, cov=c),
             time,
             assume_distr=self._approximate_distr)
         if not isinstance(state_distr, N):
             if self._approximate_distr:
                 state_distr = N.approximate(state_distr, copy=False)
             else:
                 raise ValueError(
                     'The propagated state distribution is not Normal; to approximate with a Normal distribution, set the approximate_distr parameter to True (currently False)'
                 )
         state_distrs.append(state_distr)
         row += process_dim
     state_mean = np.vstack([d.mean for d in state_distrs])
     state_cov = block_diag(*[d.cov for d in state_distrs])
     self._state_distr = N(mean=state_mean, cov=state_cov, copy=False)
     self._is_posterior = False
     self._time = time
     if filtering.FilterPypeOptions.PRIOR_STATE in self._pype_options:
         self._pype.send(self.state)
Exemple #7
0
 def predict_obs(self, time, state_distr, observable=None):
     obs_mean = np.dot(self._obs_matrix, state_distr.mean)
     cross_cov = np.dot(self._obs_matrix, state_distr.cov)
     obs_cov = np.dot(cross_cov, self._obs_matrix.T)
     return filtering.PredictedObs(observable, time,
                                   N(mean=obs_mean, cov=obs_cov), cross_cov)
Exemple #8
0
 def _sub_state_distr(self, state_distr):
     return N(mean=self._sub_state_mean(state_distr.mean),
              cov=self._sub_state_cov(state_distr.cov),
              copy=False)
Exemple #9
0
 def _sub_state_distr(self, state_distr):
     # TODO Does this even make sense?
     return N(mean=self._sub_state_mean(state_distr.mean),
              cov=self._sub_state_cov(state_distr.cov),
              copy=False)
Exemple #10
0
    def testkalmanfiltermultid(self):
        t0 = dt.datetime(2017, 5, 12, 16, 18, 25, 204000)

        process1 = proc.WienerProcess.create_from_cov(mean=3., cov=25.)
        process2 = proc.WienerProcess.create_from_cov(mean=[1., 4.],
                                                      cov=[[36.0, -9.0],
                                                           [-9.0, 25.0]])

        kf = kalman.KalmanFilter(t0,
                                 state_distr=N(mean=[100.0, 120.0, 130.0],
                                               cov=[[250.0, 0.0, 0.0],
                                                    [0.0, 360.0, 0.0],
                                                    [0.0, 0.0, 250.0]]),
                                 process=(process1, process2))

        state_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(1.0, np.eye(2)), process1,
            process2)
        coord0_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(1.), process1)
        coord1_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(npu.row(1., 0.)), process2)
        coord2_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(npu.row(0., 1.)), process2)
        sum_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(npu.row(1., 1., 1.)), process1,
            process2)
        lin_comb_observable = kf.create_observable(
            kalman.KalmanFilterObsModel.create(npu.row(2., 0., -3.)), process1,
            process2)

        t1 = t0 + dt.timedelta(hours=1)

        predicted_obs1_prior = state_observable.predict(t1)
        npt.assert_almost_equal(
            predicted_obs1_prior.distr.mean,
            npu.col(100.0 + 3.0 / 24.0, 120.0 + 1.0 / 24.0,
                    130.0 + 4.0 / 24.0))
        npt.assert_almost_equal(predicted_obs1_prior.distr.cov,
                                [[250.0 + 25.0 / 24.0, 0.0, 0.0],
                                 [0.0, 360.0 + 36.0 / 24.0, -9.0 / 24.0],
                                 [0.0, -9.0 / 24.0, 250 + 25.0 / 24.0]])
        npt.assert_almost_equal(predicted_obs1_prior.cross_cov,
                                predicted_obs1_prior.distr.cov)

        state_observable.observe(time=t1,
                                 obs=N(mean=[100.35, 121.0, 135.0],
                                       cov=[[100.0, 0.0,
                                             0.0], [0.0, 400.0, 0.0],
                                            [0.0, 0.0, 100.0]]))

        predicted_obs1_posterior = state_observable.predict(t1)
        npt.assert_almost_equal(
            predicted_obs1_posterior.distr.mean,
            npu.col(100.285905044, 120.493895183, 133.623010239))
        npt.assert_almost_equal(
            predicted_obs1_posterior.distr.cov,
            [[71.513353115, 0.0, 0.0], [0.0, 189.888267669, -0.056112925],
             [0.0, -0.056112925, 71.513338130]])
        npt.assert_almost_equal(predicted_obs1_posterior.cross_cov,
                                predicted_obs1_posterior.distr.cov)

        predicted_obs1_0 = coord0_observable.predict(t1)
        npt.assert_almost_equal(predicted_obs1_0.distr.mean, 100.285905044)
        npt.assert_almost_equal(predicted_obs1_0.distr.cov, 71.513353115)
        npt.assert_almost_equal(predicted_obs1_0.cross_cov,
                                npu.row(71.513353115, 0.0, 0.0))

        predicted_obs1_1 = coord1_observable.predict(t1)
        npt.assert_almost_equal(predicted_obs1_1.distr.mean, 120.493895183)
        npt.assert_almost_equal(predicted_obs1_1.distr.cov, 189.888267669)
        npt.assert_almost_equal(predicted_obs1_1.cross_cov,
                                npu.row(0.0, 189.888267669, -0.056112925))

        predicted_obs1_2 = coord2_observable.predict(t1)
        npt.assert_almost_equal(predicted_obs1_2.distr.mean, 133.623010239)
        npt.assert_almost_equal(predicted_obs1_2.distr.cov, 71.513338130)
        npt.assert_almost_equal(predicted_obs1_2.cross_cov,
                                npu.row(0.0, -0.056112925, 71.513338130))

        predicted_obs1_sum = sum_observable.predict(t1)
        npt.assert_almost_equal(predicted_obs1_sum.distr.mean, 354.402810466)
        npt.assert_almost_equal(predicted_obs1_sum.distr.cov, 332.802733064)
        npt.assert_almost_equal(
            predicted_obs1_sum.cross_cov,
            npu.row(71.513353115, 189.832154744, 71.457225204))

        predicted_obs1_lin_comb = lin_comb_observable.predict(t1)
        npt.assert_almost_equal(predicted_obs1_lin_comb.distr.mean,
                                -200.297220628)
        npt.assert_almost_equal(predicted_obs1_lin_comb.distr.cov,
                                929.673455633)
        npt.assert_almost_equal(
            predicted_obs1_lin_comb.cross_cov,
            npu.row(143.026706231, 0.168338776, -214.540014390))

        t2 = t1 + dt.timedelta(minutes=30)

        coord1_observable.observe(time=t2, obs=N(mean=125.25, cov=4.))

        predicted_obs2_1 = coord1_observable.predict(t2)
        npt.assert_almost_equal(predicted_obs2_1.distr.mean, 125.152685704)
        npt.assert_almost_equal(predicted_obs2_1.distr.cov, 3.917796226)
        npt.assert_almost_equal(predicted_obs2_1.cross_cov,
                                npu.row(0.0, 3.917796226, -0.005006475))

        t3 = t2 + dt.timedelta(minutes=30)

        predicted_obs3_prior_sum = sum_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_prior_sum.distr.mean,
                                359.368174232)
        npt.assert_almost_equal(predicted_obs3_prior_sum.distr.cov,
                                149.392502944)
        npt.assert_almost_equal(
            predicted_obs3_prior_sum.cross_cov,
            npu.row(72.555019782, 4.475289751, 72.36219341))

        predicted_obs3_prior0 = coord0_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_prior0.distr.mean,
                                100.410905044)
        npt.assert_almost_equal(predicted_obs3_prior0.distr.cov, 72.555019782)
        npt.assert_almost_equal(predicted_obs3_prior0.cross_cov,
                                npu.row(72.555019782, 0.0, 0.0))
        predicted_obs3_prior1 = coord1_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_prior1.distr.mean,
                                125.173519037)
        npt.assert_almost_equal(predicted_obs3_prior1.distr.cov, 4.667796226)
        npt.assert_almost_equal(predicted_obs3_prior1.cross_cov,
                                npu.row(0.0, 4.667796226, -0.192506475))
        predicted_obs3_prior2 = coord2_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_prior2.distr.mean,
                                133.783750150)
        npt.assert_almost_equal(predicted_obs3_prior2.distr.cov, 72.554699886)
        npt.assert_almost_equal(predicted_obs3_prior2.cross_cov,
                                npu.row(0.0, -0.192506475, 72.554699886))

        sum_observable.observe(time=t3, obs=N(mean=365.00, cov=9.))

        predicted_obs3_posterior_sum = sum_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_posterior_sum.distr.mean,
                                364.679994753)
        npt.assert_almost_equal(predicted_obs3_posterior_sum.distr.cov,
                                8.488612159)
        npt.assert_almost_equal(predicted_obs3_posterior_sum.cross_cov,
                                npu.row(4.122639429, 0.254289862, 4.111682867))
        predicted_obs3_posterior0 = coord0_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_posterior0.distr.mean,
                                102.990681374)
        npt.assert_almost_equal(predicted_obs3_posterior0.distr.cov,
                                39.319665849)
        npt.assert_almost_equal(predicted_obs3_posterior0.cross_cov,
                                npu.row(39.319665849, 0.0, 0.0))
        predicted_obs3_posterior1 = coord1_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_posterior1.distr.mean,
                                125.332643059)
        npt.assert_almost_equal(predicted_obs3_posterior1.distr.cov,
                                4.541349469)
        npt.assert_almost_equal(predicted_obs3_posterior1.cross_cov,
                                npu.row(0.0, 4.541349469, -2.237058941))
        predicted_obs3_posterior2 = coord2_observable.predict(t3)
        npt.assert_almost_equal(predicted_obs3_posterior2.distr.mean,
                                136.356670319)
        npt.assert_almost_equal(predicted_obs3_posterior2.distr.cov,
                                39.495767563)
        npt.assert_almost_equal(predicted_obs3_posterior2.cross_cov,
                                npu.row(0.0, -2.237058941, 39.495767563))