An undefined-precision warning can mean your classifier never predicted a particular class. Changing zero_division can control the displayed score, but it cannot make the missing predictions appear. First inspect the actual and predicted label counts; then document the reporting convention and investigate the model.
This beginner example uses deliberately constructed labels, not results from a trained production system. Run it in a disposable Python environment with scikit-learn installed. It reads no customer files and changes no model or service configuration.
Separate precision from recall
Precision asks how many predictions of a class were correct. Its denominator is the number of predictions of that class. If the model never predicts the class, there is nothing in that denominator, so precision is undefined. Recall instead asks how many actual examples of a class were found. When examples exist but none is found, recall is zero rather than undefined.
The official precision_recall_fscore_support reference documents these definitions, the support count, averaging options and zero-division behaviour. A warning is therefore useful diagnostic information, not just console noise.
Reproduce the never-predicted class
Use the complete block below in one script or notebook cell. The actual labels contain both routine and urgent cases, while every prediction is routine. The explicit label list makes the report order easy to inspect. The unexpected-label guard prevents a typing error from silently falling outside that intended list.
from collections import Counter
from sklearn.metrics import precision_recall_fscore_support
labels = ["routine", "urgent"]
y_true = ["routine", "routine", "urgent", "urgent"]
y_pred = ["routine", "routine", "routine", "routine"]
unexpected = (set(y_true) | set(y_pred)) - set(labels)
if unexpected:
raise ValueError(f"Unexpected labels: {unexpected}")
print("Actual:", dict(Counter(y_true)))
print("Predicted:", dict(Counter(y_pred)))
precision, recall, f1, support = precision_recall_fscore_support(
y_true, y_pred, labels=labels, average=None, zero_division=0
)
for row in zip(labels, precision, recall, f1, support):
print(row)
Inspect the two counters before the score rows. The urgent class has actual examples but no predictions. With the chosen convention, the report displays zero for its undefined precision; its recall is also zero because the model found none of the urgent examples. Those two zeros have different explanations. Preserve that distinction in a review note.
Choose zero_division deliberately
The default zero_division='warn' uses a zero value while raising a warning for undefined metrics. Explicit zero_division=0 uses that reporting value without the warning. It is reasonable for a documented report, provided you still retain counts and flag never-predicted classes.
Setting it to one is not a repair: it can make an undefined precision look successful if readers do not know the convention. The reference also documents numpy.nan, available from scikit-learn 1.3, which excludes undefined values from the corresponding average. That changes what the average describes. Check your installed version and do not compare reports with different conventions as though nothing changed.
Investigate the cause without contaminating evaluation
Check that the predictions and actual labels refer to the same rows in the same order. Review label mapping, preprocessing and class frequencies in the training data. A rare class may be poorly represented, but counts alone do not establish the cause. Also check that your prediction code is returning class labels rather than scores or an incorrectly selected probability column.
If a decision threshold is involved, evaluate any proposed adjustment on validation data using the application’s costs and safety requirements. Do not tune the threshold repeatedly against a final test set and then describe that test result as untouched evidence. A different threshold can trade false alarms against missed cases; suppressing a warning makes neither trade-off disappear.
Compare the model with a simple reference using the DummyClassifier baseline workflow. A model that predicts one class may obtain misleadingly comfortable overall accuracy on an imbalanced dataset.
Checklist for the evaluation report
- Record the dataset split and label order.
- Keep actual support and prediction counts alongside per-class scores.
- State the zero-division convention and averaging method.
- Flag classes with no predictions separately from classes with no actual examples.
- Retain the original report before experimenting with training or thresholds.
Does a weighted average fix this?
No. Weighted averages use actual class support, while macro averages give classes equal weight. Neither creates missing predictions or guarantees acceptable urgent-case detection. Read the per-class evidence before summarising performance, especially when a missed class has serious consequences.
This tutorial is for educational use. Test examples and evaluation changes carefully before production. The site owner is not responsible for misuse, damage, data loss or production issues. A small constructed example is not validation of a model’s reliability or fitness for deployment.



