Imagine a country has collected data on patients infected with “Pathogen A,” an infectious respiratory illness. For each patient, eight features are recorded along with one of three outcomes: (a) treated at home and recovered, (b) hospitalized and recovered, or (c) died.
Training a neural network to predict the outcome from the features is trivial—we achieved nearly perfect accuracy. However, health authorities need something more nuanced: Among patients who can be treated at home, who is most at risk of hospitalization? Among those predicted to be hospitalized, who is most at risk of dying? Can we produce a numeric score representing how severe the infection will be?
This note introduces a neural network with a bottleneck and a special head to learn a scoring system from categorical outcomes, and explores properties of small neural networks you’re likely to encounter. The accompanying code is available at https://codeberg.org/csirmaz/category-scoring.
The Dataset
To illustrate the approach, I developed a toy example: a deterministic, non-linear function that computes the outcome from eight features. This is purely illustrative—not scientifically accurate—but feature names are chosen to fit the medical scenario. The eight features are:
- Previous infection with Pathogen A (boolean)
- Previous infection with Pathogen B (boolean)
- Acute / current infection with Pathogen B (boolean)
- Cancer diagnosis (boolean)
- Weight deviation from average, arbitrary unit (-100 ≤ x ≤ 100)
- Age, years (0 ≤ x ≤ 100)
- Blood pressure deviation from average, arbitrary unit (0 ≤ x ≤ 100)
- Years smoked (0 ≤ x ≤ ~88)
Features are sampled independently from uniform distributions, except years smoked, which depends on age, with a 50% non-smoker cohort. We verified that the three outcomes occur with roughly equal probability, and we normalized inputs to zero mean and unit variance.
As an example, the plot below shows outcomes with weight on the horizontal axis and age on the vertical axis, other parameters fixed. “o” indicates hospitalization, “+” indicates death.
.................... .................... .................... .................... ...............ooooo ............oooooooo ............oooooooo ............oooooooo ............oooooooo ............oooooooo ............ooooooo+ ...........ooooooo++ ...........oooooo+++ ...........oooooo+++ ...........ooooo++++ .......oooooooo+++++ ..oooooooooooo++++++ oooooooooooooo+++++++ oooooooooooo++++++++ ooooooooooo+++++++++
Training a Classic Classifier
The data is non-linear but clean, so a small classifier network achieves 98–99% validation accuracy. To train a simple 6-layer network (each layer 8 wide) with ReLU activation, run train.py --classifier, defined in ScoringModel.build_classifier_model().
How to Train a Scoring System?
Our goal is to train a system that, given the eight features, outputs a score reflecting the patient’s danger from Pathogen A. The challenge: our training data contains only categorical outcomes, not scores. To ensure the score is meaningful, we want certain score ranges to correspond to the categories in a monotonic way—e.g., higher scores indicating more severe outcomes.
We approach this by using an ordinal regression framework: we assign an underlying continuous latent variable (the score) and thresholds that separate the categories. The network is trained to predict this latent variable, and the thresholds are learned jointly. This way, the model learns a continuous score from purely categorical labels.
Specifically, we design a network with a bottleneck layer that forces the latent representation to be low-dimensional, and a head that maps the bottleneck to a single scalar score. The loss function is a ranked-based loss (e.g., ordinal loss) that encourages correct ordering of the categories.
In our experiments, we found that using a rank-based loss (such as the proportional odds model loss) yields a smooth and interpretable score. The score correlates strongly with the true underlying severity (which we knew in the toy example). Moreover, the bottleneck helps regularize the model and reduces overfitting.
For the 2026 context, such scoring systems are increasingly relevant in healthcare for triage and personalized risk assessment. Our method ensures that even with limited labeled data, we can derive a continuous severity score, enabling more nuanced clinical decisions.
We also discuss properties of small networks, such as the effect of width and depth on the learned representation, and how the bottleneck dimensionality impacts performance. We hope this note provides a practical recipe for deriving continuous scores from categorical outcomes.
