Exemple #1
0
    def test_optimize_1D(self):
        # test on simple 1D example, plot the fit
        steps = 100
        dyn = UNGMTransition(GaussRV(1), GaussRV(1))
        x, y = dyn.simulate_discrete(steps)

        f = dyn.dyn_eval
        dim_in, dim_out = dyn.dim_in, dyn.dim_state

        par0 = 1 + np.random.rand(dim_out, dim_in + 1)
        tf = MultiOutputGaussianProcessTransform(dim_in, dim_out, par0)

        # use sampled system state trajectory to create training data
        fy = np.zeros((dim_out, steps))
        for k in range(steps):
            fy[:, k] = f(x[:, k, 0], k)

        b = [np.log((0.1, 1.0001))] + dim_in * [(None, None)]
        opt = {'xtol': 1e-2, 'maxiter': 100}
        log_par, res_list = tf.model.optimize(np.log(par0),
                                              fy,
                                              x[..., 0],
                                              bounds=b,
                                              method='L-BFGS-B',
                                              options=opt)

        print(np.exp(log_par))
        self.assertTrue(False)
Exemple #2
0
    def test_optimize(self):
        steps = 350
        m0 = np.array([1000, 300, 1000, 0, np.deg2rad(-3)])
        P0 = np.diag([100, 10, 100, 10, 0.1])
        x0 = GaussRV(5, m0, P0)
        dt = 0.1
        Q = np.array([[dt**3 / 3, dt**2 / 2], [dt**2 / 2, dt]])
        q = GaussRV(5, cov=Q)
        dyn = CoordinatedTurnTransition(x0, q, dt)
        x, y = dyn.simulate_discrete(steps)

        f = dyn.dyn_eval
        dim_in, dim_out = dyn.dim_in, dyn.dim_state

        # par0 = np.hstack((np.ones((dim_out, 1)), 5*np.ones((dim_out, dim_in+1))))
        par0 = 10 * np.ones((dim_out, dim_in + 1))
        tf = MultiOutputGaussianProcessTransform(dim_in, dim_out, par0)

        # use sampled system state trajectory to create training data
        fy = np.zeros((dim_out, steps))
        for k in range(steps):
            fy[:, k] = f(x[:, k, 0], 0)

        opt = {'maxiter': 100}
        log_par, res_list = tf.model.optimize(np.log(par0),
                                              fy,
                                              x[..., 0],
                                              method='BFGS',
                                              options=opt)

        print(np.exp(log_par))
Exemple #3
0
def hypers_demo(lscale=None):

    print(f"Seed = {np.random.get_state()[1][0]}")

    # set default lengthscales if unspecified
    if lscale is None:
        lscale = [1e-3, 3e-3, 1e-2, 3e-2, 1e-1, 3e-1, 1, 3, 1e1, 3e1, 1e2, ]

    steps, mc = 500, 100

    # setup univariate non-stationary growth model
    x0 = GaussRV(1, cov=np.atleast_2d(5.0))
    q = GaussRV(1, cov=np.atleast_2d(10.0))
    dyn = UNGMTransition(x0, q)  # dynamics
    r = GaussRV(1)
    obs = UNGMMeasurement(r, 1)  # observation model
    x = dyn.simulate_discrete(steps, mc_sims=mc)  # generate some data
    z = obs.simulate_measurements(x)

    num_el = len(lscale)
    mean_f, cov_f = np.zeros((dyn.dim_in, steps, mc, num_el)), np.zeros((dyn.dim_in, dyn.dim_in, steps, mc, num_el))
    for iel, el in enumerate(lscale):

        # kernel parameters
        ker_par = np.array([[1.0, el * dyn.dim_in]])

        # initialize BHKF with current lenghtscale
        f = GaussianProcessKalman(dyn, obs, ker_par, ker_par, points='ut', point_hyp={'kappa': 0.0})
        # filtering
        for s in range(mc):
            mean_f[..., s, iel], cov_f[..., s, iel] = f.forward_pass(z[..., s])

    # evaluate RMSE, NCI and NLL
    rmseVsEl = squared_error(x[..., na], mean_f)
    nciVsEl = rmseVsEl.copy()
    nllVsEl = rmseVsEl.copy()
    for k in range(steps):
        for iel in range(num_el):
            mse_mat = mse_matrix(x[:, k, :], mean_f[:, k, :, iel])
            for s in range(mc):
                nciVsEl[:, k, s, iel] = log_cred_ratio(x[:, k, s], mean_f[:, k, s, iel], cov_f[:, :, k, s, iel],
                                                       mse_mat)
                nllVsEl[:, k, s, iel] = neg_log_likelihood(x[:, k, s], mean_f[:, k, s, iel], cov_f[:, :, k, s, iel])

    # average out time and MC simulations
    rmseVsEl = np.sqrt(np.mean(rmseVsEl, axis=1)).mean(axis=1)
    nciVsEl = nciVsEl.mean(axis=(1, 2))
    nllVsEl = nllVsEl.mean(axis=(1, 2))

    # plot influence of changing lengthscale on the RMSE and NCI and NLL filter performance
    plt.figure()
    plt.semilogx(lscale, rmseVsEl.squeeze(), color='k', ls='-', lw=2, marker='o', label='RMSE')
    plt.semilogx(lscale, nciVsEl.squeeze(), color='k', ls='--', lw=2, marker='o', label='NCI')
    plt.semilogx(lscale, nllVsEl.squeeze(), color='k', ls='-.', lw=2, marker='o', label='NLL')
    plt.grid(True)
    plt.legend()
    plt.show()

    return {'el': lscale, 'rmse': rmseVsEl, 'nci': nciVsEl, 'neg_log_likelihood': nllVsEl}
Exemple #4
0
 def test_crash(self):
     d = 1
     tmc = MonteCarloTransform(d, n=1e4)
     f = UNGMTransition(GaussRV(1, cov=1.0), GaussRV(1, cov=10.0)).dyn_eval
     mean = np.zeros(d)
     cov = np.eye(d)
     # does it crash ?
     tmc.apply(f, mean, cov, np.atleast_1d(1.0))
Exemple #5
0
    def test_simulate_continuous(self):
        m0 = np.array([6500.4, 349.14, -1.8093, -6.7967, 0.6932])
        P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
        x0 = GaussRV(5, m0, P0)
        q = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 1e-6]))
        dyn = ReentryVehicle2DTransition(x0, q, dt=0.05)
        x = dyn.simulate_continuous(200, dt=0.05)

        plt.figure()
        plt.plot(x[0, ...], x[1, ...], color='r')
        plt.show()
Exemple #6
0
    def test_simulate(self):
        # setup CTRS with radar measurements
        x0 = GaussRV(5, cov=0.1 * np.eye(5))
        q = GaussRV(2, cov=np.diag([0.1, 0.1 * np.pi]))
        r = GaussRV(2, cov=np.diag([0.3, 0.03]))
        dyn = ConstantTurnRateSpeed(x0, q)
        obs = Radar2DMeasurement(r, 5)
        x = dyn.simulate_discrete(100, 10)
        y = obs.simulate_measurements(x)

        plt.figure()
        plt.plot(x[0, ...], x[1, ...], alpha=0.25, color='b')
        plt.show()
    def test_cho_dot_ein(self):
        # attempt to compute the transformed covariance using cholesky decomposition

        # integrand
        # input moments
        mean_in = np.array([6500.4, 349.14, 1.8093, 6.7967, 0.6932])
        cov_in = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])

        f = ReentryVehicle2DTransition(GaussRV(5, mean_in, cov_in), GaussRV(3)).dyn_eval
        dim_in, dim_out = ReentryVehicle2DTransition.dim_state, 1

        # transform
        ker_par_mo = np.hstack((np.ones((dim_out, 1)), 25 * np.ones((dim_out, dim_in))))
        tf_so = GaussianProcessTransform(dim_in, dim_out, ker_par_mo, point_str='sr')

        # Monte-Carlo for ground truth
        # tf_ut = UnscentedTransform(dim_in)
        # tf_ut.apply(f, mean_in, cov_in, np.atleast_1d(1), None)
        tf_mc = MonteCarloTransform(dim_in, 1000)
        mean_mc, cov_mc, ccov_mc = tf_mc.apply(f, mean_in, cov_in, np.atleast_1d(1))
        C_MC = cov_mc + np.outer(mean_mc, mean_mc.T)

        # evaluate integrand
        x = mean_in[:, None] + la.cholesky(cov_in).dot(tf_so.model.points)
        Y = np.apply_along_axis(f, 0, x, 1.0, None)

        # covariance via np.dot
        iK, Q = tf_so.model.iK, tf_so.model.Q
        C1 = iK.dot(Q).dot(iK)
        C1 = Y.dot(C1).dot(Y.T)

        # covariance via np.einsum
        C2 = np.einsum('ab, bc, cd', iK, Q, iK)
        C2 = np.einsum('ab,bc,cd', Y, C2, Y.T)

        # covariance via np.dot and cholesky
        K = tf_so.model.kernel.eval(tf_so.model.kernel.par, tf_so.model.points)
        L_lower = la.cholesky(K)
        Lq = la.cholesky(Q)
        phi = la.solve(L_lower, Lq)
        psi = la.solve(L_lower, Y.T)
        bet = psi.T.dot(phi)
        C3_dot = bet.dot(bet.T)
        C3_ein = np.einsum('ij, jk', bet, bet.T)

        logging.debug("MAX DIFF: {:.4e}".format(np.abs(C1 - C2).max()))
        logging.debug("MAX DIFF: {:.4e}".format(np.abs(C3_dot - C3_ein).max()))
        self.assertTrue(np.allclose(C1, C2), "MAX DIFF: {:.4e}".format(np.abs(C1 - C2).max()))
        self.assertTrue(np.allclose(C3_dot, C3_ein), "MAX DIFF: {:.4e}".format(np.abs(C3_dot - C3_ein).max()))
        self.assertTrue(np.allclose(C1, C3_dot), "MAX DIFF: {:.4e}".format(np.abs(C1 - C3_dot).max()))
Exemple #8
0
    def test_simulate(self):
        time_steps = 50
        # UNGM additive noise
        dim = 1
        init_dist = GaussRV(dim)
        noise_dist = GaussRV(dim, cov=np.atleast_2d(10.0))
        ungm_dyn = UNGMTransition(init_dist, noise_dist)
        ungm_meas = UNGMMeasurement(GaussRV(dim), ungm_dyn.dim_state)
        x = ungm_dyn.simulate_discrete(time_steps, mc_sims=20)
        y = ungm_meas.simulate_measurements(x)

        # UNGM non-additive noise
        ungmna_dyn = UNGMNATransition(init_dist, noise_dist)
        ungmna_meas = UNGMNAMeasurement(GaussRV(dim), ungm_dyn.dim_state)
        x = ungmna_dyn.simulate_discrete(time_steps, mc_sims=20)
        y = ungmna_meas.simulate_measurements(x)
Exemple #9
0
    def test_total_nlml_gradient(self):
        # nonlinear vector function from some SSM
        dyn = CoordinatedTurnTransition(GaussRV(5), GaussRV(5))

        # generate inputs
        num_x = 20
        x = 10 + np.random.randn(dyn.dim_in, num_x)

        # evaluate function at inputs
        y = np.apply_along_axis(dyn.dyn_eval, 0, x, None)

        # kernel and it's initial parameters
        from ssmtoybox.bq.bqkern import RBFGauss
        lhyp = np.log([1.0] + 5 * [3.0])
        kernel = RBFGauss(dyn.dim_in, self.ker_par_5d)

        from scipy.optimize import check_grad
        err = check_grad(self._total_nlml, self._total_nlml_grad, lhyp, kernel,
                         y.T, x)
        print(err)
        self.assertTrue(err <= 1e-5, 'Gradient error: {:.4f}'.format(err))
Exemple #10
0
    def test_apply(self):
        dyn = Pendulum2DTransition(GaussRV(2), GaussRV(2))
        f = dyn.dyn_eval
        dim_in, dim_out = dyn.dim_in, dyn.dim_state
        ker_par = np.hstack((np.ones((dim_out, 1)), 3 * np.ones(
            (dim_out, dim_in))))
        tf = MultiOutputGaussianProcessTransform(dim_in, dim_out, ker_par)
        mean, cov = np.zeros(dim_in, ), np.eye(dim_in)
        tmean, tcov, tccov = tf.apply(f, mean, cov, np.atleast_1d(1.0))
        print("Transformed moments\nmean: {}\ncov: {}\nccov: {}".format(
            tmean, tcov, tccov))

        # test positive definiteness
        try:
            la.cholesky(tcov)
        except la.LinAlgError:
            self.fail("Output covariance not positive definite.")

        # test symmetry
        self.assertTrue(np.allclose(tcov, tcov.T),
                        "Output covariance not closely symmetric.")
Exemple #11
0
def gpq_int_var_demo():
    """Compares integral variances of GPQ and GPQ+D by plotting."""
    d = 1
    f = UNGMTransition(GaussRV(d), GaussRV(d)).dyn_eval
    mean = np.zeros(d)
    cov = np.eye(d)
    kpar = np.array([[10.0] + d * [0.7]])
    gpq = GaussianProcessTransform(d,
                                   1,
                                   kern_par=kpar,
                                   kern_str='rbf',
                                   point_str='ut',
                                   point_par={'kappa': 0.0})
    gpqd = GaussianProcessDerTransform(d,
                                       1,
                                       kern_par=kpar,
                                       point_str='ut',
                                       point_par={'kappa': 0.0})
    mct = MonteCarloTransform(d, n=1e4)
    mean_gpq, cov_gpq, cc_gpq = gpq.apply(f, mean, cov, np.atleast_1d(1.0))
    mean_gpqd, cov_gpqd, cc_gpqd = gpqd.apply(f, mean, cov, np.atleast_1d(1.0))
    mean_mc, cov_mc, cc_mc = mct.apply(f, mean, cov, np.atleast_1d(1.0))

    xmin_gpq = norm.ppf(0.0001, loc=mean_gpq, scale=gpq.model.integral_var)
    xmax_gpq = norm.ppf(0.9999, loc=mean_gpq, scale=gpq.model.integral_var)
    xmin_gpqd = norm.ppf(0.0001, loc=mean_gpqd, scale=gpqd.model.integral_var)
    xmax_gpqd = norm.ppf(0.9999, loc=mean_gpqd, scale=gpqd.model.integral_var)
    xgpq = np.linspace(xmin_gpq, xmax_gpq, 500)
    ygpq = norm.pdf(xgpq, loc=mean_gpq, scale=gpq.model.integral_var)
    xgpqd = np.linspace(xmin_gpqd, xmax_gpqd, 500)
    ygpqd = norm.pdf(xgpqd, loc=mean_gpqd, scale=gpqd.model.integral_var)
    plt.figure()
    plt.plot(xgpq, ygpq, lw=2, label='gpq')
    plt.plot(xgpqd, ygpqd, lw=2, label='gpq+d')
    plt.gca().add_line(
        Line2D([mean_mc, mean_mc], [0, 150], linewidth=2, color='k'))
    plt.legend()
    plt.show()
Exemple #12
0
    def test_single_vs_multi_output(self):
        # results of the GPQ and GPQMO should be same if parameters properly chosen, GPQ is a special case of GPQMO
        m0 = np.array([6500.4, 349.14, -1.8093, -6.7967, 0.6932])
        P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
        x0 = GaussRV(5, m0, P0)
        dyn = ReentryVehicle2DTransition(x0, GaussRV(5))
        f = dyn.dyn_eval
        dim_in, dim_out = dyn.dim_in, dyn.dim_state

        # input mean and covariance
        mean_in, cov_in = m0, P0

        # single-output GPQ
        ker_par_so = np.hstack((np.ones((1, 1)), 25 * np.ones((1, dim_in))))
        tf_so = GaussianProcessTransform(dim_in, dim_out, ker_par_so)

        # multi-output GPQ
        ker_par_mo = np.hstack((np.ones((dim_out, 1)), 25 * np.ones(
            (dim_out, dim_in))))
        tf_mo = MultiOutputGaussianProcessTransform(dim_in, dim_out,
                                                    ker_par_mo)

        # transformed moments
        # FIXME: transformed covariances different
        mean_so, cov_so, ccov_so = tf_so.apply(f, mean_in, cov_in,
                                               np.atleast_1d(0))
        mean_mo, cov_mo, ccov_mo = tf_mo.apply(f, mean_in, cov_in,
                                               np.atleast_1d(0))

        print('mean delta: {}'.format(np.abs(mean_so - mean_mo).max()))
        print('cov delta: {}'.format(np.abs(cov_so - cov_mo).max()))
        print('ccov delta: {}'.format(np.abs(ccov_so - ccov_mo).max()))

        # results of GPQ and GPQMO should be the same
        self.assertTrue(np.array_equal(mean_so, mean_mo))
        self.assertTrue(np.array_equal(cov_so, cov_mo))
        self.assertTrue(np.array_equal(ccov_so, ccov_mo))
Exemple #13
0
    def test_hypers_optim_multioutput(self):
        m0 = np.array([1000, 300, 1000, 0, np.deg2rad(-3)])
        P0 = np.diag([100, 10, 100, 10, 0.1])
        x0 = GaussRV(5, m0, P0)
        dyn = CoordinatedTurnTransition(x0, GaussRV(5))
        func = dyn.dyn_eval
        dim_in, dim_out = dyn.dim_in, dyn.dim_state

        model = StudentTProcessModel(dim_in, self.ker_par_5d, 'rbf',
                                     'ut')  # , point_hyp={'degree': 10})
        x = m0[:,
               na] + model.points  # ssm.get_pars('x0_cov')[0].dot(model.points)
        y = np.apply_along_axis(func, 0, x, None)  # (d_out, n**2)

        # lhyp0 = np.log(np.ones((dim_out, dim_in+1)))
        lhyp0 = np.log(10 + np.ones((1, dim_in + 1)))

        res_ml2 = model.optimize(lhyp0, y.T, model.points, method='BFGS')
        hyp_ml2 = np.exp(res_ml2.x)

        print(res_ml2)
        np.set_printoptions(precision=4)
        print('ML-II({:.4f}) @ alpha: {:.4f}, el: {}'.format(
            res_ml2.fun, hyp_ml2[0], hyp_ml2[1:]))
Exemple #14
0
    def test_radar(self):
        r = GaussRV(2)
        dim_state = 5
        st_ind = np.array([0, 2])
        radar_location = np.array([6378.0, 0])
        obs = Radar2DMeasurement(r,
                                 dim_state,
                                 state_index=st_ind,
                                 radar_loc=radar_location)
        st, n = np.random.randn(5), np.random.randn(2)

        # check evaluation of the measurement function
        hx = obs.meas_eval(st, n, dx=False)
        self.assertTrue(hx.shape == (2, ))

        jac = obs.meas_eval(st, n, dx=True)
        # check proper dimensions
        self.assertEqual(jac.shape, (2, 5))
        # non-zero columns only at state_indexes
        self.assertTrue(np.array_equal(np.nonzero(jac.sum(axis=0))[0], st_ind))
Exemple #15
0
    def setUpClass(cls):
        # setup UNGM
        x0 = GaussRV(1, cov=np.atleast_2d(1.0))
        q = GaussRV(1, cov=np.atleast_2d(10.0))
        cls.dyn_ungm = UNGMTransition(x0, q)
        r = GaussRV(1, cov=np.atleast_2d(1.0))
        cls.obs_ungm = UNGMMeasurement(r, 1)

        # setup pendulum
        dt = 0.01
        x0 = GaussRV(2, np.array([1.5, 0]), 0.01 * np.eye(2))
        q = GaussRV(2, cov=np.array([[dt**3 / 3, dt**2 / 2], [dt**2 / 2, dt]]))
        cls.dyn_pend = Pendulum2DTransition(x0, q, dt)
        r = GaussRV(1, cov=np.atleast_2d(0.1))
        cls.obs_pend = Pendulum2DMeasurement(r, cls.dyn_pend.dim_state)
Exemple #16
0
    def setUpClass(cls):
        cls.ssm = {}
        # setup UNGM
        x0 = GaussRV(1)
        q = GaussRV(1, cov=np.array([[10.0]]))
        r = GaussRV(1)
        dyn = UNGMTransition(x0, q)
        obs = UNGMMeasurement(r, 1)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'ungm': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})

        # setup UNGM with non-additive noise
        x0 = GaussRV(1)
        q = GaussRV(1, cov=np.array([[10.0]]))
        r = GaussRV(1)
        dyn = UNGMNATransition(x0, q)
        obs = UNGMNAMeasurement(r, 1)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'ungmna': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})

        # setup 2D pendulum
        x0 = GaussRV(2, mean=np.array([1.5, 0]), cov=0.01 * np.eye(2))
        dt = 0.01
        q = GaussRV(2,
                    cov=0.01 * np.array([[(dt**3) / 3,
                                          (dt**2) / 2], [(dt**2) / 2, dt]]))
        r = GaussRV(1, cov=np.array([[0.1]]))
        dyn = Pendulum2DTransition(x0, q, dt=dt)
        obs = Pendulum2DMeasurement(r, dyn.dim_state)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'pend': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})

        # setup reentry vehicle radar tracking
        m0 = np.array([6500.4, 349.14, -1.8093, -6.7967, 0.6932])
        P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
        x0 = GaussRV(5, m0, P0)
        q = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 1e-6]))
        r = GaussRV(2, cov=np.diag([1e-6, 0.17e-6]))
        dyn = ReentryVehicle2DTransition(x0, q)
        obs = Radar2DMeasurement(r, 5)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'rer': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})

        # setup coordinated turn bearing only tracking
        m0 = np.array([1000, 300, 1000, 0, np.deg2rad(-3.0)])
        P0 = np.diag([100, 10, 100, 10, 0.1])
        x0 = GaussRV(5, m0, P0)
        dt = 0.1
        rho_1, rho_2 = 0.1, 1.75e-4
        A = np.array([[dt**3 / 3, dt**2 / 2], [dt**2 / 2, dt]])
        Q = np.zeros((5, 5))
        Q[:2, :2], Q[2:4, 2:4], Q[4, 4] = rho_1 * A, rho_1 * A, rho_2 * dt
        q = GaussRV(5, cov=Q)
        r = GaussRV(4, cov=10e-3 * np.eye(4))
        sen = np.vstack((1000 * np.eye(2), -1000 * np.eye(2))).astype(np.float)
        dyn = CoordinatedTurnTransition(x0, q)
        obs = BearingMeasurement(r, 5, state_index=[0, 2], sensor_pos=sen)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'ctb': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})

        # setup CTRS with radar measurements
        x0 = GaussRV(5, cov=0.1 * np.eye(5))
        q = GaussRV(2, cov=np.diag([0.1, 0.1 * np.pi]))
        r = GaussRV(2, cov=np.diag([0.3, 0.03]))
        dyn = ConstantTurnRateSpeed(x0, q)
        obs = Radar2DMeasurement(r, 5)
        x = dyn.simulate_discrete(100)
        y = obs.simulate_measurements(x)
        cls.ssm.update({'ctrs': {'dyn': dyn, 'obs': obs, 'x': x, 'y': y}})
Exemple #17
0
import time

import numpy as np
import pandas as pd

from research.gpq.icinco_demo import evaluate_performance
from ssmtoybox.mtran import UnscentedTransform
from ssmtoybox.ssinf import ExtendedKalman, ExtendedKalmanGPQD
from ssmtoybox.ssmod import UNGMTransition, UNGMMeasurement
from ssmtoybox.utils import GaussRV

steps, mc = 50, 10  # time steps, mc simulations

# setup univariate non-stationary growth model
x0 = GaussRV(1, cov=np.atleast_2d(5.0))
q = GaussRV(1, cov=np.atleast_2d(10.0))
dyn = UNGMTransition(x0, q)  # dynamics
r = GaussRV(1)
obs = UNGMMeasurement(r, 1)  # observation model

x = dyn.simulate_discrete(steps, mc)
z = obs.simulate_measurements(x)

# use only the central sigma-point
usp_0 = np.zeros((dyn.dim_in, 1))
usp_ut = UnscentedTransform.unit_sigma_points(dyn.dim_in)

# set the RBF kernel hyperparameters
hyp_rbf = np.array([[1.0] + dyn.dim_in * [3.0]])
hyp_rbf_ut = np.array([[8.0] + dyn.dim_in * [0.5]])
Exemple #18
0
def ukf_trunc_demo(mc_sims=50):
    disc_tau = 0.5  # discretization period in seconds
    duration = 200

    # define system
    m0 = np.array([6500.4, 349.14, -1.8093, -6.7967, 0.6932])
    P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 0])
    x0 = GaussRV(5, m0, P0)
    q = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 0]))
    sys = ReentryVehicle2DTransition(x0, q, dt=disc_tau)
    # define radar measurement model
    r = GaussRV(2, cov=np.diag([1e-6, 0.17e-6]))
    obs = Radar2DMeasurement(r, sys.dim_state)

    # simulate reference state trajectory by SDE integration
    x = sys.simulate_continuous(duration, disc_tau, mc_sims)
    x_ref = x.mean(axis=2)
    # simulate corresponding radar measurements
    y = obs.simulate_measurements(x)

    # initialize state-space model; uses cartesian2polar as measurement (not polar2cartesian)
    P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
    x0 = GaussRV(5, m0, P0)
    q = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 1e-6]))
    dyn = ReentryVehicle2DTransition(x0, q, dt=disc_tau)

    # initialize UKF and UKF in truncated version
    alg = (
        UnscentedKalman(dyn, obs),
        TruncatedUnscentedKalman(dyn, obs),
    )
    num_alg = len(alg)

    # space for filtered mean and covariance
    steps = x.shape[1]
    x_mean = np.zeros((dyn.dim_in, steps, mc_sims, num_alg))
    x_cov = np.zeros((dyn.dim_in, dyn.dim_in, steps, mc_sims, num_alg))

    # filtering estimate of the state trajectory based on provided measurements
    from tqdm import trange
    for i_est, estimator in enumerate(alg):
        for i_mc in trange(mc_sims):
            x_mean[..., i_mc, i_est], x_cov[..., i_mc, i_est] = estimator.forward_pass(y[..., i_mc])
            estimator.reset()

    # Plots
    plt.figure()
    g = GridSpec(2, 4)
    plt.subplot(g[:, :2])

    # Earth surface w/ radar position
    radar_x, radar_y = dyn.R0, 0
    t = 0.02 * np.arange(-1, 4, 0.1)
    plt.plot(dyn.R0 * np.cos(t), dyn.R0 * np.sin(t), color='darkblue', lw=2)
    plt.plot(radar_x, radar_y, 'ko')

    plt.plot(x_ref[0, :], x_ref[1, :], color='r', ls='--')
    # Convert from polar to cartesian
    meas = np.stack(( + y[0, ...] * np.cos(y[1, ...]), radar_y + y[0, ...] * np.sin(y[1, ...])), axis=0)
    for i in range(mc_sims):
        # Vehicle trajectory
        # plt.plot(x[0, :, i], x[1, :, i], alpha=0.35, color='r', ls='--')

        # Plot measurements
        plt.plot(meas[0, :, i], meas[1, :, i], 'k.', alpha=0.3)

        # Filtered position estimate
        plt.plot(x_mean[0, 1:, i, 0], x_mean[1, 1:, i, 0], color='g', alpha=0.3)
        plt.plot(x_mean[0, 1:, i, 1], x_mean[1, 1:, i, 1], color='orange', alpha=0.3)

    # Performance score plots
    error2 = x_mean.copy()
    lcr = np.zeros((steps, mc_sims, num_alg))
    for a in range(num_alg):
        for k in range(steps):
            mse = mse_matrix(x[:4, k, :], x_mean[:4, k, :, a])
            for imc in range(mc_sims):
                error2[:, k, imc, a] = squared_error(x[:, k, imc], x_mean[:, k, imc, a])
                lcr[k, imc, a] = log_cred_ratio(x[:4, k, imc], x_mean[:4, k, imc, a], x_cov[:4, :4, k, imc, a], mse)

    # Averaged RMSE and Inclination Indicator in time
    pos_rmse_vs_time = np.sqrt((error2[:2, ...]).sum(axis=0)).mean(axis=1)
    inc_ind_vs_time = lcr.mean(axis=1)

    # Plots
    plt.subplot(g[0, 2:])
    plt.title('RMSE')
    plt.plot(pos_rmse_vs_time[:, 0], label='UKF', color='g')
    plt.plot(pos_rmse_vs_time[:, 1], label='UKF-trunc', color='r')
    plt.legend()
    plt.subplot(g[1, 2:])
    plt.title('Inclination Indicator $I^2$')
    plt.plot(inc_ind_vs_time[:, 0], label='UKF', color='g')
    plt.plot(inc_ind_vs_time[:, 1], label='UKF-trunc', color='r')
    plt.legend()
    plt.show()

    print('Average RMSE: {}'.format(pos_rmse_vs_time.mean(axis=0)))
    print('Average I2: {}'.format(inc_ind_vs_time.mean(axis=0)))
Exemple #19
0
 def setUpClass(cls):
     cls.models = []
     cls.models.append(UNGMTransition(GaussRV(1), GaussRV(1)))
     cls.models.append(Pendulum2DTransition(GaussRV(2), GaussRV(2)))
Exemple #20
0
def tables():
    steps, mc = 500, 100
    # initialize UNGM model
    dyn = UNGMTransition(GaussRV(1, cov=5.0), GaussRV(1, cov=10.0))
    obs = UNGMMeasurement(GaussRV(1, cov=1.0), 1)
    # generate some data
    np.random.seed(0)
    x = dyn.simulate_discrete(steps, mc)
    z = obs.simulate_measurements(x)

    par_ut = np.array([[3.0, 0.3]])
    par_gh5 = np.array([[5.0, 0.6]])
    par_gh7 = np.array([[3.0, 0.4]])

    mulind_ut = np.array([[0, 1, 2]])
    mulind_gh = lambda degree: np.atleast_2d(np.arange(degree))

    # initialize filters/smoothers
    algorithms = (
        # Classical filters
        UnscentedKalman(dyn, obs, alpha=1.0, beta=0.0),
        GaussHermiteKalman(dyn, obs, deg=5),
        GaussHermiteKalman(dyn, obs, deg=7),
        # GPQ filters
        GaussianProcessKalman(dyn,
                              obs,
                              par_ut,
                              par_ut,
                              kernel='rbf',
                              points='ut',
                              point_hyp={'alpha': 1.0}),
        GaussianProcessKalman(dyn,
                              obs,
                              par_gh5,
                              par_gh5,
                              kernel='rbf',
                              points='gh',
                              point_hyp={'degree': 5}),
        GaussianProcessKalman(dyn,
                              obs,
                              par_gh7,
                              par_gh7,
                              kernel='rbf',
                              points='gh',
                              point_hyp={'degree': 7}),
        # BSQ filters
        BayesSardKalman(dyn,
                        obs,
                        par_ut,
                        par_ut,
                        mulind_ut,
                        mulind_ut,
                        points='ut',
                        point_hyp={'alpha': 1.0}),
        BayesSardKalman(dyn,
                        obs,
                        par_gh5,
                        par_gh5,
                        mulind_gh(5),
                        mulind_gh(5),
                        points='gh',
                        point_hyp={'degree': 5}),
        BayesSardKalman(dyn,
                        obs,
                        par_gh7,
                        par_gh7,
                        mulind_gh(7),
                        mulind_gh(7),
                        points='gh',
                        point_hyp={'degree': 7}),
    )
    num_algs = len(algorithms)

    # space for estimates
    dim = dyn.dim_state
    mean_f, cov_f = np.zeros((dim, steps, mc, num_algs)), np.zeros(
        (dim, dim, steps, mc, num_algs))
    mean_s, cov_s = np.zeros((dim, steps, mc, num_algs)), np.zeros(
        (dim, dim, steps, mc, num_algs))
    # do filtering/smoothing
    t0 = time.time()  # measure execution time
    print('Running filters/smoothers ...')
    for a, alg in enumerate(algorithms):
        print('{}'.format(
            alg.__class__.__name__))  # print filter/smoother name
        for sim in range(mc):
            mean_f[..., sim, a], cov_f[..., sim, a] = alg.forward_pass(z[...,
                                                                         sim])
            mean_s[..., sim, a], cov_s[..., sim, a] = alg.backward_pass()
            alg.reset()
    print('Done in {0:.4f} [sec]'.format(time.time() - t0))

    # evaluate perfomance
    scores = evaluate_performance(x, mean_f, cov_f, mean_s, cov_s)
    rmseMean_f, nciMean_f, nllMean_f, rmseMean_s, nciMean_s, nllMean_s = scores[:
                                                                                6]
    rmseStd_f, nciStd_f, nllStd_f, rmseStd_s, nciStd_s, nllStd_s = scores[6:]

    # put data into Pandas DataFrame for fancy printing and latex export
    # row_labels = ['SR', 'UT', 'GH-5', 'GH-7', 'GH-10', 'GH-15', 'GH-20']
    row_labels = ['UT', 'GH-5', 'GH-7']
    num_labels = len(row_labels)
    col_labels = [
        'Classical', 'GPQ', 'BSQ', 'Classical (2std)', 'GPQ (2std)',
        'BSQ (2std)'
    ]
    rmse_table_f = pd.DataFrame(np.hstack(
        (rmseMean_f.reshape(3,
                            num_labels).T, rmseStd_f.reshape(3,
                                                             num_labels).T)),
                                index=row_labels,
                                columns=col_labels)
    nci_table_f = pd.DataFrame(np.hstack(
        (nciMean_f.reshape(3, num_labels).T, nciStd_f.reshape(3,
                                                              num_labels).T)),
                               index=row_labels,
                               columns=col_labels)
    nll_table_f = pd.DataFrame(np.hstack(
        (nllMean_f.reshape(3, num_labels).T, nllStd_f.reshape(3,
                                                              num_labels).T)),
                               index=row_labels,
                               columns=col_labels)
    rmse_table_s = pd.DataFrame(np.hstack(
        (rmseMean_s.reshape(3,
                            num_labels).T, rmseStd_s.reshape(3,
                                                             num_labels).T)),
                                index=row_labels,
                                columns=col_labels)
    nci_table_s = pd.DataFrame(np.hstack(
        (nciMean_s.reshape(3, num_labels).T, nciStd_s.reshape(3,
                                                              num_labels).T)),
                               index=row_labels,
                               columns=col_labels)
    nll_table_s = pd.DataFrame(np.hstack(
        (nllMean_s.reshape(3, num_labels).T, nllStd_s.reshape(3,
                                                              num_labels).T)),
                               index=row_labels,
                               columns=col_labels)

    # print kernel parameters
    print('Kernel parameters')
    print('{:5}: {}'.format('UT', par_ut))
    print('{:5}: {}'.format('GH-5', par_gh5))
    print('{:5}: {}'.format('GH-7', par_gh7))
    print()

    # print tables
    pd.set_option('precision', 2, 'display.max_columns', 6)
    print('Filter RMSE')
    print(rmse_table_f)
    print('Filter NCI')
    print(nci_table_f)
    print('Filter NLL')
    print(nll_table_f)
    print('Smoother RMSE')
    print(rmse_table_s)
    print('Smoother NCI')
    print(nci_table_s)
    print('Smoother NLL')
    print(nll_table_s)
    # return computed metrics for filters and smoothers
    return {
        'filter_RMSE': rmse_table_f,
        'filter_NCI': nci_table_f,
        'filter_NLL': nll_table_f,
        'smoother_RMSE': rmse_table_s,
        'smoother_NCI': nci_table_s,
        'smoother_NLL': nll_table_s
    }
Exemple #21
0
def lengthscale_filter_demo(lscale):
    steps, mc = 500, 20
    # initialize UNGM model
    dyn = UNGMTransition(GaussRV(1, cov=5.0), GaussRV(1, cov=10.0))
    obs = UNGMMeasurement(GaussRV(1, cov=1.0), 1)
    # generate some data
    x = dyn.simulate_discrete(steps, mc)
    z = obs.simulate_measurements(x)

    dim = dyn.dim_state
    num_el = len(lscale)
    # lscale = [1e-3, 3e-3, 1e-2, 3e-2, 1e-1, 3e-1, 1, 3, 1e1, 3e1]  # , 1e2, 3e2]
    mean_f, cov_f = np.zeros((dim, steps, mc, num_el)), np.zeros(
        (dim, dim, steps, mc, num_el))
    for iel, el in enumerate(lscale):

        # kernel parameters
        ker_par = np.array([[1.0, el * dim]])

        # initialize BHKF with current lenghtscale
        f = GaussianProcessKalman(dyn,
                                  obs,
                                  ker_par,
                                  ker_par,
                                  kernel='rbf',
                                  points='ut')
        # filtering
        for s in range(mc):
            mean_f[..., s, iel], cov_f[..., s, iel] = f.forward_pass(z[..., s])

    # evaluate RMSE, NCI and NLL
    rmseVsEl = squared_error(x[..., na], mean_f)
    nciVsEl = rmseVsEl.copy()
    nllVsEl = rmseVsEl.copy()
    for k in range(steps):
        for iel in range(num_el):
            mse_mat = mse_matrix(x[:, k, :], mean_f[:, k, :, iel])
            for s in range(mc):
                nciVsEl[:, k, s,
                        iel] = log_cred_ratio(x[:, k, s], mean_f[:, k, s, iel],
                                              cov_f[:, :, k, s, iel], mse_mat)
                nllVsEl[:, k, s,
                        iel] = neg_log_likelihood(x[:, k, s], mean_f[:, k, s,
                                                                     iel],
                                                  cov_f[:, :, k, s, iel])

    # average out time and MC simulations
    rmseVsEl = np.sqrt(np.mean(rmseVsEl, axis=1)).mean(axis=1)
    nciVsEl = nciVsEl.mean(axis=(1, 2))
    nllVsEl = nllVsEl.mean(axis=(1, 2))

    # plot influence of changing lengthscale on the RMSE and NCI and NLL filter performance
    plt.figure()
    plt.semilogx(lscale,
                 rmseVsEl.squeeze(),
                 color='k',
                 ls='-',
                 lw=2,
                 marker='o',
                 label='RMSE')
    plt.semilogx(lscale,
                 nciVsEl.squeeze(),
                 color='k',
                 ls='--',
                 lw=2,
                 marker='o',
                 label='NCI')
    plt.semilogx(lscale,
                 nllVsEl.squeeze(),
                 color='k',
                 ls='-.',
                 lw=2,
                 marker='o',
                 label='NLL')
    plt.grid(True)
    plt.legend()
    plt.show()

    plot_data = {
        'el': lscale,
        'rmse': rmseVsEl,
        'nci': nciVsEl,
        'neg_log_likelihood': nllVsEl
    }
    return plot_data
Exemple #22
0
def tables(steps=500, sims=100):
    # setup univariate non-stationary growth model
    x0 = GaussRV(1, cov=np.atleast_2d(5.0))
    q = GaussRV(1, cov=np.atleast_2d(10.0))
    dyn = UNGMTransition(x0, q)  # dynamics
    r = GaussRV(1)
    obs = UNGMMeasurement(r, 1)  # observation model
    x = dyn.simulate_discrete(steps, mc_sims=sims)  # generate some data
    z = obs.simulate_measurements(x)

    kern_par_sr = np.array([[1.0, 0.3 * dyn.dim_in]])
    kern_par_ut = np.array([[1.0, 3.0 * dyn.dim_in]])
    kern_par_gh = np.array([[1.0, 0.1 * dyn.dim_in]])

    # initialize filters/smoothers
    algorithms = (
        CubatureKalman(dyn, obs),
        UnscentedKalman(dyn, obs),
        GaussHermiteKalman(dyn, obs),
        GaussHermiteKalman(dyn, obs),
        GaussHermiteKalman(dyn, obs),
        GaussHermiteKalman(dyn, obs),
        GaussHermiteKalman(dyn, obs),
        GaussianProcessKalman(dyn, obs, kern_par_sr, kern_par_sr, points='sr'),
        GaussianProcessKalman(dyn, obs, kern_par_ut, kern_par_ut, points='ut'),
        GaussianProcessKalman(dyn, obs, kern_par_sr, kern_par_sr, points='gh', point_hyp={'degree': 5}),
        GaussianProcessKalman(dyn, obs, kern_par_gh, kern_par_gh, points='gh', point_hyp={'degree': 7}),
        GaussianProcessKalman(dyn, obs, kern_par_gh, kern_par_gh, points='gh', point_hyp={'degree': 10}),
        GaussianProcessKalman(dyn, obs, kern_par_gh, kern_par_gh, points='gh', point_hyp={'degree': 15}),
        GaussianProcessKalman(dyn, obs, kern_par_gh, kern_par_gh, points='gh', point_hyp={'degree': 20}),
    )
    num_algs = len(algorithms)

    # space for estimates
    mean_f, cov_f = np.zeros((dyn.dim_in, steps, sims, num_algs)), np.zeros((dyn.dim_in, dyn.dim_in, steps, sims, num_algs))
    mean_s, cov_s = np.zeros((dyn.dim_in, steps, sims, num_algs)), np.zeros((dyn.dim_in, dyn.dim_in, steps, sims, num_algs))
    # do filtering/smoothing
    t0 = time.time()  # measure execution time
    print('Running filters/smoothers ...', flush=True)
    for a, alg in enumerate(algorithms):
        for sim in trange(sims, desc='{:25}'.format(alg.__class__.__name__), file=sys.stdout):
            mean_f[..., sim, a], cov_f[..., sim, a] = alg.forward_pass(z[..., sim])
            mean_s[..., sim, a], cov_s[..., sim, a] = alg.backward_pass()
            alg.reset()
    print('Done in {0:.4f} [sec]'.format(time.time() - t0))

    # evaluate perfomance
    scores = evaluate_performance(x, mean_f, cov_f, mean_s, cov_s)
    rmseMean_f, nciMean_f, nllMean_f, rmseMean_s, nciMean_s, nllMean_s = scores[:6]
    rmseStd_f, nciStd_f, nllStd_f, rmseStd_s, nciStd_s, nllStd_s = scores[6:]

    # put data into Pandas DataFrame for fancy printing and latex export
    row_labels = ['SR', 'UT', 'GH-5', 'GH-7', 'GH-10', 'GH-15',
                  'GH-20']  # [alg.__class__.__name__ for alg in algorithms]
    col_labels = ['Classical', 'Bayesian', 'Classical (2std)', 'Bayesian (2std)']
    rmse_table_f = pd.DataFrame(np.hstack((rmseMean_f.reshape(2, 7).T, rmseStd_f.reshape(2, 7).T)),
                                index=row_labels, columns=col_labels)
    nci_table_f = pd.DataFrame(np.hstack((nciMean_f.reshape(2, 7).T, nciStd_f.reshape(2, 7).T)),
                               index=row_labels, columns=col_labels)
    nll_table_f = pd.DataFrame(np.hstack((nllMean_f.reshape(2, 7).T, nllStd_f.reshape(2, 7).T)),
                               index=row_labels, columns=col_labels)
    rmse_table_s = pd.DataFrame(np.hstack((rmseMean_s.reshape(2, 7).T, rmseStd_s.reshape(2, 7).T)),
                                index=row_labels, columns=col_labels)
    nci_table_s = pd.DataFrame(np.hstack((nciMean_s.reshape(2, 7).T, nciStd_s.reshape(2, 7).T)),
                               index=row_labels, columns=col_labels)
    nll_table_s = pd.DataFrame(np.hstack((nllMean_s.reshape(2, 7).T, nllStd_s.reshape(2, 7).T)),
                               index=row_labels, columns=col_labels)
    # print tables
    print('Filter RMSE')
    print(rmse_table_f)
    print('Filter NCI')
    print(nci_table_f)
    print('Filter NLL')
    print(nll_table_f)
    print('Smoother RMSE')
    print(rmse_table_s)
    print('Smoother NCI')
    print(nci_table_s)
    print('Smoother NLL')
    print(nll_table_s)
    # return computed metrics for filters and smoothers
    return {'filter_RMSE': rmse_table_f, 'filter_NCI': nci_table_f, 'filter_NLL': nll_table_f,
            'smoother_RMSE': rmse_table_s, 'smoother_NCI': nci_table_s, 'smoother_NLL': nll_table_s}
Exemple #23
0
def reentry_demo(dur=200, mc_sims=100, outfile=None):
    # use default filename if unspecified
    if outfile is None:
        outfile = 'reentry_demo_results.dat'
    outfile = os.path.join('..', outfile)

    if not os.path.exists(outfile) or True:
        tau = 0.05
        disc_tau = 0.1

        # initial condition statistics
        m0 = np.array([6500, 350, -1.8, -6.8, 0.7])
        P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 0])
        init_rv = GaussRV(5, m0, P0)

        # process noise statistics
        noise_rv = GaussRV(3, cov=np.diag([2.4e-5, 2.4e-5, 0]))
        sys = ReentryVehicle2DTransition(init_rv, noise_rv)

        # measurement noise statistics
        meas_noise_rv = GaussRV(2, cov=np.diag([1e-6, 0.17e-6]))
        obs = Radar2DMeasurement(meas_noise_rv,
                                 5,
                                 radar_loc=np.array([6374, 0.0]))

        np.random.seed(0)
        # Generate reference trajectory by SDE simulation
        x = sys.simulate_continuous(duration=dur, dt=tau, mc_sims=mc_sims)
        y = obs.simulate_measurements(x)

        # subsample data for the filter and performance score calculation
        x = x[:, ::2, ...]  # take every second point on the trajectory
        y = y[:, ::2, ...]  # and corresponding measurement

        # Initialize state-space model with mis-specified initial mean
        # m0 = np.array([6500.4, 349.14, -1.1093, -6.1967, 0.6932])
        m0 = np.array([6500, 350, -1.1, -6.1, 0.7])
        P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
        init_rv = GaussRV(5, m0, P0)
        noise_rv = GaussRV(3, cov=np.diag([2.4e-5, 2.4e-5, 1e-6]))
        dyn = ReentryVehicle2DTransition(init_rv, noise_rv, dt=disc_tau)
        # NOTE: higher tau causes higher spread of trajectories at the ends

        # Initialize filters
        par_dyn = np.array([[1.0, 1, 1, 1, 1, 1]])
        par_obs = np.array([[1.0, 0.9, 0.9, 1e4, 1e4,
                             1e4]])  # np.atleast_2d(np.ones(6))
        mul_ut = np.hstack((np.zeros((dyn.dim_in, 1)), np.eye(dyn.dim_in),
                            2 * np.eye(dyn.dim_in))).astype(np.int)
        alg = OrderedDict({
            # GaussianProcessKalman(ssm, par_dyn, par_obs, kernel='rbf', points='ut'),
            'bsqkf':
            BayesSardKalman(dyn,
                            obs,
                            par_dyn,
                            par_obs,
                            mul_ut,
                            mul_ut,
                            points='ut'),
            'bsqkf_2e-6':
            BayesSardKalman(dyn,
                            obs,
                            par_dyn,
                            par_obs,
                            mul_ut,
                            mul_ut,
                            points='ut'),
            'bsqkf_2e-7':
            BayesSardKalman(dyn,
                            obs,
                            par_dyn,
                            par_obs,
                            mul_ut,
                            mul_ut,
                            points='ut'),
            'ukf':
            UnscentedKalman(dyn, obs, beta=0.0),
        })

        alg['bsqkf'].tf_dyn.model.model_var = np.diag(
            [0.0002, 0.0002, 0.0002, 0.0002, 0.0002])
        alg['bsqkf'].tf_obs.model.model_var = 0 * np.eye(2)
        alg['bsqkf_2e-6'].tf_dyn.model.model_var = 2e-6 * np.eye(5)
        alg['bsqkf_2e-6'].tf_obs.model.model_var = 0 * np.eye(2)
        alg['bsqkf_2e-7'].tf_dyn.model.model_var = 2e-7 * np.eye(5)
        alg['bsqkf_2e-7'].tf_obs.model.model_var = 0 * np.eye(2)

        # print experiment setup
        print('System (reality)')
        print('{:10s}: {}'.format('x0_mean', sys.init_rv.mean))
        print('{:10s}: {}'.format('x0_cov', sys.init_rv.cov.diagonal()))
        print()
        print('State-Space Model')
        print('{:10s}: {}'.format('x0_mean', dyn.init_rv.mean))
        print('{:10s}: {}'.format('x0_cov', dyn.init_rv.cov.diagonal()))
        print()
        print('BSQ Expected Model Variance')
        print('{:10s}: {}'.format(
            'dyn_func', alg['bsqkf'].tf_dyn.model.model_var.diagonal()))
        print('{:10s}: {}'.format(
            'obs_func', alg['bsqkf'].tf_obs.model.model_var.diagonal()))
        print()

        num_alg = len(alg)
        d, steps, mc_sims = x.shape
        mean, cov = np.zeros((d, steps, mc_sims, num_alg)), np.zeros(
            (d, d, steps, mc_sims, num_alg))
        for ia, a in enumerate(alg):
            print('Running {:<5} ... '.format(a.upper()), end='', flush=True)
            t0 = time.time()
            for imc in range(mc_sims):
                mean[..., imc, ia], cov[..., imc,
                                        ia] = alg[a].forward_pass(y[..., imc])
                alg[a].reset()
            print('{:>30}'.format('Done in {:.2f} [sec]'.format(time.time() -
                                                                t0)))

        # Performance score plots
        print()
        print('Computing performance scores ...')
        error2 = mean.copy()
        lcr_x = np.zeros((steps, mc_sims, num_alg))
        lcr_pos = lcr_x.copy()
        lcr_vel = lcr_x.copy()
        lcr_theta = lcr_x.copy()
        for a in range(num_alg):
            for k in range(steps):
                mse = mse_matrix(x[:, k, :], mean[:, k, :, a])
                for imc in range(mc_sims):
                    error2[:, k, imc,
                           a] = squared_error(x[:, k, imc], mean[:, k, imc, a])
                    lcr_x[k, imc,
                          a] = log_cred_ratio(x[:, k, imc], mean[:, k, imc, a],
                                              cov[:, :, k, imc, a], mse)
                    lcr_pos[k, imc,
                            a] = log_cred_ratio(x[:2, k, imc], mean[:2, k, imc,
                                                                    a],
                                                cov[:2, :2, k, imc,
                                                    a], mse[:2, :2])
                    lcr_vel[k, imc,
                            a] = log_cred_ratio(x[2:4, k, imc], mean[2:4, k,
                                                                     imc, a],
                                                cov[2:4, 2:4, k, imc,
                                                    a], mse[2:4, 2:4])
                    lcr_theta[k, imc,
                              a] = log_cred_ratio(x[4, k, imc], mean[4, k, imc,
                                                                     a],
                                                  cov[4, 4, k, imc, a], mse[4,
                                                                            4])

        # Averaged RMSE and Inclination Indicator in time
        x_rmse_vs_time = np.sqrt(error2.sum(axis=0)).mean(axis=1)
        pos_rmse_vs_time = np.sqrt((error2[:2, ...]).sum(axis=0)).mean(axis=1)
        vel_rmse_vs_time = np.sqrt((error2[2:4, ...]).sum(axis=0)).mean(axis=1)
        theta_rmse_vs_time = np.sqrt((error2[4, ...])).mean(axis=1)
        x_inc_vs_time = lcr_x.mean(axis=1)
        pos_inc_vs_time = lcr_pos.mean(axis=1)
        vel_inc_vs_time = lcr_vel.mean(axis=1)
        theta_inc_vs_time = lcr_theta.mean(axis=1)

        print('{:10s}: {}'.format('RMSE', x_rmse_vs_time.mean(axis=0)))
        print('{:10s}: {}'.format('INC', x_inc_vs_time.mean(axis=0)))

        # Save the simulation results into outfile
        data_dict = {
            'duration': dur,
            'disc_tau': disc_tau,
            'alg_str': list(alg.keys()),
            'x': x,
            'mean': mean,
            'cov': cov,
            'state': {
                'rmse': x_rmse_vs_time,
                'inc': x_inc_vs_time
            },
            'position': {
                'rmse': pos_rmse_vs_time,
                'inc': pos_inc_vs_time
            },
            'velocity': {
                'rmse': vel_rmse_vs_time,
                'inc': vel_inc_vs_time
            },
            'parameter': {
                'rmse': theta_rmse_vs_time,
                'inc': theta_inc_vs_time
            },
        }
        joblib.dump(data_dict, outfile)

        # Visualize simulation results, plots, tables
        reentry_demo_results(data_dict)
    else:
        reentry_demo_results(joblib.load(outfile))
Exemple #24
0
def reentry_analysis_demo(dur=50, mc_sims=10):
    tau = 0.05
    disc_tau = 0.1

    # initial condition statistics
    m0 = np.array([6500.4, 349.14, -1.8093, -6.7967, 0.6932])
    P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 0])
    init_rv = GaussRV(5, m0, P0)

    # process noise statistics
    noise_rv = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 0]))
    sys = ReentryVehicle2DTransition(init_rv, noise_rv)

    # measurement noise statistics
    dim_obs = 2
    meas_noise_rv = GaussRV(dim_obs, cov=np.diag([1e-6, 0.17e-6]))
    obs = Radar2DMeasurement(meas_noise_rv, 5, radar_loc=np.array([6374, 0.0]))

    np.random.seed(0)
    # Generate reference trajectory by SDE simulation
    x = sys.simulate_continuous(duration=dur, dt=tau, mc_sims=mc_sims)
    y = obs.simulate_measurements(x)

    # subsample data for the filter and performance score calculation
    x = x[:, ::2, ...]  # take every second point on the trajectory
    y = y[:, ::2, ...]  # and corresponding measurement

    # Initialize state-space model with mis-specified initial mean
    m0 = np.array([6500.4, 349.14, -1.1093, -6.1967, 0.6932])
    P0 = np.diag([1e-6, 1e-6, 1e-6, 1e-6, 1])
    init_rv = GaussRV(5, m0, P0)
    noise_rv = GaussRV(3, cov=np.diag([2.4064e-5, 2.4064e-5, 1e-6]))
    dyn = ReentryVehicle2DTransition(init_rv, noise_rv, dt=disc_tau)
    # NOTE: higher tau causes higher spread of trajectories at the ends

    # Initialize filters
    par_dyn = np.array([[1.0, 1, 1, 1, 1, 1]])
    par_obs = np.array([[1.0, 0.9, 0.9, 1e4, 1e4,
                         1e4]])  # np.atleast_2d(np.ones(6))
    mul_ut = np.hstack((np.zeros((dyn.dim_in, 1)), np.eye(dyn.dim_in),
                        2 * np.eye(dyn.dim_in))).astype(np.int)
    alg = OrderedDict({
        # GaussianProcessKalman(ssm, par_dyn, par_obs, kernel='rbf', points='ut'),
        'bsqkf':
        BayesSardKalman(dyn,
                        obs,
                        par_dyn,
                        par_obs,
                        mul_ut,
                        mul_ut,
                        points='ut'),
        'ukf':
        UnscentedKalman(dyn, obs, kappa=0.0, beta=2.0),
    })

    alg['bsqkf'].tf_dyn.model.model_var = np.diag([0.1, 0.1, 0.1, 0.1, 0.015])
    alg['bsqkf'].tf_obs.model.model_var = 0 * np.eye(2)
    print('BSQ EMV\ndyn: {} \nobs: {}'.format(
        alg['bsqkf'].tf_dyn.model.model_var.diagonal(),
        alg['bsqkf'].tf_obs.model.model_var.diagonal()))

    # FILTERING
    num_alg = len(alg)
    d, steps, mc_sims = x.shape
    mean, cov = np.zeros((d, steps, mc_sims, num_alg)), np.zeros(
        (d, d, steps, mc_sims, num_alg))
    mean_x, cov_x = mean.copy(), cov.copy()
    mean_y, cov_y = np.zeros((dim_obs, steps, mc_sims, num_alg)), np.zeros(
        (dim_obs, dim_obs, steps, mc_sims, num_alg))
    cov_yx = np.zeros((dim_obs, d, steps, mc_sims, num_alg))

    # y = np.hstack((np.zeros((dim_obs, 1, mc_sims)), y))
    for ia, a in enumerate(alg):
        print('Running {:<5} ... '.format(a.upper()), end='', flush=True)
        t0 = time.time()
        for imc in range(mc_sims):
            for k in range(steps):

                # TIME UPDATE
                alg[a]._time_update(k)
                # record predictive moments
                mean_x[:, k, imc,
                       ia], cov_x[..., k, imc,
                                  ia] = alg[a].x_mean_pr, alg[a].x_cov_pr
                mean_y[:, k, imc,
                       ia], cov_y[..., k, imc,
                                  ia] = alg[a].y_mean_pr, alg[a].y_cov_pr
                cov_yx[..., k, imc, ia] = alg[a].xy_cov

                # MEASUREMENT UPDATE
                alg[a]._measurement_update(y[:, k, imc])
                # record filtered moments
                mean[:, k, imc,
                     ia], cov[..., k, imc,
                              ia] = alg[a].x_mean_fi, alg[a].x_cov_fi

            # reset filter storage
            alg[a].reset()
        print('{:>30}'.format('Done in {:.2f} [sec]'.format(time.time() - t0)))