Machine learning

Synthetic data for fine-tuning: teaching models the right patterns

A model learns whatever regularities are in its training data, including the wrong ones. If your synthetic data has broken relationships, you are not augmenting a dataset, you are teaching a model to be confidently incorrect. Here is how to generate training data that carries real signal.

CrossRow team 7 min read

Synthetic data is attractive for training exactly when real data is scarce, sensitive, or imbalanced: the situations where you most need it and can least afford for it to be subtly wrong. A fine-tuned model does not know the difference between a real correlation and an artifact of a lazy generator. It fits both. The whole value of synthetic training data depends on whether the patterns in it are the patterns you want the model to learn.

That makes the invariants from the rest of this series (resolving foreign keys, exact derived values, legal state transitions, correct distributions) not a nice-to-have but the entire point. Below are three concrete fine-tuning use cases and exactly which CrossRow capabilities make each one work.

1. Text-to-SQL: fine-tuning on databases that make sense

To teach a model to translate natural language into SQL, you generate training triples: a question, the SQL that answers it, and the result of running that SQL. The quality of every triple depends on the database underneath. If foreign keys dangle and values are random, your queries execute against nonsense (a JOIN returns nothing, a SUM returns a meaningless figure) and the model learns to emit SQL that “works” against data no real system would hold.

CrossRow gives you the substrate the task actually needs: realistic multi-table databases (from 125 industry schemas or your own DDL) where foreign keys resolve, distributions are shaped correctly, and cross-row invariants hold. Run your query generator against that and every triple is grounded:

text-to-sql training triplegrounded in real relationships
# question
"Total revenue from customers in Germany last quarter"

# sql (executes against a coherent DB)
SELECT SUM(o.total) FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE c.country = 'Germany' ...

# result: a real number, because
 o.customer_id resolves to a real customer
 c.country agrees with c.city (Berlin → Germany)
 o.total = Σ(line_items), so the SUM is meaningful

Because the schemas span dozens of industries, you also get the diversity a general text-to-SQL model needs, rather than overfitting to one toy database.

2. Structured extraction and tool use

Fine-tuning a model to pull structured fields out of documents (invoice totals, claim details, order line items) needs ground-truth records that are internally consistent. Train it on invoices whose total does not equal the sum of the line items, and you teach it that totals are arbitrary. CrossRow’s derived columns guarantee the arithmetic: total = Σ(line_items), tax = subtotal × rate, dates that offset correctly. The extraction target is always the value that is actually correct for the record, so the model learns the real relationship instead of noise.

The same holds for function-calling and agent training: the tool outputs you fine-tune on are only as trustworthy as the data behind them. Consistent geography, resolving references, and legal state transitions mean the “observations” your agent learns from could have come from a real system.

3. Tabular model training: fraud, churn, forecasting

Classic and deep tabular models are where wrong signal does the most quiet damage. Three CrossRow capabilities map directly to what these tasks demand:

Controllable class balance for rare events

Fraud is a fraction of a percent of transactions; churn, a single-digit share of customers. You cannot train a useful classifier on a 50/50 coin flip. CrossRow lets you set the positive rate directly (a boolean is_fraud flag at 0.3%, a categorical outcome weighted to your real mix) so you can generate a training set with the imbalance you actually face, or deliberately oversample the rare class to study it, without hand-filtering millions of rows.

transactions · controlled positive rateis_fraud @ 0.3%
amount     merchant_cat   is_fraud
  42.10    grocery        false
 118.55    fuel           false
2,940.00   electronics    true   ← rare, but shaped like real fraud
  17.30    grocery        false
            amounts follow Benford; fraud concentrated in the tail

Correct distributions, so the model learns real structure

Fraud detection leans on the shape of the data: leading-digit patterns (Benford’s law), long-tailed amounts, the relationship between fields. CrossRow generates numeric columns to the distribution you specify (lognormal, Benford, normal) within bounds, so the model trains on the statistical structure it will meet in production, not a uniform spread that teaches it nothing.

Diversity scoring, so the set is not degenerate

A synthetic training set that quietly repeats a handful of patterns produces a model that looks great in validation and collapses in the field. Every CrossRow run reports a diversity score alongside its quality scores, so a low-variety dataset is visible before you train on it, not after.

And it is privacy-safe by construction. None of this touches production data. You can fine-tune on synthetic customers, transactions, and records without a copy of real PII in your training pipeline, which is often the reason you reached for synthetic data in the first place. The compliance story is “no real personal data was used,” not “we anonymized it and hoped.”

The through-line

Every one of these use cases fails the same way when the data is generated a column at a time: the model learns relationships that are not real. And every one is fixed by the same thing: data generated with each row aware of the others, then verified and scored before it becomes training signal. A fine-tune is only as good as the regularities it is fed. The job is to make sure those are the real ones.

Generate training data that carries real signal

Realistic, scored, privacy-safe datasets from your own schema, in minutes.

Open CrossRow