> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mathfi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Model Crucible

> Model Crucible trains every algorithm family against your data at once, scores them on held-back data, and keeps the best three. How it ranks, what a champion is, and how to predict.

Model Crucible builds the model. You give it a dataset, it runs many training attempts at once
across three algorithm families, scores every one of them on data they never saw, and keeps the
best three as v1, v2 and v3 of a single model.

The name is literal: everything goes in, one comes out.

<img src="https://mintcdn.com/mathficast/4qpNbSEYwxk4O7C4/images/walkthrough/model-crucible.png?fit=max&auto=format&n=4qpNbSEYwxk4O7C4&q=85&s=ca124579b68b9f47999b3e7e7e5096e5" alt="Model Crucible" width="1440" height="900" data-path="images/walkthrough/model-crucible.png" />

## The three stages

<Steps>
  <Step title="Dataset">
    The labelled data to train from. Either a finished Feature Refinery run handed straight over,
    or your own 80/20 split uploaded as two files.
  </Step>

  <Step title="Training">
    Every attempt runs at once and is scored live. When the run settles, you pick the champion from
    its best candidates.
  </Step>

  <Step title="Prediction">
    Upload unlabelled rows. They are scored against the champion and returned as a CSV.
  </Step>
</Steps>

## Why two files

A model scored on the rows it learned from will always look good. It can score them from memory.
The only honest measure is how it does on data it has never seen.

So the Crucible asks you to hold back roughly a fifth of your labelled data as a test set. It
trains on the larger part, then scores every candidate against the part you held back. That
held-back score is what you are shown, and what the champion is chosen on.

**Keep the labels in both files.** The test set needs its answers so the run can mark itself. It
just never gets to look at them while learning.

If your data came from Feature Refinery, this is already done. Choose **Use Outputs of Refinery**
and there is nothing to upload.

<img src="https://mintcdn.com/mathficast/4qpNbSEYwxk4O7C4/images/walkthrough/dataset-create.png?fit=max&auto=format&n=4qpNbSEYwxk4O7C4&q=85&s=816af1782feccaa15931f22250deddd2" alt="New dataset" width="1440" height="900" data-path="images/walkthrough/dataset-create.png" />

## What a training run does

One run is many attempts, not one. Three algorithm families compete: the family that varies most
run to run contributes the bulk of the attempts, and the other two contribute one each. They all
train against the same data and are all scored the same way.

Running many independent attempts is not redundancy, it is the point. Each one attacks the problem
from a different starting position. When the pattern in your data shifts, the attempt that was
winning may fall behind and another takes over. That diversity is what makes the result hold up as
your data moves.

### How they are ranked

By **false decisions**: how many rows the model got wrong on the held-back test set. Fewest wins.
Accuracy, F1, precision and recall are all reported, but the ranking is on false decisions, because
that is the number that maps to what a mistake actually costs you.

<img src="https://mintcdn.com/mathficast/4qpNbSEYwxk4O7C4/images/walkthrough/training-detail.png?fit=max&auto=format&n=4qpNbSEYwxk4O7C4&q=85&s=8594b835982347be7263e35f67060a5c" alt="Training run detail" width="1440" height="1000" data-path="images/walkthrough/training-detail.png" />

The grid shows every attempt's live score. A timeout there is a normal outcome, not a failure:
an attempt that did not reach the target inside its time cap simply reports what it reached.

### Settings

| Setting     | What it does                                                                  |
| ----------- | ----------------------------------------------------------------------------- |
| **Target**  | The accuracy each attempt aims for.                                           |
| **Scaling** | An internal parameter, 0 to 499. 19 is the working default.                   |
| **Buckets** | Set on the dataset, not the run. See [Tuning](/guides/hyperparameter-tuning). |

<Warning>
  **Set the target to what the data supports, not to what you want.**

  A dataset that came from Feature Refinery carries the target that refinement actually reached. The
  console pre-fills it. Over the API you must read `recommendedThreshold` from the dataset and send
  it yourself.

  Setting a target far above what the data supports does not produce a better model. Every attempt
  runs to its time cap, and the run can settle on a model that predicts one class for every row:
  accuracy that looks plausible, F1 of zero, and a confident-looking grid behind it.
</Warning>

<img src="https://mintcdn.com/mathficast/4qpNbSEYwxk4O7C4/images/walkthrough/training-create.png?fit=max&auto=format&n=4qpNbSEYwxk4O7C4&q=85&s=c14917b4489199081a1b2734e53bf465" alt="New training job" width="1440" height="900" data-path="images/walkthrough/training-create.png" />

## Champion and versions

A finished run offers up to three models, ranked best first. v1 starts as the champion.

* **Predictions always run against the champion.** Changing the champion changes what future
  predictions use.
* **Changing it never rewrites history.** Every prediction records the version it ran against, so
  an earlier result keeps meaning what it meant.
* **Nothing is rebuilt when you switch.** A flag moves. Switch as often as you like.

Why switch? Because the best model on false decisions is not always the model you want. A credit
decision might justify accepting more false alarms to catch more real risk, which means taking a
candidate with higher recall over the one with the lowest error count. The candidates table shows
you the trade, and you make the call.

## Prediction

Upload a CSV with the same columns as your training data, minus the target. You get back the same
rows with the prediction appended.

<img src="https://mintcdn.com/mathficast/4qpNbSEYwxk4O7C4/images/walkthrough/prediction-create.png?fit=max&auto=format&n=4qpNbSEYwxk4O7C4&q=85&s=575a1236983fb211b154a418eb638c99" alt="New prediction" width="1440" height="900" data-path="images/walkthrough/prediction-create.png" />

If the model's dataset came from a refinement, you do not have to work out which columns were
dropped. The API's `applyColumnStatusFilter` option strips them for you, by position. A file you
have already stripped yourself passes through untouched.

Prediction runs on a file: you send a CSV, you get a CSV.

## Using it without Feature Refinery

The Crucible works fine on its own. Upload your own 80/20 split and train.

Do that when you already know your feature set, when your target is multi-class, or when you are
benchmarking against a model you already run.

The reason to refine first is that most real datasets carry columns that add nothing and a few that
actively mislead. Refining removes them and hands over a target that reflects what the cleaned data
can actually do. Without it, you are choosing the target yourself, and that choice matters more
than anything else you set.

## Limits

| Limit                             | Value      |
| --------------------------------- | ---------- |
| Concurrent training runs per user | 5          |
| File size per upload              | 510 MB     |
| Signed upload URL lifetime        | 60 minutes |
| Models kept per run               | 3          |

<CardGroup cols={2}>
  <Card title="Walk through it" icon="play" href="/use-cases/german-credit">
    Refinery to Crucible to prediction, with the numbers.
  </Card>

  <Card title="Do it over the API" icon="code" href="/developers/api-recipes#model-crucible">
    Dataset, train, poll, choose, predict.
  </Card>
</CardGroup>
