Random projection dimensionality reducer

Paste a wide table of numbers and project it onto fewer dimensions with a random Gaussian, sparse, Achlioptas or Rademacher matrix. The report shows how far pairwise distances actually moved and what the Johnson–Lindenstrauss bound asks for. Runs entirely in your browser, nothing is uploaded.

Try:
Projection report

About this tool

Random projection is the cheapest useful dimensionality reduction there is. Instead of studying your data to find good axes — the way PCA computes eigenvectors — it multiplies the table by a matrix of random numbers and simply relies on a theorem: the Johnson–Lindenstrauss lemma says that a random linear map into enough dimensions keeps every pairwise distance almost unchanged, and that "enough" depends only on how many points you have, never on how wide the table was.

That makes it the tool of choice when a table is far too wide to decompose — thousands of term-frequency columns, embedding dimensions, sensor channels — and when what you need preserved is distances (for nearest-neighbour search, clustering, duplicate detection) rather than variance.

Paste your matrix and this reducer does the whole thing in the browser:

Nothing is uploaded. The random numbers come from a fixed, portable integer stream rather than a platform generator, so a given seed reproduces exactly the same projection on this page, on the command line and in chat.

Worked example — eight channels down to three

Paste six observations of eight channels (the first row is read as a header of column names) and set Target dimensions to 3:

ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8
1,2,3,4,5,6,7,8
8,7,6,5,4,3,2,1
2,4,6,8,10,12,14,16
0,1,0,1,0,1,0,1
5,5,5,5,5,5,5,5
9,1,8,2,7,3,6,4

The report opens with the settings and the honest verdict on quality:

Random projection: 6 rows × 8 columns → 3 dimensions (37.5000% of the input width)
  method        gaussian — dense matrix, entries drawn from N(0, 1/k)
  target dims   3 (set explicitly)
  density       100.0000% non-zero entries
  seed          42
  input columns ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8

Distance preservation (15 of 15 row pairs measured):
  mean distortion     22.4111%
  median distortion   21.1289%
  max distortion      42.5474%
  mean ratio          1.051128  (projected ÷ original distance)
  within ±10.0000%  3 of 15 pairs (20.0000%)

and ends with the projected coordinates:

Projected data (first 6 of 6 rows):
  row           RP1           RP2           RP3
    1    -17.064939     -0.160032     -8.288287
    2    -13.495953      4.349463     -1.436021
    3    -34.129877     -0.320064    -16.576574
    4     -1.341949     -0.556681     -0.113729
    5    -16.978273      2.327462     -5.402393
    6    -20.080918      7.953206     -6.799878

A 22% mean distortion is bad, and the tool says so rather than hiding it — three dimensions is simply not enough for a guarantee. The Johnson–Lindenstrauss block in the same report explains why: even six points want k ≥ 1535 for a ±10% embedding. Random projection is a large-k, wide-data method, and a six-row toy is the case where it works worst. It is still the right example to start from, because every number above is exactly reproducible — same seed, same result, on every surface.

What it looks like when there is room to work

On a table of 60 rows and 200 columns of random values, raising k tightens the embedding in exactly the way the lemma predicts:

Target kMean distortionMedianPairs within ±10%
1615.67%13.24%672 of 1770 (37.97%)
646.50%5.43%1386 of 1770 (78.31%)
1284.82%3.96%1589 of 1770 (89.77%)

The sparse family at the same k = 64 lands at 7.51% mean distortion while touching roughly one entry in fourteen of the matrix — slightly noisier, much less work. That trade is the whole reason the sparse variants exist.

Choosing the target dimension

Reading the output formats

text is the report above and prints the first 20 projected rows. csv emits every projected row as row,RP1,RP2,… so it can go straight into a plot or another tool. json returns the whole result: every row, the diagnostics, and the projection matrix. matrix returns just the k × columns projection matrix as CSV — that is what you keep if you need to project new rows onto the same axes later, since the matrix plus the seed is the entire model.

Limits and edge cases

FAQ

How many dimensions do I actually need?

The Johnson–Lindenstrauss bound in the report is the theoretical answer: k = 4·ln(rows) / (eps²/2 − eps³/3), which for a ±10% embedding is about 1,535 dimensions for 6 points and 11,841 for a million. Those numbers are famously pessimistic — they are a worst-case guarantee over every possible dataset, and real data almost always survives far fewer dimensions. That is exactly why this tool measures the distortion instead of only quoting the bound: set the k your downstream task can afford, look at the mean distortion and the "within ±eps" count, and raise k until those numbers are good enough. Note that the bound depends only on the number of rows, not on how wide the table is — projecting 500 documents is the same problem whether they have 5,000 or 50,000 features.

Which random matrix should I choose?

Start with gaussian: it is the classic construction, entries drawn from N(0, 1/k), and it gives the lowest distortion of the four in practice. Switch to sparse when the table is wide — its default density of 1/√columns means most entries are zero, so the projection touches a small fraction of the data for a small penalty in distortion. achlioptas is the same family pinned at density 1/3, the classic "database-friendly" result, and rademacher is a dense matrix of ± signs, which is the fastest per entry because it needs no multiplication at all. All four are scaled so that expected distances match; they differ in how much they vary around that expectation.

Why do I get different numbers than scikit-learn with the same seed?

Because a seed only means something inside one generator. scikit-learn draws from NumPy's Mersenne Twister; this tool uses a fixed xoshiro256++ stream so that the page, the command line and the chat tool agree byte for byte. The distributions are the same, so the statistics match — the same family, density and k give the same distortion behaviour — but the individual matrix entries are a different draw. If you need one specific projection reproduced elsewhere, export it with matrix output and apply that matrix directly rather than re-seeding.

Can I project new rows onto the same axes later?

Yes. The projection is a plain linear map, so it is fully described by the k × columns matrix. Either re-run with the same seed, method, density, k and column count — the matrix depends on nothing else, so it will be identical — or take the matrix output once and multiply new rows by it yourself. What you must not do is re-run with a different k or a different column count and expect the coordinates to be comparable: those are different random matrices and the two sets of coordinates live in unrelated spaces.

How is this different from PCA?

PCA looks at your data and computes the axes that capture the most variance; random projection ignores the data entirely and picks axes at random. That sounds strictly worse, and for a fixed k it usually is — but PCA needs an eigen-decomposition of a columns × columns matrix, which is cubic in the width and simply not viable at tens of thousands of features. Random projection is a single matrix multiply, needs no fitting pass, and its accuracy guarantee is about pairwise distances rather than variance, which is what nearest-neighbour search and clustering actually depend on. Use PCA when the table is narrow enough to decompose and you want interpretable components; use random projection when it is not, or when you need a projection in one pass.

What does the "mean ratio" tell me that the distortion figures do not?

Distortion is |projected ÷ original − 1|, so it throws away the direction of the error. The mean ratio keeps it: a value above 1 means distances came out systematically too long, below 1 too short. For a correctly scaled projection it should sit near 1 even when individual pairs are far off, because the scaling makes distance preservation exact in expectation. A mean ratio that drifts well away from 1 on a large sample is a sign that k is small enough for the estimator itself to be biased upward — the same thing the rising mean distortion is telling you.

Is my data uploaded anywhere?

No. The whole computation is compiled to WebAssembly and runs inside your browser tab, so the matrix you paste never leaves your device, and the tool works with the network switched off. The same engine backs the command line and the chat tool, and because the random stream is a fixed integer sequence rather than a platform RNG, all three produce identical numbers from identical inputs.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool random-projection-reducer "ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8
1,2,3,4,5,6,7,8
8,7,6,5,4,3,2,1
2,4,6,8,10,12,14,16"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/random-projection-reducer/?data=ch1%2Cch2%2Cch3%2Cch4%2Cch5%2Cch6%2Cch7%2Cch8%0A1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%0A8%2C7%2C6%2C5%2C4%2C3%2C2%2C1%0A2%2C4%2C6%2C8%2C10%2C12%2C14%2C16&components=auto&method=gaussian&density=0&eps=0.1&seed=42&format=text

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.