In [110]:
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from pandas import DataFrame
from numpy.random import multivariate_normal
from numpy.linalg  import inv
from pykalman import KalmanFilter
%matplotlib inline

In [111]:
def Relu(z):
    return np.max((z, np.zeros(z.shape)), axis=0)

def dRelu(z):
    return (z > 0) * 1

p = 3
q = 10
T = 500

data = loadmat('Tut11_file1.mat')
locals().update(data)
data.keys()


Out[111]:
dict_keys(['__header__', '__version__', '__globals__', 'A', 'B', 'Gamma', 'Sigma', 'W', 'mu0'])

In [144]:
z = np.zeros((p, T + 1))
x = np.zeros((q, T + 1))
np.random.seed(10)
z[:,[0]] = mu0 #+ multivariate_normal(np.zeros(p), Sigma).reshape(mu0.shape)

In [145]:
for t in range(T):
    x[:, [t + 1]] = B.dot(z[:, [t]]) #+ multivariate_normal(np.zeros(q), Gamma).reshape((q, 1))
    z[:, [t + 1]] = A.dot(z[:, [t]]) #+ multivariate_normal(np.zeros(p), Sigma).reshape(mu0.shape)
#z = z[:, 1:]
#x = x[:, 1:]
z.shape


Out[145]:
(3, 501)

In [9]:
x[:, 0], mu0


Out[9]:
(array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),
 array([[-0.78482435],
        [-0.31064034],
        [-1.04847957]]))

In [112]:
z = np.zeros((p, T + 1))
x = np.zeros((q, T + 1))
np.random.seed(10)
z[:,[0]] = mu0 #+ multivariate_normal(np.zeros(p), Sigma).reshape(mu0.shape)

def transition_f(z):
    return A.dot(z) + W.dot(np.maximum(z, 0.))

def obs_g(x):
    return B.dot(x)

for t in range(T):
    x[:, t + 1] = obs_g(z[:, t]) + multivariate_normal(np.zeros(q), Gamma)
    z[:, t + 1] = transition_f(z[:, t]) + multivariate_normal(np.zeros(p), Sigma)
x[:, 0] = np.ma.masked

In [96]:
kf = KalmanFilter()
kf.initial_state_mean = mu0.flatten()
kf.initial_state_covariance = np.zeros(Sigma.shape)
kf.transition_matrices = A
kf.transition_covariance = Sigma
kf.observation_matrices = B
kf.observation_covariance = Gamma
filtered, _= kf.filter(x[:, 1:].T)
#(smoothed_state_means, smoothed_state_covariances) = kf.smooth(x.T)
print ('Non smoothed result:', np.sum((filtered - z[:, :-1].T) ** 2))
#print('Smoothed result:', np.sum((smoothed_state_means - z.T) ** 2))
z.shape, filtered.shape


Non smoothed result: 0.0
Out[96]:
((3, 501), (500, 3))

In [86]:
Sigma


Out[86]:
array([[ 0.01,  0.01,  0.01],
       [ 0.01,  0.01,  0.01],
       [ 0.01,  0.01,  0.01]])

In [94]:
#plt.plot(smoothed_state_means)
plt.plot((filtered - z[:, :-1].T))


Out[94]:
[<matplotlib.lines.Line2D at 0x7f81b3090ef0>,
 <matplotlib.lines.Line2D at 0x7f81b3090f28>,
 <matplotlib.lines.Line2D at 0x7f81b30909b0>]

In [92]:
def transition_f(z):
    return A.dot(z) + W.dot(np.maximum(z, 0.))

def obs_g(x):
    return B.dot(x)

In [63]:
kf = AdditiveUnscentedKalmanFilter()
kf.initial_state_mean = mu0.flatten()
kf.initial_state_covariance = Sigma
kf.transition_functions = transition_f
kf.transition_covariance = Sigma
kf.observation_functions = obs_g
kf.observation_covariance = Gamma
filtered, _= kf.filter(x[:, 1:].T)
#(smoothed_state_means, smoothed_state_covariances) = kf.smooth(x.T)
print ('Non smoothed result:', np.sum((filtered - z[:, :-1].T) ** 2))


Non smoothed result: 3.01314164875

In [64]:
plt.plot(smoothed_state_means)
plt.plot(z.T)
print ('Non smoothed result:', np.sum((filtered - z.T) ** 2))
print('Smoothed result:', np.sum((smoothed_state_means - z.T) ** 2))


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-64-8f98bbf81f1e> in <module>()
      1 plt.plot(smoothed_state_means)
      2 plt.plot(z.T)
----> 3 print ('Non smoothed result:', np.sum((filtered - z.T) ** 2))
      4 print('Smoothed result:', np.sum((smoothed_state_means - z.T) ** 2))

ValueError: operands could not be broadcast together with shapes (500,3) (501,3) 

In [15]:
plt.plot(x.T[1:, :], ':');
plt.figure()
plt.plot(z.T, ':');



In [169]:
# Filter

mu = np.zeros(z.shape)
K = np.zeros((p, q, T))
V = np.zeros((p, p, T))
L = np.zeros((p, p, T))

L[..., 0] = Sigma
# mu[..., [0]] = mu0
K[...,0] = L[..., 0].dot(B.T.dot(inv(B.dot(L[..., 0].dot(B.T)) + Gamma)))
mu[..., [0]] = A.dot(mu0) + K[..., 0].dot(x[:, [0]] - B.dot(A.dot(mu0)))
V[..., 0] = (np.eye(p) - K[..., 0].dot(B)).dot(Sigma)
#L[..., 0] = A.dot(V[..., 0].dot(A.T)) + Sigma

for t in range(1, T):
    L[..., t] = A.dot(V[..., t - 1].dot(A.T)) + Sigma

    K[...,t] = L[..., t].dot(B.T.dot(inv(B.dot(L[..., t].dot(B.T)) + Gamma)))
    mu[..., [t]] = A.dot(mu[..., [t-1]]) + K[..., t].dot(x[:, [t]] - B.dot(A.dot(mu[..., [t-1]])))
    V[..., t] = (np.eye(p) - K[..., t].dot(B)).dot(L[..., t])
    #L[..., t] = A.dot(V[..., t].dot(A.T)) + Sigma


# Smoother
V_tilde = np.zeros(V.shape)
mu_tilde = np.zeros(mu.shape)
V_tilde[..., -1] = V[..., -1]
mu_tilde[..., [-1]] = mu[..., [-1]]

for t in range(T - 2, -1, -1):

    temp = V[..., t].dot(A.T.dot(inv(L[..., t])))
    V_tilde[..., t] = V[..., t] + temp.dot(V_tilde[..., t+1] - L[..., t]).dot(temp.T)
    mu_tilde[..., [t]] = mu[..., [t]] + temp.dot(mu_tilde[..., [t+1]] - A.dot(mu[..., [t]]))

In [173]:
mu[:, 0:2]


Out[173]:
array([[-0.49309647, -0.42085202],
       [ 0.2719109 , -0.26398786],
       [ 0.61657095, -0.41404933]])

In [171]:
print ('Non smoothed result:', np.sum((mu[:, :-1] - z[:, 1:]).T ** 2))
print('Smoothed result:', np.sum((mu_tilde - z).T ** 2))
plt.plot(mu_tilde.T)


Non smoothed result: 0.065095059062
Smoothed result: 11.0494616653
Out[171]:
[<matplotlib.lines.Line2D at 0x7f81abec0a90>,
 <matplotlib.lines.Line2D at 0x7f81abec0c50>,
 <matplotlib.lines.Line2D at 0x7f81abec0e48>]

In [134]:
mu[:, :-1].shape


Out[134]:
(3, 500)

In [146]:
# Filter

mu = np.zeros(z.shape)
K = np.zeros((p, q, T))
V = np.zeros((p, p, T))
L = np.zeros((p, p, T))

K[...,0] = Sigma.dot(B.T.dot(inv(B.dot(Sigma.dot(B.T)) + Gamma)))
mu[..., [0]] = A.dot(mu0) + W.dot(Relu(mu0)) + \
               K[..., 0].dot(x[:, [0]]  - B.dot(A.dot(mu0) + W.dot(Relu(mu0))))
V[..., 0] = (np.eye(p) - K[..., 0].dot(B)).dot(Sigma)
L[..., 0] = (A + W.dot(dRelu(mu0))).dot(V[..., 0].dot((A + W.dot(dRelu(mu0))).T)) + Sigma

for t in range(1, T):
    K[...,t] = L[..., t - 1].dot(B.T.dot(inv(B.dot(L[..., t - 1].dot(B.T)) + Gamma)))
    mu[..., [t]] = A.dot(mu[..., [t-1]]) + W.dot(Relu(mu[..., [t-1]])) + \
                   K[..., t].dot(x[:, [t]] - B.dot(A.dot(mu[..., [t-1]]) + W.dot(Relu(mu[..., [t-1]]))))
    V[..., t] = (np.eye(p) - K[..., t].dot(B)).dot(L[..., t-1])
    L[..., t] = (A + W.dot(dRelu(mu[..., [t-1]]))).dot(V[..., t].dot(A + W.dot(dRelu(mu[..., [t-1]])))) + Sigma


# Smoother
V_tilde = np.zeros(V.shape)
mu_tilde = np.zeros(mu.shape)
V_tilde[..., -1] = V[..., -1]
mu_tilde[..., [-1]] = mu[..., [-1]]

for t in range(T - 2, -1, -1):
    temp = V[..., t].dot((A + W.dot(dRelu(mu[..., [t]]))).T.dot(inv(L[..., t])))
    V_tilde[..., t] = V[..., t] + temp.dot(V_tilde[..., t+1] - L[..., t]).dot(temp.T)
    mu_tilde[..., [t]] = mu[..., [t]] + temp.dot(mu_tilde[..., [t+1]] - A.dot(mu[..., [t]]) + W.dot(Relu(mu[..., [t]])))

In [147]:
plt.plot(mu_tilde.T)


Out[147]:
[<matplotlib.lines.Line2D at 0x7f81b03592b0>,
 <matplotlib.lines.Line2D at 0x7f81b0359470>,
 <matplotlib.lines.Line2D at 0x7f81b0359668>]

In [148]:
plt.plot(z.T)


Out[148]:
[<matplotlib.lines.Line2D at 0x7f81b02ee2e8>,
 <matplotlib.lines.Line2D at 0x7f81b02ee4a8>,
 <matplotlib.lines.Line2D at 0x7f81b02ee6a0>]

In [117]:
print ('Non smoothed result:', np.sum((mu[:, :-1] - z[:, 1:]).T ** 2))
print('Smoothed result:', np.sum((mu_tilde - z).T ** 2))


Non smoothed result: 13.1683796552
Smoothed result: 33530355.8112

In [39]:
plt.plot(z[2, :].T)
plt.plot(mu_tilde[2, :].T, ':')


Out[39]:
[<matplotlib.lines.Line2D at 0x7f02724c5080>]

In [130]:
mu.shape


Out[130]:
(3, 501)

In [115]:
W


Out[115]:
array([[ 0.        ,  0.80411064,  0.9743619 ],
       [-0.40484371, -0.        ,  0.18712315],
       [-0.65341481,  0.90179116,  0.        ]])

In [116]:
W


Out[116]:
array([[ 0.        ,  0.80411064,  0.9743619 ],
       [-0.40484371, -0.        ,  0.18712315],
       [-0.65341481,  0.90179116,  0.        ]])

In [13]:
w = np.asarray([[1,0], [0,0], [0,1]])

In [14]:
w.shape


Out[14]:
(3, 2)

In [44]:
np.maximum(np.arange(10), 5)


Out[44]:
array([5, 5, 5, 5, 5, 5, 6, 7, 8, 9])

In [139]:
plt.plot((mu[:, :-1] - z[:, 1:]).T ** 2)


Out[139]:
[<matplotlib.lines.Line2D at 0x7fbcdd0c0fd0>,
 <matplotlib.lines.Line2D at 0x7fbcdd0d71d0>,
 <matplotlib.lines.Line2D at 0x7fbcdd0d73c8>]

In [132]:
plt.plot(z.T)


Out[132]:
[<matplotlib.lines.Line2D at 0x7f81b0575e48>,
 <matplotlib.lines.Line2D at 0x7f81b0575fd0>,
 <matplotlib.lines.Line2D at 0x7f81b057b240>]

In [136]:
A.dot(np.zeros(3) + .02)


Out[136]:
array([ 0.01573934, -0.01931825, -0.01296652])

In [152]:
z[:, 1]


Out[152]:
array([-0.6176309 ,  0.30005145,  0.67975669])

In [ ]: