Skip to content

refactor: remove DefaultModelEvaluator and IModelEvaluator - #820

Merged
ooples merged 2 commits into
masterfrom
refactor/remove-default-model-evaluator
Feb 6, 2026
Merged

ooples merged 2 commits into
masterfrom
refactor/remove-default-model-evaluator

Conversation

@ooples

@ooples ooples commented Feb 5, 2026

Copy link
Copy Markdown
Owner

Summary

Remove legacy DefaultModelEvaluator and IModelEvaluator interfaces in favor of the new MetricEvaluationEngine through AiModelResult facade pattern.

  • Delete DefaultModelEvaluator.cs and IModelEvaluator.cs
  • Add AiModelResult.Evaluation.cs with EvaluateFull() and GetDataSetStats() methods
  • Remove IModelEvaluator dependency from AutoML, Optimizer, and Genetics classes
  • Update StepwiseRegression with inline evaluation
  • Remove ConfigureModelEvaluator from AiModelBuilder
  • Update tests to use new evaluation pattern

Test plan

  • Build succeeds with 0 errors
  • No remaining references to DefaultModelEvaluator or IModelEvaluator in src/
  • Tests updated to use new facade pattern

Closes #334

🤖 Generated with Claude Code

Remove legacy DefaultModelEvaluator and IModelEvaluator interfaces in favor of
the new MetricEvaluationEngine through AiModelResult facade pattern.

Changes:
- Delete DefaultModelEvaluator.cs and IModelEvaluator.cs
- Add AiModelResult.Evaluation.cs with EvaluateFull() and GetDataSetStats()
- Remove IModelEvaluator dependency from AutoML classes
- Remove IModelEvaluator dependency from Optimizer classes
- Remove IModelEvaluator dependency from Genetics classes
- Remove IModelEvaluator from OptimizationAlgorithmOptions
- Update StepwiseRegression with inline evaluation
- Remove ConfigureModelEvaluator from AiModelBuilder
- Update tests to use new evaluation pattern

Closes #334

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 5, 2026 19:23
@vercel

vercel Bot commented Feb 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aidotnet-playground-api Ready Ready Preview, Comment Feb 6, 2026 4:29pm

@coderabbitai

coderabbitai Bot commented Feb 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added result-level evaluation APIs: EvaluateFull() and GetDataSetStats() to compute training/validation/test statistics and model metrics post-build.
  • Refactor

    • Consolidated evaluation into model result APIs; builders and optimizers no longer accept external evaluators and perform evaluation during build.
    • Removed legacy evaluator configuration methods; cross-validation and evaluation are now performed via result-level APIs after build.

Walkthrough

This PR removes the IModelEvaluator abstraction and DefaultModelEvaluator, inlines model evaluation into consumers, and adds post-build evaluation APIs on AiModelResult. Constructor signatures and public APIs that accepted IModelEvaluator were removed across AutoML, optimizers, genetic algorithms, and regression components.

Changes

Cohort / File(s) Summary
Core evaluation removal
src/Interfaces/IModelEvaluator.cs, src/Evaluation/DefaultModelEvaluator.cs, src/Interfaces/IAutoMLModel.cs
Deleted the IModelEvaluator interface and DefaultModelEvaluator class; removed SetModelEvaluator from IAutoMLModel.
Builder & AutoML updates
src/AiModelBuilder.cs, src/Interfaces/IAiModelBuilder.cs, src/AutoML/AutoMLModelBase.cs, src/AutoML/BuiltInSupervisedAutoMLModelBase.cs, src/AutoML/SupervisedAutoMLModelBase.cs, src/AutoML/RandomSearchAutoML.cs, src/AutoML/BayesianOptimizationAutoML.cs, src/AutoML/EvolutionaryAutoML.cs, src/AutoML/MultiFidelityAutoML.cs
Removed _modelEvaluator and ConfigureModelEvaluator API; updated AutoML strategy constructors to drop evaluator parameter; AutoMLModelBase now evaluates models directly via internal helpers instead of delegating to external evaluator.
AiModelResult evaluation API
src/Models/Results/AiModelResult.Evaluation.cs
Added public EvaluateFull and GetDataSetStats with internal evaluation pipeline (prediction alignment, dataset/model stats, optional uncertainty support) for post-build evaluation.
Optimizers refactor
src/Optimizers/OptimizerBase.cs, src/Optimizers/GeneticAlgorithmOptimizer.cs, src/Optimizers/TabuSearchOptimizer.cs
Removed model evaluator fields/params from optimizers; replaced external evaluation calls with inline EvaluateModelDirectly and dataset-stat helpers; adjusted default genetic algorithm instantiation.
Genetics constructors & inline evaluation
src/Genetics/GeneticBase.cs, src/Genetics/StandardGeneticAlgorithm.cs, src/Genetics/AdaptiveGeneticAlgorithm.cs, src/Genetics/IslandModelGeneticAlgorithm.cs, src/Genetics/NonDominatedSortingGeneticAlgorithm.cs, src/Genetics/SteadyStateGeneticAlgorithm.cs
Removed IModelEvaluator constructor parameters across genetic algorithm classes; added private evaluation helpers in GeneticBase to compute dataset/model stats internally.
Regression & feature-selection changes
src/Regression/StepwiseRegression.cs
Removed _modelEvaluator field/param; replaced evaluator-based scoring with inline EvaluateModelDirectly during forward/backward selection and instance cloning.
Finance & options
src/Finance/AutoML/FinancialAutoML.cs, src/Models/Options/OptimizationAlgorithmOptions.cs
Removed modelEvaluator parameter from FinancialAutoML constructor and removed ModelEvaluator property from OptimizationAlgorithmOptions.
Tests updated
tests/AiDotNet.Tests/IntegrationTests/Evaluation/EvaluationIntegrationTests.cs, tests/AiDotNet.Tests/IntegrationTests/UncertaintyQuantificationFacadeTests.cs
Removed DefaultModelEvaluator constructor tests; updated tests to use AiModelResult.EvaluateFull and adjusted type-reflection lookups and assertions.
Misc playground API tweak
src/AiDotNet.Playground/Services/ExampleService.cs
Parameter rename usage updated for MaternKernel constructor call (length → lengthScale).

Sequence Diagram(s)

sequenceDiagram
    participant Builder as AiModelBuilder
    participant AutoML as AutoML (strategy)
    participant Model as AiModelResult
    participant Eval as AiModelResult.Evaluation

    Builder->>AutoML: Build() (train + produce AiModelResult)
    AutoML->>Model: return AiModelResult
    Model->>Eval: EvaluateFull(inputData)
    Eval-->>Model: ModelEvaluationData (Training/Validation/Test, ModelStats)
    Model-->>Builder: evaluation results available post-build
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

feature

Poem

🐇
I hopped through code with nimble paws,
Snipped the evaluator from its clause.
Now models bloom, then I report—
Post-build stats, no extra port.
A carrot song for cleanest laws.

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning MaternKernel parameter rename (length→lengthScale) in ExampleService.cs appears unrelated to the IModelEvaluator removal objectives and the unified evaluation framework requirements. Remove the MaternKernel parameter rename from this PR or explain its necessity. This change should be in a separate refactoring PR to maintain scope clarity.
Docstring Coverage ⚠️ Warning Docstring coverage is 34.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive PR addresses refactoring for Phase 1 unified evaluation (removing old evaluator pattern) but does not fully implement Phase 1 requirements (ModelEvaluator, EvaluationReport classes with specified signatures) or Phase 2 (LearningCurveAnalyzer). Clarify whether this PR is preparatory refactoring for #334 or if remaining Phase 1/2 implementation is pending. Document scope alignment with issue acceptance criteria.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title 'refactor: remove DefaultModelEvaluator and IModelEvaluator' clearly describes the main change: removing legacy evaluation interfaces in favor of a new facade pattern.
Description check ✅ Passed Description accurately summarizes the changeset: removal of legacy evaluator classes, addition of new evaluation methods in AiModelResult, removal of dependencies across multiple modules, and test updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/remove-default-model-evaluator

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request removes the legacy DefaultModelEvaluator and IModelEvaluator interfaces in favor of a new facade pattern through AiModelResult. The refactoring eliminates dependency injection of model evaluators across the codebase and replaces them with inline evaluation methods.

Changes:

  • Deleted IModelEvaluator interface and DefaultModelEvaluator implementation
  • Added new AiModelResult.Evaluation.cs partial class with EvaluateFull() and GetDataSetStats() facade methods
  • Replaced model evaluator dependencies with inline evaluation logic in OptimizerBase, GeneticBase, AutoMLModelBase, and StepwiseRegression
  • Removed ConfigureModelEvaluator() from AiModelBuilder and SetModelEvaluator() from AutoML interfaces
  • Removed automatic cross-validation execution during Build() in favor of manual invocation
  • Updated test code to use the new EvaluateFull() facade pattern

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/Interfaces/IModelEvaluator.cs Deleted legacy model evaluator interface
src/Evaluation/DefaultModelEvaluator.cs Deleted default implementation with 649 lines of evaluation logic
src/Models/Results/AiModelResult.Evaluation.cs New 466-line partial class providing evaluation facade with comprehensive multi-class support
src/Optimizers/OptimizerBase.cs Added inline evaluation methods (153 lines) to replace evaluator dependency
src/Genetics/GeneticBase.cs Added inline evaluation methods (118 lines) to replace evaluator dependency
src/AutoML/AutoMLModelBase.cs Added inline evaluation methods (279 lines) to replace evaluator dependency
src/Regression/StepwiseRegression.cs Added inline evaluation method (63 lines) and removed evaluator parameter
src/Models/Options/OptimizationAlgorithmOptions.cs Removed ModelEvaluator property and initialization
src/Interfaces/IAiModelBuilder.cs Removed ConfigureModelEvaluator method and updated documentation
src/Interfaces/IAutoMLModel.cs Removed SetModelEvaluator method
src/AiModelBuilder.cs Removed evaluator field, ConfigureModelEvaluator method, and automatic cross-validation execution
src/Finance/AutoML/FinancialAutoML.cs Removed modelEvaluator constructor parameter
src/AutoML/*.cs Removed modelEvaluator parameters from all AutoML class constructors
src/Genetics/*.cs Removed modelEvaluator parameters from all genetic algorithm constructors
src/Optimizers/*.cs Removed modelEvaluator parameters from optimizer constructors
tests/AiDotNet.Tests/IntegrationTests/UncertaintyQuantificationFacadeTests.cs Updated to use new EvaluateFull facade
tests/AiDotNet.Tests/IntegrationTests/Evaluation/EvaluationIntegrationTests.cs Removed DefaultModelEvaluator constructor tests and updated reflection code

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Genetics/GeneticBase.cs
Comment thread src/Genetics/GeneticBase.cs
Comment thread src/Regression/StepwiseRegression.cs
Comment thread src/Models/Results/AiModelResult.Evaluation.cs
Comment thread src/AutoML/AutoMLModelBase.cs
Comment thread src/Optimizers/OptimizerBase.cs
Comment thread src/Optimizers/OptimizerBase.cs
Comment thread src/Genetics/GeneticBase.cs
Comment thread src/AiModelBuilder.cs
Comment thread src/AutoML/AutoMLModelBase.cs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/Genetics/NonDominatedSortingGeneticAlgorithm.cs (1)

11-21: ⚠️ Potential issue | 🟡 Minor

Validate objectives before indexing in the base initializer.

objectives[0] is evaluated before the null/Count check, so null or empty inputs throw before your intended validation error.

🛠️ Suggested fix
 public class NSGAII<T, TInput, TOutput> :
     StandardGeneticAlgorithm<T, TInput, TOutput>
 {
@@
     private readonly List<IFitnessCalculator<T, TInput, TOutput>> _objectives;
 
+    private static IFitnessCalculator<T, TInput, TOutput> GetPrimaryObjective(
+        List<IFitnessCalculator<T, TInput, TOutput>> objectives)
+    {
+        if (objectives == null || objectives.Count < 2)
+        {
+            throw new ArgumentException("NSGA-II requires at least two objectives", nameof(objectives));
+        }
+
+        return objectives[0];
+    }
+
     public NSGAII(
         Func<IFullModel<T, TInput, TOutput>> modelFactory,
         List<IFitnessCalculator<T, TInput, TOutput>> objectives)
-        : base(modelFactory, objectives[0])
+        : base(modelFactory, GetPrimaryObjective(objectives))
     {
-        if (objectives == null || objectives.Count < 2)
-        {
-            throw new ArgumentException("NSGA-II requires at least two objectives", nameof(objectives));
-        }
-
         _objectives = objectives;
     }
src/Optimizers/OptimizerBase.cs (1)

344-359: ⚠️ Potential issue | 🟠 Major

Cache key still ignores selected features → wrong cache hits.
Applying feature selection earlier doesn’t help if GenerateCacheKey only hashes parameters; different feature subsets can collide and reuse incorrect step data.

✅ Suggested fix: include selected features in the cache key
-        string cacheKey = GenerateCacheKey(solution, inputData);
+        string cacheKey = GenerateCacheKey(solution, inputData, selectedFeaturesIndices);
-protected virtual string GenerateCacheKey(IFullModel<T, TInput, TOutput> solution, OptimizationInputData<T, TInput, TOutput> inputData)
+protected virtual string GenerateCacheKey(
+    IFullModel<T, TInput, TOutput> solution,
+    OptimizationInputData<T, TInput, TOutput> inputData,
+    IReadOnlyCollection<int>? selectedFeatures = null)
 {
     // Generate a simple cache key based on parameter values
     var parameters = solution.GetParameters();
     var paramHash = parameters.GetHashCode();
-    return $"{solution.GetType().Name}_{paramHash}";
+    var featuresHash = selectedFeatures is null
+        ? 0
+        : HashCode.Combine(selectedFeatures.Count, string.Join(",", selectedFeatures));
+    return $"{solution.GetType().Name}_{paramHash}_{featuresHash}";
 }

Also applies to: 730-736

🤖 Fix all issues with AI agents
In `@src/AiModelBuilder.cs`:
- Around line 1794-1796: The code currently sets cvResults to null and never
uses _crossValidator so ConfigureCrossValidation() is a no-op; fix by checking
if _crossValidator is configured and either (A) execute it to populate cvResults
(e.g., if (_crossValidator != null) cvResults = await
_crossValidator.RunCrossValidationAsync<T, TInput, TOutput>(...) or call the
CrossValidationEngine entry point with the same inputs used elsewhere), or (B)
if you prefer deferred evaluation, pass the configured _crossValidator instance
into the AiModelResult (set AiModelResult.CrossValidationResult or a new
CrossValidator property) so downstream evaluation can run it; update the
AiModelResult construction site to accept and store the validator or the
computed CrossValidationResult<T,TInput,TOutput> accordingly so
ConfigureCrossValidation() is no longer ignored.

In `@src/Optimizers/OptimizerBase.cs`:
- Around line 441-566: TryGetAlignedVectorsForOptimizer currently only converts
outputs to Vector<T>, losing multiclass metrics when predicted/actual are
matrices/tensors; update TryGetAlignedVectorsForOptimizer to detect
matrix/tensor outputs (using ConversionsHelper.ConvertToMatrix / ConvertToTensor
or equivalent) when PredictionType indicates multiclass, compute argmax across
the class dimension to produce label vectors for both actual and predicted, then
convert those argmax indices to Vector<T> so lengths align; keep the existing
ConvertToVector path and exception handling as a fallback so non-multiclass
cases still work and return false on any conversion mismatch.
🧹 Nitpick comments (1)
src/Optimizers/TabuSearchOptimizer.cs (1)

52-63: Missing XML documentation for fitnessCalculator parameter.

The constructor parameter fitnessCalculator on line 62 lacks a corresponding <param> XML documentation entry. All other parameters have documentation.

📝 Proposed fix to add missing documentation
 /// <param name="model">The model to be optimized.</param>
 /// <param name="options">Options specific to the Tabu Search algorithm.</param>
 /// <param name="geneticAlgorithm">The genetic algorithm to use for mutations. If null, a StandardGeneticAlgorithm will be used.</param>
+/// <param name="fitnessCalculator">The fitness calculator to use for evaluating solutions. If null, a MeanSquaredErrorFitnessCalculator will be used.</param>
 /// <param name="engine">The computation engine (CPU or GPU) for vectorized operations.</param>

Comment thread src/AiModelBuilder.cs
Comment thread src/Optimizers/OptimizerBase.cs

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

The matern-kernel playground example used 'length' but the constructor
parameter is named 'lengthScale', causing compilation test failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Feb 6, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.1% Coverage on New Code (required ≥ 80%)
26.2% Duplication on New Code (required ≤ 3%)
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@ooples
ooples merged commit 76223c9 into master Feb 6, 2026
41 of 42 checks passed
@ooples
ooples deleted the refactor/remove-default-model-evaluator branch February 6, 2026 19:34

This branch was successfully deployed

1 active deployment
Preview — aee867d5 Deployed Feb 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Feature work item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Gap Analysis] Implement Unified Model Evaluation Framework and Learning Curves

4 participants