Back to Streaming Sketching

Sparse Recovery from Count-Sketch Measurements

September 28, 2026 Wasil Zafar 21 min read

Decode heavy coordinates from hashed signed measurements.

Table of Contents

  1. Recovering Spikes from Hashed Measurements
  2. Isolation and Median Coordinate Estimates
  3. From Point Error to Sparse Recovery
  4. Sparse Signals in Telemetry and Science
  5. Reconstruct and Verify a Sparse Vector

Recovering Spikes from Hashed Measurements

Suppose a long signal (x\in\mathbb R^n) contains a few large coordinates and a diffuse background. Storing every coordinate is like giving every musician a separate microphone; Count-Sketch instead routes many musicians into a small set of channels, flips each contribution by a reproducible random sign, and repeats the mixing several times. A loud soloist can then be estimated from channels in which the other sounds mostly cancel.

For row (r), choose a bucket hash (h_r:[n]\to[b]) and a sign hash (s_r:[n]\to\{-1,+1\}). The stored counter is \[ C_{r,t}=\sum_{j:h_r(j)=t}s_r(j)x_j. \] An update ((j,\Delta)) adds (s_r(j)\Delta) to bucket (h_r(j)) in every row. The point estimate for coordinate (i) is \[ \widetilde x_i=\operatorname{median}_{r\in[d]}\bigl(s_r(i)C_{r,h_r(i)}\bigr). \] In one row this equals (x_i+\sum_{j\ne i:h_r(j)=h_r(i)}s_r(i)s_r(j)x_j): the target plus signed collision noise.

For example, let (x=(0,9,1,0,-2,0)). If a row sends coordinate 2 to a bucket with coordinate 5, using signs (s(2)=+1,s(5)=-1), that counter is (9+2=11), so the row estimates (11), not (9). Other independent rows create different collisions; the median resists the minority of contaminated estimates.

The support contains nonzero coordinates. A vector is (k)-sparse when at most (k) coordinates are nonzero. Its best (k)-term approximation (x_k) retains the (k) largest magnitudes, and the tail energy is \(\lVert x-x_k\rVert_2^2\). Isolation means a heavy coordinate shares no bucket with the other chosen heavy coordinates in a row. Candidate generation produces a small set worth querying; a Count-Sketch point-query structure alone does not reveal names without scanning the universe. An \(\ell_2/\ell_2\) recovery returns a sparse (\widehat x) whose residual energy is close to the optimal tail energy.

This fills the gap between the earlier Count-Min-versus-Count-Sketch comparison and an actual decoder. Signed counters remove Count-Min's one-sided bias, but a useful recovery pipeline still needs enough buckets for low noise, enough rows for confidence, and a defensible way to enumerate candidates.

From shared audio channels to Count-Sketch recovery Signal coordinates are signed and hashed into repeated bucket rows. A heavy coordinate is isolated in enough rows and its median estimate becomes reliable. Signal: many sourcesspike: x₂ = 9spike: x₅ = −2small tail coordinateslike musicians sharing inputs Signed hash rowsrow 1: collision → 11row 2: isolated → 9row 3: tail noise → 8same key, independent mixtures Decodemedian(11, 9, 8) = 9rank candidatescandidate source required heavy coordinategood rowcollision
ConceptIntuitive meaningExact exampleNon-example or boundaryAssumptionQuestion answered
(k)-sparsityOnly (k) meaningful locationsThree nonzeros in (10^6) positionsMany tiny nonzeros are not exactly sparseCoordinate basis is meaningfulHow compact could the answer be?
Tail energyEnergy outside the best (k) entries(\lVert x-x_k\rVert_2^2=25)Sum of tail magnitudesTop (k) defined by magnitudeHow much unavoidable error remains?
IsolationOne heavy item avoids other heavy itemsKey 7 alone among top-(k) keys in its bucketAlone only from small tail itemsSufficiently random bucket hashIs heavy-heavy collision absent?
Signed estimateUndo target sign after reading its bucket(s(i)C[h(i)])Reading an unsigned bucket totalReproducible near-independent signsWhat is one row's estimate?
Median amplificationMajority of good rows defeats outliersMedian of (9,9,31,8,10) is 9Mean of collision-heavy rowsIndependent or suitably limited-independent rowsHow is constant success amplified?
Candidate generationProduce names to point-queryScan all (n) keys in a small universeAssuming counters contain key labelsScan or auxiliary identification sketchWhich coordinates should be queried?
(\ell_2/\ell_2) recoveryNear-optimal residual energy(\lVert x-\widehat x\rVert_2\le(1+\varepsilon)\lVert x-x_k\rVert_2)Accurate estimates for only preselected keysCorrect candidate/selection theoremIs the whole sparse approximation good?
Warm-up

Recovering Spikes from Hashed Measurements

Use (x=(8,1,-2,0)), one row with buckets (h(1)=0,h(2)=1,h(3)=0,h(4)=1), and signs (s=(+1,-1,-1,+1)).

  1. Compute counters: (C_0=(+1)8+(-1)(-2)=10) and (C_1=(-1)1=-1).
  2. Query coordinate 1: (s(1)C_0=10), so collision noise is (+2).
  3. Query coordinate 3: (s(3)C_0=-10), while (x_3=-2); the spike corrupts this row by (-8).
  4. In a second row, suppose coordinates 1 and 3 separate. Their estimates become exact in this toy signal.
  5. Expected result: a row can be excellent for one coordinate and poor for another; repetitions and a median are coordinate-specific.

Reflection: why do random signs make many small collisions behave differently from one same-sign accumulation, and why can they not rescue a repeated collision with a much larger coordinate?

Isolation and Median Coordinate Estimates

Fix a coordinate (i) and let (H) contain the (k) largest-magnitude coordinates other than (i). In a row, split the error (Z_r=\widetilde x_i^{(r)}-x_i) into heavy and tail collisions. With (b\ge 4k), a union bound gives \[ \Pr[\exists j\in H:h_r(j)=h_r(i)]\le k/b\le1/4. \] Thus (i) is isolated from (H) with probability at least (3/4).

Conditioned on the bucket hashes, pairwise-independent zero-mean signs cancel cross terms. For the remaining tail (T=[n]\setminus(H\cup\{i\})), \[ \mathbb E[Z_r^2]=\sum_{j\in T}\Pr[h_r(j)=h_r(i)]x_j^2 \le \frac{\lVert x_T\rVert_2^2}{b}. \] Markov's inequality applied to (Z_r^2) implies a constant-probability bound (\lvert Z_r\rvert\le c\lVert x_T\rVert_2/\sqrt b) for an explicit constant (c). Combining the isolation and tail-noise events leaves a constant probability that one row is good. If rows are independent and (d=\Theta(\log(n/\delta))), a Chernoff bound makes the median good for all (n) queried coordinates with probability at least (1-\delta).

Setting (b=\Theta(k/\varepsilon^2)) yields the familiar simultaneous point-error scale \[ \lvert\widetilde x_i-x_i\rvert\le O\!\left(\frac{\varepsilon}{\sqrt{k}}\lVert x-x_k\rVert_2\right). \] The exact constant depends on the hash independence and the allocation of failure probability. The proof obligation is not merely “the median is robust”: one must establish a per-row good-event probability strictly above (1/2), independence across rows, then union-bound over every coordinate actually queried.

There are important boundaries. With no random signs, positive collisions introduce Count-Min-style bias. With (b\ll k), heavy-heavy collisions occur too often. Pairwise independence is enough for the second-moment calculation but not automatically for every adaptive or high-probability claim. If an adversary chooses updates after learning the hashes, it can engineer collisions. Count-Sketch also differs from an expander-based identification sketch: the latter encodes enough neighbor structure or messages to recover coordinate identities without scanning all (n).

Sparse Recovery from Count-Sketch Measurements: Isolation and Median Coordinate Estimates
flowchart TD
    A[Linear signed bucket counters] --> B[Fix coordinate i and one row]
    B --> C[Separate heavy set H from tail T]
    C --> D[Enough buckets isolate i from H]
    C --> E[Random signs give zero-mean tail noise]
    E --> F[Second moment bounds tail error]
    D --> G[One row is good with probability above one half]
    F --> G
    G --> H[Independent rows and median amplification]
    H --> I[Simultaneous point estimates]
    I --> J[Candidate selection plus pruning]
    J --> K[l2 over l2 sparse recovery]
    C --> L{Too few buckets or exposed hashes?}
    L -->|yes| M[Isolation or concentration can fail]
    L -->|no| D
    classDef navy fill:#17365D,color:#fff,stroke:#17365D;
    classDef teal fill:#147D84,color:#fff,stroke:#0D565B;
    classDef purple fill:#6C3BAA,color:#fff,stroke:#472675;
    classDef crimson fill:#C6284D,color:#fff,stroke:#861B35;
    class A,B,C navy;
    class D,E,F,G,H purple;
    class I,J,K teal;
    class L,M crimson;
Isolation turns a mixed bucket into a point estimateBefore hashing there is one target, other heavy coordinates, and a small tail. In a good row, other heavy coordinates occupy different buckets, leaving only signed tail noise with the target. Before: signal coordinatesiH₁H₂tail T: many small values hash + sign Good rowbucket 0itarget + tailbkt 1H₁bkt 2H₂heavy competitors are separated Estimatexᵢ + ZE[Z] = 0E[Z²] ≤ ||T||²/b targetother heavytailcertified good event

With (b=\Theta(k/\varepsilon^2)) buckets and (d=\Theta(\log(n/\delta))) independent rows, signed-median estimates achieve simultaneous additive error (O((\varepsilon/\sqrt{k})\lVert x-x_k\rVert_2)) with probability (1-\delta). Isolation controls heavy collisions and a second-moment bound controls the tail; constants and robustness depend on the hash families, and point estimates alone do not solve sublinear-time identification.

From Point Error to Sparse Recovery

Assume estimates obey (\lvert\widetilde x_i-x_i\rvert\le\eta) simultaneously. If all coordinates can be queried, form (S), the indices of the largest (k) values of (\lvert\widetilde x_i\rvert), and output (\widehat x_i=\widetilde x_i) for (i\in S), zero otherwise. The selection argument pairs any missed true top-(k) coordinate with a selected outsider having at least as large an estimated magnitude. Triangle inequalities charge the swap to estimation error and tail energy. A sufficiently smaller point-error constant—normally obtained by sizing buckets with the desired recovery accuracy—yields \[ \lVert x-\widehat x\rVert_2\le(1+O(\varepsilon))\lVert x-x_k\rVert_2. \] Thresholding often keeps (O(k)), rather than exactly (k), candidates before a final pruning step. That slack prevents near-ties around rank (k) from causing a brittle proof.

The guarantee is relative to the best (k)-term approximation, not exact coordinate recovery. When (x) is exactly (k)-sparse, the tail is zero and the ideal theorem forces exact recovery, but only under arithmetic and identification assumptions strong enough to realize the zero-error conclusion. Floating-point counters, quantization, finite fields, and imperfect candidate lists add separate error terms.

Worked Example

From Point Error to Sparse Recovery

Let (x=(10,7,2,1,-1,0)), (k=2), and suppose the median estimates are (widetilde x=(9.7,7.3,1.6,1.2,-0.7,0.2)).

  1. The exact best two-term vector is (x_2=(10,7,0,0,0,0)).
  2. Tail energy is (2^2+1^2+(-1)^2=6), so (\lVert x-x_2\rVert_2=\sqrt6\approx2.449).
  3. Ranking estimated magnitudes selects (S=\{1,2\}). Output (widehat x=(9.7,7.3,0,0,0,0)).
  4. Residual squared error is (0.3^2+(-0.3)^2+6=6.18), hence residual norm is (2.486), a ratio (2.486/2.449\approx1.015).
  5. Independent verification: directly square all six residual coordinates; do not infer the guarantee merely from correct support.
  6. Perturb (widetilde x_2) to (1.4). Coordinate 3 is then selected instead of coordinate 2, and the residual grows sharply. This violates the assumed uniform error bound because (\lvert1.4-7\rvert=5.6).

Reflection: if the second and third magnitudes are nearly tied, why can support recovery fail while the (\ell_2/\ell_2) approximation remains good?

from hashlib import blake2b
from math import sqrt

def hash_u64(seed, row, domain, key):
    data = f"{seed}|{row}|{domain}|{key}".encode()
    return int.from_bytes(blake2b(data, digest_size=8, person=b"cs-demo-v1").digest(), "big")

class CountSketch:
    def __init__(self, universe, buckets, rows, seed=17):
        if min(universe, buckets, rows) <= 0:
            raise ValueError("universe, buckets, and rows must be positive")
        self.n, self.b, self.d, self.seed = universe, buckets, rows, seed
        self.counters = [[0.0] * buckets for _ in range(rows)]

    def _bucket(self, row, key):
        return hash_u64(self.seed, row, "bucket", key) % self.b

    def _sign(self, row, key):
        return 1 if hash_u64(self.seed, row, "sign", key) & 1 else -1

    def update(self, key, delta):
        if not 0 <= key < self.n:
            raise ValueError("key outside universe")
        for row in range(self.d):
            self.counters[row][self._bucket(row, key)] += self._sign(row, key) * delta

    def estimate(self, key):
        if not 0 <= key < self.n:
            raise ValueError("key outside universe")
        values = [self._sign(r, key) * self.counters[r][self._bucket(r, key)]
                  for r in range(self.d)]
        values.sort()
        m = len(values) // 2
        return values[m] if len(values) % 2 else (values[m - 1] + values[m]) / 2

    def recover_by_scan(self, k):
        if not 1 <= k <= self.n:
            raise ValueError("k must lie in [1, universe]")
        estimates = [self.estimate(i) for i in range(self.n)]
        support = sorted(range(self.n), key=lambda i: (-abs(estimates[i]), i))[:k]
        return {i: estimates[i] for i in support}

def residual_norm(vector, recovered):
    return sqrt(sum((value - recovered.get(i, 0.0)) ** 2
                    for i, value in enumerate(vector)))

def best_k_error(vector, k):
    keep = set(sorted(range(len(vector)), key=lambda i: -abs(vector[i]))[:k])
    return sqrt(sum(value * value for i, value in enumerate(vector) if i not in keep))

signal = [0, 10, 0, -7, 2, 1, -1, 0, 0, 0, 0, 0]
sketch = CountSketch(len(signal), buckets=32, rows=9, seed=23)
for index, value in enumerate(signal):
    if value:
        sketch.update(index, value)
recovered = sketch.recover_by_scan(2)
assert set(recovered) == {1, 3}
assert residual_norm(signal, recovered) <= best_k_error(signal, 2) + 1e-12

sketch.update(1, -10)
assert abs(sketch.estimate(1)) < 1e-12
after_delete = sketch.recover_by_scan(2)
assert 3 in after_delete

empty = CountSketch(8, buckets=8, rows=5)
assert all(empty.estimate(i) == 0 for i in range(8))

try:
    empty.update(8, 1)
    raise AssertionError("invalid key accepted")
except ValueError:
    pass

collision_heavy = CountSketch(12, buckets=1, rows=5, seed=23)
for index, value in enumerate(signal):
    if value:
        collision_heavy.update(index, value)
assert any(abs(collision_heavy.estimate(i) - signal[i]) > 0 for i in range(len(signal)))

print("recovered:", recovered)
print("best-k error:", best_k_error(signal, 2), "residual:", residual_norm(signal, recovered))
print("after deletion:", after_delete)
ConstructionAssumptionsMeasurement or query costGuarantee or roleStrengthFailure modePrefer when
Count-Sketch point querySigned hashes; suitable independence(O(bd)) counters, (O(d)) per queryAdditive error tied to tail energyTurnstile-linear and mergeableHeavy collisions or adaptive hashesCandidate keys are already known
Scan-and-prune recoveryPoint guarantee holds for every coordinate(O(n d)) decode timeSparse approximation from top estimated magnitudesSimple and auditableToo slow for huge universesUniverse is moderate or testing
Count-Sketch plus identificationAuxiliary coding, multilevel hashing, or expander structureTypically (k\operatorname{polylog}n) measurements and decode workSublinear candidate discovery plus estimationAvoids full scanMore constants and implementation complexityVery large sparse domains
Count-Min heavy hittersNonnegative counts and one-sided objective(O(\varepsilon^{-1}\log(1/\delta))) countersUpper-biased frequency estimatesSimple and nonnegativeSigned deletions break interpretationCash-register streams
Exact sparse mapMemory proportional to live support(O(\lVert x\rVert_0)) memoryExact support and valuesExcellent oracleNot sublinear for dense supportValidation or genuinely tiny support
Dense random projectionSubgaussian or related measurement modelUsually dense update and decode operationsCompressed-sensing recoveryStrong geometryPoor streaming update localityOffline linear measurement systems

Sparse Signals in Telemetry and Science

In a teaching case, use (n=64), plant three spikes, add bounded random tail noise, then compare every point estimate and the recovered top three against the exact vector. Vary buckets while holding the signal fixed: collision error should fall statistically, not monotonically on every seed.

In professional telemetry, coordinates may be service-error signatures or endpoint/status-code pairs. Updates can be positive and negative when late corrections arrive, making signed linear sketches attractive. Candidate generation might come from a bounded service catalog, a separate heavy-hitter identifier, or periodic dictionary snapshots. Choose (k) from the incident budget, size (b) from the tolerated tail error, size (d) from the number of queried candidates and failure budget, and version all hash seeds so distributed sketches remain merge-compatible.

In science, coordinates may be spectral bins or genomic features. Recovery is defensible when the signal is compressible in the chosen basis and measurement noise fits the error model. It is not defensible when important structure is dense, when “large” coordinates are scientifically biased by preprocessing, or when an adaptive party can learn the hash functions and construct collisions.

Evidence that invalidates deployment includes a tail norm far above the design range, false-negative rates concentrated near operational thresholds, residual ratios exceeding the promised tolerance on exact audits, row estimates with persistent same-direction bias, incompatible seeds across shards, arithmetic saturation, or decode time dominated by a supposedly impossible full-universe scan.

Count-Sketch sparse recovery in a telemetry pipelineVersioned signed updates enter merge-compatible sketches, candidate identities enter from a trusted catalog or identifier, and decoded spikes are validated against exact audits. Adaptive input and incompatible metadata are marked as failure boundaries. Telemetry edgecanonical keysigned updateadaptive input risk Sketch and identifyversioned rows, buckets, seedscatalog or identifier candidatesmedian estimates + pruningreject incompatible merge metadata Decision and auditrank suspected spikesexact sampled auditreject on residual drift data contractrandomized corefailure boundary
Sparse Recovery from Count-Sketch Measurements: Sparse Signals in Telemetry and Science
flowchart TD
    A[Define sparse objective and coordinate basis] --> B[Measure k tail energy and query volume]
    B --> C{Candidate identities available?}
    C -->|yes| D[Size buckets rows and counters]
    C -->|no| E[Add identification structure or reject]
    D --> F[Validate against exact held-out streams]
    F --> G{Point error residual and recall pass?}
    G -->|yes| H[Deploy versioned merge-compatible sketches]
    G -->|no| I[Resize change model or reject]
    H --> J[Monitor tail drift saturation and seed exposure]
    J --> K{Assumptions still valid?}
    K -->|yes| J
    K -->|no| I
    classDef navy fill:#17365D,color:#fff,stroke:#17365D;
    classDef teal fill:#147D84,color:#fff,stroke:#0D565B;
    classDef purple fill:#6C3BAA,color:#fff,stroke:#472675;
    classDef crimson fill:#C6284D,color:#fff,stroke:#861B35;
    class A,B,C navy;
    class D,F purple;
    class G,H,J teal;
    class E,I,K crimson;
Case Study

Sparse Signals in Telemetry and Science: Sparse Recovery from Count-Sketch Measurements

Scenario: a platform observes (n=5\times10^7) possible endpoint/error keys across 200 shards. It needs the largest (k=100) signed net-error changes every minute; corrections can delete earlier events.

  1. Establish an exact audit on a rotating 1% of shards and measure (\lVert x-x_k\rVert_2), top-(k) recall, residual ratio, and point-error quantiles.
  2. Candidate source: use the registered endpoint catalog plus a separate identifier for unseen keys. Document that Count-Sketch counters alone do not carry names.
  3. Start with bucket count proportional to (k/\varepsilon^2), then choose rows from the total candidate-query failure budget rather than from (n) if only a certified subset is queried.
  4. Require identical universe encoding, bucket/sign seeds, dimensions, numeric type, and epoch before merging shards.
  5. Test normal traffic, deletion-heavy correction traffic, a dense incident with elevated tail energy, counter saturation, deliberately colliding keys in a seed-exposure exercise, and candidate omissions.
  6. Expected observations: unbiased-looking row errors, better error quantiles with more buckets, exponential confidence improvement with independent rows, and degraded guarantees when tail energy or candidate miss rate rises.
  7. Selection decision: deploy only if the observed residual ratio meets the stated tolerance across incident classes and the candidate layer meets recall targets. Reject or rotate protected seeds if clients can adapt to revealed hashes.

Written deliverable: a parameter sheet mapping (k,\varepsilon,\delta), candidate count, update rate, counter range, and merge metadata to measured memory, latency, recall, and residual error.

Reconstruct and Verify a Sparse Vector

Complete the following stages in order. Keep the exact vector beside the sketch during development; a recovery theorem is not a substitute for an oracle on controlled tests.

Practice

Practice: Reconstruct and Verify a Sparse Vector

Starter input: (x=(12,0,3,-9,0,1,-2,0)), (k=2), with three supplied hash rows of your choice and at least four buckets per row.

  1. Recall: write (C_{r,t}) and the signed row estimate formula. Artifact: one correctly labelled equation for each. Criterion: target and collision signs are both present.
  2. Trace: fill every bucket by hand, then calculate all eight coordinate estimates and their medians. Artifact: row-by-row table. Criterion: recomputing counters from updates matches the direct dot products.
  3. Optimal baseline: compute (x_2), tail energy, and (\lVert x-x_2\rVert_2). Expected tail squared energy is (3^2+1^2+(-2)^2=14).
  4. Recover: select two estimated magnitudes, form (widehat x), and report (\lVert x-\widehat x\rVert_2/\lVert x-x_2\rVert_2). Criterion: distinguish value error from support error.
  5. Debug: flip one query sign, reuse one row three times, and reduce to one bucket. Predict each symptom before running it: biased/wrong estimates, no confidence amplification, and systematic heavy collisions.
  6. Boundary: delete coordinate 1 with update ((1,-12)), then recover again. Criterion: every affected counter cancels linearly and the new top two are coordinates 4 and 3.
  7. Comparison: explain why Count-Min is inappropriate for signed turnstile corrections and why exact support storage may still be preferable when support is tiny.
  8. Extension: replace the universe scan with a candidate list that intentionally omits coordinate 4. Measure the resulting error and state which premise failed. Then propose an identification layer.

Hints: inspect individual row estimates before the median; separate heavy collisions from tail collisions; near a top-(k) tie, judge residual energy rather than exact support alone.

Rubric: 20% correct counters, 20% auditable estimates, 20% exact baseline and residual, 15% deletion test, 15% failure diagnosis, 10% justified production choice. Mastery requires at least 80% and no unexplained candidate-generation assumption.

Decision checklist: define the coordinate basis and (k); measure tail energy; provide candidates; size buckets for error and rows for the actual query budget; protect or rotate randomness; version merge metadata; test deletions, saturation, and adaptive collisions; and compare residuals with an exact oracle. Do not confuse unbiasedness with low variance, point queries with identification, exact support recovery with (\ell_2/\ell_2) recovery, or more rows with relief from too few buckets—the next bridge is to identification sketches and expander-style sparse recovery that recover names without scanning the universe.