Beispiel #1
0
    def sample(self, n_timesteps, initial_state=None, random_state=None):
        '''Sample from model defined by the Unscented Kalman Filter

        Parameters
        ----------
        n_timesteps : int
            number of time steps
        initial_state : optional, [n_dim_state] array
            initial state.  If unspecified, will be sampled from initial state
            distribution.
        random_state : optional, int or Random
            random number generator
        '''
        (transition_functions, observation_functions, transition_covariance,
         observation_covariance, initial_state_mean,
         initial_state_covariance) = (self._initialize_parameters())

        n_dim_state = transition_covariance.shape[-1]
        n_dim_obs = observation_covariance.shape[-1]

        # logic for instantiating rng
        if random_state is None:
            rng = check_random_state(self.random_state)
        else:
            rng = check_random_state(random_state)

        # logic for selecting initial state
        if initial_state is None:
            initial_state = rng.multivariate_normal(initial_state_mean,
                                                    initial_state_covariance)

        # logic for generating samples
        x = np.zeros((n_timesteps, n_dim_state))
        z = np.zeros((n_timesteps, n_dim_obs))
        for t in range(n_timesteps):
            if t == 0:
                x[0] = initial_state
            else:
                transition_function = (_last_dims(transition_functions,
                                                  t - 1,
                                                  ndims=1)[0])
                transition_noise = (rng.multivariate_normal(
                    np.zeros(n_dim_state),
                    transition_covariance.newbyteorder('=')))
                x[t] = transition_function(x[t - 1], transition_noise)

            observation_function = (_last_dims(observation_functions,
                                               t,
                                               ndims=1)[0])
            observation_noise = (rng.multivariate_normal(
                np.zeros(n_dim_obs), observation_covariance.newbyteorder('=')))
            z[t] = observation_function(x[t], observation_noise)

        return (x, ma.asarray(z))
Beispiel #2
0
def augmented_unscented_filter(mu_0, sigma_0, f, g, Q, R, Z):
    '''Apply the Unscented Kalman Filter with arbitrary noise

    Parameters
    ----------
    mu_0 : [n_dim_state] array
        mean of initial state distribution
    sigma_0 : [n_dim_state, n_dim_state] array
        covariance of initial state distribution
    f : function or [T-1] array of functions
        state transition function(s). Takes in an the current state and the
        process noise and outputs the next state.
    g : function or [T] array of functions
        observation function(s). Takes in the current state and outputs the
        current observation.
    Q : [n_dim_state, n_dim_state] array
        transition covariance matrix
    R : [n_dim_state, n_dim_state] array
        observation covariance matrix

    Returns
    -------
    mu_filt : [T, n_dim_state] array
        mu_filt[t] = mean of state at time t given observations from times [0,
        t]
    sigma_filt : [T, n_dim_state, n_dim_state] array
        sigma_filt[t] = covariance of state at time t given observations from
        times [0, t]
    '''
    # extract size of key components
    T = Z.shape[0]
    n_dim_state = Q.shape[-1]
    n_dim_obs = R.shape[-1]

    # construct container for results
    mu_filt = np.zeros((T, n_dim_state))
    sigma_filt = np.zeros((T, n_dim_state, n_dim_state))

    for t in range(T):
        # Calculate sigma points for augmented state:
        #   [actual state, transition noise, observation noise]
        if t == 0:
            mu, sigma = mu_0, sigma_0
        else:
            mu, sigma = mu_filt[t - 1], sigma_filt[t - 1]

        # extract sigma points using augmented representation
        (points_state, points_transition,
         points_observation) = (augmented_unscented_filter_points(
             mu, sigma, Q, R))

        # Calculate E[x_t | z_{0:t-1}], Var(x_t | z_{0:t-1}) and sigma points
        # for P(x_t | z_{0:t-1})
        if t == 0:
            points_pred = points_state
            moments_pred = points2moments(points_pred)
        else:
            transition_function = _last_dims(f, t - 1, ndims=1)[0]
            (points_pred, moments_pred) = (unscented_filter_predict(
                transition_function,
                points_state,
                points_transition=points_transition))

        # Calculate E[z_t | z_{0:t-1}], Var(z_t | z_{0:t-1})
        observation_function = _last_dims(g, t, ndims=1)[0]
        mu_filt[t], sigma_filt[t] = (unscented_filter_correct(
            observation_function,
            moments_pred,
            points_pred,
            Z[t],
            points_observation=points_observation))

    return (mu_filt, sigma_filt)
Beispiel #3
0
def augmented_unscented_smoother(mu_filt, sigma_filt, f, Q):
    '''Apply the Unscented Kalman Smoother with arbitrary noise

    Parameters
    ----------
    mu_filt : [T, n_dim_state] array
        mu_filt[t] = mean of state at time t given observations from times
        [0, t]
    sigma_filt : [T, n_dim_state, n_dim_state] array
        sigma_filt[t] = covariance of state at time t given observations from
        times [0, t]
    f : function or [T-1] array of functions
        state transition function(s). Takes in an the current state and the
        process noise and outputs the next state.
    Q : [n_dim_state, n_dim_state] array
        transition covariance matrix

    Returns
    -------
    mu_smooth : [T, n_dim_state] array
        mu_smooth[t] = mean of state at time t given observations from times
        [0, T-1]
    sigma_smooth : [T, n_dim_state, n_dim_state] array
        sigma_smooth[t] = covariance of state at time t given observations from
        times [0, T-1]
    '''
    # extract size of key parts of problem
    T, n_dim_state = mu_filt.shape

    # instantiate containers for results
    mu_smooth = np.zeros(mu_filt.shape)
    sigma_smooth = np.zeros(sigma_filt.shape)
    mu_smooth[-1], sigma_smooth[-1] = mu_filt[-1], sigma_filt[-1]

    for t in reversed(range(T - 1)):
        # get sigma points for [state, transition noise]
        mu = mu_filt[t]
        sigma = sigma_filt[t]

        moments_state = Moments(mu, sigma)
        moments_transition_noise = Moments(np.zeros(n_dim_state), Q)
        (points_state, points_transition) = (augmented_points(
            [moments_state, moments_transition_noise]))

        # compute E[x_{t+1} | z_{0:t}], Var(x_{t+1} | z_{0:t})
        f_t = _last_dims(f, t, ndims=1)[0]
        (points_pred,
         moments_pred) = unscented_transform(points_state,
                                             f_t,
                                             points_noise=points_transition)

        # Calculate Cov(x_{t+1}, x_t | z_{0:t-1})
        sigma_pair = ((points_pred.points - moments_pred.mean).T.dot(
            np.diag(points_pred.weights_covariance)).dot(points_state.points -
                                                         moments_state.mean).T)

        # compute smoothed mean, covariance
        smoother_gain = sigma_pair.dot(linalg.pinv(moments_pred.covariance))
        mu_smooth[t] = (
            mu_filt[t] +
            smoother_gain.dot(mu_smooth[t + 1] - moments_pred.mean))
        sigma_smooth[t] = (
            sigma_filt[t] +
            smoother_gain.dot(sigma_smooth[t + 1] -
                              moments_pred.covariance).dot(smoother_gain.T))

    return (mu_smooth, sigma_smooth)