状态空间模型中用户提供的初始状态
User Supplied Initial States in Statespace Model
我正在尝试复制 Trends and Cycles in Macroeconomic Time Series (1985) 中的结果。如果仅使用局部线性模型,我能够得到相同的结果,但在添加固定周期性组件时却未能这样做。虽然我不完全确定,但我怀疑这与我对所有状态使用完全漫射先验而不是仅对局部线性分量有关。为了保持一定程度的灵活性,我想使用 known
关键字将首字母提供给 statsmodels
,并在 update
方法中更新它们。现在我不太担心使用近似漫反射。实现这一目标的最佳方法是什么?
从 v0.10 开始,您可以通过创建自己的 Initialization
实例来灵活地设置初始化。使用这种方法,每个状态或状态块都可以独立设置为使用可用方法之一:known
、stationary
、approximate_diffuse
或 diffuse
.
这里是局部模型的示例,但其中不规则组件被建模为 AR(1)。第一个状态是 AR(1),我指定 stationary
初始化。第二个状态是级别,我使用 known
初始化通过最大似然估计初始级别。第三个状态是斜率,我设置它的初始化为diffuse
.
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.statespace.initialization import Initialization
from statsmodels.tsa.statespace.tools import (
constrain_stationary_univariate,
unconstrain_stationary_univariate)
class LocalLevelAR1(sm.tsa.statespace.MLEModel):
def __init__(self, endog):
super().__init__(endog, k_states=3, k_posdef=3)
self['design', 0, :2] = 1
self['transition', 1:, 1:] = np.array([[1., 1.],
[0., 1.]])
self['selection'] = np.eye(3)
init = Initialization(3)
init.set(0, 'stationary')
init.set(1, 'known', stationary_cov=[[0]])
init.set(2, 'diffuse')
self.ssm.initialization = init
@property
def state_names(self):
return ['ar1', 'level', 'slope']
@property
def param_names(self):
return ['level0', 'phi', 'sigma2.ar1', 'sigma2.level', 'sigma2.slope']
@property
def start_params(self):
return np.r_[0, 0, 1e-5, 1e-5, 1e-5]
def transform_params(self, unconstrained):
constrained = unconstrained.copy()
constrained[1] = constrain_stationary_univariate(unconstrained[1:2])
constrained[2:5] = constrained[2:5]**2
return constrained
def untransform_params(self, constrained):
unconstrained = constrained.copy()
unconstrained[1] = unconstrain_stationary_univariate(constrained[1:2])
unconstrained[2:5] = constrained[2:5]**0.5
return constrained
def update(self, params, **kwargs):
params = super().update(params, **kwargs)
self['transition', 0, 0] = params[1]
self['state_cov'] = np.diag(params[2:5])
self.ssm.initialization.set(1, 'known', constant=params[:1], stationary_cov=[[0.]])
dta = sm.datasets.macrodata.load_pandas().data
dta.index = pd.period_range(start='1959Q1', end='2009Q3', freq='Q')
mod = LocalLevelAR1(dta['infl'])
res = mod.fit()
print(res.summary())
我正在尝试复制 Trends and Cycles in Macroeconomic Time Series (1985) 中的结果。如果仅使用局部线性模型,我能够得到相同的结果,但在添加固定周期性组件时却未能这样做。虽然我不完全确定,但我怀疑这与我对所有状态使用完全漫射先验而不是仅对局部线性分量有关。为了保持一定程度的灵活性,我想使用 known
关键字将首字母提供给 statsmodels
,并在 update
方法中更新它们。现在我不太担心使用近似漫反射。实现这一目标的最佳方法是什么?
从 v0.10 开始,您可以通过创建自己的 Initialization
实例来灵活地设置初始化。使用这种方法,每个状态或状态块都可以独立设置为使用可用方法之一:known
、stationary
、approximate_diffuse
或 diffuse
.
这里是局部模型的示例,但其中不规则组件被建模为 AR(1)。第一个状态是 AR(1),我指定 stationary
初始化。第二个状态是级别,我使用 known
初始化通过最大似然估计初始级别。第三个状态是斜率,我设置它的初始化为diffuse
.
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.statespace.initialization import Initialization
from statsmodels.tsa.statespace.tools import (
constrain_stationary_univariate,
unconstrain_stationary_univariate)
class LocalLevelAR1(sm.tsa.statespace.MLEModel):
def __init__(self, endog):
super().__init__(endog, k_states=3, k_posdef=3)
self['design', 0, :2] = 1
self['transition', 1:, 1:] = np.array([[1., 1.],
[0., 1.]])
self['selection'] = np.eye(3)
init = Initialization(3)
init.set(0, 'stationary')
init.set(1, 'known', stationary_cov=[[0]])
init.set(2, 'diffuse')
self.ssm.initialization = init
@property
def state_names(self):
return ['ar1', 'level', 'slope']
@property
def param_names(self):
return ['level0', 'phi', 'sigma2.ar1', 'sigma2.level', 'sigma2.slope']
@property
def start_params(self):
return np.r_[0, 0, 1e-5, 1e-5, 1e-5]
def transform_params(self, unconstrained):
constrained = unconstrained.copy()
constrained[1] = constrain_stationary_univariate(unconstrained[1:2])
constrained[2:5] = constrained[2:5]**2
return constrained
def untransform_params(self, constrained):
unconstrained = constrained.copy()
unconstrained[1] = unconstrain_stationary_univariate(constrained[1:2])
unconstrained[2:5] = constrained[2:5]**0.5
return constrained
def update(self, params, **kwargs):
params = super().update(params, **kwargs)
self['transition', 0, 0] = params[1]
self['state_cov'] = np.diag(params[2:5])
self.ssm.initialization.set(1, 'known', constant=params[:1], stationary_cov=[[0.]])
dta = sm.datasets.macrodata.load_pandas().data
dta.index = pd.period_range(start='1959Q1', end='2009Q3', freq='Q')
mod = LocalLevelAR1(dta['infl'])
res = mod.fit()
print(res.summary())