从以前的帖子构建模型,以及有用的答案,我已经对MLEModel进行了子类化,以封装该模型。我想考虑两个参数q1和q2,以便将状态噪声协方差矩阵推广到Sarkka (2013年)的示例4.3 (为我的惯例重新排列的术语):

我想我可以用下面的update方法来完成这个任务,但是fit方法遇到了问题,因为它返回了一个UFuncTypeError: Cannot cast ufunc 'multiply' output from dtype('complex128') to dtype('float64') with casting rule 'same_kind'。我在这里错过了什么?
import numpy as np
import scipy.linalg as linalg
import statsmodels.api as sm
class Tracker2D(sm.tsa.statespace.MLEModel):
"""Position tracker in two dimensions with four states
"""
start_params = [1.0, 1.0]
param_names = ["q1", "q2"]
def __init__(self, endog):
super(Tracker2D, self).__init__(endog, k_states=4)
self.endog = endog
self._state_names = ["x1", "dx1/dt",
"x3", "dx3/dt"]
# dt: sampling rate; s = standard deviation of the process noise
# common to both dimensions
dt, s = 0.1, 0.5
# dynamic model matrices A and Q
A2d = [[1, dt],
[0, 1]]
A = linalg.block_diag(A2d, A2d)
Q2d = [[dt ** 3 / 3, dt ** 2 / 2],
[dt ** 2 / 2, dt]]
Q = linalg.block_diag(Q2d, Q2d)
# measurement model matrices H and R
H = np.array([[1, 0, 0, 0],
[0, 0, 1, 0]])
R = s ** 2 * np.eye(2)
self["design"] = H
self["obs_cov"] = R
self["transition"] = A
self["selection"] = np.eye(4)
self["state_cov"] = Q
def update(self, params, **kwargs):
self["state_cov", :2, :2] *= params[0]
self["state_cov", 2:, 2:] *= params[1]
# Initialization
m0 = np.array([[0, 1, 0, -1]]).T # state vector column vector
P0 = np.eye(4) # process covariance matrix
# With object Y below being the simulated measurements in downloadable
# data file from previous post
with open("measurements_2d.npy", "rb") as f:
Y = np.load(f)
tracker2D = Tracker2D(pd.DataFrame(Y.T))
tracker2D.initialize_known((tracker2D["transition"] @ m0.flatten()),
(tracker2D["transition"] @ P0 @
tracker2D["transition"].T +
tracker2D["state_cov"]))
# Below throws the error
tracker2D.fit()发布于 2022-01-03 16:00:28
您正在接收的错误消息是试图在dtype=float矩阵中设置一个复杂的值。您将从以下方面获得相同的错误:
A = np.eye(2)
A *= 1.0j错误出现在:
def update(self, params, **kwargs):
self["state_cov", :2, :2] *= params[0]
self["state_cov", 2:, 2:] *= params[1]因为您正在修改"state_cov“的位置。当params是一个复杂的向量,但现有的"state_cov“矩阵有dtype浮点数时,就会出现错误。当计算参数的标准误差时,Statsmodel会将参数向量设置为复杂的,因为它使用了复杂的阶跃微分。
你可以用这样的
def update(self, params, **kwargs):
self["state_cov", :2, :2] = params[0] * self["state_cov", :2, :2]
self["state_cov", 2:, 2:] = params[1] * self["state_cov", 2:, 2:]尽管我应该指出,这不会给您提供我认为您想要的东西,因为它将基于以前的任何内容修改"state_cov“。相反,你想要的是:
class Tracker2D(sm.tsa.statespace.MLEModel):
"""Position tracker in two dimensions with four states
"""
start_params = [1.0, 1.0]
param_names = ["q1", "q2"]
def __init__(self, endog):
super(Tracker2D, self).__init__(endog, k_states=4)
self.endog = endog
self._state_names = ["x1", "dx1/dt",
"x3", "dx3/dt"]
# dt: sampling rate; s = standard deviation of the process noise
# common to both dimensions
dt, s = 0.1, 0.5
# dynamic model matrices A and Q
A2d = [[1, dt],
[0, 1]]
A = linalg.block_diag(A2d, A2d)
Q2d = [[dt ** 3 / 3, dt ** 2 / 2],
[dt ** 2 / 2, dt]]
# First we save the base Q matrix
self.Q = linalg.block_diag(Q2d, Q2d)
# measurement model matrices H and R
H = np.array([[1, 0, 0, 0],
[0, 0, 1, 0]])
R = s ** 2 * np.eye(2)
self["design"] = H
self["obs_cov"] = R
self["transition"] = A
self["selection"] = np.eye(4)
self["state_cov"] = self.Q.copy()
def update(self, params, **kwargs):
# Now update the state cov based on the original Q
# matrix, and set entire blocks of the matrix, rather
# than modifying it in-place.
self["state_cov", :2, :2] = params[0] * self.Q[:2, :2]
self["state_cov", 2:, 2:] = params[1] * self.Q[2:, 2:]https://stackoverflow.com/questions/70553360
复制相似问题