Quant Memo
Core

The Hashing Trick

A way to turn categorical variables with huge or unbounded vocabularies into fixed-size numeric features by hashing category names into a small number of buckets, trading a controlled amount of collision noise for a fixed memory footprint.

Prerequisites: One-Hot Encoding and the High-Cardinality Problem

A ticker universe with 8,000 symbols, a broker-ID field with new counterparties added weekly, a free-text order-tag column — all of these are categorical variables where one-hot encoding either blows up your feature matrix into tens of thousands of columns or breaks the moment a new category shows up in production that the training set never saw. You need a fixed-width numeric representation that doesn't require ever building or storing a lookup table of every category you might encounter.

The idea: bucket by hash, not by lookup

Instead of assigning each category its own column by looking it up in a table built from training data, feed the category's name (as a string) through a hash function and take the result modulo some fixed number of buckets, mm. "AAPL" might hash to bucket 41, "GOOG" to bucket 8, a counterparty called "NEWBROKER2026" that never appeared during training hashes to bucket 41 too — deterministically, with no dictionary lookup at all. The feature vector has exactly mm columns no matter how many distinct categories exist in the data, now or in the future.

Formally, for a hash function hh mapping strings to integers, the bucket index is

b=h(category)modm.b = h(\text{category}) \bmod m .

In plain English: pick a fixed number of buckets mm, run every category name through the same hash function, and the remainder after dividing by mm tells you which bucket to light up. Two different categories that happen to land in the same bucket are said to collide — the model can no longer fully distinguish them, and this collision noise is the price paid for a fixed, unbounded-vocabulary-proof feature width.

Worked example: hashing four tickers into 8 buckets

Suppose m=8m = 8 and a (illustrative) hash function gives: h(AAPL)=41h(\text{AAPL}) = 41, h(MSFT)=17h(\text{MSFT}) = 17, h(GOOG)=8h(\text{GOOG}) = 8, h(TSLA)=33h(\text{TSLA}) = 33. Taking each mod 8: AAPL → bucket 1 (41mod8=141 \bmod 8 = 1), MSFT → bucket 1 (17mod8=117 \bmod 8 = 1), GOOG → bucket 0, TSLA → bucket 1. AAPL, MSFT and TSLA all collide into bucket 1 — the model sees a single "bucket-1 indicator" turn on for any of the three tickers and cannot tell them apart from that feature alone. With only 8 buckets and 4 tickers, collisions are likely; doubling mm to 16 or 32 sharply reduces the chance any two specific tickers collide, at the cost of a wider feature vector.

AAPL, MSFT, TSLA → bucket 1 (collision) GOOG → bucket 0 0 1 (×3) 2 3
Bar height shows how many category names landed in each of the eight hash buckets — bucket 1 collects three different tickers, a collision the model cannot resolve.

What this means in practice

The hashing trick is the standard fix for high-cardinality or open-ended categoricals — order-tag free text, exchange venue codes, counterparty IDs — where a lookup-table encoding would either be too wide or fail on unseen values at inference time. Choosing mm is a direct bias-collision trade-off: too small and unrelated categories get merged into meaningless shared signal; too large and you're back to a near one-hot-sized matrix with little benefit. A common check is estimating the birthday-paradox-style collision rate for your actual vocabulary size and picking mm several times larger than the number of distinct categories you expect.

The hashing trick maps categories to a fixed number of buckets via a hash function and modulo, giving constant-width features that work on categories never seen during training — at the cost of occasional, uncontrollable collisions between unrelated categories.

Pick mm a few times larger than your expected vocabulary size, and prefer a value like 2102^{10} or 2162^{16} so downstream bitwise operations stay cheap.

Related concepts

Practice in interviews

Further reading

  • Weinberger et al., Feature Hashing for Large Scale Multitask Learning
ShareTwitterLinkedIn