You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implements the mathematical core for the approval-outcome prediction
epic (#645): a pure-Java logistic regression trainer and model evaluator.
No Spring, no database, no external ML libraries — hand-rolled, matching
the precedent set by StatisticalAnomalyDetector.
What's included
TrainedApprovalModel.java — immutable record holding intercept,
weights, feature means/stddevs, and a predict() method that
standardizes + applies sigmoid. JSON round-trip via Jackson 3
(tools.jackson.databind).
LogisticRegressionTrainer.java — stateless batch gradient descent
trainer with L2 regularization, zero-initialized weights, and z-score
feature standardization. Deterministic by design — no randomness
anywhere.
ModelEvaluator.java — stateless evaluator computing AUC via the
rank-sum method (with average-rank tie handling) and accuracy at a
configurable threshold.
Testing
All three classes have dedicated test classes per the coverage-parity
rule:
LogisticRegressionTrainerTest — verifies >95% accuracy on a
linearly separable synthetic dataset, exact bit-identical determinism
across repeated training runs, L2 shrinkage effect, and standardization
correctness (including constant-column edge case).
ModelEvaluatorTest — known-answer AUC cases (perfect/inverted/tied
rankings) and hand-computed accuracy.
mvn verify -Pcoverage: 10/10 new tests pass. ApplicationModulesTest
passes — all three classes live in ai/internal, no cross-module
dependency violations.
Note: ran without Docker, so Testcontainers-based integration tests
were skipped locally. Saw 9 pre-existing teardown errors unrelated to
this change (DefaultDriverCatalogServiceTest, DefaultQueryEngineCatalogTest — JUnit extension context lifecycle
issue), flagging in case it's already a known issue.
The reason will be displayed to describe this comment to others. Learn more.
A few robustness/convention items to address before merge — details inline. The math itself checks out (verified the standardization, gradient, and rank-sum AUC against the spec in #648).
@babltiga Thanks for the detailed review! I've addressed all the robustness and edge-case items.
Here is what was updated:
TrainedApprovalModel Serialization: Replaced the generic catch (Exception e) with catch (JacksonException e) and wrapped it in a new, public ApprovalModelSerializationException so the retraining jobs can properly catch corrupt DB rows as a sentinel.
Fail-fast map lookups: Updated predict() to strictly use .get() rather than .getOrDefault(). Added validation to the compact constructor to reject duplicate feature names and ensure weights, means, and stddevs are fully populated.
Array shape guards: Added explicit IllegalArgumentException checks to both LogisticRegressionTrainer.train and ModelEvaluator (calculateAuc / calculateAccuracy) to fail fast on length mismatches and ragged rows before entering any loops.
Test Parity: Added 9 new unit tests covering all the new exception branches, including the existing empty-input edge cases.
Everything is pushed and CI should be fully green. Ready for another look!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #648
Implements the mathematical core for the approval-outcome prediction
epic (#645): a pure-Java logistic regression trainer and model evaluator.
No Spring, no database, no external ML libraries — hand-rolled, matching
the precedent set by StatisticalAnomalyDetector.
What's included
TrainedApprovalModel.java— immutable record holding intercept,weights, feature means/stddevs, and a
predict()method thatstandardizes + applies sigmoid. JSON round-trip via Jackson 3
(
tools.jackson.databind).LogisticRegressionTrainer.java— stateless batch gradient descenttrainer with L2 regularization, zero-initialized weights, and z-score
feature standardization. Deterministic by design — no randomness
anywhere.
ModelEvaluator.java— stateless evaluator computing AUC via therank-sum method (with average-rank tie handling) and accuracy at a
configurable threshold.
Testing
All three classes have dedicated test classes per the coverage-parity
rule:
LogisticRegressionTrainerTest— verifies >95% accuracy on alinearly separable synthetic dataset, exact bit-identical determinism
across repeated training runs, L2 shrinkage effect, and standardization
correctness (including constant-column edge case).
TrainedApprovalModelTest— JSON round-trip fidelity, sigmoid bounds.ModelEvaluatorTest— known-answer AUC cases (perfect/inverted/tiedrankings) and hand-computed accuracy.
mvn verify -Pcoverage: 10/10 new tests pass.ApplicationModulesTestpasses — all three classes live in
ai/internal, no cross-moduledependency violations.
Note: ran without Docker, so Testcontainers-based integration tests
were skipped locally. Saw 9 pre-existing teardown errors unrelated to
this change (
DefaultDriverCatalogServiceTest,DefaultQueryEngineCatalogTest— JUnit extension context lifecycleissue), flagging in case it's already a known issue.