advanced neural-retrieval 31 min read

Dense Retrieval and Dual Encoders: Architecture, Expressivity, and the Cost of Negatives

Why a query tower and a document tower trained to a separable score let you precompute every document, collapse retrieval to a single maximum-inner-product lookup, and represent exactly the relevance patterns of rank at most d by Eckart–Young — and why one batch of 2B encodings secretly buys B² training comparisons

Overview & motivation

Contrastive learning gave us a loss that teaches an encoder to place a query near its relevant document and far from everything else. It left one question deliberately unasked: what kind of encoder, and what does that choice buy and cost? This topic answers it. The architecture nearly every dense retriever uses is the dual encoder — two towers, a query encoder EQE_Q and a document encoder EPE_P, whose relevance score is the inner product of their outputs. The choice looks innocuous. It is the most consequential decision in the whole pipeline.

The reason is a single structural fact: the score separates. Query and document never interact until one inner product at the very end. That separability is what we will follow through three movements. First, it is exactly what lets a system precompute every document offline and answer a query with a single maximum-inner-product lookup — the bridge to the entire approximate-nearest-neighbor track, and to the hardness of MIPS. Second, it imposes a hard expressivity ceiling: stack the scores into a relevance matrix and a dd-dimensional dual encoder can only realize matrices of rank at most dd, with the truncated SVD — Eckart–Young — the best it can do below that rank. Third, it makes training cheap in a precise, countable way: a batch of BB pairs yields a B×BB \times B Gram matrix of similarities, so 2B2B encoder passes buy B(B1)B(B-1) negative comparisons. The loss is the previous topic’s; here we read the matrix that loss consumes as the object the architecture produces.

documentscorpus Cquery qpassage matrix G(encoded offline,once)MIPSG · E_Q(q)10102103104105corpus size |C|query-time encoder passesbi-encoder (constant: 1)cross-encoder (linear: |C|)
query-time encoder passes
1 (the query) + MIPS
at |C| = 21,000,000
1 pass + index lookup
passages precomputable?
yes — encode once offline

A dual encoder's score separates: query and document meet only in a single inner product. So every document vector is encoded once, offline into the matrix G, and a query is answered by one matrix-vector product G·EQ(q) followed by top-k — maximum-inner-product search whose query-time cost is constant in the corpus size. A cross-encoder fuses [q ; d] and must run a joint forward pass for everydocument at query time, so it cannot precompute anything. That separability is exactly what lets the rest of the curriculum index dense vectors (IVF, HNSW, PQ) — and why exact MIPS at scale is its own hard problem.

The first panel toggles the dual encoder against a cross-encoder and watches the query-time cost: the dual encoder is flat in the corpus size because its documents are precomputed, the cross-encoder linear because it must re-score every pair. The second is the rank ceiling — a relevance matrix with finance-sector block structure and its best rank-dd reconstruction, with recall collapsing as dd drops below the intrinsic rank. The third is the Gram trick: the B×BB \times B matrix whose diagonal is the positives, with the quadratic count of negatives appearing from a linear number of encodings.

The dual encoder and notation

Fix a query qq and a corpus of documents C={d1,,dn}\mathcal{C} = \{d_1, \dots, d_n\}. A dual encoder is a pair of maps EQ,EPE_Q, E_P into a shared space Rd\mathbb{R}^d, and it scores a query–document pair by the inner product of their embeddings,

s(q,d)=EQ(q),EP(d).s(q, d) = \langle E_Q(q),\, E_P(d)\rangle.

Because dense retrievers L2-normalize, the embeddings are unit vectors and the score is the cosine similarity the retrieval problem took as the relevance functional — but now the vectors are learned, by the InfoNCE loss of the previous topic, rather than counted from term frequencies as in the vector-space model. The defining property is separability: the query appears only through EQ(q)E_Q(q), the document only through EP(d)E_P(d), and they meet exactly once. Contrast a cross-encoder, which scores a fused input, s(q,d)=h([q;d])s(q,d) = h([q ; d]), letting query and document attend to each other at every layer. The cross-encoder is strictly more expressive — and, as we are about to see, strictly more expensive. Throughout, MF=(ijMij2)1/2\|M\|_F = (\sum_{ij} M_{ij}^2)^{1/2} denotes the Frobenius norm and rank(M)\operatorname{rank}(M) the rank of a matrix MM.

Movement 1 — separability ⇒ precomputability ⇒ MIPS

The first consequence of separability is the one that makes dense retrieval deployable at all. Because the document side of the score does not depend on the query, it can be computed before any query arrives.

Theorem 1 (Factorization reduces retrieval to MIPS).

Let a dual encoder score s(q,d)=EQ(q),EP(d)s(q,d) = \langle E_Q(q), E_P(d)\rangle, and stack the corpus into the matrix PRn×dP \in \mathbb{R}^{n \times d} whose jj-th row is EP(dj)E_P(d_j). Then for every query qq,

top-kjs(q,dj)  =  top-kj(PEQ(q))j,\operatorname*{top\text{-}k}_{j}\, s(q, d_j) \;=\; \operatorname*{top\text{-}k}_{j}\, \big(P\,E_Q(q)\big)_j,

so retrieval is exactly maximum-inner-product search over the matrix PP. Because PP does not depend on qq, it is computed once, offline; the only query-time work is one encode EQ(q)E_Q(q) and one MIPS over PP.

Proof (Proof).

By the definition of the matrix–vector product, the jj-th coordinate of PEQ(q)P\,E_Q(q) is EP(dj),EQ(q)=s(q,dj)\langle E_P(d_j), E_Q(q)\rangle = s(q, d_j). The top-kk documents are determined entirely by the order of these coordinates, and every coordinate is one entry of the single product PEQ(q)P\,E_Q(q). The matrix PP is a function of the corpus alone — the query enters only through the vector EQ(q)E_Q(q) it multiplies — so PP can be built and stored before any query is seen, and answering a query touches the encoder once. \blacksquare

This is one line, but it is the entire architectural justification for dense retrieval, so we prove it rather than assert it. Its force is in what it makes possible downstream. The precomputed matrix PP is precisely the object the approximate-nearest-neighbor track indexes: inverted file partitions, navigable graphs, and product quantization are all sublinear MIPS structures over a fixed PP that exists only because the score factorized. The laboratory’s first panel makes the cost gap concrete: a dual encoder’s query-time work is constant in the corpus size — one query encode plus an index lookup — while a cross-encoder, unable to precompute anything, must run a joint forward pass for every one of the C|\mathcal{C}| documents. At a Wikipedia-scale index of twenty-one million passages, that is one encode versus twenty-one million. The reduction also inherits an honest ceiling: MIPS hardness shows exact high-dimensional inner-product search has no truly sublinear worst-case algorithm, which is why the index must approximate — but that is a property of the MIPS instance this movement produces, not something it can wish away.

Movement 2 — the rank-d expressivity ceiling

Separability buys precomputability. It also charges a price, and the price is expressivity. Collect the scores of every query against every document into a relevance matrix; the dual encoder can only ever produce matrices of a bounded rank.

Theorem 2 (The rank ceiling of a dual encoder).

Let QRm×dQ \in \mathbb{R}^{m \times d} stack mm query embeddings and GRn×dG \in \mathbb{R}^{n \times d} stack nn document embeddings, so the realizable score matrix is S=QGS = Q G^\top. Then rank(S)d\operatorname{rank}(S) \le d. Conversely, a target relevance matrix MM is realized exactly by some dd-dimensional dual encoder, M=QGM = Q G^\top, if and only if rank(M)d\operatorname{rank}(M) \le d.

Proof (Proof).

(\Rightarrow) S=QGS = Q G^\top is a product of matrices with inner dimension dd, and the rank of a product is at most the inner dimension: rank(S)min(rankQ,rankG)d\operatorname{rank}(S) \le \min(\operatorname{rank} Q, \operatorname{rank} G) \le d.

(\Leftarrow) Suppose rank(M)=rd\operatorname{rank}(M) = r \le d. Take a thin singular value decomposition M=UΣVM = U \Sigma V^\top with URm×rU \in \mathbb{R}^{m \times r}, ΣRr×r\Sigma \in \mathbb{R}^{r \times r} diagonal and positive, and VRn×rV \in \mathbb{R}^{n \times r}. Set Q=UΣ1/2Q = U \Sigma^{1/2} and G=VΣ1/2G = V \Sigma^{1/2}, padding each with drd - r zero columns to width dd. Then QG=UΣ1/2Σ1/2V=UΣV=MQ G^\top = U \Sigma^{1/2}\Sigma^{1/2} V^\top = U \Sigma V^\top = M, an exact dd-dimensional realization. If instead rank(M)>d\operatorname{rank}(M) > d, then rank(QG)d<rank(M)\operatorname{rank}(Q G^\top) \le d < \operatorname{rank}(M) for every factorization, so MM is unrealizable. \blacksquare

When the target relevance pattern has rank above dd, the dual encoder cannot match it — and the best it can do has a name. By the Eckart–Young–Mirsky theorem (proved in formalML’s SVD topic, which we cite rather than reprove), the closest rank-dd matrix to MM in Frobenius norm is the truncated SVD Md=idσiuiviM_d = \sum_{i \le d} \sigma_i u_i v_i^\top, with error MMdF=(i>dσi2)1/2\|M - M_d\|_F = \big(\sum_{i > d} \sigma_i^2\big)^{1/2} — exactly the energy in the discarded singular values. The dual encoder’s reach is therefore the top-dd singular structure of the relevance matrix, and nothing more.

The laboratory’s second panel turns this into something you can watch. We build a synthetic finance relevance matrix — four market sectors, each split into two companies, one document per company — so the score matrix has intrinsic rank 88, the company count. Its singular values fall in two groups: the four largest, 4.86,3.63,2.78,1.844.86, 3.63, 2.78, 1.84, are the sectors; the next four, 0.86,0.62,0.55,0.340.86, 0.62, 0.55, 0.34, are the finer within-sector company splits. Truncating to a low dimension keeps the sectors and discards the company distinctions, so the best rank-dd dual encoder confuses companies inside a sector. Recall@1, measured over all thirty-two queries, climbs from 0.250.25 at d=1d = 1 — barely better than guessing which of four sectors — through 0.780.78 at d=3d = 3, and recovers to a perfect 1.01.0 only at d=6d = 6, with exact reconstruction at d=8=rankd = 8 = \operatorname{rank}. Below the intrinsic rank the relevance pattern is literally unrepresentable; the collapse is a theorem, not a tuning artifact.

A cross-encoder has no such ceiling. Because it scores the fused pair rather than a product of separate embeddings, it can realize a full-rank relevance pattern a dual encoder of the same width cannot — the expressivity the bi-encoder trades away for precomputability. (How that extra power is spent in a retrieve-then-rerank cascade is the subject of a later topic; here it is only the rank-free counterpoint.) One caveat is load-bearing, and we state it plainly: rank(M)d\operatorname{rank}(M) \le d says how many dimensions suffice to realize a real-valued score matrix. The dimension relevance actually needs to get the top-kk ordering right is governed by the sign-rank (equivalently the margin complexity) of the relevance pattern, which can be far smaller than the rank, or for adversarial patterns far larger. That tight measure is a topic of its own; the rank ceiling here is a clean upper bound, not the last word.

Movement 3 — in-batch negatives and the B²-from-2B Gram trick

The previous topic noted that in-batch negatives are “free.” This movement is the accounting that proves it, and it falls straight out of the same factorization. Training proceeds on batches of paired examples, and the architecture turns each batch into a matrix of similarities for almost nothing.

Theorem 3 (In-batch negatives from a Gram matrix).

For a batch of BB pairs (qi,di+)(q_i, d_i^+), stack the query embeddings QRB×dQ \in \mathbb{R}^{B \times d} and the document embeddings GRB×dG \in \mathbb{R}^{B \times d}, and form the Gram matrix S=QGRB×BS = Q G^\top \in \mathbb{R}^{B \times B}. Then row ii is an (N+1=B)(N{+}1 = B)-way InfoNCE problem with the positive SiiS_{ii} on the diagonal and the other B1B - 1 documents as negatives, and the batch loss

L=1Bi=1B[log ⁣jeSij/τSii/τ]\mathcal{L} = \frac{1}{B}\sum_{i=1}^{B} \Big[\log\!\textstyle\sum_{j} e^{S_{ij}/\tau} - S_{ii}/\tau\Big]

is exactly the in-batch InfoNCE loss of the previous topic. From only 2B2B encoder forward passes (BB queries and BB documents), the batch supplies B(B1)=Θ(B2)B(B-1) = \Theta(B^2) negative comparisons.

Proof (Proof).

Row ii of S/τS/\tau is the vector of temperature-scaled logits of query ii against all BB in-batch documents, with its positive on the diagonal. The negative log-softmax probability of the positive, logsoftmax(Si/τ)i=logjeSij/τSii/τ-\log\operatorname{softmax}(S_{i\cdot}/\tau)_i = \log\sum_j e^{S_{ij}/\tau} - S_{ii}/\tau, is the (N+1)(N{+}1)-way cross-entropy that defines the InfoNCE loss; averaging over the BB rows gives L\mathcal{L}. For the count, each of the BB rows contributes its B1B - 1 off-diagonal entries as negatives, for B(B1)B(B-1) negative comparisons in total, while the encoder is invoked once per query and once per document, 2B2B times. \blacksquare

The companion notebook makes the reuse literal: it never reimplements the loss, only re-reads the Gram matrix the architecture produces, and asserts its row-wise logexp\log\sum\exp-minus-diagonal value equals the imported InfoNCE batch loss to within floating-point error. The counting is the headline. A batch of B=8B = 8 pairs costs 1616 encoder passes and yields 5656 negatives; B=64B = 64 costs 128128 passes and yields 4,0324{,}032 negatives — the negatives grow as B2B^2 while the encoding grows as BB, quadratic utility from linear cost. This is the entire reason in-batch-negative training is the default, and combined with Movement 1 of the previous topic — that more negatives raise the log(N+1)\log(N{+}1) ceiling on the mutual information — it is why larger training batches are not just faster but better. The loss has a symmetric form too, Lsym=12(L(qd)+L(dq))\mathcal{L}_{\text{sym}} = \tfrac12(\mathcal{L}(q \to d) + \mathcal{L}(d \to q)), the second direction being the same loss on the transposed Gram matrix.

The trick is not free of subtlety, and the honesty matters. The in-batch negatives are shared across the batch — the same BB documents serve as negatives for every query — so they are correlated rather than the independent draws the mutual-information bound assumes, and because the positives are mined heuristically, some in-batch “negatives” are false negatives: unlabeled documents that really are relevant to another query, which the loss punishes anyway. Choosing better, harder negatives without falling into that trap is the work of the negative-sampling topic that follows; here we have only established what the in-batch matrix costs and contains.

Proposition 1 (What the laboratory measures).

The three panels run on a deterministic synthetic setup, not a trained transformer. Panel A’s cost curve is the exact arithmetic of the two architectures; Panel B’s relevance matrix and its rank-dd reconstructions are built from the InfoNCE topic’s von Mises–Fisher finance geometry (four sectors, two companies each, one document per company), with recall measured over thirty-two queries; Panel C’s Gram matrix is one batch of that same geometry. Every measured number — the singular values, the recall-by-dimension curve, the Gram entries, the in-batch loss — is owned by the companion notebook and mirrored here to the decimal; the laboratory recomputes only closed forms (the per-query cost, B(B1)B(B-1) and 2B2B, and the truncated-SVD reconstruction from the baked singular vectors).

Finance case study

Honest accounting

The dual encoder is the architecture; the engineering that makes it competitive is where the track goes next. Negative sampling — mining hard negatives without falling into the false-negative trap this topic flagged — turns the in-batch matrix from a cheap source of weak negatives into a strong training signal. The cross-encoder that this topic kept invoking as the rank-free, un-precomputable counterpoint becomes the reranker in a retrieve-then-rerank cascade. And late interaction escapes the single-vector rank ceiling entirely, replacing one pooled dot product with a token-level comparison between many vectors per document. Each builds on the architecture, the expressivity ceiling, and the cost law established here.

Connections

  • InfoNCE owns the loss that trains the two towers, including in-batch negatives as a free source of negatives and the hard-negative gradient; this topic takes that loss as given and accounts for the architecture it trains — why the score must be separable, why that makes documents precomputable, and why those same in-batch negatives are free, the B-by-B Gram matrix that 2B encodings produce infonce-contrastive-objective
  • the separable dual-encoder score lets every document vector be precomputed, so serving a query is exactly argmax over inner products — a maximum-inner-product-search instance; this topic produces that MIPS instance and hands off to the hardness topic, which proves why exact high-dimensional MIPS has no truly-sublinear worst-case algorithm and why the rest of the curriculum approximates, a reduction this topic relies on but never reproves mips-hardness-and-sublinearity-limits
  • the vector-space model scored a query against documents by the similarity of sparse term vectors it did not learn; a dual encoder keeps the vector-similarity scoring but replaces the hand-built sparse vectors with two learned dense towers, so this topic is the learned successor to that one — the same geometry of scores, now trained end to end rather than counted from term frequencies vector-space-model-tfidf
  • both topics turn on Eckart-Young: there the truncated SVD is the variance-optimal projection of an embedding cloud, here it is the optimal rank-d approximation of a relevance matrix, so the same low-rank machinery that decides how few dimensions an embedding can be squeezed into decides what relevance patterns a d-dimensional dual encoder can represent at all pca-dimensionality-reduction
  • late interaction relaxes the single-vector bottleneck this topic establishes: ColBERT replaces one dot product between pooled vectors with a token-level MaxSim over many vectors per document, trading the clean precompute-then-MIPS path for higher expressivity, so it is the architectural escape from the rank-d ceiling proved here late-interaction-learned-sparse

References & Further Reading

  • paper Dense Passage Retrieval for Open-Domain Question Answering — Karpukhin, Oguz, Min, Lewis, Wu, Edunov, Chen & Yih (2020) The dual-encoder DPR architecture: two BERT towers, in-batch-negative training, the BM25 hard-negative recipe, and a FAISS MIPS index at serving — the canonical instantiation this topic formalizes; the DOI resolves to the ACL Anthology EMNLP 2020 main proceedings
  • paper The Approximation of One Matrix by Another of Lower Rank — Eckart & Young (1936) The Eckart-Young theorem: the truncated SVD is the optimal low-rank approximation in Frobenius norm, the engine of the rank-d expressivity result; Mirsky later extended it to all unitarily invariant norms; the DOI resolves to Psychometrika
  • paper Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks — Reimers & Gurevych (2019) The bi-encoder versus cross-encoder distinction made explicit: a siamese bi-encoder precomputes sentence vectors for fast similarity search where a cross-encoder must jointly encode each pair — the separability-versus-expressivity trade-off this topic proves
  • paper Representation Learning with Contrastive Predictive Coding — van den Oord, Li & Vinyals (2018) InfoNCE / CPC, the loss the dual encoder is trained with — cited here for the in-batch-negative cost framing and the log(N+1) ceiling that explains why the Gram trick's quadratic negatives matter, with the loss itself developed in the InfoNCE topic
  • documentation Faiss: A library for efficient similarity search — Johnson, Douze & Jégou (2021) FAISS, the library DPR uses to serve the precomputed document vectors as a MIPS index — the concrete realization of the precompute-then-argmax serving path, handing off to the MIPS-hardness topic for why the index must be approximate