Search code examples
random-walktensorflow-probabilitystate-space

How to Implement Integrated Random Walk Trend Component in Tensorflow Probability


I'm running tensorflow 2.1 and tensorflow_probability 0.9. I have fit a Structural Time Series Model with a seasonal component.

I wish to implement an Integrated Random walk in order to smooth the trend component, as per Time Series Analysis by State Space Methods: Second Edition, Durbin & Koopman. The integrated random walk is achieved by setting the level component variance to equal 0.

Is implementing this constraint possible in Tensorflow Probability?

Further to this in Durbin & Koopman, higher order random walks are discussed. Could this be implemented?

Thanks in advance for your time.


Solution

  • If I understand correctly, an integrated random walk is just the special case of LocalLinearTrend in which the level simply integrates the randomly-evolving slope component (ie it has no independent source of variation). You could patch this in by subclassing LocalLinearTrend and fixing level_scale = 0. in the models it builds:

    class IntegratedRandomWalk(sts.LocalLinearTrend):
    
      def __init__(self,
                   slope_scale_prior=None,
                   initial_slope_prior=None,
                   observed_time_series=None,
                   name=None):
        super(IntegratedRandomWalk, self).__init__(
          slope_scale_prior=slope_scale_prior,
          initial_slope_prior=initial_slope_prior,
          observed_time_series=observed_time_series,
          name=None)
        # Remove 'level_scale' parameter from the model.
        del self._parameters[0]
    
      def _make_state_space_model(self,
                                  num_timesteps,
                                  param_map,
                                  initial_state_prior=None,
                                  initial_step=0):
    
        # Fix `level_scale` to zero, so that the level
        # cannot change except by integrating the
        # slope.
        param_map['level_scale'] = 0.
    
        return super(IntegratedRandomWalk, self)._make_state_space_model(
          num_timesteps=num_timesteps,
          param_map=param_map,
          initial_state_prior=initial_state_prior,
          initial_step=initial_step)
    

    (it would be mathematically equivalent to build a LocalLinearTrend with level_scale_prior concentrated at zero, but that constraint makes inference difficult, so it's generally better to just ignore or remove the parameter entirely, as I did here).

    By higher-order random walks, do you mean autoregressive models? If so, sts.Autoregressive might be relevant.