IVF Index: Clustering-Based Vector Search & Partitioning › Worked Example

Michael BrenndoerferJanuary 27, 20268 min read
Language AI HandbookAll chapters
Part 44 of 67Retrieval-Augmented Generation
Chapter 340IVF Index: Clustering-Based Vector Search & Partitioning › Worked Example
Reading section 4 of 12 · Worked Example · 8 minSection 4 of 12 · 8 min

Book contents

Section 4 of 12 · 8 min read

IVF Index: Clustering-Based Vector Search & Partitioning › Worked ExampleOne section · Sections in this chapter4 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Let's walk through a concrete 2D example to ground the abstract concepts in tangible calculations. Working in two dimensions lets us follow every computation by hand and verify our geometric intuition. Suppose we have 12 vectors and partition them into k=3k = 3 clusters.

Training phase: K-means identifies three centroids. These are the points that minimize the within-cluster variance for their respective groups:

  • c1=(2,3)c_1 = (2, 3)
  • c2=(8,2)c_2 = (8, 2)
  • c3=(5,8)c_3 = (5, 8)

Assignment phase: Each vector is assigned to its nearest centroid, creating three inverted lists. Notice how the vectors in each cell are geographically close to their centroid. This is exactly the grouping property that makes IVF effective:

CellCentroidVectors

| 1 | (2,3)(2, 3) | {(1,2),(3,4),(2,1),(1,3)}\{(1,2), (3,4), (2,1), (1,3)\} | | 2 | (8,2)(8, 2) | {(7,1),(9,3),(8,1),(7,2)}\{(7,1), (9,3), (8,1), (7,2)\} | | 3 | (5,8)(5, 8) | {(4,7),(6,9),(5,7),(4,9)}\{(4,7), (6,9), (5,7), (4,9)\} |

: Vector assignments to IVF cells after k-means clustering. {#tbl-ivf-assignments}

Each cell contains exactly 4 vectors, giving us perfectly balanced inverted lists. In practice, cells are rarely this uniform; the balance here makes the example easier to follow.

Query phase: A query q=(6,6)\mathbf{q} = (6, 6) arrives, and we set nprobe=2\texttt{nprobe} = 2.

where q=(6,6)\mathbf{q} = (6, 6) is the query vector and nprobe=2\texttt{nprobe} = 2 means we will search the 2 cells whose centroids are closest to the query.

The first task is to determine which cells are most promising. We compute distances from the query to all centroids using Euclidean distance. The Euclidean distance between two 2D points (x1,y1)(x_1, y_1) and (x2,y2)(x_2, y_2) is:

(x2−x1)2+(y2−y1)2\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2}

where:

  • (x1,y1)(x_1, y_1): the coordinates of the first point
  • (x2,y2)(x_2, y_2): the coordinates of the second point
  • (x2−x1)2+(y2−y1)2(x_2-x_1)^2 + (y_2-y_1)^2: the sum of squared differences in each dimension

Taking the square root of this sum gives us the actual straight-line geometric distance and ensures the distance obeys the triangle inequality.

Applying this formula to each centroid, we can determine which regions of space are closest to our query:

d(q,c1)=(6−2)2+(6−3)2(substitute query and centroid coordinates)=16+9(compute squared differences)=5.0(final distance)d(q,c2)=(6−8)2+(6−2)2(substitute coordinates)=4+16(compute squared differences)≈4.47(final distance)d(q,c3)=(6−5)2+(6−8)2(substitute coordinates)=1+4(compute squared differences)≈2.24(final distance)\begin{aligned} d(\mathbf{q}, c_1) &= \sqrt{(6-2)^2 + (6-3)^2} && \text{(substitute query and centroid coordinates)} \\ &= \sqrt{16 + 9} && \text{(compute squared differences)} \\ &= 5.0 && \text{(final distance)} \\ \\ d(\mathbf{q}, c_2) &= \sqrt{(6-8)^2 + (6-2)^2} && \text{(substitute coordinates)} \\ &= \sqrt{4 + 16} && \text{(compute squared differences)} \\ &\approx 4.47 && \text{(final distance)} \\ \\ d(\mathbf{q}, c_3) &= \sqrt{(6-5)^2 + (6-8)^2} && \text{(substitute coordinates)} \\ &= \sqrt{1 + 4} && \text{(compute squared differences)} \\ &\approx 2.24 && \text{(final distance)} \end{aligned}

where:

  • d(q,ci)d(\mathbf{q}, c_i): the Euclidean distance between the query vector q\mathbf{q} and centroid cic_i
  • q=(6,6)\mathbf{q} = (6, 6): the query vector coordinates
  • c1=(2,3)c_1 = (2, 3): the first centroid coordinates
  • c2=(8,2)c_2 = (8, 2): the second centroid coordinates
  • c3=(5,8)c_3 = (5, 8): the third centroid coordinates

Ranking these distances from smallest to largest, centroid c3c_3 is closest at distance 2.24, followed by centroid c2c_2 at distance 4.47, and finally centroid c1c_1 at distance 5.0. The two closest centroids are c3c_3 (distance 2.24) and c2c_2 (distance 4.47). With nprobe=2\texttt{nprobe} = 2, we search the inverted lists for cells 3 and 2, scanning 8 of the 12 vectors. We skip cell 1 entirely, saving those 4 distance computations. In this small example, we save only 4 comparisons, but in a real dataset with millions of vectors and hundreds of centroids, this same principle eliminates the large majority of distance computations.

Among the 8 vectors searched, the closest to q=(6,6)\mathbf{q} = (6, 6) is (6,9)(6, 9) at distance 3.0 from cell 3:

(6−6)2+(6−9)2=0+9=3.0\sqrt{(6-6)^2 + (6-9)^2} = \sqrt{0 + 9} = 3.0

where:

  • (6,9)(6, 9): the vector from the scanned cells that is nearest to the query
  • (6−6)2+(6−9)2\sqrt{(6-6)^2 + (6-9)^2}: the Euclidean distance calculation between query and result vector
  • distance 3.0: the final computed distance

The zero contribution from the x-dimension shows the vector is directly above the query, differing only in the y-coordinate.

Note that if the actual nearest neighbor had been in cell 1 (which it isn't in this case), we would have missed it. This is the approximation trade-off. The decision to skip cell 1 was made based solely on centroid distances. While centroids are good summaries of their cells, they are not perfect predictors of which cell contains the nearest neighbor. In this example the approximation worked perfectly, but in general there is always a chance that a skipped cell harbors a closer vector, which is why increasing nprobe\texttt{nprobe} improves recall.

Out[3]:
Visualization
2D scatter plot showing IVF space partitioning with three Voronoi cells, centroids as triangles, twelve vectors as circles, and a red star query at (6,6) with nprobe=2 probing the two nearest cells.
IVF space partitioning in 2D with a worked clustering-based search. Twelve vectors (circles) are organized into three cells, with centroids shown as triangles. The query (red star at coordinates 6,6) identifies the two nearest centroids using nprobe=2, examining the blue and green cells while skipping the gray cell. The search finds the true nearest neighbor at coordinates (6,9), distance 3.0, by comparing against 8 of 12 vectors—a 33% reduction in vector-distance computations compared with brute force.