This module contains the update algorithm for a DGLM. After observing a new value $y_t$, updating incorporates the new information into the DGLM coefficients. It also applies the discount factors to reduce the impact of older information. For any model mod, the correct method usage is mod.update(y, X).

Updating occurs after observing a new value, $y_t$. The update function accepts $y_t$ and the predictors $X_t$. It will update the state vector from $\theta_t$ into $\theta_{t+1}$, producing the new mean $a_{t+1}$ and variance matrix $R_{t+1}$. In a normal DLM, the updating also impacts the mean of the observation variance, $s_{t+1}$. The coefficients can be accessed with mod.get_coef, or more directly as mod.a, mod.R, and for a normal DLM, mod.s.

To give the more formal Bayesian interpretation of these steps:

• At time $t$, we know the prior moments of the state vector $\theta_t | \mathcal{D_t} \sim [a_t, R_t]$, where $\mathcal{D_t}$ is all of the observations up to time $t$.
• We then observe $y_t$, and incorporate the new information to give the posterior: $\theta_t | \mathcal{D_t}, y_t \sim [m_t, C_t]$.
• Finally, we discount the old information, to give us our new priors for the next time step: $\theta_{t+1} | \mathcal{D_{t+1}} \sim [a_{t+1}, R_{t+1}]$.

If you are interested in the posterior moments of $\theta_t | \mathcal{D_t}, y_t$ before the discounting is applied, then you can access mod.m and mod.C, although these are rarely used.

Again, these functions do not need to be accessed independently from a model. Every model in PyBATS has a mod.update(y, X) method, which will call the appropriate update function.

## Update Functions

#### update[source]

update(mod, y=None, X=None)

This update method works for Poisson and Bernoulli DGLMs. Below are very simple tests which:

• Manually define a DGLM with an intercept and 2 regression predictors
• Define a new $y_t, X_t$
• Update the model, given $y_t, X_t$
• Check that the posterior mean $a_t$ and variance $R_t$ of the state vector is correct
import numpy as np
from pybats.dglm import dlm, pois_dglm, bern_dglm, bin_dglm
from pybats.analysis import analysis

a0 = np.array([1, 1, 1])
R0 = np.eye(3)
mod_p = pois_dglm(a0, R0, ntrend=1, nregn=2, deltrend=1, delregn=.9)
mod_bern = bern_dglm(a0, R0, ntrend=1, nregn=2, deltrend=1, delregn=.9)

# New data:
y = 5
X = np.array([1,2])

# Test the Poisson DGLM
mod_p.update(y=y, X=X)
ans = np.array([[0.59974735],
[0.59974735],
[0.1994947 ]])
assert (np.equal(np.round(ans, 5), np.round(mod_p.a, 5)).all())

ans = np.array([-0.16107008, 0.93214436])
assert (np.equal(np.round(ans, 5), np.round(mod_p.R[0:2, 1], 5)).all())

# Test the Bernoulli DGLM
mod_bern.update(y=1, X=X)
ans = np.array([[1.02626224],
[1.02626224],
[1.05252447]])
assert (np.equal(np.round(ans, 5), np.round(mod_bern.a, 5)).all())

ans = np.array([-1.00331466e-04,  1.11099963])
assert (np.equal(np.round(ans, 5), np.round(mod_bern.R[0:2, 1], 5)).all())


#### update_dlm[source]

update_dlm(mod, y=None, X=None)

This update method works for normal DLMs. Here is a similar updating test, calling the method as mod_n.update:

mod_n = dlm(a0, R0, ntrend=1, nregn=2, deltrend=1, delregn=.9)

# Test the normal DLM
mod_n.update(y = y, X=X)
ans = np.array([[1.14285714],
[1.14285714],
[1.28571429]])
assert(np.equal(np.round(ans, 5), np.round(mod_n.a, 5)).all())

ans = np.array([-0.08163265, 0.54421769])
assert(np.equal(np.round(ans, 5), np.round(mod_n.R[0:2,1], 5)).all())


#### update_bindglm[source]

update_bindglm(mod, n=None, y=None, X=None)

This update method works for binomial DGLMs. Here is a similar updating test, calling the method as mod_b.update. Note that for a binomial DGLM, we must specify the number of trials, $n_t$.

mod_b = bin_dglm(a0, R0, ntrend=1, nregn=2, deltrend=1, delregn=.9)

# New data - the number of trials
n = 10

# Test the Binomial DGLM
mod_b.update(y=y, X=X, n=n)
ans = np.array([[ 0.46543905],
[ 0.46543905],
[-0.0691219 ]])
assert (np.equal(np.round(ans, 5), np.round(mod_b.a, 5)).all())

ans = np.array([-0.15854342, 0.93495175])
assert (np.equal(np.round(ans, 5), np.round(mod_b.R[0:2, 1], 5)).all())