Linzer 2013 - Extensions - House Effects, Correlated Errors and Election-Night Updating (Concept Note)

Summary

Concept note, no raw source. It collects the extensions that the PyMC examples E40, E94 and E95 add to Linzer’s model: pollster/mode/population effects, a shared polling error, correlated state innovations, a fundamentals prior learned from history, and, on election night, updating the frozen forecast by importance reweighting with race calls treated as interval (censored) data. Literature to consult: Jackman (2005, Aust J Polit Sci, “Pooling the polls”); Gelman & King (1993); Heidemanns, Gelman & Morris (2020, Harvard Data Science Review, updated Economist model); Rubin (1987, SIR); Kish (1965, effective sample size).

Overview

Linzer (2013) deliberately omits house effects (“impractical”) and treats states as conditionally independent given . Later models (Jackman 2005; Heidemanns et al. 2020) add them back.

Main Content

Poll-level model with house, mode and population effects

For poll in state , day , pollster , mode and population : with , pollster effects (partial pooling), and a shared (non-sampling) polling error common to all polls of the same race. Because truth and a common bias are not separately identified from polls alone, E40 uses a rotation (reparameterisation) that puts the unidentified combination under the fundamentals prior.

Correlated state innovations

Replace independent state random walks with , , with from an LKJ prior or a kernel on demographic distance (ACS state covariates). This makes simultaneous misses across similar states likely and widens the tails of the electoral-vote distribution (compare Linzer 2013 - Forecast Computation and Electoral College Simulation).

Fundamentals prior learned from history

Instead of fixing by hand (Linzer’s Time-for-Change plus home-state rule), fit a regression of past state results (1976-2016 in E40; 2016-2026 in E94 for midterms with FEC money and partisan lean) on incumbency, economy, previous result and covariates, and use its predictive distribution for (and = its predictive variance, replacing the analyst’s ).

Election-night updating (E95)

Importance reweighting of a frozen forecast

Let posterior draws , , of race margins come from the pre-election model. A race call is data: the call “Democrat wins race ” is the event where is race-level noise between the frozen margin and the final tally. Integrating out, the likelihood is the interval probability

with for a Democratic call, for a Republican call, for “too close to call”, and a normal density once a final margin is known. Weights , and any functional (seat count, control probability) is . Effective sample size signals degeneracy; when ESS gets small, refit. The identical posterior arises from refitting in PyMC with pm.Potential(...) adding .

Examples

One race, 4 draws

Margins (D-R, points) , , the AP calls the race for the Democrat. gives ; normalised weights (sum 1). The reweighted mean margin is , up from 0, and ESS of 4.

import numpy as np
from scipy.stats import norm
def reweight(margins, calls, sigma=2.0, close=1.0):
    """margins: M x R draws; calls: dict race_idx -> 'D','R','TCTC'."""
    logw=np.zeros(len(margins))
    for r,c in calls.items():
        a,b={'D':(0,np.inf),'R':(-np.inf,0),'TCTC':(-close,close)}[c]
        logw+=np.log(norm.cdf((b-margins[:,r])/sigma)-norm.cdf((a-margins[:,r])/sigma)+1e-300)
    w=np.exp(logw-logw.max()); w/=w.sum()
    return w, 1.0/np.sum(w**2)

Connections

Linzer’s final posterior is exactly the object that gets frozen and reweighted. Marketing: the same “reweight frozen posterior draws by new aggregate data” is a cheap way to update an MMM posterior with a newly arrived experiment result (importance sampling with ESS check) before a full refit; see Bayesian Workflow - Overview.

See Also

Linzer 2013 - Dynamic Bayesian Forecasting of Presidential Elections - Overview · Hierarchical Models