{"record":{"id":"e2574e752f5e7de9","repo":"stanfordnlp/CoreNLP","slug":"got-nan-for-prob-in-crflogconditionalobjectivefunc","errorCode":null,"errorMessage":"Got NaN for prob in CRFLogConditionalObjectiveFunction.calculate() - this may well indicate numeric underflow due to overly long documents.","messagePattern":"Got NaN for prob in CRFLogConditionalObjectiveFunction\\.calculate\\(\\) - this may well indicate numeric underflow due to overly long documents\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/ie/crf/CRFLogConditionalObjectiveFunction.java","lineNumber":425,"sourceCode":"  /**\n   * Calculates both value and partial derivatives at the point x, and save them internally.\n   */\n  @Override\n  public void calculate(double[] x) {\n\n    // final double[][] weights = to2D(x);\n    to2D(x, weights);\n    setWeights(weights);\n\n    // the expectations over counts\n    // first index is feature index, second index is of possible labeling\n    // double[][] E = empty2D();\n    clear2D(E);\n\n    double prob = regularGradientAndValue(); // the log prob of the sequence given the model, which is the negation of value at this point\n\n    if (Double.isNaN(prob)) { // shouldn't be the case\n      throw new RuntimeException(\"Got NaN for prob in CRFLogConditionalObjectiveFunction.calculate()\" +\n              \" - this may well indicate numeric underflow due to overly long documents.\");\n    }\n\n    // because we minimize -L(\\theta)\n    value = -prob;\n    if (VERBOSE) {\n      log.info(\"value is \" + Math.exp(-value));\n    }\n\n    // compute the partial derivative for each feature by comparing expected counts to empirical counts\n    int index = 0;\n    for (int i = 0; i < E.length; i++) {\n      double[] E_i = E[i], Ehat_i = Ehat[i];\n      for (int j = 0; j < E_i.length; j++) {\n        // because we minimize -L(\\theta)\n        derivative[index] = (E_i[j] - Ehat_i[j]);\n        if (VERBOSE) {\n          log.info(\"deriv(\" + i + \",\" + j + \") = \" + E_i[j] + \" - \" + Ehat_i[j] + \" = \" + derivative[index]);","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/ie/crf/CRFLogConditionalObjectiveFunction.java#L407-L443","documentation":"CRFLogConditionalObjectiveFunction.calculate() computes the log-probability of the labeled sequences given the model. If that value comes back as NaN, the function throws a RuntimeException because training cannot proceed on a non-finite objective. The message explicitly warns that overly long documents can cause numeric underflow (log of 0) in the forward/backward computations.","triggerScenarios":"Calling calculate(double[] x, double[] batch, double[] E) in the single-threaded path when regularGradientAndValue() returns NaN — typically when the log-probability of a sequence underflows (very long documents, extreme feature weights, or weights x containing NaN/Inf).","commonSituations":"Training a CRF on very long documents (underflow in the log-sum of sequence probabilities), a learning-rate blowup producing Inf/NaN weights, or pathological feature scaling before calling CRFClassifier training.","solutions":["Shorten training documents (split into sentences/segments) so sequence probabilities do not underflow.","Inspect the parameter vector x for NaN/Inf before training (print/validate weights; reduce learning rate or use a more stable optimizer like L-BFGS with line search).","Scale/normalize feature values so log-linear scores stay in a sane range.","Enable VERBOSE and log intermediate values to find the offending document, then fix or drop it.","As a last resort, catch the RuntimeException and skip/re-initialize the offending training batch."],"exampleFix":"// before: one huge training document\nDocumentReader dr = new DocumentReader(\"longdoc.txt\");\n// after: split into sentence-level windows\nList<List<CoreLabel>> sentences = DocumentPreprocessor.split(\"longdoc.txt\");\n// train on sentences instead of the full document","handlingStrategy":"try-catch","validationCode":"for (double w : x) { if (Double.isNaN(w) || Double.isInfinite(w)) throw new IllegalArgumentException(\"NaN/Inf weight before CRF calculate\"); }\nif (docLength > MAX_SEQUENCE_LENGTH) doc = chunk(doc, MAX_SEQUENCE_LENGTH);","typeGuard":"static boolean isFinite(double[] v) { for (double d : v) if (Double.isNaN(d) || Double.isInfinite(d)) return false; return true; }","tryCatchPattern":"try {\n  crf.calculate(x, batch, E);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"NaN for prob\")) {\n    // shrink documents, reduce learning rate, restore checkpoint\n    x = lastGoodCheckpoint;\n    learningRate *= 0.5;\n  } else throw e;\n}","preventionTips":["Split long documents into sentence-level segments before CRF training.","Validate weight vectors for NaN/Inf each optimizer iteration.","Normalize feature values to keep log-linear scores bounded.","Use a stable optimizer (L-BFGS) with line search instead of fixed aggressive steps."],"tags":["crf","nan","numeric-underflow","training"],"backgroundTag":"value-out-of-range","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}