Burg and Levinson-Durbin AR tools

Tutorial goal

Estimate AR coefficients using autocorrelation/Levinson and Burg-style recursions.

Note

New to the terminology? See the lattice DSP concept map and the causality/data-use guide for how online, offline, block, and MIMO examples should be read.

Context

This tutorial compares two common AR estimation routes. Levinson-Durbin solves the Yule-Walker equations from autocorrelations. Burg estimates reflection coefficients from forward/backward prediction errors.

Key idea and equations

The AR model is

\[x[n]+a_1x[n-1]+\cdots+a_px[n-p]=e[n].\]

How to read the result

Compare the estimated coefficients with the known synthetic model and check the final prediction error values.

Run command

python examples/burg_levinson_ar_tools.py

Run status

Return code: 0

Captured stdout

true reflection:      [ 0.62 -0.34  0.18 -0.08]
Levinson reflection:  [ 0.6144 -0.3415  0.1843 -0.0766]
Burg reflection:      [ 0.6144 -0.3416  0.1843 -0.0766]
Burg denominator:     [ 1.      0.3274 -0.2466  0.1581 -0.0766]

Source code

 1"""Burg and Levinson-Durbin AR estimation demo."""
 2
 3from __future__ import annotations
 4
 5import numpy as np
 6
 7from lattice_dsp import (
 8    LatticeIIR,
 9    autocorrelation,
10    burg_reflection,
11    levinson_durbin_reflection,
12    reflection_to_denominator,
13)
14
15
16def main() -> None:
17    rng = np.random.default_rng(123)
18    n = 12000
19    true_reflection = [0.62, -0.34, 0.18, -0.08]
20    # AR process: white excitation through a stable all-pole lattice/IIR.
21    excitation = rng.normal(scale=0.2, size=n)
22    ar = LatticeIIR(true_reflection, [1.0, 0.0, 0.0, 0.0, 0.0])
23    x = np.asarray(ar.process(excitation), dtype=float)
24    x = x[1000:]  # drop startup transient
25
26    order = 4
27    r = autocorrelation(x, order, True)
28    k_lev = np.asarray(levinson_durbin_reflection(r, order))
29    k_burg = np.asarray(burg_reflection(x, order))
30
31    print("true reflection:     ", np.round(true_reflection, 4))
32    print("Levinson reflection: ", np.round(k_lev, 4))
33    print("Burg reflection:     ", np.round(k_burg, 4))
34    print("Burg denominator:    ", np.round(reflection_to_denominator(k_burg), 4))
35
36
37if __name__ == "__main__":
38    main()