Tune for your data
A published PFN model is trained on a prior — a synthetic data distribution. That’s great for zero-shot prediction on any data in the prior’s family, but if your plant has structural quirks (a sensor that drifts, a process that’s bi-modal, a regime nothing in the prior captured), tuning on your own examples bridges the gap.
This guide walks you through fine-tuning Robertson’s do-pfn on your own observation/intervention pairs in PFN Studio.
When to tune vs use base model
Tune only if you’ve tried the base model on a representative sample and the predictions are systematically biased — not just noisy. PFNs are designed for zero-shot use; tuning helps when the prior genuinely doesn’t cover your data, but it costs time and can degrade general performance if your tuning set is small.
| Symptom on base model | Tune? |
|---|---|
| Predictions ±20% across all rows | No — that’s noise; collect more in-context examples |
| Predictions systematically high on weekends, low on weekdays | Yes — a regime the prior didn’t see |
| Predictions wrong on one specific sensor | Yes — sensor-specific calibration |
| Predictions wrong on rare interventions | Yes if you have ≥50 examples of those interventions |
Before you start
- A published model on HuggingFace (Publish to HuggingFace if you don’t have one yet, or pick one from the Marketplace)
- A CSV of your own data — see Bring your own data for the schema. For Do-PFN tuning, you need observation rows AND intervention rows (the
tcolumn flips between 0 and 1) - ~30 minutes of CPU time for a small tune; longer for bigger datasets
1. Clone the model
From /marketplace → find the published model → Clone. PFN Studio creates a new project pre-wired with:
- The base model (the HF checkpoint you cloned)
- A seed
tunerun withmode: tuneandfreeze_layers: [...]set so only the head retrains by default
2. Add your data as a dataset
From the project page → Datasets tab → Upload CSV. Pick your prepared CSV. PFN Studio runs schema inference and shows:
- Column types (numeric / categorical / target / treatment)
- A
compatible_task_typesproposal — e.g.['causal_intervention']if it sees atcolumn
Verify the columns map the way you expect. If something’s wrong, edit the column types and re-save.
3. Open the tune run
From the Runs tab, click tune-on-my-data (the seed run). Its YAML looks roughly like:
slug: tune-on-my-datamode: tune # fine-tune from a checkpointcheckpoint_ref: model.pt: hf://<your-hf-username>/<base>/checkpoint/model.pt topology.json: hf://<your-hf-username>/<base>/checkpoint/topology.jsondataset_ref: my-plant-data # the CSV you just uploadedhyperparams: epochs: 10 # tune is short — 5-20 epochs is typical lr: 1e-5 # 10-100× smaller than from-scratch training freeze_layers: [transformer] # only the head retrains; saves time + reduces overfit batch_size: 8 seed: 42Defaults are safe. The key knobs:
lr— start small (1e-5). If the loss is flat after 2-3 epochs, raise to3e-5. If you see loss explode, lower to3e-6freeze_layers: [transformer]— by default only the head retrains, fastest and safest. Set to[]to retrain everything (slower, more prone to overfit, but stronger if your data is genuinely far from the prior)epochs— 5–20. Watch the validation loss; stop when it stops improving
4. Run the tune
Hit Train top-right. The CPU worker picks up the job. Live logs appear in the Logs tab; loss curves in Charts.
A healthy tune curve looks different from a from-scratch curve: small drop on epoch 1 (the model already knew most of what you’re teaching), then gradual decline. If the loss doesn’t move at all, your data may be too similar to the prior — base model is already good enough, you don’t need to tune.
5. Evaluate
After the run completes, PFN Studio runs the project’s evals against your held-out test set. Compare to the base model’s evals on the same split:
- Tuned model better on your data → ship the tuned checkpoint
- Tuned model worse → you tuned on too little data, or wrong LR, or the base prior already covered your case. Drop tuning, use the base model
6. Publish (optional)
If your tuned model is plant-specific (not generalisable), don’t publish — keep it private to your project. If it captures a real new regime that others might benefit from, Publish to HuggingFace under a name like <base>-<plant>-tuned so the lineage is obvious.
Common failure modes
| What you see | Likely cause | Fix |
|---|---|---|
| Loss flat for 5 epochs | LR too small | Raise to 3e-5 or 1e-4 |
| Loss explodes (NaN) | LR too large | Lower to 3e-6 |
| Tuned model worse than base on test | Tuned on too little data (<200 rows) | Collect more, or stick with the base model |
| Worker OOM on epoch 1 | Batch size too large for CPU | Lower batch_size to 4 |
| HF download timeout at start | Network blip pulling the base checkpoint | Re-run; it’ll cache locally on success |
Next steps
- Predict API — call your tuned model from your stack
- Publish to HuggingFace — share if it generalises
- Bring your own data — schema reference for the CSV you uploaded