{"record":{"id":"4b73387f2c1bb8f9","repo":"stanfordnlp/CoreNLP","slug":"predict-not-implemented-for-max-margin","errorCode":null,"errorMessage":"Predict not implemented for max margin","messagePattern":"Predict not implemented for max margin","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/coref/statistical/SimpleLinearClassifier.java","lineNumber":184,"sourceCode":"            (mistake - 1) * label / gamma : -label);\n      }\n\n      @Override\n      public String toString() {\n        return String.format(\"quadraticallySmoothed(%s)\", gamma);\n      }\n    };\n  }\n\n  public static Loss hinge() {\n    return quadraticallySmoothedSVM(0);\n  }\n\n  public static Loss maxMargin(final double h) {\n    return new Loss() {\n      @Override\n      public double predict(double product) {\n        throw new UnsupportedOperationException(\"Predict not implemented for max margin\");\n      }\n\n      @Override\n      public double derivative(double label, double product) {\n        return product < -h ? 0 : 1;\n      }\n\n      @Override\n      public String toString() {\n        return String.format(\"max-margin(%s)\", h);\n      }\n    };\n  }\n\n  public static Loss risk() {\n    return new Loss() {\n      @Override\n      public double predict(double product) {","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/coref/statistical/SimpleLinearClassifier.java#L166-L202","documentation":"The maxMargin loss function intentionally has no predict() implementation; calling predict on a Loss returned by SimpleLinearClassifier.maxMargin(h) throws UnsupportedOperationException. Max-margin losses only define the hinge derivative for training, not a scoring function.","triggerScenarios":"Calling classifier.predict(example, ...) (SimpleLinearClassifier.predict at line 184) when the classifier was constructed with the Loss returned by maxMargin(h).","commonSituations":"Training a coref classifier with max-margin loss, then reusing it for inference/scoring instead of switching to a loss that supports prediction (e.g. logistic).","solutions":["Do not call predict with a maxMargin loss; use a differentiable/scoreable loss such as logistic for inference","Rebuild the classifier with logistic loss before scoring","Use the raw weights dot-product yourself instead of Loss.predict if you need margin scores"],"exampleFix":"// before\nSimpleLinearClassifier clf = new SimpleLinearClassifier(SimpleLinearClassifier.maxMargin(1.0), modelFile);\ndouble score = clf.predict(example, features, compressor); // throws\n// after\nSimpleLinearClassifier clf = new SimpleLinearClassifier(Loss.logistic, modelFile);\ndouble score = clf.predict(example, features, compressor);","handlingStrategy":"validation","validationCode":"if (loss instanceof SimpleLinearClassifier.Loss) {\n  // ensure loss is not maxMargin before calling predict\n  assert !isMaxMargin(loss) : \"maxMargin loss does not support predict\";\n}","typeGuard":null,"tryCatchPattern":"try {\n  double score = classifier.predict(example, feats, compressor);\n} catch (UnsupportedOperationException e) {\n  throw new IllegalStateException(\"use a scoreable loss (e.g. logistic) for predict\", e);\n}","preventionTips":["Use maxMargin only for training loops that call derivative()","Switch to logistic loss before any inference/scoring","Document which loss the classifier was built with"],"tags":["unsupported-operation","max-margin","loss-function","inference"],"backgroundTag":"unsupported-operation","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"}