0.7, // Initial threshold 'z_score_threshold' => 3.0, 'iqr_multiplier' => 1.5, ], createdAt: Timestamp::now() ); $registry->register($metadata); echo " ✓ Model registered: {$modelName} v{$version->toString()}\n"; echo " ✓ Initial threshold: 0.7\n\n"; // ======================================================================== // Setup: Simulate 150 predictions with varying confidence scores // ======================================================================== echo "3. Simulating 150 historical predictions...\n"; $timestamp = Timestamp::now(); // Simulate predictions with various confidence scores and ground truth $simulatedPredictions = [ // True Positives (high confidence, correctly classified) ...array_fill(0, 40, ['confidence' => 0.85, 'actual' => true]), ...array_fill(0, 20, ['confidence' => 0.75, 'actual' => true]), // True Negatives (low confidence, correctly classified) ...array_fill(0, 40, ['confidence' => 0.15, 'actual' => false]), ...array_fill(0, 20, ['confidence' => 0.25, 'actual' => false]), // False Positives (moderate-high confidence, incorrectly classified) ...array_fill(0, 15, ['confidence' => 0.72, 'actual' => false]), // False Negatives (moderate-low confidence, incorrectly classified) ...array_fill(0, 15, ['confidence' => 0.65, 'actual' => true]), ]; // Store predictions in performance storage foreach ($simulatedPredictions as $pred) { $prediction = $pred['confidence'] >= 0.7; // Using current threshold $storage->storePrediction([ 'model_name' => $modelName, 'version' => $version->toString(), 'prediction' => $prediction, 'actual' => $pred['actual'], 'confidence' => $pred['confidence'], 'features' => [], 'timestamp' => $timestamp->toDateTime(), 'is_correct' => $prediction === $pred['actual'], ]); } echo " ✓ Stored 150 predictions\n"; echo " ✓ Distribution:\n"; echo " - 60 anomalies (true positives)\n"; echo " - 60 normal behaviors (true negatives)\n"; echo " - 15 false positives (FP)\n"; echo " - 15 false negatives (FN)\n\n"; // ======================================================================== // Test 1: Current Performance Baseline // ======================================================================== echo "4. Evaluating current performance (threshold = 0.7)...\n"; $currentMetrics = $performanceMonitor->getCurrentMetrics($modelName, $version); echo " → Current Metrics:\n"; echo " Accuracy: " . sprintf("%.2f%%", $currentMetrics['accuracy'] * 100) . "\n"; echo " Precision: " . sprintf("%.2f%%", $currentMetrics['precision'] * 100) . "\n"; echo " Recall: " . sprintf("%.2f%%", $currentMetrics['recall'] * 100) . "\n"; echo " F1-Score: " . sprintf("%.2f%%", $currentMetrics['f1_score'] * 100) . "\n"; echo " Total predictions: {$currentMetrics['total_predictions']}\n\n"; // ======================================================================== // Test 2: Threshold Optimization (Grid Search) // ======================================================================== echo "5. Running threshold optimization (grid search)...\n"; $optimizationResult = $autoTuning->optimizeThreshold( modelName: $modelName, version: $version, metricToOptimize: 'f1_score', thresholdRange: [0.5, 0.9], step: 0.05 ); echo " → Optimization Results:\n"; echo " Current threshold: {$optimizationResult['current_threshold']}\n"; echo " Current F1-score: " . sprintf("%.2f%%", $optimizationResult['current_metric_value'] * 100) . "\n"; echo " Optimal threshold: {$optimizationResult['optimal_threshold']}\n"; echo " Optimal F1-score: " . sprintf("%.2f%%", $optimizationResult['optimal_metric_value'] * 100) . "\n"; echo " Improvement: " . sprintf("%.1f%%", $optimizationResult['improvement_percent']) . "\n"; echo " → Recommendation:\n"; echo " {$optimizationResult['recommendation']}\n\n"; // ======================================================================== // Test 3: Adaptive Threshold Adjustment // ======================================================================== echo "6. Testing adaptive threshold adjustment...\n"; $adaptiveResult = $autoTuning->adaptiveThresholdAdjustment( modelName: $modelName, version: $version ); echo " → Adaptive Adjustment:\n"; echo " Current threshold: {$adaptiveResult['current_threshold']}\n"; echo " Recommended threshold: {$adaptiveResult['recommended_threshold']}\n"; echo " False Positive Rate: " . sprintf("%.1f%%", $adaptiveResult['current_fp_rate'] * 100) . "\n"; echo " False Negative Rate: " . sprintf("%.1f%%", $adaptiveResult['current_fn_rate'] * 100) . "\n"; echo " → Reasoning:\n"; echo " {$adaptiveResult['adjustment_reason']}\n"; echo " → Expected Improvements:\n"; echo " Accuracy: " . sprintf("%+.2f%%", $adaptiveResult['expected_improvement']['accuracy'] * 100) . "\n"; echo " Precision: " . sprintf("%+.2f%%", $adaptiveResult['expected_improvement']['precision'] * 100) . "\n"; echo " Recall: " . sprintf("%+.2f%%", $adaptiveResult['expected_improvement']['recall'] * 100) . "\n\n"; // ======================================================================== // Test 4: Precision-Recall Trade-off Optimization // ======================================================================== echo "7. Optimizing precision-recall trade-off...\n"; echo " → Target: 95% precision with maximum recall\n"; $tradeoffResult = $autoTuning->optimizePrecisionRecallTradeoff( modelName: $modelName, version: $version, targetPrecision: 0.95, thresholdRange: [0.5, 0.99] ); echo " → Trade-off Results:\n"; echo " Optimal threshold: {$tradeoffResult['optimal_threshold']}\n"; echo " Achieved precision: " . sprintf("%.2f%%", $tradeoffResult['achieved_precision'] * 100) . "\n"; echo " Achieved recall: " . sprintf("%.2f%%", $tradeoffResult['achieved_recall'] * 100) . "\n"; echo " F1-Score: " . sprintf("%.2f%%", $tradeoffResult['f1_score'] * 100) . "\n\n"; // ======================================================================== // Test 5: Model Configuration Update Workflow // ======================================================================== echo "8. Demonstrating configuration update workflow...\n"; // Get optimal threshold from grid search $newThreshold = $optimizationResult['optimal_threshold']; echo " → Updating model configuration with optimal threshold...\n"; echo " Old threshold: {$metadata->configuration['threshold']}\n"; echo " New threshold: {$newThreshold}\n"; // Update metadata with new configuration $updatedMetadata = $metadata->withConfiguration([ 'threshold' => $newThreshold, 'tuning_timestamp' => (string) Timestamp::now(), 'tuning_method' => 'grid_search', 'optimization_metric' => 'f1_score', ]); $registry->update($updatedMetadata); echo " ✓ Configuration updated successfully\n"; echo " ✓ Registry updated with new threshold\n\n"; // ======================================================================== // Test Summary // ======================================================================== echo "=== Test Summary ===\n"; echo "✓ Threshold Optimization (Grid Search): Working\n"; echo "✓ Adaptive Threshold Adjustment: Working\n"; echo "✓ Precision-Recall Trade-off: Working\n"; echo "✓ Configuration Update Workflow: Working\n\n"; echo "Key Findings:\n"; echo " - Current threshold (0.7): F1-score = " . sprintf("%.2f%%", $optimizationResult['current_metric_value'] * 100) . "\n"; echo " - Optimal threshold ({$optimizationResult['optimal_threshold']}): F1-score = " . sprintf("%.2f%%", $optimizationResult['optimal_metric_value'] * 100) . "\n"; echo " - Performance gain: " . sprintf("%.1f%%", $optimizationResult['improvement_percent']) . "\n"; echo " - Adaptive recommendation: {$adaptiveResult['adjustment_reason']}\n"; echo " - High precision threshold (95%): {$tradeoffResult['optimal_threshold']} with recall = " . sprintf("%.2f%%", $tradeoffResult['achieved_recall'] * 100) . "\n\n"; echo "=== AutoTuning Workflows PASSED ===\n"; } catch (\Throwable $e) { echo "\n!!! TEST FAILED !!!\n"; echo "Error: " . $e->getMessage() . "\n"; echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n"; echo "\nStack trace:\n" . $e->getTraceAsString() . "\n"; exit(1); }