> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Predict Multiple Labels on Linux

> Train a temporal multilabel model and read a probability for each order channel

Predict whether each customer will place online orders, offline orders, or both in the next 90 days.
More than one order channel can occur in the same prediction window.
This example trains a small multilabel model and saves a separate probability and decision for each type.
Evaluate its per-label performance before using the decisions in a business workflow.
This guide uses the local Python API from the Linux setup. Do not combine its calls with legacy Kumo Studio examples.

## Run the Complete Example

Complete [Linux Machine Deployment Setup](/kumo-engine/1.0.0/get-started-with-kumo-engine/installation/linux-machine-deployment), then download the [Linux examples bundle and prepare the sample CSV files](/kumo-engine/1.0.0/examples/linux-local-examples#prepare-the-input-files).
Use the four prepared AdventureWorks CSVs.
Activate the installed Python environment and keep `ADVENTUREWORKS_DATA` set to the prepared CSV directory.

Run this command from the extracted bundle directory.
Replace the two output paths with new, separate directories.
Use local storage for scratch and retain results on storage whose lifetime meets your needs.
Keep both directories separate from the inputs and from each other.

```bash
export KUMO_MULTILABEL_OUTPUT=/path/to/retained-results/adventureworks-multilabel-01
python adventureworks_multilabel.py \
  --input-dir "$ADVENTUREWORKS_DATA" \
  --scratch-dir /path/to/local-storage/adventureworks-multilabel-scratch \
  --output-dir "$KUMO_MULTILABEL_OUTPUT" \
  --prediction-time 2025-06-30T00:00:00
```

The script builds the graph, generates historical labels from the event data, suggests a model plan, trains the model, and saves it under `model/`.
It writes `predictions.parquet` with one row for each returned customer and order channel.
Review the model plan and training budget before adapting it to production data.

A nonzero exit means the example did not complete.
Preserve its error and existing outputs, correct the reported problem, and choose a new output directory before another attempt.

## Understand the Prediction Task

The script uses this predictive query:

```text
PREDICT LIST_DISTINCT(SalesOrderHeader.OnlineOrderFlag, 0, 90, days)
CLASSIFY TOP 2 FOR EACH Customer.CustomerID
WHERE COUNT(SalesOrderHeader.*, -365, 0, days) > 0
```

At each training time, `LIST_DISTINCT` collects the order-channel values that occur after that time and up to and including 90 days later.
Repeated occurrences of the same type contribute one label.
The result can contain no types, one type, or several types.
The query uses `CLASSIFY TOP 2`, and the inference call separately requests both values with `num_classes_to_return=2`.
A customer does not need to have both labels.

Generated training rows use `ENTITY1`, `TIMESTAMP`, and `TARGET1`.
The query's task type is `multilabel_classification`.

The prediction time is June 30, 2025, at midnight UTC.
Pass a datetime without timezone information; Kumo interprets it as UTC.
The script sets this time when it generates the prediction table, then passes that table and the matching snapshot to inference.

## Inspect the Saved Predictions

After the script exits, read the output in a new Python process with the same `KUMO_MULTILABEL_OUTPUT` environment variable:

```python
import os
from pathlib import Path

import numpy as np
import pandas as pd

output = Path(os.environ["KUMO_MULTILABEL_OUTPUT"]).expanduser().resolve()
predicted = pd.read_parquet(output / "predictions.parquet")
columns = ["ENTITY", "TIMESTAMP", "PREDICTED", "CLASS", "SCORE"]
missing = set(columns) - set(predicted.columns)
if missing:
    raise KeyError(f"Missing prediction columns: {sorted(missing)}")
expected_classes = {"0", "1"}
assert all(set(group["CLASS"].astype(str)) == expected_classes
           for _, group in predicted.groupby("ENTITY"))
assert np.isfinite(predicted["SCORE"].to_numpy()).all()
assert predicted["SCORE"].between(0, 1).all()
print("Rows:", len(predicted))
print(predicted.head(8))
print("Selected labels per customer:")
print(predicted.groupby("ENTITY")["PREDICTED"].sum().value_counts().sort_index())
```

Expect one row per customer and class, with these columns:

| Column      | Meaning                                                            |
| ----------- | ------------------------------------------------------------------ |
| `ENTITY`    | Customer identifier                                                |
| `TIMESTAMP` | Requested prediction time                                          |
| `CLASS`     | Offline (`0`) or online (`1`) order flag                           |
| `SCORE`     | Predicted probability that this order channel occurs in the window |
| `PREDICTED` | Model's true or false decision for this order channel              |

These probabilities describe separate labels and do not need to sum to one for a customer.
`PREDICTED` is a decision for each label, so it can select no labels or several labels.
It is not a ground-truth value or a marker for one winning class.
The script requests both class rows with `num_classes_to_return=2`; do not discard classes before checking that both values are present.

## Handle Threshold and Time Errors

Omit `binary_classification_threshold` for multilabel prediction output.
Supplying it raises a `ValueError` stating that an explicit classification threshold is unsupported for this output.
Remove the argument and use the returned per-class scores and decisions.
If you need a separate business decision rule, apply it to the saved `SCORE` values in your own analysis and validate that rule on an appropriate evaluation dataset.

If the script rejects a timestamp with timezone information, supply the intended UTC time without the timezone suffix, as in the command above.
Convert other local times to UTC before removing timezone information.

Use an appropriate evaluation dataset and training budget before relying on the model's decisions.
See [Making Predictions](/kumo-engine/1.0.0/user-code-guide/making-predictions) for prediction parameters and output retention, and [Publish and Retrieve Models](/kumo-engine/1.0.0/user-code-guide/train-a-model/publish-and-retrieve-models) for model reload requirements.