Evidence for ML engineers

Your first question: Will a model trained on Ground's rows work on real data, including on the rare class I care about?

Short answer, from one benchmark run: on 4 public classification tables a model trained only on Ground's rows scored within 0.007 AUC of the same model trained on the real rows, tested on real rows neither had seen. On 2 regression tables it lost 0.058–0.060 R², a larger gap you should check on your own target. With the rare-cases option on, a rare class shows up in every preview and exact counts per combination hold to the row; adding rows where your model fails did not help.

Train on synthetic, test on real

Classification: AUC on the real holdout

Each model is a random forest tested on the same 20% of real rows. Trained on real = the ceiling. Higher is better; the axis starts at 0.7.

Classification: AUC on the real holdout: the numbers in the chart
DatasetTrained on realTrained on GroundTrained on Ground (DP ε=3)Trained on MOSTLY AI
Adult0.9040.8970.8740.897
Bank0.9190.9130.8690.896
Credit0.8330.8270.7550.823
Telco0.8330.8290.8040.821

Regression: R² on the real holdout

Same setup for the two numeric targets (house value, insurance charges). Higher is better.

Regression: R² on the real holdout: the numbers in the chart
DatasetTrained on realTrained on GroundTrained on Ground (DP ε=3)Trained on MOSTLY AI
Housing0.6880.6280.5330.607
Insurance0.8710.8130.6430.019
Every method in the run: utility of a model trained on its synthetic rows (AUC or R²), next to training on real rows (the Ground run's baseline; other methods' runs recorded baselines within 0.002 of it)
DatasetTrained on realGroundGround (DP ε=3)Ground (DP ε=3, MST)MOSTLY AI (TabularARGN, local)SDV CTGAN (50 epochs)SDV GaussianCopula
Adult (AUC)0.9040.8970.8740.8840.8970.8650.867
Bank (AUC)0.9190.9130.8690.8800.8960.7220.882
Credit (AUC)0.8330.8270.7550.7760.8230.4560.801
Telco (AUC)0.8330.8290.8040.8100.8210.6100.810
Housing (R²)0.6880.6280.5330.3970.6070.0580.436
Insurance (R²)0.8710.8130.6430.7260.0190.0880.507
How it was measured
Each public table is shuffled with seed 7 and split 80/20. Every synthesizer trains on the same 80% (at most 30,000 rows); a random forest is trained on its synthetic rows and tested on the real 20%, next to one trained on the real 80%. Details on the benchmark overview.
Uncertainty
One run with fixed seeds, no confidence intervals. Differences of a point or two in Overall, or a few thousandths of AUC, are within noise.
Scored by
Ground's own report (self-scored). Independent scoring is pending first independent run.
Limits
SDV CTGAN ran 50 epochs (default 300) and MOSTLY AI had a 5-minute training cap, so their numbers understate what tuned runs could do.
Source
apps/web/lib/benchmark-results.json; docs/benchmarks.md

Rare classes you can see and count

A 25-row preview of card transactions (is_fraud (2.9%)) has no fraud row in 47% of seeds today. The rare-cases option swaps rows so the rare class is always in the preview, and the exported file keeps the real rate once it passes about 1,000 rows. It is behind options that are off by default, with no UI yet.

Previews that contain the rare class

Share of 25-row previews over 200 seeds with at least one, and at least three, rare rows. Higher is better.

Previews that contain the rare class: the numbers in the chart
PreviewOption offRare cases on
is_fraud (2.9%): at least 1 rare row53%100%
is_fraud (2.9%): at least 3 rare rows3%100%
Priority = urgent (6.9%): at least 1 rare row80.5%100%
Priority = urgent (6.9%): at least 3 rare rows26%100%
Exact counts per combination: largest error over 20 seeds
DatasetWhat was askedLargest count error
support-ticketsEnterprise ∧ urgent = 120 of 10,0000 rows
card-transactionsonline ∧ fraud = 500 of 10,0000 rows
loans (upload)West ∧ defaulted = 150 of 3,0000 rows
loans (upload)30% defaulted within West0 rows
Do counted rows keep real relationships? Mean amount among fraud and online card rows (USD)
How the rows were madeMean amount
true conditional (400k rows)$1,336
same-size true sample$1,320
attempt search (prototype)$1,364
forced values$873

Searching for rows that meet a combination keeps what the other columns do inside it, where forcing the values breaks it (table above). What this doesn't show: whether a model trained on rebalanced rare-class rows does better on real rare cases. That measurement is pending first independent run.

How it was measured
200 preview seeds and 20 count seeds per dataset, on the card-transactions and support-tickets templates and the loan sample fitted as an upload. TVD against two unconstrained runs with different seeds is the noise floor.
Uncertainty
Shares over 200 seeds; the baseline matches the closed form (1 − 0.971²⁵ = 0.52). Count errors are the largest over 20 seeds.
Scored by
Ground's assessment harness (self-scored).
Raw output
rare-cases.json
Source
docs/assessments/rare-cases.md

Measured no-go: generating rows where your model fails

Failure-sliced minus plain synthetic rows: slice AUC

Paired difference, mean ± sd over 5 seeds. Right of the line means failure-sliced rows helped; every whisker crosses it.

Failure-sliced minus plain synthetic rows: slice AUC: the numbers in the chart
Table, real rowsDifference in slice AUC
Adult, 1,000 real rows+0.002 ± 0.009
Adult, 5,000 real rows−0.002 ± 0.004
Bank, 1,000 real rows−0.002 ± 0.009
Bank, 5,000 real rows+0.006 ± 0.008
Credit, 1,000 real rows−0.003 ± 0.013
Credit, 3,557 real rows+0.002 ± 0.017
Telco, 1,000 real rows0.000 ± 0.016
Telco, 5,000 real rows+0.005 ± 0.013
Regression: change in slice RMSE (target units, lower is better), mean ± sd over 5 seeds
Table, real rowsvs plain syntheticvs repeated real slice rows
Housing, 1,000+3,057 ± 1,749+4,802 ± 1,876
Housing, 5,000+766 ± 1,564+3,114 ± 978
Insurance, 1,000+1,066 ± 737+1,514 ± 1,171
Insurance, 1,071+297 ± 431+850 ± 442
How it was measured
Same six tables and split as the benchmark. Gradient-boosted trees (or a regression forest) trained on 1,000 or 5,000 real rows; five-fold out-of-fold errors find the worst slice (at least 50 rows); four arms add the same number of rows: none, plain synthetic, failure-sliced synthetic, or repeated real slice rows.
Uncertainty
sd of paired differences over 5 seeds. The test set is the same in every seed, so small test slices (insurance smokers: 56 rows) are less certain than the sd suggests.
Scored by
Ground's assessment harness (self-scored).
Source
docs/assessments/failure-driven-generation.md

Check it on your own task: the notebook

Benchmarks on public tables are not your data. Most exports of an uploaded dataset (single-table files, not zip or related-table exports) come with a ready-to-run notebook: it trains a model on the synthetic rows and tests it on the real rows Ground held back when it learned your data, next to a model trained on the other real rows and one trained on both. It runs in Jupyter, VS Code or Google Colab with pandas and scikit-learn. Its result is the number that matters for your model; Ground doesn't publish it.

Next: what the same synthetic rows reveal about real people, or read synthetic data for machine learning.