stanfordnlp/CoreNLP · warning

QNInfo:update() : PROBLEM WITH DIAGONAL UPDATE

Error message

QNInfo:update() : PROBLEM WITH DIAGONAL UPDATE

What it means

QNMinimizer.QNInfo.update maintains a diagonal inverse-Hessian approximation built from s/y vector pairs. If the computed diagonal contains non-positive entries, infinities, or an extreme condition ratio (>1e12), the update is deemed corrupt and the diagonal is reset to the scalar approximation yy/sy with a warning.

Solutions

  1. Scale/normalize input features so the objective is well-conditioned.
  2. Check line-search/step-size settings and verify the gradient contains no NaNs/infinities before the update.
  3. Verify the function/diffFunction implementation returns correct values and gradients (a buggy gradient yields corrupt s/y pairs).
  4. The minimizer self-recovers by filling with yy/sy — confirm training proceeds and converges; the warning alone is not fatal.

Example fix

// before: unscaled features spanning [0, 1e9]
double[] x = qn.minimize(f, 1e-4, initial, maxIters);
// after — scale features to comparable ranges first
for (int i = 0; i < initial.length; i++) initial[i] /= featureScale[i];
double[] x = qn.minimize(f, 1e-4, initial, maxIters);
Defensive patterns

Strategy: validation

Validate before calling

for (double v : grad) {
  if (Double.isNaN(v) || Double.isInfinite(v)) {
    throw new IllegalStateException("bad gradient value: " + v);
  }
}

Try / catch

// the minimizer already recovers by resetting d to yy/sy;
// wrap the training run and retrain with scaled features if the warning recurs
if (logWarningsContain("PROBLEM WITH DIAGONAL UPDATE")) {
  retrainWithNormalizedFeatures();
}

Prevention

When it happens

Trigger: update() called after a line search producing degenerate s/y pairs — e.g. y = g_new - g_old ≈ 0, non-positive curvature, or exploding values from an ill-conditioned objective or bad step size.

Common situations: Training with nearly zero gradient change between iterations; features on wildly different scales; too-large steps causing oscillation and bad curvature estimates.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/optimization/QNMinimizer.java:776

        final double newSi = newS[i];
        sDs += newSi * (d[i] *= gamma) * newSi;
      }
      // This diagonal update was introduced by Andrew Bradley
      for(int i = 0; i < d.length; i++) {
        final double di = d[i], newSi = newS[i], newYi = newY[i];
        d[i] = (1 - di * newSi * newSi / sDs) * di + newYi * newYi / sy;
      }
      // Here we make sure that the diagonal is alright
      double minD = d[0], maxD = minD;
      for(int i = 1; i < d.length; i++) {
        final double v = d[i];
        minD = v < minD ? v : minD;
        maxD = v > maxD ? v : maxD;
      }

      // If things have gone bad, just fill with the SCALAR approx.
      if(minD <= 0 || Double.isInfinite(maxD) || maxD / minD > 1e12) {
        log.warn("QNInfo:update() : PROBLEM WITH DIAGONAL UPDATE");
        Arrays.fill(d, yy / sy);
      }

      // If s is already of size mem, remove the oldest vector and free it up.
      if(used == mem)
        removeFirst();

      // Actually add the pair.
      s[used] = newS;
      y[used] = newY;
      rho[used] = 1 / sy;
      ++used;

      return used;
    } // end update
  } // end class DiagonalQNInfo

  public void setHistory(List<double[]> s, List<double[]> y) {

View on GitHub (pinned to 1b7edd19c4)