Error when using tfp.sts.Sum with StateSpace Components
Running this simple Example:
from tensorflow_probability import sts
local_ssm = sts.LocalLinearTrendStateSpaceModel(name='local',num_timesteps=30,level_scale=0.5,slope_scale=0.1,
initial_state_prior=tfd.MultivariateNormalDiag(loc=[0., 0.], scale_diag=[1., 1.]))
model = sts.Sum([local_ssm])
Gives the error ( in tfp version 0.17.0):
File "/usr/local/lib/python3.8/dist-packages/tensorflow_probability/python/sts/components/sum.py", line 462, in init name='{}_{}'.format(component.name, parameter.name), AttributeError: 'str' object has no attribute 'name'
Note:
The variable "parameter" in SS components are Python str. So this loop in /tensorflow_probability/python/sts/components/sum.py fails:
for component in components:
for parameter in component.parameters:
parameters.append(Parameter(
name='{}_{}'.format(component.name, parameter.name), # FAILS because 'parameter' is str for StateSpace components
prior=parameter.prior, bijector=parameter.bijector))
tfp.sts.Sum can only combine tfp.sts.components, whereas the output of tfp.sts.LocalLinearTrendStateSpaceModel is a tfd.LocalLinearTrendStateSpaceModel.
If you are using tfp.sts.Sum to add observation noise and want to also fix the parameter level_scale and slope_scale, I would do the below:
local_ssm = sts.LocalLinearTrend(name='local')
model = sts.Sum([local_ssm])
print([param.name for param in model.parameters])
# ==> ['observation_noise_scale', 'local/_level_scale', 'local/_slope_scale']
ssm = model.make_state_space_model(
num_timesteps=30,
param_vals={
'observation_noise_scale': 1.,
'local/_level_scale': 0.5,
'local/_slope_scale': 0.1,
},
initial_state_prior=tfd.MultivariateNormalDiag(
loc=[0.0, 0.0], scale_diag=[1.0, 1.0]
),
)
ssm.sample()
If you want to keep the observation scale as a free parameter, I would do something like:
ssm_jd = model.joint_distribution(num_timesteps=30)
pinned_ssm = ssm_jd.experimental_pin({
'local/_level_scale': 0.5,
'local/_slope_scale': 0.1,
})
pinned_ssm.sample_unpinned()
Hope this helps.
Hi, I would like to solve this issue, could you assigned it to me please?
@junpenglao Thank you for your feedback and comment. Unfortunately it is not very helpful.
You mentioned:
"tfp.sts.Sum can only combine tfp.sts.components, whereas the output of tfp.sts.LocalLinearTrendStateSpaceModel is a tfd.LocalLinearTrendStateSpaceModel."
If that is true, then why does the documentation for AdditiveStateSpaceModel says:
"To construct an additive state space model combining a local linear trend and day-of-week seasonality component (note, the StructuralTimeSeries classes, e.g., Sum, provide a higher-level interface for this construction, which will likely be preferred by most users)"
Is this a documentation mistake ?
What I want to do is something very simple: train a structured state space model build from TFP sub-components using the sts's API ( right now it seems like we can't even combine them) . For instance, a working example of the following:
local_linear = sts.LocalLinearTrendStateSpaceMode(name='local',num_timesteps=30,level_scale=0.5,slope_scale=0.1, initial_state_prior=tfd.MultivariateNormalDiag(loc=[0., 0.], scale_diag=[1., 1.]))
model = tfp.sts.Sum(components=[local_linear],observed_time_series=observed_time_series)
samples, kernel_results = tfp.sts.fit_with_hmc(model, observed_time_series)
The documentation might not be specific enough but you can see from the docstring example that tfp.sts.Sum works on tfp.sts.component like: https://github.com/tensorflow/probability/blob/ec401044750619d79383f976d9bf80f91e8bc124/tensorflow_probability/python/sts/fitting.py#L351-L376
In your case, it goes something like:
local_linear = sts.LocalLinearTrend(name='local')
model = tfp.sts.Sum(components=[local_linear], observed_time_series=observed_time_series)
samples, kernel_results = tfp.sts.fit_with_hmc(model, observed_time_series)
sts.LocalLinearTrendStateSpaceMode
So why tfp.sts.Sum works with "sts.LocalLinearTrend" but not with "sts.LocalLinearTrendStateSpaceMode"? Isn't "sts.LocalLinearTrendStateSpaceMode" also a tfp.sts.component?
This really seems like a bug to me.
Isn't "sts.LocalLinearTrendStateSpaceMode" also a tfp.sts.component?
Nope, it's a LinearGaussianStateSpaceModel which is a tfp.distribution.
It might help to understand the implementation from the perspective of parameters:
-
tfd.LinearGaussianStateSpaceModel: a distribution, the parameter is in the format of transition matrix, observation matrix etc. -
tfp.sts.*StateSpaceModelikests.LocalLinearTrendStateSpaceMode: also a distribution but they initialised atfd.LinearGaussianStateSpaceModelwith more intuitive parameter name that related to thetfp.sts.*StateSpaceMode, likelevel_scale,slope_scaleetc. -
tfp.sts.components.*likests.LocalLinearTrend: aStructuralTimeSeriesthat internally will calltfp.sts.*StateSpaceModeto return atfd.LinearGaussianStateSpaceModel(e.g., https://github.com/tensorflow/probability/blob/cb31acb2a2b2fb41a4013a9b2a2d03dbd8429fd1/tensorflow_probability/python/sts/components/local_linear_trend.py#L416-L428). It also use more intuitive parameter and format them into transition matrix etc. Moreover user specify the priors for the parameter (instead intfp.sts.*StateSpaceModeyou need to provide the parameter values itself as some array object). -
tfp.sts.Sum: also aStructuralTimeSeries, internally combinetfp.sts.components.*together and give a final observation noise to the model.
Got it. That was very helpful!! Thank you.