Dynamic linear models: a coefficient that drifts over time

Today let's understand dynamic linear models clearly, using one small retailer's ad spend and orders as the running example throughout.

Say you run a small online retailer. Every week you spend money on ads, and every week you count how many orders come in. Here are those order counts for the first 24 weeks.

RInteractive R
# Simulate 24 weeks of a small retailer's ad spend and orders week <- 1:24 set.seed(30) spend <- round(runif(24, 5, 25), 1) alpha_true <- 10 set.seed(31) beta_true <- numeric(24) beta_true[1] <- 0.80 for (t in 2:24) { beta_true[t] <- beta_true[t - 1] + rnorm(1, mean = 0.035, sd = 0.015) } set.seed(32) v <- rnorm(24, mean = 0, sd = 2.5) orders <- round(alpha_true + beta_true * spend + v) orders #> [1] 16 25 18 24 22 19 35 19 40 20 19 25 30 39 23 40 27 39 35 32 21 32 21 29

  

Here is that same count, plotted week by week.

The count climbs across the 24 weeks, from 16 in the first week up to 40, but not at a steady pace. Some weeks jump a lot, others barely move. That raises the real question this lesson answers: does one number explain how ad spend turns into orders, or does something about that relationship itself change as the weeks go by?

The general DLM notation

Every dynamic linear model, DLM for short, is built from the same two equations: one for what you observe, and one for how a hidden state moves underneath it.

\[ y_t = F_t' \theta_t + v_t, \qquad v_t \sim N(0, V) \]

This is the observation equation. \(y_t\) is what you actually measure at time t, a number sitting right there in your data. \(\theta_t\) is the hidden state: the quantity, or quantities, the model is trying to track, which you never observe directly.

\(F_t\) is a vector that turns the hidden state into a prediction for \(y_t\); the prime after it means transpose, flipping a column of numbers into a row so the two can be multiplied together. \(v_t\) is that period's own observation noise, with variance V.

\[ \theta_t = G \theta_{t-1} + w_t, \qquad w_t \sim N(0, W) \]

This is the state equation. It says the hidden state this period, \(\theta_t\), equals the previous period's hidden state, \(\theta_{t-1}\), carried forward by the matrix G, plus a small nudge, \(w_t\), with variance W. G decides how the state moves from one period to the next.

What makes a model "dynamic" is that \(F_t\), and sometimes G, is allowed to change with t, or carry that period's own data, instead of staying fixed. The simplest DLM does not do this at all: it has a single hidden level, \(\theta_t\) is one number, and \(F_t = 1\) and \(G = 1\) stay fixed for every t. This lesson's model keeps two numbers in \(\theta_t\) at once, and lets \(F_t\) carry that period's own spend. The table below lines the two cases up side by side.

Symbol What it is Single hidden level This lesson's model
theta_t the hidden state the filter tracks one number, the level two numbers, an intercept and a slope
F_t maps the state to a prediction for y_t fixed at 1 every period carries that period's own spend
G carries the state from one period to the next fixed at 1 the identity matrix, each entry carried forward unchanged before noise
V the observation noise's variance one number one number
W the state noise's variance one number one number for every entry of theta_t