Model Scoring¶
You've trained a model and logged it to MLflow (and perhaps your promotion process has registered it), or saved it to a file in your project. The Model Scoring node loads it, checks your data against the features the model was trained on, and produces predictions - all without writing scoring code. The model is cached, and reloaded when its file changes.
What is MLflow?
MLflow is an open-source platform for tracking model experiments and storing trained models - think of it as version control for models. If your team has set up MLflow (or uses Databricks, which includes it), your trained models are stored in a model registry where they can be loaded by version.
When to use
- Your models are managed in MLflow with versioning and a model registry.
- Your model is a file in the project, saved with Model Training's Save model to file or handed over by a colleague.
- You want the model's features checked and the model cached for you.
This node takes a single input. It outputs the input rows with the prediction added as a new column (two columns for a classification model).
The CONFIG tab¶
The INPUT strip at the top names the connected input; its × removes the connection.
MODEL SOURCE chooses how the model is found:
- Experiment Run: one specific training run, picked by experiment. Useful during development, before a model is registered.
- Registered Model (the default): a named, versioned model in the registry. This is the most common setup.
- Model file: a model file in your project folder.
Below it, for Experiment Run and Registered Model, the destination buttons choose where the node browses for and loads the model: Databricks, MLflow server or Local folder (the default, the project's local MLflow folder). A remote that is not configured is greyed out, and clicking it opens MLflow settings instead. Switching destination clears the chosen model and says Selection cleared - run and model identifiers are not portable across destinations. A Model file has no destination buttons, because the file is read from the project, not from MLflow.
With Experiment Run:
| Field | What it does |
|---|---|
| EXPERIMENT | The MLflow experiment to browse (Select an experiment... until you choose). |
| RUN | A finished run in that experiment that holds a model. An experiment without one shows No finished runs with a model artifact in this experiment yet. |
| RUN ID | The chosen run's ID. You can also paste one here. |
| ARTIFACT PATH | The model's path inside the run (for example model.cbm). Picking a run fills it with the run's first artifact. |
With Registered Model:
| Field | What it does |
|---|---|
| MODEL NAME | The registered model, from the destination's registry (Select a model... until you choose). With an empty registry the pane says No registered models yet - haute logs training runs; your promotion process registers them. |
| VERSION | latest (the default), an alias such as @champion → v3, or a version, listed as v3 with its status and description. |
With Model file:
| Field | What it does |
|---|---|
| MODEL FILE | The model file, chosen in the file browser, which lists only model files: .cbm, .ebm, .lgbm, .rsglm, .tboost and .ubj. Once a file is chosen, change opens the browser again. |
Under the file the panel shows what it found: the kind of model, its features, its offset (or none) and the feature contract it scores with. A file the node cannot score shows the reason here instead, the same message the preview would give.
Then, for every source:
| Field | What it does |
|---|---|
| TASK | Regression (the default) or Classification. |
| OUTPUT COLUMN | The name of the prediction column. Defaults to prediction. |
Following an alias
If your promotion process moves an alias such as champion to each newly approved version, pick the alias in the VERSION list (it shows as @champion → v3). The node then always scores the version the alias targets. Deploying records which version the alias pointed to at deploy time.
Task type¶
Use Regression when your model predicts a number (frequency, severity, premium). Use Classification when your model predicts a category or probability (e.g. likelihood of claim, fraud detection).
A classification model also adds an <output column>_proba column (for example prediction_proba) beside the predicted class: the probability of the positive class, which is usually what you use downstream. It appears when the model can produce probabilities. The panel reminds you of the extra column when Classification is chosen.
A run logged by Haute's Model Training node records its task. When you pick such a run or registered version, TASK shows it read-only with Task recorded by the training run. A model file records its task too, in the feature contract beside it or, for an XGBoost, LightGBM or t-boost file, in the file itself; the panel shows it with Task recorded with the model. A model logged elsewhere may not record one, so you choose the task yourself. If the node's task and the recorded one disagree, the panel warns and offers a button to use the recorded task. Either way, scoring a model as the wrong task fails with an error naming the task it was trained for.
Model files¶
Model Scoring loads the native model a Model Training run logged or Save model to
file wrote: CatBoost (.cbm), XGBoost (.ubj), LightGBM (.lgbm), t-boost
(.tboost), EBM (.ebm) or GLM (.rsglm). From MLflow it also loads an MLflow pyfunc model.
A pyfunc model reads the inputs its signature names; one the signature marks optional, such as
the exposure of a model Haute logged, is used when your input has it. It must return one
prediction per row, or a classifier's pred_label and pred_proba, which fill the prediction
and _proba columns.
A model file scores with the feature contract saved beside it: <model name>.feature_contract.json,
or else feature_contract.json in the same folder. Save model to file writes the
first. The contract names the model's features, categories and offset, so keep it next to
the model when you copy the model elsewhere in the project. XGBoost, LightGBM, t-boost and
EBM files describe their own inputs and offset. An XGBoost, LightGBM or t-boost model trained
outside Haute scores too, from what its own file records, with no offset: save an XGBoost
booster as .ubj and a LightGBM model's text as .lgbm. An XGBoost model must say whether
it was trained with a margin (base_margin), because the file cannot tell and XGBoost
scores such a model wrongly without one. Before saving, run
booster.set_attr(haute_offset="none") for a model trained without a margin, or
booster.set_attr(haute_offset="exposure:log") for one trained with log-exposure margins
("premium:identity" for an additive one); a feature contract that declares the offset
works too.
Two things a model file from outside Haute cannot tell Haute, so check them yourself: a
missing-value marker other than an empty value (an XGBoost model trained with
missing=-999 reads -999 in the input as a number, so prepare the input as you did for
training), and a custom XGBoost objective, which XGBoost saves under the name of a built-in
one. Compare a few of Haute's prices with your own before relying on them. An EBM saved
outside Haute is not read: log it with MLflow's sklearn flavour instead, and it scores as
an MLflow model. A multi-class or ranking model, and
an XGBoost model saved without feature names, cannot be scored. An EBM file also records the
interpret-core version it was trained with, and loads only under that version; a
contract for a different loss is refused rather than scored. A category the
model never saw still scores; see Values the model was not trained on.
A CatBoost model file does not record its own offset. Models trained by Haute record it
in the model; for any other CatBoost model a feature contract can say whether the model
was trained with an offset (its offset_column and offset_link, log for an exposure
or identity for an additive term) or without one. A CatBoost model whose offset nothing
declares scores with no offset, whether it comes from a file, a run or the registry: a
quote is priced for a full policy term, and an exposure of one adds nothing to a log-link
model. A contract that disagrees with what the model records is refused.
A CatBoost, XGBoost, LightGBM, t-boost, EBM or GLM model from a run or the registry scores with the feature contract its training run logged beside it, in the editor and when deployed, so its input is checked against the features and types it was trained on. A model whose run logged no contract, such as one trained outside Haute, scores against the features its own file names.
Scoring checks the input against the model's features before it runs: a missing feature or a numeric column where the model expects a categorical one fails with an error listing what is wrong, rather than predicting from mismatched data. An exposure offset (one the model applies through a log link) is optional: a quote is priced for a full policy term, so a missing exposure column, or a row whose exposure is empty, scores as an exposure of one. An exposure of zero or less is still refused. An additive offset, such as a base premium the model adds to, is required: a missing column or an empty value fails, naming it. Haute treats every log-link offset as an exposure, so give a base premium applied through a log link in every quote: one left out would be priced as a full policy term. A model with a feature contract also refuses a column whose type differs from training, such as whole numbers where it was trained on decimals, with the same error a deployed pipeline gives. The order the input's columns arrive in does not matter.
Values the model was not trained on¶
A categorical value the model's training data never held, such as a new vehicle make or region code, never stops scoring, and neither does a missing value in a column that had none in training. Each model family scores the value its own way:
| Family | A value it was not trained on scores |
|---|---|
| t-boost | in its pooled rare level, like the levels too thin to model alone (the default level on a feature where nothing was pooled) |
| LightGBM | as a missing value. At LightGBM's default categorical settings that is also where its thinnest levels go |
| XGBoost | as a missing value |
| EBM | at zero, the average across the training data |
| CatBoost | as a category with no history |
| GLM | at the reference level for a categorical term (with any level Levels leaves out), and at the overall average for a target-encoding term |
A feature that often meets new values suits a family that pools rare levels (t-boost, or LightGBM at its default settings) or a GLM target-encoding term.
The TRANSFORM tab¶
See Transform.
The COLUMNS tab¶
The COLUMNS tab chooses which output columns the node passes on; see Working with any node.
Example¶
Scoring a registered frequency model:
- Connect the data to score to a Model Scoring node.
- Leave the destination on Local folder (or choose where your registry lives) and MODEL SOURCE on Registered Model.
- Choose
frequency_modelin MODEL NAME and leave VERSION on latest. - Set OUTPUT COLUMN to
predicted_frequency. TASK shows Regression, recorded by the training run.
The preview shows your input rows with a new predicted_frequency column.
Instances¶
Instances let you reuse the same scoring configuration with different inputs - for example, scoring the same model against both training and validation data. See Reusing a node for full details.
In the pipeline file
The node's settings are stored in a JSON sidecar, config/model_scoring/<node name>.json, which the pipeline's .py file names in the node's decorator: @pipeline.model_score(config="config/model_scoring/<node name>.json"). When the node has TRANSFORM steps, their generated code is the body of the node's function, which receives the scored frame as df.
| Setting in the editor | Stored as |
|---|---|
| MLflow destination | mlflow_destination: "databricks" or "server"; absent for the local folder |
| MODEL SOURCE | source_type: "registered", "run" or "file" |
| MODEL FILE | model_path: the model file, relative to the project folder |
| MODEL NAME | registered_model |
| VERSION | version (a version number or "latest"), or alias for an alias such as "champion"; never both |
| EXPERIMENT | experiment_id (and experiment_name, the name the panel shows) |
| RUN, RUN ID | run_id (and run_name, the name the panel shows) |
| ARTIFACT PATH | artifact_path |
| TASK | task: "regression" or "classification" |
| OUTPUT COLUMN | output_column (defaults to "prediction") |
| TRANSFORM tab | the function body, which Haute reads the steps back from |
| COLUMNS tab | selected_columns |
These keys have no editor control:
| Key | What it does |
|---|---|
feature_contract_path |
An in-project feature-contract file the model scores with, in place of the one saved beside a model file, and bundled with the model when deploying. |
The example above is stored as:
{
"source_type": "registered",
"registered_model": "frequency_model",
"version": "latest",
"task": "regression",
"output_column": "predicted_frequency"
}
Every key the config may hold:
| Key | Type | Description |
|---|---|---|
code |
text | The Polars code the node's function runs; when steps are present, their rendering. |
steps |
list of map of text to any JSON value | The low-code steps, in order, rebuilt from the node's code each time it loads; the config file does not hold them. |
source_type |
"" or "run" or "registered" or "file" |
Where the model comes from; empty or absent when no source is chosen yet. |
model_path |
text | For a file source, the model file in the project, such as models/freq.cbm. |
experiment_name |
text | For a run source, the experiment's name, shown when the panel reopens. |
experiment_id |
text | For a run source, the MLflow experiment's id. |
run_id |
text | For a run source, the MLflow run whose model is scored. |
run_name |
text | For a run source, the run's name, shown when the panel reopens. |
artifact_path |
text | For an MLflow source, the model's path inside the run's artifacts, such as model.cbm. |
registered_model |
text | For a registered source, the registered model's name, such as catalog.schema.model. |
version |
text | For a registered source, the version scored, or latest; absent when alias is set. |
alias |
text | For a registered source, the alias whose version is scored, such as champion; excludes version. |
task |
"regression" or "classification" |
Whether the model predicts a value or a class probability. |
output_column |
text | The column the prediction is written to; prediction when absent. |
feature_contract_path |
text | The feature contract the model scores under, when it is not beside the model. |
mlflow_destination |
"" or "databricks" or "server" |
The MLflow server or Databricks workspace an MLflow source is read from; empty or absent is the local folder. |
input_mapping |
map of text to text | The input names the node's code uses, each mapped to the connected input it reads. |
contract |
"opaque" or object |
The node's column contract as its decorator declares it: "opaque", or the columns it reads and produces. |
selected_columns |
list of text | The columns the node passes downstream, chosen on its Columns tab; absent passes all. |
column_renames |
map of text to text | New names for columns passed downstream, from each column's name to its new one. |
See also:
- Load File - for pickle, joblib and JSON objects you apply with your own code
- Model Training - to train models that can be scored here