How Elasticsearch auto-tunes vector quantization to hit your recall target

Learn the geometric model that lets Elasticsearch predict recall with R² > 0.98 accuracy and auto-select vector quantization parameters from a small data sample.

Try out vector search for yourself using this self-paced hands-on learning for Search AI. You can start a free cloud trial or try Elastic on your local machine now.

What makes a good vector store?

A vector store that achieves good performance without tuning is more valuable than one that requires expert tuning. In fact, our contention is a data store that can be coaxed to exceptional performance by an expert who spends a week hand-tuning it is less useful than one that beats it consistently out of the box. In other words, easily achieving good performance is a first class property, not a nice to have. We can see this clearly in our telemetry. The great majority of users will never tune the internals of vector search at all, and why should they: it is just an enabler for what they're trying to build.

This is the imperative behind features like auto-calibration. The system as a whole should look at your data and your quality target and choose good parameters for you. Indeed we think this is a win-win, since it has far more nuanced information available to it to make these choices than we expose.

To make "good performance" precise, it helps to name the three attributes that characterize any vector search system, because they trade off against one another and you can't talk about one without fixing the others:

  1. Performance: throughput (QPS), latency, and so on.
  2. Hardware cost: a fair comparison always holds cost fixed. It's trivial to buy your way to more QPS or better recall by throwing hardware at the problem; the interesting question is what you achieve per dollar.
  3. Search quality: recall, nDCG, and related measures of whether you're returning the right results.

The three form a frontier. Push one and, at fixed budget, you pay in another. Any honest comparison of approaches pins two down and measures the third. What we describe in this post is the mechanism we're introducing to pick quantization parameters for a fixed recall budget. It is a step on a longer journey towards a vector store that configures itself well across the board.

Search quality is tricky, because the "right" results depend on relevance labels you usually don't have at index time. So we lean on recall as a safe proxy. The argument is simple: recall measures how well the approximate index reproduces the results of exact search over the same embeddings. If recall is high, you have not degraded search quality relative to what the underlying model can do; you can be confident you’ve faithfully preserved the baseline. You might still wish for a better embedding model, we've got you covered, but that's a separate concern from the index not damaging what the model already gives you.

This is why controlling recall matters so much, and why you should be wary of any system that doesn't reliably control it. If a vendor can't control recall, they can silently degrade your search experience, achieving impressive QPS numbers while quietly returning worse results, and you'd have no way to know without a labeled evaluation set. The method in this post is about maximizing performance while keeping a firm, predictable grip on quality.

Why vector quantization parameters must be chosen at index time

What makes the problem genuinely hard is that vectors are quantized as they are indexed, so the parameters that govern quality (how many bits, how deep to rerank, whether to precondition) have to be evaluated before we've seen the data laid out in its final form. We can't index everything, measure recall, and iterate; by then the quantization is baked in.

So we need to estimate what we'll need from a small sample, cheaply and in advance. Fortunately the Elasticsearch gives us natural moments to do this: segment merges are exactly such an opportunity. When segments are combined we have to rewrite the data anyway and can assess the data and (re)choose parameters. And as we'll see, models fit to small random samples give excellent estimates of the quantities we actually need to control. They’re typically good enough to set parameters once, with a small margin, and trust them as the index grows.

How vector quantization affects nearest-neighbor recall

With that motivation in place, let's start to dig into the details.

Vector quantization is a critical component for making approximate nearest-neighbor (ANN) search affordable at scale; it's an area we've innovated in the past. Instead of storing and comparing full-precision embeddings, we store a lossy, compressed representation and search over that. The catch is the one above: lossy representations move distances around, so the "nearest" neighbors under quantized distances are not always the true nearest neighbors and recall suffers.

The standard fix is to over-retrieve and rerank. We use the cheap quantized distances to pull back the top nn candidates, then recompute exact distances for those nn and keep the best kk. As long as the true top-kk are present somewhere in the retrieved top-nn, reranking recovers them exactly.

Reranking isn’t free, we have to fetch high precision vectors from disk. However, we can precisely characterize the performance of reranking based on hardware characteristics alone. This reframes the whole problem. The question is no longer "how much does quantization distort distances?" in the abstract, but something which relates back to the attributes we care about:

Given a quantization scheme with some error magnitude, and a rerank budget of nn candidates, what recall@kk should we expect. As an immediate consequence, what is the cheapest set of parameters that hits our recall target?

This post derives a model that answers exactly that. The core of it is a single, surprisingly clean idea: if we can characterize the distribution of distances to the kk-th nearest neighbor, and we have a model of the quantization error distribution, then we can compute expected recall after reranking in closed form (up to a one-dimensional integral). Everything else – bit counts, rerank depth, whether to precondition – becomes a search over a model we can fit cheaply from a small sample, instead of an expensive empirical sweep over full indices built with those parameters.

We build it up to this in three stages: the geometry of nearest-neighbor distances, the scaling law that falls out of it, and then the recall model that ties quantization error to recall given a reranking budget. Be warned, the following gets a little bit involved, but to give you intuition about what is happening see the video below.

Quantization error vs. the nearest-neighbor distance gap

Fix a query qq and rank the database vectors by their true distance to it: R(1)R(2)R_{(1)} \le R_{(2)} \le \dots, so R(i)R_{(i)} is the distance to the ii-th nearest neighbor. Reranking the top nn succeeds for the true kk-th neighbor whenever it is not pushed past rank nn by quantization noise.

Two competing quantities govern this:

  • The quantization error that is essentially fixed for a given scheme and dataset: it depends on the embedding dimension, the vector distribution, and the number of bits, but not on how big the index is.
  • The criticality gap Δk,n=R(n)R(k)\Delta_{k,n} = R_{(n)} - R_{(k)}, which is the distance between the kk-th and the nn-th nearest neighbor. This is the margin we have to absorb error. Crucially, it shrinks as the index grows: pack more vectors into the same region and neighbors crowd together.

There’s a detail here we’ll gloss over for the sake of presentation: for IVF style indices, we’re quantizing the residual from a cluster’s centroid. This does in fact couple the quantization error to the index size, but we can handle it much the same way we handle the distance to the ii-th nearest neighbor.

For reranking to recover the recall lost to quantization, we need the error to only rarely exceed the gap. If we can write down the distribution of Δk,n\Delta_{k,n} and the distribution of the error, we can make that statement quantitative. The first job is to estimate the distribution of nearest-neighbor distances.

Deriving the nearest-neighbor distance distribution

Real embeddings don't fill their ambient space; they concentrate on a lower-dimensional manifold. Near a query, though, we can make a mild local assumption: in a small neighborhood ΩRd\Omega \subset \mathbb{R}^d around the query, the data density is roughly uniform. Here dd is the intrinsic dimension of the manifold; it is unknown and generally far smaller than the embedding dimension. How to estimate it is the subject of Section 4.

Let X={Xi}\mathcal{X} = \{X_i\} be the NN vectors falling in Ω\Omega, modeled as i.i.d. uniform on Ω\Omega, and define the distance from qq to its nearest neighbor:

R=minXiXXiq.R = \min_{X_i \in \mathcal{X}} \lVert X_i - q \rVert\text{.}

To get the distribution of RR we use the standard order-statistics trick: rather than ask where the minimum is, ask for the probability it exceeds some radius rr. The event {R>r}\{R > r\} is exactly the event that every point lands outside the dd-ball centered on the query Br(q)B_r(q).

A single point lands inside Br(q)B_r(q) with probability equal to the ratio of the ball's volume to the region's volume VV

P(XiBr(q))=ωdrdV,ωd=πd/2Γ(d/2+1),(1)P(X_i \in B_r(q)) = \frac{\omega_d\, r^d}{V}, \qquad \omega_d = \frac{\pi^{d/2}}{\Gamma(d/2 + 1)}\text{,} \tag{1}

where ωd\omega_d is the volume of the unit dd-ball. (We assume NN is large enough that the relevant rr is small, so the ball doesn't spill outside Ω\Omega and boundary effects are negligible.) Because the points positions are assumed to be independent, the survival function is

P(R>r)=(1ωdrdV)N.(2)P(R > r) = \left(1 - \frac{\omega_d\, r^d}{V}\right)^{N}\text{.} \tag{2}

What we're really interested in is how R behaves on average. To compute this, we use the identity that the expectation of a non-negative random variable is the integral of its survival function, E[R]=0P(R>r)dr\mathbb{E}[R] = \int_0^\infty P(R > r)\, dr. Evaluating this with (2) gives the headline result:

  E[R](VωdN)1/d  \boxed{\;\mathbb{E}[R] \approx \left(\frac{V}{\omega_d\, N}\right)^{1/d}\;}

(The exact integral carries an extra Γ(1+1/d)\Gamma(1 + 1/d) factor; it's an O(1)O(1) constant that we can fold into a fitted coefficient later, so we drop it here.)

Glacial scaling: why neighbor distances barely change as your index grows

It is interesting to consider what this formula tells us about how distances change with dataset size: E[R]N1/d\mathbb{E}[R] \propto N^{-1/d}. The exponent is 1/d-1/d, and in high intrinsic dimensions that is a very small number. This is a property the method leans on, so it's worth plugging in some numbers:

  • If d=2d = 2 then doubling NN multiplies E[R]\mathbb{E}[R] by 21/20.7072^{-1/2} \approx 0.707, so distances drop by ~30%.
  • If d=50d = 50 then doubling NN multiplies E[R]\mathbb{E}[R] by 21/500.9862^{-1/50} \approx 0.986, so distances drop by a little over 1%.

In high dimensions, neighbor distances barely move even if you add a lot of data; call it glacial scaling. It's the reason we can choose quantization parameters once from a tiny sample, with a small safety margin, and trust them to remain valid even after the index grows substantially before the next re-quantization.

Expected distance to the k-th neighbor and the criticality gap

We actually care about the whole sequence of order statistics R(k)R_{(k)}, R(n)R_{(n)}, not just the minimum. There's a simple way to get them.

Map each radius to the cumulative volume it encloses by defining

Ui=ωdRidV.U_i = \frac{\omega_d\, R_i^d}{V}\text{.}

By (1), each UiU_i is exactly the probability of landing within radius RiR_i, so the {Ui}\{U_i\} are uniform on [0,1][0,1]. The order statistics of uniforms are textbook: the ii-th smallest of NN uniforms follows a Beta distribution,

U(i)Beta(i,Ni+1),E[U(i)]=iN+1.U_{(i)} \sim \mathrm{Beta}(i, N - i + 1), \qquad \mathbb{E}[U_{(i)}] = \frac{i}{N+1}\text{.}

Inverting the volume map, R(i)U(i)1/dR_{(i)} \propto U_{(i)}^{1/d}, gives the scaling of the ii-th neighbor distance:

E[R(i)](iN)1/d.\mathbb{E}[R_{(i)}] \propto \left(\frac{i}{N}\right)^{1/d}\text{.}

That's all we need for the expected gap:

E[Δn,k]=E[R(n)]E[R(k)]α((nN)1/d(kN)1/d)=E[R(k)]((nk)1/d1).\begin{align*} \mathbb{E}[\Delta_{n,k}] &= \mathbb{E}[R_{(n)}] - \mathbb{E}[R_{(k)}] &\approx \alpha\left(\left(\tfrac{n}{N}\right)^{1/d} - \left(\tfrac{k}{N}\right)^{1/d}\right) &= \mathbb{E}[R_{(k)}]\left(\left(\tfrac{n}{k}\right)^{1/d} - 1\right)\text{.} \tag{3} \end{align*}

The last form is the intuitive one: the gap between the kk-th and nn-th neighbors is the distance to the kk-th neighbor, scaled by ((n/k)1/d1)\big((n/k)^{1/d} - 1\big). Widening the rerank depth nn relative to kk opens the gap; higher intrinsic dimension dd closes it (the exponent 1/d1/d pushes (n/k)1/d(n/k)^{1/d} toward 1).

Why the expected gap is sufficient to predict recall

Working with an expectation is only legitimate if the gap doesn't fluctuate wildly around it. It doesn't because concentration of measure saves us. Applying the delta method to R(k)U(k)1/dR_{(k)} \propto U_{(k)}^{1/d} and using Var(U(k))k/N2\mathrm{Var}(U_{(k)}) \approx k/N^2 from the Beta distribution, a little algebra gives

Var(R(k))E[R(k)]2d2k.\mathrm{Var}(R_{(k)}) \approx \frac{\mathbb{E}[R_{(k)}]^2}{d^2\, k}\text{.}

So the coefficient of variation is about 1dk\frac{1}{d\sqrt{k}}. For any reasonable intrinsic dimension this is negligible, which justifies modeling only the expected distances. (If you're worried about the delta method approximation, you can check the results numerically: the delta-method variance and the resulting 1/(dk)1/(d\sqrt{k}) coefficient of variation match the exact expressions to several significant figures.)

The derivation is for the Euclidean metric, but the other common metrics reduce to it:

  • For cosine similarity, the equidistant surface is the intersection of a sphere around the query with the unit sphere. This is called a hyperspherical cap, whose volume scales as sin(θ)d1θd1\sin(\theta)^{d-1} \approx \theta^{d-1} for small θ\theta. Therefore, the analysis carries over unchanged up to constants, with the dimension reduced by one.
  • For MIPS (maximum inner product), some extra care is needed, because nearest neighbors aren't confined to a compact region. A distant vector can still win on inner product if its norm is large enough, so the gap is really governed by the tail of the norm distribution. However, there is a clean fix, which is to use the Neyshabur–Srebro transformation. This lifts vectors onto a unit hypersphere in d+1d+1 dimensions. After this operation, it's just the cosine case.

Fitting intrinsic dimension and scale from a small sample

Equation (3) has a known functional form but two unknown parameters: the intrinsic dimension dd and the scale α\alpha. Both are easy to fit, and it's more convenient to fit them from raw neighbor distances than from gaps directly.

Sample several subsets of database vectors {Di}\{D_i\} of sizes Ni=DiN_i = |D_i| and a set of query vectors QQ. For each query qQq\in Q and each subset, measure ri,j(q)r_{i,j}(q), the distance to the jj-th nearest neighbor of qq within DiD_i. Taking logs of the scaling law E[R(j)]α(j/Ni)1/d\mathbb{E}[R_{(j)}] \approx \alpha (j\,/\,N_i)^{1/d} linearises it:

log(1QqQri,j(q))logα+1d(logjlog(Ni/N0)).\log\left(\frac{1}{|Q|}\sum_{q \in Q} r_{i,j}(q)\right) \approx \log\alpha + \frac{1}{d}\Big(\log j - \log(N_i/N_0)\Big)\text{.}

Specifically, this is linear in logj\log j and log(Ni/N0)\log(N_i/N_0), so ordinary least squares recovers α^\hat{\alpha} and d^\hat{d}. Varying the subset size NiN_i is what makes it possible to estimate dd: it's precisely the rate at which distances shrink with data volume. With the fitted parameters, the whole-index expected gap is

E[Δn,k]α^(kN0N)1/d^((nk)1/d^1).(4)\mathbb{E}[\Delta_{n,k}] \approx \hat\alpha\left(\frac{kN_0}{N}\right)^{1/\hat d}\left(\left(\frac{n}{k}\right)^{1/\hat d} - 1\right)\text{.} \tag{4}

Figure 1 shows how well this fits in practice (and it’s remarkably good): predicted versus actual average distance to the kk-th neighbor, across a range of datasets and metrics, have R2R^2 between 0.996 and 0.999.

Modeling vector quantization error as Gaussian

With the nearest-neighbor distance model established, the second component is the quantization error distribution. For every metric we use, the quantized distance estimate differs from the true distance by an error that is a sum of many independent per-dimension contributions. By the Central Limit Theorem that sum tends to Gaussian, so we model the error as normal with a variance we estimate empirically:

σb2=1ZqQi,j(ri,j(q)r~i,j(qb))2,\sigma_b^2 = \frac{1}{Z}\sum_{q \in Q}\sum_{i,j}\big(r_{i,j}(q) - \tilde{r}_{i,j}(q \mid b)\big)^2\text{,}

where r~i,j(qb)\tilde{r}_{i,j}(q \mid b) is the quantized distance estimate using bb-bit vectors and ZZ is the total number of (query, neighbor) pairs in our sample set. In other words: sample, quantize, measure the squared distance errors, average.

Figure 2 shows the empirical basis for the Gaussian assumption: measured quantization error densities against best-fit Gaussians across a variety of datasets. The fit is good, which is what lets the rest of the model stay analytic.

We could stop here and take a minimax view: threshold the probability that the kk-th and nn-th neighbors swap, using the expected gap (4) against the error scale σb\sigma_b. But that controls a worst-case event, and what we actually want to control is average recall. The outcome would be overly conservative quantization parameters and we'd pay some performance. The next section estimates expected recall properly.

Predicting expected recall after reranking

Combining the distance model and the error model gives a closed-form estimate of expected recall after reranking. Model the noisy distance of the ii-th true neighbor as a Gaussian centered on its true distance:

Xi=N(R(i),σb).X_i = \mathcal{N}\big(R_{(i)}, \sigma_b\big)\text{.}

The ii-th neighbor survives reranking, i.e., lands in the retrieved top nn, if fewer than nn other vectors have a smaller noisy distance. Condition on Xi=xX_i = x and count the competitors closer than xx:

S(x)=ji1(Xj<x).S(x) = \sum_{j \ne i} \mathbf{1}(X_j < x)\text{.}

Then the probability of recalling neighbor ii integrates over where its own noisy distance lands:

P(recall(i))=0P(S(x)<n)fXi(x)dx.P(\text{recall}(i)) = \int_0^\infty P\big(S(x) < n\big)\, f_{X_i}(x)\, dx\text{.}

The terms of S(x)S(x) are independent Bernoullis but not identically distributed, since every neighbor jj sits at a different true distance R(j)R_{(j)}, so each has its own probability of intruding on the top-kk set:

pj(x)=P(Xj<x)=Φ ⁣(xR(j)σb),(5)p_j(x) = P(X_j < x) = \Phi\!\left(\frac{x - R_{(j)}}{\sigma_b}\right)\text{,} \tag{5}

with Φ\Phi the standard normal CDF. This makes S(x)S(x) a Poisson-binomial variable. Since we sum many of them (because NnN \gg n), the Lyapunov CLT applies and we approximate

S(x)N(μS(x),σS2(x)),S(x) \sim \mathcal{N}\big(\mu_S(x)\,, \sigma_S^2(x)\big)\text{,}

with the standard Poisson-binomial moments

μS(x)=jipj(x),σS2(x)=jipj(x)(1pj(x)).\mu_S(x) = \sum_{j \ne i} p_j(x), \qquad \sigma_S^2(x) = \sum_{j \ne i} p_j(x)\big(1 - p_j(x)\big)\text{.}

The survival probability then has a clean closed form:

P(S(x)<n)Φ ⁣(nμS(x)σS(x)).P\big(S(x) < n\big) \approx \Phi\!\left(\frac{n - \mu_S(x)}{\sigma_S(x)}\right)\text{.}

This is where the two halves of the post so far finally meet. We don't need to know the individual R(j)R_{(j)} because the manifold scaling law from Section 3 supplies them: R(j)=α(jN0/N)1/dR_{(j)} = \alpha\,(jN_0/N)^{1/d}. So the moments become explicit sums over ranks, which we truncate at a safe cutoff (say 10n10n, since distant neighbors contribute negligibly):

μS(x)j=110nΦ ⁣(xα(jN0/N)1/dσb),\mu_S(x) \approx \sum_{j=1}^{10n} \Phi\!\left(\frac{x - \alpha(jN_0/N)^{1/d}}{\sigma_b}\right)\text{,}
σS2(x)μS(x)j=110nΦ ⁣(xα(jN0/N)1/dσb)2.\sigma_S^2(x) \approx \mu_S(x) - \sum_{j=1}^{10n} \Phi\!\left(\frac{x - \alpha(jN_0/N)^{1/d}}{\sigma_b}\right)^{2}\text{.}

Finally, average recall@kk given rerank depth nn sums the per-neighbor recall over the top kk:

  P(recall@kn)=i=1kP(recall(i)n)i=1k0Φ ⁣(nμS(x)σS(x))ϕ ⁣(xR(i)σb)dx.  \boxed{\;P(\text{recall}@k \mid n) = \sum_{i=1}^{k} P(\text{recall}(i) \mid n) \approx \sum_{i=1}^{k} \int_0^\infty \Phi\!\left(\frac{n - \mu_S(x)}{\sigma_S(x)}\right)\phi\!\left(\frac{x - R_{(i)}}{\sigma_b}\right) dx.\;}

Here ϕ\phi is the standard normal density. Each integral is smooth and one-dimensional, so Gauss–Legendre quadrature evaluates it in microseconds. The entire recall prediction for a set of candidate parameters costs a handful of quadrature evaluations, not index build and benchmark run.

Figure 3 validates the end-to-end model: predicted average recall against measured recall across many parameter settings and multiple datasets has R2=0.982R^2 = 0.982.

How the recall model selects vector quantization parameters

With a fast recall predictor available, parameter selection becomes a cheap ordered search. Given a target recall and a rerank budget nn (typically expressed as a multiple of kk), we can find the minimum document and query bit counts, and other knobs, that clear the target. There are a few things to note that are practically important:

  1. Glacial scaling gives us some safety because R(k)R_{(k)} moves so slowly with NN for even moderate intrinsic dimension. A small margin in the calculation means the chosen parameters stay valid if a lot of vectors are added before parameters are restimated.
  2. Small kk is the worst case if nn is a fixed multiple of kk. The gap \mathbb{E}[R_{(k)}]((n/k)1/d1)(n/k)^{1/d} - 1) is smallest for small kk so if a parameter choice satisfies the recall target at k=10k = 10 then it will for larger kk will too.
  3. We can treat quantization as a black box because the error model only needs the empirical error variance. This means we can test any configuration, including preconditioning, the same way and we can simply order candidate parameter tuples by increasing index and query cost, and stop at the first choice that hits the target recall. For tuples of (query bits, doc bits, rerank depth, precondition) a sensible search sequence increases query precision first, then document precision (1,1)(1,1), (2,1)(2,1), (3,1)(3,1), (4,1)(4,1), (2,2)(2,2), (3,3)(3,3), (4,2)(4,2), (4,4)(4,4), (7,4)(7,4) and (7,7)(7,7) each combined (via an outer product \otimes) with rerank depths like (1.5k,2k,3k)(1.5k,\,2k,\,3k) and precondition {true,false}\in \{\text{true},\, \text{false}\}, exiting as soon as the target is met.

Results: auto-selected quantization parameters and recall across datasets

In this section, we discuss the results of the initial experiments on the end-to-end behavior. We’ve made some further refinements as part of the work to fully integrate with Elasticsearch that we discuss in our other post.

The table below shows auto-selected parameters targeting recall 0.97, measured with brute-force search, so the number reflects loss due to quantization alone (64 query clusters, targeting document clusters of size 384, which matches the settings of DiskBBQ).

DatasetQuery bitsDoc bitsPreconditionDepthRecall
FiQA E5 small42false300.97
FiQA arctic22false300.95
FiQA GTE21true300.98
MNIST31true300.99
Fashion MNIST31true300.99
Quora E5 small22false300.99
Quora arctic21false300.97
Quora GTE11false300.98
Dbpedia E5 small42false300.99
Dbpedia arctic21false300.94
Dbpedia GTE21false300.96
Wiki Cohere22false300.99
Hotpot E5 small42false300.97
Hotpot GTE21false300.96
Glove 10042false300.87
Glove 20042false300.89
SIFT12844false200.99

There are a few things worth highlighting:

  • The recall is very sensitive to rerank depth. This is why we nearly always end up choosing the maximum depth available: a step up in rerank depth from 20 to 30 is typically what pushes us to hit the recall target for fewer bits and we prefer fewer bits. In the real system, we tuned this behavior based on a more representative reranking cost.
  • Glove underperforms partly we approximate the query distribution with random samples from the corpus, but Glove is also less well characterized by the model than the other datasets. A plausible explanation is that the approximately uniform local density assumption from Section 2 is less reliable for Glove embeddings, which would show up as higher recall variance between queries. However, Glove embeddings are not representative of the actual vectors we need to store.
  • The FiQA GTE preconditioning choice is a knife-edge case: preconditioning produced only a tiny expected recall improvement, but the prediction sat right at the recall cutoff and allows us to drop the query from 3 to 2 bits. If we'd rather only keep preconditioning where its benefit is clear-cut, we can enforce a minimum uplift threshold. This sort of fine-tuning of the decision logic leaves all the heavy lifting to estimate recall unaffected.

Key takeaways: auto-tuning vector quantization from first principles

We presented a method to pick optimal quantization parameters to achieve a target recall. It rests on two models that compose cleanly:

  1. A geometric model of neighbor distances that follows from a local uniform density assumption. We use this to derive the nearest-neighbor distance, the N1/dN^{-1/d} glacial scaling law of the expected distance, and the expected distance profile R(j)=α(jN0/N)1/dR_{(j)} = \alpha(jN_0/N)^{1/d}. We show that fitting α\alpha and dd by a simple log-linear regression to average distances in small random samples from the corpus gives an extremely accurate predictive model.
  2. A Gaussian quantization error model that is justified by the CLT. Its only parameter σb\sigma_b is an empirical variance we estimate by comparing quantized and raw vector similarities for a sample of the corpus.

Finally, we show that it is possible to feed the estimated distance model into a Poisson-binomial count of neighbors that intrude on the top-kk set. Applying the Lyapunov CLT the expected recall@kk after reranking to depth nn falls out as a one-dimensional integral we evaluate by quadrature.

The outcome is an accurate (R2>0.95R^2>0.95) predictive model of recall as a function of the quantization parameters. Choosing quantization parameters then becomes an ordered search with a predictive model telling us if we’ve hit the recall constraint. And nicely one that also comes with a built-in argument (glacial scaling) for why the chosen parameters remain safe even when estimated from a relatively small fraction of the data.

We’ve built this entire mechanism into Elasticsearch using segment merges as an opportunity to reassess our quantization choices. Aside from the peace of mind this brings (that you’ll achieve good recall whatever vectors you throw at it), it also allows us to chose near optimal parameters from a performance perspective. This closes the loop on our original objective: near optimal performance out of the box, at least as far as quantization goes. We’re pretty excited about the advantages that model based tuning can bring to vector search and look forward to sharing other work we have in this direction in the near future.

How helpful was this content?

Not helpful

Somewhat helpful

Very helpful

Related Content

Ready to build state of the art search experiences?

Sufficiently advanced search isn’t achieved with the efforts of one. Elasticsearch is powered by data scientists, ML ops, engineers, and many more who are just as passionate about search as you are. Let’s connect and work together to build the magical search experience that will get you the results you want.

Try it yourself