stanfordnlp/CoreNLP · error · RuntimeException

Got NaN for prob in…

Error message

Got NaN for prob in CRFLogConditionalObjectiveFunctionForLOP.calculate()

What it means

CRFLogConditionalObjectiveFunctionForLOP computes a Log-Linear-Output-Pile (LOP) CRF objective; after accumulating prob across documents it throws a RuntimeException if the result is NaN. This indicates the LOP-style computation produced a non-finite log-probability, so the optimizer is stopped rather than continuing on corrupt values.

Solutions

  1. Re-normalize the LOP mixture/feature weights so the per-document computations stay finite.
  2. Split long training documents into shorter sequences to avoid log underflow.
  3. Validate the parameter vector for NaN/Inf before each optimizer step.
  4. Print intermediate per-document probs (enable VERBOSE) to locate the failing document.
  5. Lower the learning rate and retrain from a known-good initialization.

Example fix

// before
lopCRF.calculate(x, batch, E); // throws on NaN
// after
boolean bad = false;
for (double w : x) if (Double.isNaN(w) || Double.isInfinite(w)) bad = true;
if (!bad) lopCRF.calculate(x, batch, E); else x = lastGoodCheckpoint;
Defensive patterns

Strategy: try-catch

Validate before calling

if (!isFinite(x)) x = lastGoodCheckpoint; // ensure params finite before LOP calculate
boolean isFinite(double[] v) { for (double d : v) if (!Double.isFinite(d)) return false; return true; }

Type guard

static boolean isFinite(double[] v) { for (double d : v) if (Double.isNaN(d) || Double.isInfinite(d)) return false; return true; }

Try / catch

try {
  lopCrf.calculate(x, batch, E);
} catch (RuntimeException e) {
  if (e.getMessage().contains("NaN for prob")) {
    normalizeMixtureWeights();
    x = lastGoodCheckpoint;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling calculate() on the LOP objective when the accumulated prob is NaN — typically from underflow in mixture/ensemble weight computations, extreme parameters, or long input sequences in the LOP training data.

Common situations: LOP-CRF training (useNA / feature mixture setups) with badly scaled mixture weights or very long documents; also seen when a prior optimization step yields non-finite weights.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/40c949b3cf678f62. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/ie/crf/CRFLogConditionalObjectiveFunctionForLOP.java:414

              eScales[lopIter] += (p * expected);

              double[][] eOfIter = E[lopIter];
              if (backpropTraining) {
                for (int k = 0; k < docData[i][j].length; k++) { // k iterates over features
                  int featureIdx = docData[i][j][k];
                  if (indicesSet.contains(featureIdx)) {
                    eOfIter[featureIdx][l] += p;
                  }
                }
              }
            }
          }
        }
      }
    }

    if (Double.isNaN(prob)) { // shouldn't be the case
      throw new RuntimeException("Got NaN for prob in CRFLogConditionalObjectiveFunctionForLOP.calculate()");
    }

    value = -prob;
    if(VERBOSE){
      log.info("value is " + value);
    }
    // compute the partial derivative for each feature by comparing expected counts to empirical counts
    for (int lopIter = 0; lopIter < numLopExpert; lopIter++) {
      double scale = scales[lopIter];
      double observed = sumOfObservedLogPotential[lopIter];
      for (int j = 0; j < numLopExpert; j++) {
        observed -= scales[j] * sumOfObservedLogPotential[j];
      }
      observed *= scale;
      double expected = eScales[lopIter];

      derivative[lopIter] = (expected - observed);
      if (VERBOSE) {

View on GitHub (pinned to 1b7edd19c4)