{"slug": "honey-i-shrunk-the-embeddings-matryoshka-vs-pca", "title": "Honey, I shrunk the embeddings: Matryoshka vs. PCA", "summary": "A new experiment by Dylan Castillo comparing Matryoshka Representation Learning (MRL) and Principal Component Analysis (PCA) for reducing embedding dimensions found that both methods preserve retrieval quality, but MRL requires training-time support while PCA works with any model. The study, using OpenAI's text-embedding-3-small and Alibaba's qwen3-embedding-8b across eight BEIR datasets, reduced embeddings to 512, 256, 128, 64, and 32 dimensions and found that PCA can be a viable alternative for models without MRL training.", "body_md": "As people began using LLMs with their own documents, storing and searching those documents became an important problem. That need drove the rapid adoption of [vector databases](https://en.wikipedia.org/wiki/Vector_database). But these can be easily get expensive and slow, when you store large vector representations of documents.\n\nSo [AI labs](https://openai.com/index/new-embedding-models-and-api-updates/) [responded](https://docs.cohere.com/changelog/embed-multimodal-v4) with a technique called [Matryoshka Representation Learning (MRL)](https://arxiv.org/abs/2205.13147), which lets you use fewer embedding dimensions without sacrificing much accuracy in your retrieval. Since then, we’ve more or less lived happily ever after, with smaller vector database bills and faster queries.\n\nI’m not one to be worried about my vector database cost on a typical Wednesday, but Doug Turnbull’s [article](https://softwaredoug.com/blog/2026/07/24/pca-shrink-ray) about using [Principal Component Analysis (PCA)](https://arxiv.org/abs/1404.1100), to reduce vector dimensions, got me curious: how would it compare with MRL?\n\nSo I ran an experiment comparing both methods across eight standard retrieval-quality datasets. In this article, I share what I found.\n\nAll the code and data is available on [GitHub](https://github.com/dylanjcastillo/blog/tree/main/_extras/matryoshka-vs-pca).\n\nBoth methods produce smaller vectors that behave almost like the full ones. But they get there in different ways.\n\n**MRL** works during training. You train the model with the loss applied at several prefix lengths at once: the first 64 dimensions, the first 128, and so on. This teaches it to pack the most important information at the start of the vector, like a set of nested matryoshka dolls.\n\nAt inference time, you simply keep the first *d* dimensions and re-normalize the resulting vector. Many modern embedding models are trained this way, but older models aren’t, so MRL-based truncation is not available for many popular embedding models.\n\n**PCA** works after training, which means it can be used with any model. You take a sample of embeddings, find the directions along which they vary the most, and keep the top *d* of them as a projection matrix1. From then on, every document and query gets multiplied by that matrix (and re-normalized) before it goes into the index.\n\nBut you get additional operational complexity. You need to store and version the PCA transformation, then apply the same version consistently when adding to and querying the index.\n\nThe idea behind the experiment was simple: I would shrink the embeddings with each method, run the benchmarks, and see how much retrieval quality suffers at each size.\n\nI generated all embeddings through OpenRouter and evaluated retrieval on eight [BEIR](https://github.com/beir-cellar/beir) datasets: SciFact, NFCorpus, ArguAna, FiQA, SciDocs, Quora, TREC-COVID, and Webis-Touché 2020. For each dataset, I reduced the embeddings to 512, 256, 128, 64, and 32 dimensions.\n\n| dataset | task | corpus | queries |\n|---|---|---|---|\n| SciFact | scientific claim verification | 5.2K | 300 |\n| NFCorpus | medical search | 3.6K | 323 |\n| ArguAna | counterargument retrieval | 8.7K | 1,406 |\n| FiQA-2018 | financial question answering | 57K | 648 |\n| SciDocs | citation recommendation | 25K | 1,000 |\n| Quora | duplicate question retrieval | 523K | 10,000 |\n| TREC-COVID | biomedical search (COVID-19) | 171K | 50 |\n| Touché 2020 | argument retrieval from web docs | 382K | 49 |\n\nThere were three questions I wanted to answer.\n\nTo answer this, I used two MRL-trained models: OpenAI’s `text-embedding-3-small`\n\n(1,536 dims), and Alibaba’s `qwen3-embedding-8b`\n\n(4,096 dims), which sits at the top of the open-weights MTEB BEIR leaderboard.\n\nI reduced each model’s embeddings in two ways:\n\nThen I ran the benchmarks on the eight datasets, comparing the two methods on both models, to see which one preserves more retrieval quality as the embeddings get smaller.\n\nIf PCA does well, that might be because MRL training has already organized the embedding space in a convenient way. To test that, I added `text-embedding-ada-002`\n\n, an older 1,536-dimensional model that wasn’t trained using MRL, as a control.\n\nI applied PCA to both models. If PCA retains a similar share of retrieval quality on `text-embedding-3-small`\n\nand `text-embedding-ada-002`\n\n, that suggests its performance does not depend on MRL training.\n\nPCA has to be fit on something, which raises two practical questions: how much fitting data do you need, and does it need to come from the corpus you’ll be searching?\n\nFor the first question, I fit PCA on random samples of FiQA’s 57K documents (1,000, 5,000, 20,000, and the full corpus) and checked how much the size of the fitting sample changes retrieval quality.\n\nFor the second, I compared regular PCA against **out-of-domain PCA**: a projection fit once on 100,000 MS MARCO passages and reused, unchanged, on every other dataset. This is the lazy version: fit on whatever data you have at the start and never update it.\n\nBefore running the experiment, I wanted to make sure the evaluation pipeline was producing sensible results. So I first tried to reproduce the official MTEB scores for the models.\n\nThe table below compares NDCG@10 at full dimensions: the official MTEB score vs. the score produced by my evaluation pipeline.\n\n| dataset | ada-002 | 3-small | qwen3-8b | |||\n|---|---|---|---|---|---|---|\n| MTEB | mine | MTEB | mine | MTEB | mine | |\n| SciFact | 0.7275 | 0.7277 | 0.7337 | 0.7296 | 0.7846 | 0.7863 |\n| NFCorpus | 0.3697 | 0.3705 | 0.3833 | 0.3847 | 0.4145 | 0.4150 |\n| ArguAna | 0.5744 | 0.5757 | 0.5549 | 0.5573 | 0.7685 | 0.7689 |\n| FiQA | 0.4441 | 0.4440 | 0.4491 | 0.4484 | 0.6457 | 0.6492 |\n| SciDocs | 0.1836 | 0.1837 | 0.2080 | 0.2077 | 0.3274 | 0.3268 |\n| Quora | 0.8760 | 0.8759 | 0.8883 | 0.8880 | 0.8890 | 0.8901 |\n| TREC-COVID | 0.6847 | 0.6884 | 0.7790 | 0.7775 | 0.9499 | 0.9492 |\n| Touché 2020 | 0.2161 | 0.2143 | 0.2428 | 0.2433 | 0.3593 | 0.3596 |\n\nOfficial numbers come from the MTEB results repository ([text-embedding-3-small](https://github.com/embeddings-benchmark/results/tree/main/results/openai__text-embedding-3-small), [text-embedding-ada-002](https://github.com/embeddings-benchmark/results/tree/main/results/openai__text-embedding-ada-002), [qwen3-embedding-8b](https://github.com/embeddings-benchmark/results/tree/main/results/Qwen__Qwen3-Embedding-8B)). My results are close enough to the official numbers that I’m confident the pipeline is working as expected.\n\nPCA matched or outperformed MRL truncation at nearly every dimension across both MRL-trained models.\n\nEach cell below shows how much retrieval quality survives the reduction: NDCG@10 at that dimension divided by NDCG@10 at full dimensions (1,536 for `text-embedding-3-small`\n\n, 4,096 for `qwen3-embedding-8b`\n\n), averaged over the eight datasets.\n\n| dims | 3-small (MRL) | qwen3-8b (MRL) | ||\n|---|---|---|---|---|\n| Truncation | PCA | Truncation | PCA | |\n| 512 | 98% | 97% | 99% | 98% |\n| 256 | 94% | 95% | 96% | 96% |\n| 128 | 86% | 90% | 91% | 91% |\n| 64 | 71% | 82% | 83% | 84% |\n| 32 | 46% | 65% | 68% | 71% |\n\nAt 512 dimensions, MRL truncation has a slight advantage. But as the vectors get smaller, PCA catches up and either beats or matches MRL.\n\nOn `text-embedding-3-small`\n\n, PCA is clearly better below 256 dims (65% vs 46% retained at 32). On `qwen3-embedding-8b`\n\nthe race is much closer (71% vs 68% at 32).\n\nOne thing I found interesting is that the MRL training in `qwen3-embedding-8b`\n\nis strong enough that its truncated 32-dim vectors, cut from 4,096 dimensions, retain more quality than 3-small’s cut from 1,536.\n\nGoing dataset by dataset, you find some differences:\n\nAt the smallest dimensions, PCA wins on seven of the eight datasets for `text-embedding-3-small`\n\nand six of the eight for `qwen3-embedding-8b`\n\n.\n\nAcross dimensions, PCA performs better on SciFact, FiQA, and NFCorpus for both models. ArguAna and SciDocs also favor PCA with `text-embedding-3-small`\n\n, although the results are less conclusive with `qwen3-embedding-8b`\n\n. Truncation performs better on Quora for both models. Touché favors truncation on `qwen3-embedding-8b`\n\nbut is basically a tie on `text-embedding-3-small`\n\n, and the result for TREC-COVID depends on the dimension.\n\nI worried that PCA might only look good on `text-embedding-3-small`\n\nand `qwen3-embedding-8b`\n\nbecause MRL training had already organized their embedding spaces in some convenient way. If that were true, PCA on `text-embedding-ada-002`\n\n, which never saw MRL training, should be noticeably worse.\n\nFor the most part, it isn’t. Down to 128 dimensions, PCA retains nearly the same share of quality on `text-embedding-ada-002`\n\nas on `text-embedding-3-small`\n\n; below that, a small gap opens:\n\n| dims | ada-002 (no MRL) | 3-small (MRL) | |\n|---|---|---|---|\n| PCA | Truncation | PCA | |\n| 512 | 99% | 98% | 97% |\n| 256 | 96% | 94% | 95% |\n| 128 | 89% | 86% | 90% |\n| 64 | 78% | 71% | 82% |\n| 32 | 59% | 46% | 65% |\n\nPCA on `text-embedding-ada-002`\n\nretains 78% at 64 dims and 59% at 32, against 82% and 65% on `text-embedding-3-small`\n\n. It might be that MRL genuinely helps, or simply that `text-embedding-3-small`\n\nis a newer, better model. I can’t separate the two with this experiment. But either way, the hypothesis that PCA only works because of MRL seems unlikely given that even PCA on the non-MRL model beats truncation on the MRL model at those dimensions (59% vs 46% at 32 dims).\n\nOut of curiosity, I also tried truncation on `text-embedding-ada-002`\n\n, even though the model was never trained for it. It held up much better than I imagined, with 83% retained at 128 dimensions.\n\nCompared to MRL, PCA adds more operational complexity: fitting and versioning the projection, using it while querying, updating the projection when the index changes. So I wanted to know what happens if you’re lazy: fit PCA once, when you first create the index, and never touch it again.\n\n**In-domain fit on a small sample.** In this scenario, you fit PCA on the documents you have at the start (1,000, 5,000, 20,000, or all of FiQA’s 57K) and use that projection for everything you index afterwards. At this scale, it doesn’t matter much: the projection fit on 1,000 documents performs almost the same as the one fit on the full corpus, at every dimension, on both models.\n\n**Out-of-domain fit.** In this scenario, the data you fit on doesn’t match the data you end up searching, either because your corpus drifted over time or because you fit on whatever was available. To simulate the extreme version, I fit PCA once on 100K generic MS MARCO passages and searched every other dataset with that projection.\n\nOn `text-embedding-3-small`\n\n, the transferred fit is as good or better on average from 512 through 64 dimensions. Dataset-level gaps are larger in both directions, as the chart shows. On `qwen3-embedding-8b`\n\nit keeps up down to 128 dimensions but falls behind at lower dimensions (56% vs 71% retained at 32 dims).\n\nGood news for lazy people like me. Fit-sample size matters much less than I expected, and an out-of-domain fit holds up at moderate compression. Qwen at 32 dimensions is the clear exception. These patterns may be a consequence of the scale of the experiments or the particular benchmarks I used.\n\nYou can also shrink vectors using a technique called quantization. Instead of reducing the number of dimensions, quantization stores each dimension using fewer bits. With `int8`\n\n, each dimension uses 1 byte (4x smaller than `float32`\n\n); with binary, just the sign bit (32x smaller). For the numbers below, int8 quantizes the document vectors while keeping queries at float32; binary quantizes both documents and queries and ranks by dot product, which is equivalent to Hamming-distance ranking.\n\nUsing quantization alone, you get these results for `text-embedding-3-small`\n\nat full 1,536 dimensions:\n\n| config | bytes per vector | size vs full float32 | quality retained |\n|---|---|---|---|\n| int8 | 1,536 | 25% | 100% |\n| binary | 192 | 3.1% | 95% |\n\nYou can push this further by combining quantization with truncation or PCA. The resulting vectors can be dramatically smaller while still preserving a surprising amount of retrieval quality.\n\nFor example, combining binary quantization with PCA at 512 dimensions retains 82% of the original performance while reducing the raw vector size to about 1% of the float32 baseline. That seems a bit too optimistic, so it might just be my AI psychosis. Here are the full [results](https://github.com/dylanjcastillo/blog/tree/main/_extras/matryoshka-vs-pca/data/analysis/openai__text-embedding-3-small/quantization_summary.csv).\n\nPCA not only held its own against MRL truncation, it won on most dimensions.\n\nOn `text-embedding-3-small`\n\n, PCA beat MRL truncation at nearly every dimension, and by a wide margin at aggressive compression: 65% of quality retained at 32 dims against truncation’s 46%. On `qwen3-embedding-8b`\n\n, MRL had a small edge at 512 dimensions and was effectively tied at 256, while PCA led below that.\n\nThese results also don’t appear to be an artifact of MRL training. PCA worked similarly well on ada-002, which wasn’t trained for truncation.\n\nIt’s also lower-maintenance than I expected. Results barely changed when fitting on a small in-domain sample. An out-of-domain fit also held up at moderate compression.\n\nNot bad for a technique that’s older than the washing machine2!\n\nIf you want to look at the data yourself, the full pipeline is in the [repo](https://github.com/dylanjcastillo/blog/tree/main/_extras/matryoshka-vs-pca).\n\nthis [page](https://setosa.io/ev/principal-component-analysis/) explains it quite well↩︎\n\nelectric washing machine↩︎\n\n```\n@online{castillo2026,\n  author = {Castillo, Dylan},\n  title = {Honey, {I} Shrunk the Embeddings: {Matryoshka} Vs. {PCA}},\n  date = {2026-08-01},\n  url = {https://dylancastillo.co/posts/matryoshka-vs-pca.html},\n  langid = {en}\n}\n```\n\n", "url": "https://wpnews.pro/news/honey-i-shrunk-the-embeddings-matryoshka-vs-pca", "canonical_source": "https://dylancastillo.co/posts/matryoshka-vs-pca.html", "published_at": "2026-08-01 00:00:00+00:00", "updated_at": "2026-08-02 18:03:05.198189+00:00", "lang": "en", "topics": ["machine-learning", "artificial-intelligence"], "entities": ["Dylan Castillo", "OpenAI", "Alibaba", "text-embedding-3-small", "qwen3-embedding-8b", "BEIR", "Matryoshka Representation Learning", "Principal Component Analysis"], "alternates": {"html": "https://wpnews.pro/news/honey-i-shrunk-the-embeddings-matryoshka-vs-pca", "markdown": "https://wpnews.pro/news/honey-i-shrunk-the-embeddings-matryoshka-vs-pca.md", "text": "https://wpnews.pro/news/honey-i-shrunk-the-embeddings-matryoshka-vs-pca.txt", "jsonld": "https://wpnews.pro/news/honey-i-shrunk-the-embeddings-matryoshka-vs-pca.jsonld"}}