/ concept-collection / timeseries-compressibility
Sign in
concept-collection / timeseries-compressibility
timeseries-compressibility / exploration / RESULTS.md
5.3 KBPreviewCodeBlameHistoryRaw

Why LPC+ANS gets 14x when the entropy rate says 23x#

Setting: --sigma 5 --filter bandpass --low 300 --high 2000 --taps 31 --rate 30000. All numbers are bits/sample on the quantized signal z (ratio = 16 / bits).

Verdict#

The entropy estimate is right, and the gap is real. LPC+ANS is not suboptimal by accident — integer-residual prediction followed by a memoryless entropy coder structurally cannot reach the conditional entropy of this process. A codec that codes each sample against a discretized Gaussian centred at the real-valued prediction reaches 22.3x with a verified lossless round-trip; a Monte-Carlo model-based codec reaches ~23.7x.

The mechanism#

After optimal linear prediction from the quantized past, the prediction error of y_next has std s ~= 0.28 quantization steps. The conditional distribution of z_next = round(y_next) is therefore a Gaussian bump covering ~1-3 integer bins, and its shape depends strongly on the fractional part of the prediction mu: mu near a bin centre gives ~0.4 bits, mu near a bin edge gives ~1.1 bits.

The ~0.35-0.38 bit gap is the 14x-vs-22x discrepancy. Raising the LPC order does nothing (14.6x plateau by order 64): the loss is in the residual coding, not the prediction.

Measurements (4M-sample realizations; codecs charged for all side info)#

method bits/sample ratio
raw int16 16 1x
order-0 entropy of z 1.954 8.2x
LPC(32) + ANS (app's method, reproduced) 1.101 (+~1.5% ANS) 14.3x
LPC(128) + ANS ceiling 1.098 14.6x
conditional-Gaussian arithmetic codec (real bytes, exact round-trip) 0.7184 22.27x
Gibbs posterior-predictive codec (achievable rate, 60 sweeps) 0.674 +/- 0.065 23.7x
timeseries-entropy estimator, M=512 (default settings) 0.615 +/- 0.065 26x
timeseries-entropy estimator, M=1024, thin=2 0.658 +/- 0.046 24.3x
semi-analytic conditional entropy (rounding-as-noise model) 0.723 22.1x

The true entropy rate is bracketed: <= 0.718 is proven by real compressed bytes that round-trip; ~0.674 is achievable by the model-based codec; the Monte-Carlo estimator's 0.62-0.68 is consistent with both. The estimator's Rhee-Glynn pilot (--pilot 6) shows RMS Delta_m <= 0.016 decaying at exponent ~2, so its r=1.5 truncation is sound at these settings.

The codec that proves it (codec_gaussian.py)#

  1. Fit an order-64 real-coefficient predictor on the block (Levinson); send coefficients as float32 in the header (270 B total).
  2. Fit a single residual scale s (grid search on the block); send it too.
  3. For each sample: mu_t = dot(coeffs, previous 64 decoded samples); code z_t with an arithmetic coder under P(k) proportional to Phi((k+1/2-mu_t)/s) - Phi((k-1/2-mu_t)/s), tails folded into edge bins, 16-bit frequencies. Decoder computes the identical mu_t from decoded samples, so tables agree bit for bit.
  4. First 64 samples are coded under the marginal N(0, std_z) table.

1,048,576 samples -> 94,157 bytes = 0.7184 bits/sample = 22.27x, np.array_equal(z, decoded) == True. Encode/decode ~7 s each in pure Python+numpy.

gibbs_predictive_rate.py pushes further: both sides could run the timeseries-entropy Gibbs sampler on the decoded past (shared seed) and code against the Rao-Blackwellized posterior predictive of the generative model — the nonlinear optimum. Its measured cross-entropy is 0.674 +/- 0.065 bits/sample (23.7x). The -log2-of-a-mean is Jensen-biased upward, so more sweeps would only lower it toward the true conditional entropy.

Files#

Notes for the app / estimator#

moveopenescclose