deeplearning4j/deeplearning4j · error · IllegalStateException

Classifier evaluation using

Error message

Classifier evaluation using ${classifierEval.getSimpleName()} class cannot be applied to output layers with activation functions that are not probabilities (in range 0 to 1). Output layer type: ${outputLayer.getClass().getSimpleName()} has activation function ${bl.getActivationFn().getClass().getSimpleName()}. This check can be disabled using MultiLayerNetwork.getLayerWiseConfigurations().setValidateOutputLayerConfig(false) or ComputationGraph.getConfiguration().setValidateOutputLayerConfig(false)

What it means

This IllegalStateException is thrown when classifier evaluation (Evaluation, ROCMultiClass, etc.) is requested but the output layer's activation function can produce values outside [0,1], so its outputs are not probabilities and probability-based metrics would be invalid. Deeplearning4j inspects the layer's IActivation via OutputLayerUtil.activationExceedsZeroOneRange and rejects obviously wrong activation choices (e.g. ReLU/tanh/identity on an output layer used for classification). For non-explicitly-Output layers the check is stricter since probabilities aren't guaranteed.

Solutions

  1. Set the output layer activation to a probability activation: softmax for multi-class, sigmoid for multi-label/binary (e.g. .activation(Activation.SOFTMAX) on OutputLayer).
  2. If the mismatch is intentional, disable the check: getLayerWiseConfigurations().setValidateOutputLayerConfig(false) for MultiLayerNetwork or getConfiguration().setValidateOutputLayerConfig(false) for ComputationGraph.
  3. Verify the layer type is a proper output layer (OutputLayer/RnnOutputLayer/CenterLossOutputLayer); if the last layer is a DenseLayer, replace with OutputLayer.
  4. Choose evaluation matching the model: use regression evaluation (RegressionEvaluation) for non-probability outputs instead of classifier evaluation.

Example fix

// before
.layer(new OutputLayer.Builder(LossFunctions.LossFunction.MCXENT)
    .activation(Activation.RELU) // not a probability
    .nOut(numClasses).build())
...
model.evaluate(iter, new Evaluation()); // throws

// after
.layer(new OutputLayer.Builder(LossFunctions.LossFunction.MCXENT)
    .activation(Activation.SOFTMAX)
    .nOut(numClasses).build())
Defensive patterns

Strategy: validation

Validate before calling

BaseLayer out = (BaseLayer) net.getOutputLayer();
IActivation fn = ((org.deeplearning4j.nn.conf.layers.BaseLayer)out.conf().getLayer()).getActivationFn();
if (!(fn instanceof ActivationSoftmax || fn instanceof ActivationSigmoid)) {
    throw new IllegalStateException("Output activation " + fn + " is not a probability activation; use SOFTMAX/SIGMOID for classifier evaluation");
}

Type guard

boolean isProbActivation = fn instanceof org.nd4j.linalg.activations.impl.ActivationSoftmax || fn instanceof org.nd4j.linalg.activations.impl.ActivationSigmoid;

Try / catch

try {
    model.evaluate(iter, new Evaluation());
} catch (IllegalStateException e) {
    if (e.getMessage().contains("not probabilities")) {
        // fix activation or disable validation
    } else throw e;
}

Prevention

When it happens

Trigger: Calling model.evaluate(...) or passing a classifier IEvaluation class while the final layer uses an activation like ReLU, Tanh, Identity, LeakyReLU, ELU, SELU, Softsign-ish bounds violations, e.g. an OutputLayer with activation Activation.RELU and loss function suitable for regression, then evaluating as classification. Also triggered for hidden layers last in the network because the check is stricter when the layer isn't OutputLayer/RnnOutputLayer/CenterLossOutputLayer.

Common situations: Copying a regression example (identity/relu activation) and then evaluating with classification metrics; using Activation.SIGMOID vs SOFTMAX mistakes; after editing the .conf builder and leaving a wrong activation on the output layer; newer DL4J versions added this validation, so older models/code that previously 'worked' now fail with it.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of deeplearning4j/deeplearning4j@4c22ac5fe4 (2026-09-07). Data as JSON: /api/errors/4b246dca8ba7b009. Report an issue: GitHub.

Appendix: source

Thrown at deeplearning4j/deeplearning4j-nn/src/main/java/org/deeplearning4j/util/OutputLayerUtil.java:185

     * This method won't catch all possible invalid cases, but should catch some common problems.
     *
     * @param outputLayer          Output layer
     * @param classifierEval       Class for the classifier evaluation
     */
    public static void validateOutputLayerForClassifierEvaluation(Layer outputLayer, Class<? extends IEvaluation> classifierEval){
        if(outputLayer instanceof Yolo2OutputLayer){
            throw new IllegalStateException("Classifier evaluation using " + classifierEval.getSimpleName() + " class cannot be applied for object" +
                    " detection evaluation using Yolo2OutputLayer: " + classifierEval.getSimpleName() + "  class is for classifier evaluation only.");
        }

        //Check that the activation function provides probabilities. This can't catch everything, but should catch a few
        // of the common mistakes users make
        if(outputLayer instanceof BaseLayer){
            BaseLayer bl = (BaseLayer)outputLayer;
            boolean isOutputLayer = outputLayer instanceof OutputLayer || outputLayer instanceof RnnOutputLayer || outputLayer instanceof CenterLossOutputLayer;

            if(activationExceedsZeroOneRange(bl.getActivationFn(), !isOutputLayer)){
                throw new IllegalStateException("Classifier evaluation using " + classifierEval.getSimpleName() + " class cannot be applied to output" +
                        " layers with activation functions that are not probabilities (in range 0 to 1). Output layer type: " +
                        outputLayer.getClass().getSimpleName() + " has activation function " + bl.getActivationFn().getClass().getSimpleName() +
                        ". This check can be disabled using MultiLayerNetwork.getLayerWiseConfigurations().setValidateOutputLayerConfig(false)" +
                        " or ComputationGraph.getConfiguration().setValidateOutputLayerConfig(false)");
            }
        }
    }
}

View on GitHub (pinned to 4c22ac5fe4)