1#![allow(dead_code)]
10
11use super::types::*;
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct EnhancedLayerGradientAnalysis {
18 pub layer_details: HashMap<String, LayerGradientDetails>,
19 pub network_level_analysis: NetworkLevelAnalysis,
20 pub gradient_hierarchy: GradientHierarchy,
21 pub optimization_priorities: Vec<OptimizationPriority>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct LayerGradientDetails {
27 pub layer_name: String,
28 pub gradient_statistics: GradientStatistics,
29 pub flow_characteristics: FlowCharacteristics,
30 pub health_metrics: LayerHealthMetrics,
31 pub optimization_suggestions: Vec<LayerOptimizationSuggestion>,
32 pub comparative_analysis: ComparativeAnalysis,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct NetworkLevelAnalysis {
38 pub overall_gradient_health: LayerHealth,
39 pub gradient_distribution: GradientDistribution,
40 pub layer_interactions: Vec<LayerInteraction>,
41 pub convergence_indicators: ConvergenceIndicators,
42 pub training_dynamics: TrainingDynamics,
43 pub stability_assessment: StabilityAssessment,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct GradientDistribution {
49 pub mean_gradient_norm: f64,
50 pub gradient_variance: f64,
51 pub gradient_skewness: f64,
52 pub gradient_kurtosis: f64,
53 pub layer_gradient_ratios: HashMap<String, f64>,
54 pub distribution_type: DistributionType,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub enum DistributionType {
59 Normal,
60 Skewed,
61 HeavyTailed,
62 Multimodal,
63 Degenerate,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct LayerInteraction {
69 pub layer1: String,
70 pub layer2: String,
71 pub interaction_strength: f64,
72 pub interaction_type: InteractionType,
73 pub impact_score: f64,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub enum InteractionType {
78 Cooperative,
79 Competitive,
80 Neutral,
81 Disruptive,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct ConvergenceIndicators {
87 pub gradient_convergence_score: f64,
88 pub parameter_convergence_score: f64,
89 pub loss_convergence_score: f64,
90 pub convergence_trend: ConvergenceTrend,
91 pub estimated_steps_to_convergence: Option<usize>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub enum ConvergenceTrend {
96 Converging,
97 Stable,
98 Diverging,
99 Oscillating,
100 Unknown,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct TrainingDynamics {
106 pub learning_phase: LearningPhase,
107 pub gradient_momentum: f64,
108 pub learning_velocity: f64,
109 pub adaptation_rate: f64,
110 pub plateau_detection: PlateauDetection,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
114pub enum LearningPhase {
115 InitialLearning,
116 RapidLearning,
117 Refinement,
118 Convergence,
119 Plateau,
120 Overfitting,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct PlateauDetection {
126 pub is_plateau: bool,
127 pub plateau_duration: usize,
128 pub plateau_severity: PlateauSeverity,
129 pub suggested_actions: Vec<String>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub enum PlateauSeverity {
134 Mild,
135 Moderate,
136 Severe,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct StabilityAssessment {
142 pub overall_stability: f64,
143 pub stability_trend: StabilityTrend,
144 pub instability_sources: Vec<InstabilitySource>,
145 pub stability_forecast: StabilityForecast,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub enum StabilityTrend {
150 Improving,
151 Stable,
152 Degrading,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct InstabilitySource {
158 pub source_type: InstabilityType,
159 pub affected_layers: Vec<String>,
160 pub severity: f64,
161 pub description: String,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub enum InstabilityType {
166 GradientExplosion,
167 GradientVanishing,
168 Oscillation,
169 Stagnation,
170 Chaos,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct StabilityForecast {
176 pub short_term_outlook: StabilityOutlook,
177 pub long_term_outlook: StabilityOutlook,
178 pub confidence_level: f64,
179 pub recommended_monitoring: Vec<String>,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub enum StabilityOutlook {
184 Stable,
185 Improving,
186 Deteriorating,
187 Uncertain,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct GradientHierarchy {
193 pub layer_groups: Vec<LayerGroup>,
194 pub hierarchy_levels: Vec<HierarchyLevel>,
195 pub cross_level_interactions: Vec<CrossLevelInteraction>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct LayerGroup {
201 pub group_name: String,
202 pub layers: Vec<String>,
203 pub group_characteristics: GroupCharacteristics,
204 pub internal_coherence: f64,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct GroupCharacteristics {
210 pub average_gradient_norm: f64,
211 pub gradient_synchronization: f64,
212 pub learning_rate_sensitivity: f64,
213 pub optimization_difficulty: OptimizationDifficulty,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub enum OptimizationDifficulty {
218 Easy,
219 Moderate,
220 Difficult,
221 VeryDifficult,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct HierarchyLevel {
227 pub level_id: usize,
228 pub level_name: String,
229 pub layer_groups: Vec<String>,
230 pub level_importance: f64,
231 pub optimization_impact: f64,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct CrossLevelInteraction {
237 pub from_level: usize,
238 pub to_level: usize,
239 pub interaction_strength: f64,
240 pub interaction_direction: InteractionDirection,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
244pub enum InteractionDirection {
245 TopDown,
246 BottomUp,
247 Bidirectional,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct OptimizationPriority {
253 pub target_name: String,
254 pub target_type: OptimizationTarget,
255 pub priority_score: f64,
256 pub urgency_level: UrgencyLevel,
257 pub optimization_potential: f64,
258 pub recommended_actions: Vec<PrioritizedAction>,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
262pub enum OptimizationTarget {
263 IndividualLayer,
264 LayerGroup,
265 NetworkLevel,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
269pub enum UrgencyLevel {
270 Low,
271 Medium,
272 High,
273 Critical,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct PrioritizedAction {
279 pub action_name: String,
280 pub action_type: ActionType,
281 pub expected_impact: f64,
282 pub implementation_effort: ImplementationEffort,
283 pub prerequisites: Vec<String>,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub enum ActionType {
288 ParameterAdjustment,
289 ArchitecturalChange,
290 OptimizationTechnique,
291 RegularizationMethod,
292 LearningRateScheduling,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
296pub enum ImplementationEffort {
297 Minimal,
298 Low,
299 Moderate,
300 High,
301 Extensive,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct LayerOptimizationSuggestion {
307 pub suggestion_type: SuggestionType,
308 pub description: String,
309 pub rationale: String,
310 pub expected_improvement: f64,
311 pub implementation_complexity: ImplementationComplexity,
312 pub side_effects: Vec<String>,
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize)]
316pub enum SuggestionType {
317 WeightInitialization,
318 LearningRateAdjustment,
319 RegularizationAdd,
320 ArchitecturalModification,
321 OptimizationAlgorithm,
322 BatchNormalization,
323 DropoutAdjustment,
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub enum ImplementationComplexity {
328 Simple,
329 Moderate,
330 Complex,
331 RequiresRetraining,
332}
333
334#[derive(Debug)]
336pub struct EnhancedGradientAnalyzer {
337 analysis_depth: AnalysisDepth,
338 convergence_window: usize,
339 stability_threshold: f64,
340}
341
342#[derive(Debug, Clone)]
343pub enum AnalysisDepth {
344 Basic,
345 Standard,
346 Comprehensive,
347 Expert,
348}
349
350impl Default for EnhancedGradientAnalyzer {
351 fn default() -> Self {
352 Self {
353 analysis_depth: AnalysisDepth::Standard,
354 convergence_window: 100,
355 stability_threshold: 0.8,
356 }
357 }
358}
359
360impl EnhancedGradientAnalyzer {
361 pub fn new(depth: AnalysisDepth, window: usize, threshold: f64) -> Self {
362 Self {
363 analysis_depth: depth,
364 convergence_window: window,
365 stability_threshold: threshold,
366 }
367 }
368
369 pub fn generate_enhanced_analysis(
370 &self,
371 gradient_histories: &HashMap<String, GradientHistory>,
372 ) -> EnhancedLayerGradientAnalysis {
373 let layer_details = self.generate_layer_details(gradient_histories);
374 let network_level_analysis = self.analyze_network_level_gradients(&layer_details);
375 let gradient_hierarchy = self.build_gradient_hierarchy(&layer_details);
376 let optimization_priorities =
377 self.rank_optimization_priorities(&layer_details, &network_level_analysis);
378
379 EnhancedLayerGradientAnalysis {
380 layer_details,
381 network_level_analysis,
382 gradient_hierarchy,
383 optimization_priorities,
384 }
385 }
386
387 fn generate_layer_details(
388 &self,
389 gradient_histories: &HashMap<String, GradientHistory>,
390 ) -> HashMap<String, LayerGradientDetails> {
391 let mut layer_details = HashMap::new();
392
393 for (layer_name, history) in gradient_histories {
394 let gradient_statistics = self.compute_detailed_gradient_stats(history);
395 let flow_characteristics = self.analyze_flow_characteristics(history);
396 let health_metrics = self.compute_layer_health_metrics(history);
397 let optimization_suggestions =
398 self.generate_layer_optimization_suggestions(layer_name, history);
399 let comparative_analysis =
400 self.compare_with_other_layers(layer_name, history, gradient_histories);
401
402 let analysis = LayerGradientDetails {
403 layer_name: layer_name.clone(),
404 gradient_statistics,
405 flow_characteristics,
406 health_metrics,
407 optimization_suggestions,
408 comparative_analysis,
409 };
410
411 layer_details.insert(layer_name.clone(), analysis);
412 }
413
414 layer_details
415 }
416
417 fn compute_detailed_gradient_stats(&self, history: &GradientHistory) -> GradientStatistics {
418 if history.gradient_norms.is_empty() {
419 return GradientStatistics {
420 mean: 0.0,
421 std: 0.0,
422 median: 0.0,
423 percentile_95: 0.0,
424 percentile_5: 0.0,
425 samples: 0,
426 variance: 0.0,
427 skewness: 0.0,
428 kurtosis: 0.0,
429 };
430 }
431
432 let values: Vec<f64> = history.gradient_norms.iter().cloned().collect();
433 let n = values.len() as f64;
434 let mean = values.iter().sum::<f64>() / n;
435 let variance = values.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / n;
436 let std = variance.sqrt();
437
438 let mut sorted_values = values.clone();
439 sorted_values.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
440
441 let median_idx = values.len() / 2;
442 let median = if values.len().is_multiple_of(2) {
443 (sorted_values[median_idx - 1] + sorted_values[median_idx]) / 2.0
444 } else {
445 sorted_values[median_idx]
446 };
447
448 let percentile_5_idx = (values.len() as f64 * 0.05) as usize;
449 let percentile_95_idx = (values.len() as f64 * 0.95) as usize;
450 let percentile_5 = sorted_values[percentile_5_idx];
451 let percentile_95 = sorted_values[percentile_95_idx.min(sorted_values.len() - 1)];
452
453 let skewness = if std > 0.0 {
455 values.iter().map(|&x| ((x - mean) / std).powi(3)).sum::<f64>() / n
456 } else {
457 0.0
458 };
459
460 let kurtosis = if std > 0.0 {
461 values.iter().map(|&x| ((x - mean) / std).powi(4)).sum::<f64>() / n - 3.0
462 } else {
463 0.0
464 };
465
466 GradientStatistics {
467 mean,
468 std,
469 median,
470 percentile_95,
471 percentile_5,
472 samples: values.len(),
473 variance,
474 skewness,
475 kurtosis,
476 }
477 }
478
479 fn analyze_flow_characteristics(&self, history: &GradientHistory) -> FlowCharacteristics {
480 let consistency_score = self.compute_flow_consistency(history);
481 let smoothness_index = self.compute_smoothness_index(history);
482 let trend_strength = self.compute_trend_strength(history);
483 let oscillation_frequency = self.compute_oscillation_frequency(history);
484 let stability_measure = self.compute_stability_measure(history);
485
486 FlowCharacteristics {
487 consistency_score,
488 smoothness_index,
489 trend_strength,
490 oscillation_frequency,
491 stability_measure,
492 }
493 }
494
495 fn compute_flow_consistency(&self, history: &GradientHistory) -> f64 {
496 if history.gradient_norms.len() < 2 {
497 return 1.0;
498 }
499
500 let variations: Vec<f64> = history
501 .gradient_norms
502 .iter()
503 .collect::<Vec<&f64>>()
504 .windows(2)
505 .map(|pair| (*pair[1] - *pair[0]).abs() / (*pair[0] + 1e-8))
506 .collect();
507
508 let avg_variation = variations.iter().sum::<f64>() / variations.len() as f64;
509 (1.0_f64 / (1.0 + avg_variation)).min(1.0)
510 }
511
512 fn compute_smoothness_index(&self, history: &GradientHistory) -> f64 {
513 if history.gradient_norms.len() < 3 {
514 return 1.0;
515 }
516
517 let second_derivatives: Vec<f64> = history
519 .gradient_norms
520 .iter()
521 .collect::<Vec<&f64>>()
522 .windows(3)
523 .map(|window| *window[2] - 2.0 * *window[1] + *window[0])
524 .collect();
525
526 let avg_second_derivative = second_derivatives.iter().map(|&x| x.abs()).sum::<f64>()
527 / second_derivatives.len() as f64;
528 (1.0_f64 / (1.0 + avg_second_derivative)).min(1.0)
529 }
530
531 fn compute_trend_strength(&self, history: &GradientHistory) -> f64 {
532 history.get_trend_slope().map(|slope| slope.abs().min(1.0)).unwrap_or(0.0)
533 }
534
535 fn compute_oscillation_frequency(&self, history: &GradientHistory) -> f64 {
536 if history.gradient_norms.len() < 4 {
537 return 0.0;
538 }
539
540 let sign_changes = history
541 .gradient_norms
542 .iter()
543 .collect::<Vec<&f64>>()
544 .windows(2)
545 .map(|pair| *pair[1] - *pair[0])
546 .collect::<Vec<f64>>()
547 .windows(2)
548 .filter(|pair| pair[0] * pair[1] < 0.0)
549 .count();
550
551 sign_changes as f64 / history.gradient_norms.len() as f64
552 }
553
554 fn compute_stability_measure(&self, history: &GradientHistory) -> f64 {
555 if history.gradient_norms.is_empty() {
556 return 0.0;
557 }
558
559 let mean = history.gradient_norms.iter().sum::<f64>() / history.gradient_norms.len() as f64;
560 let variance = history.gradient_norms.iter().map(|&x| (x - mean).powi(2)).sum::<f64>()
561 / history.gradient_norms.len() as f64;
562
563 if mean == 0.0 {
564 return 0.0;
565 }
566
567 let coefficient_of_variation = variance.sqrt() / mean;
568 (1.0 / (1.0 + coefficient_of_variation)).min(1.0)
569 }
570
571 fn compute_layer_health_metrics(&self, history: &GradientHistory) -> LayerHealthMetrics {
572 let gradient_statistics = self.compute_detailed_gradient_stats(history);
573 let flow_characteristics = self.analyze_flow_characteristics(history);
574
575 let gradient_stability = flow_characteristics.stability_measure;
576 let information_flow_rate = self.compute_information_flow_rate(history);
577 let neuron_activity_ratio = self.estimate_neuron_activity_ratio(history);
578 let convergence_indicator = self.compute_convergence_indicator(history);
579
580 let mut risk_factors = Vec::new();
581 if gradient_statistics.mean < 1e-5 {
582 risk_factors.push("Very low gradient magnitude".to_string());
583 }
584 if gradient_statistics.mean > 100.0 {
585 risk_factors.push("Very high gradient magnitude".to_string());
586 }
587 if gradient_stability < 0.5 {
588 risk_factors.push("High gradient instability".to_string());
589 }
590 if flow_characteristics.oscillation_frequency > 0.5 {
591 risk_factors.push("High oscillation frequency".to_string());
592 }
593
594 let overall_health = if !risk_factors.is_empty() {
595 if risk_factors.len() > 2 {
596 LayerHealth::Critical
597 } else {
598 LayerHealth::Warning
599 }
600 } else {
601 LayerHealth::Healthy
602 };
603
604 LayerHealthMetrics {
605 overall_health,
606 gradient_stability,
607 information_flow_rate,
608 neuron_activity_ratio,
609 convergence_indicator,
610 risk_factors,
611 }
612 }
613
614 fn compute_information_flow_rate(&self, history: &GradientHistory) -> f64 {
615 if history.gradient_norms.len() < 2 {
616 return 0.0;
617 }
618
619 let total_change: f64 = history
620 .gradient_norms
621 .iter()
622 .collect::<Vec<&f64>>()
623 .windows(2)
624 .map(|pair| (*pair[1] - *pair[0]).abs())
625 .sum();
626
627 total_change / history.gradient_norms.len() as f64
628 }
629
630 fn estimate_neuron_activity_ratio(&self, history: &GradientHistory) -> f64 {
631 let mean_gradient =
633 history.gradient_norms.iter().sum::<f64>() / history.gradient_norms.len() as f64;
634 (mean_gradient / (mean_gradient + 1e-5)).min(1.0)
635 }
636
637 fn compute_convergence_indicator(&self, history: &GradientHistory) -> f64 {
638 if history.gradient_norms.len() < self.convergence_window {
639 return 0.5; }
641
642 let recent: Vec<f64> = history
643 .gradient_norms
644 .iter()
645 .rev()
646 .take(self.convergence_window)
647 .cloned()
648 .collect();
649 let trend_slope = self.compute_trend_for_values(&recent);
650
651 if trend_slope < 0.0 {
653 (-trend_slope).min(1.0)
654 } else {
655 0.0
656 }
657 }
658
659 fn compute_trend_for_values(&self, values: &[f64]) -> f64 {
660 if values.len() < 3 {
661 return 0.0;
662 }
663
664 let n = values.len() as f64;
665 let sum_x: f64 = (0..values.len()).map(|i| i as f64).sum();
666 let sum_y: f64 = values.iter().sum();
667 let sum_xy: f64 = values.iter().enumerate().map(|(i, &y)| i as f64 * y).sum();
668 let sum_x2: f64 = (0..values.len()).map(|i| (i as f64).powi(2)).sum();
669
670 (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x.powi(2))
671 }
672
673 fn generate_layer_optimization_suggestions(
674 &self,
675 _layer_name: &str,
676 history: &GradientHistory,
677 ) -> Vec<LayerOptimizationSuggestion> {
678 let mut suggestions = Vec::new();
679 let stats = self.compute_detailed_gradient_stats(history);
680 let flow = self.analyze_flow_characteristics(history);
681
682 if stats.mean < 1e-5 {
684 suggestions.push(LayerOptimizationSuggestion {
685 suggestion_type: SuggestionType::WeightInitialization,
686 description: "Consider better weight initialization methods".to_string(),
687 rationale: "Very low gradients may indicate poor initialization".to_string(),
688 expected_improvement: 0.7,
689 implementation_complexity: ImplementationComplexity::Simple,
690 side_effects: vec!["May require retraining from scratch".to_string()],
691 });
692 }
693
694 if stats.mean > 10.0 {
696 suggestions.push(LayerOptimizationSuggestion {
697 suggestion_type: SuggestionType::LearningRateAdjustment,
698 description: "Reduce learning rate for this layer".to_string(),
699 rationale: "High gradients may indicate learning rate is too large".to_string(),
700 expected_improvement: 0.6,
701 implementation_complexity: ImplementationComplexity::Simple,
702 side_effects: vec!["May slow down convergence".to_string()],
703 });
704 }
705
706 if flow.oscillation_frequency > 0.5 {
708 suggestions.push(LayerOptimizationSuggestion {
709 suggestion_type: SuggestionType::RegularizationAdd,
710 description: "Add dropout or weight decay".to_string(),
711 rationale: "High oscillation may indicate overfitting or instability".to_string(),
712 expected_improvement: 0.5,
713 implementation_complexity: ImplementationComplexity::Moderate,
714 side_effects: vec!["May reduce model capacity".to_string()],
715 });
716 }
717
718 suggestions
719 }
720
721 fn compare_with_other_layers(
722 &self,
723 layer_name: &str,
724 history: &GradientHistory,
725 all_histories: &HashMap<String, GradientHistory>,
726 ) -> ComparativeAnalysis {
727 let current_stats = self.compute_detailed_gradient_stats(history);
728 let mut other_means = Vec::new();
729
730 for (other_name, other_history) in all_histories {
731 if other_name != layer_name {
732 let other_stats = self.compute_detailed_gradient_stats(other_history);
733 other_means.push(other_stats.mean);
734 }
735 }
736
737 if other_means.is_empty() {
738 return ComparativeAnalysis {
739 relative_performance: 1.0,
740 rank_among_layers: 1,
741 similar_layers: vec![],
742 performance_gap: 0.0,
743 optimization_potential: 0.5,
744 };
745 }
746
747 other_means.sort_by(|a, b| b.partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal));
748 let rank = other_means
749 .iter()
750 .position(|&x| x <= current_stats.mean)
751 .unwrap_or(other_means.len())
752 + 1;
753
754 let avg_other_mean = other_means.iter().sum::<f64>() / other_means.len() as f64;
755 let relative_performance =
756 if avg_other_mean > 0.0 { current_stats.mean / avg_other_mean } else { 1.0 };
757
758 let performance_gap = (current_stats.mean - avg_other_mean).abs();
759
760 let similar_layers: Vec<String> = all_histories
762 .iter()
763 .filter(|(other_name, other_history)| {
764 if *other_name == layer_name {
765 return false;
766 }
767 let other_stats = self.compute_detailed_gradient_stats(other_history);
768 let ratio = (current_stats.mean / (other_stats.mean + 1e-8))
769 .max(other_stats.mean / (current_stats.mean + 1e-8));
770 ratio <= 1.2
771 })
772 .map(|(name, _)| name.clone())
773 .collect();
774
775 let optimization_potential = if relative_performance < 0.5 {
776 0.8
777 } else if relative_performance < 0.8 {
778 0.6
779 } else {
780 0.3
781 };
782
783 ComparativeAnalysis {
784 relative_performance,
785 rank_among_layers: rank,
786 similar_layers,
787 performance_gap,
788 optimization_potential,
789 }
790 }
791
792 fn analyze_network_level_gradients(
793 &self,
794 layer_details: &HashMap<String, LayerGradientDetails>,
795 ) -> NetworkLevelAnalysis {
796 let overall_gradient_health = self.assess_overall_health(layer_details);
797 let gradient_distribution = self.analyze_gradient_distribution(layer_details);
798 let layer_interactions = self.analyze_layer_interactions(layer_details);
799 let convergence_indicators = self.analyze_convergence_indicators(layer_details);
800 let training_dynamics = self.analyze_training_dynamics(layer_details);
801 let stability_assessment = self.assess_network_stability(layer_details);
802
803 NetworkLevelAnalysis {
804 overall_gradient_health,
805 gradient_distribution,
806 layer_interactions,
807 convergence_indicators,
808 training_dynamics,
809 stability_assessment,
810 }
811 }
812
813 fn assess_overall_health(
814 &self,
815 layer_details: &HashMap<String, LayerGradientDetails>,
816 ) -> LayerHealth {
817 let health_counts = layer_details
818 .values()
819 .map(|details| &details.health_metrics.overall_health)
820 .fold([0, 0, 0], |mut acc, health| {
821 match health {
822 LayerHealth::Healthy => acc[0] += 1,
823 LayerHealth::Warning => acc[1] += 1,
824 LayerHealth::Critical => acc[2] += 1,
825 LayerHealth::Unknown => {}, }
827 acc
828 });
829
830 let total = health_counts.iter().sum::<usize>();
831 if total == 0 {
832 return LayerHealth::Healthy;
833 }
834
835 let critical_ratio = health_counts[2] as f64 / total as f64;
836 let warning_ratio = health_counts[1] as f64 / total as f64;
837
838 if critical_ratio > 0.3 {
839 LayerHealth::Critical
840 } else if critical_ratio > 0.1 || warning_ratio > 0.5 {
841 LayerHealth::Warning
842 } else {
843 LayerHealth::Healthy
844 }
845 }
846
847 fn analyze_gradient_distribution(
848 &self,
849 layer_details: &HashMap<String, LayerGradientDetails>,
850 ) -> GradientDistribution {
851 let gradient_means: Vec<f64> =
852 layer_details.values().map(|details| details.gradient_statistics.mean).collect();
853
854 if gradient_means.is_empty() {
855 return GradientDistribution {
856 mean_gradient_norm: 0.0,
857 gradient_variance: 0.0,
858 gradient_skewness: 0.0,
859 gradient_kurtosis: 0.0,
860 layer_gradient_ratios: HashMap::new(),
861 distribution_type: DistributionType::Degenerate,
862 };
863 }
864
865 let n = gradient_means.len() as f64;
866 let mean_gradient_norm = gradient_means.iter().sum::<f64>() / n;
867 let gradient_variance =
868 gradient_means.iter().map(|&x| (x - mean_gradient_norm).powi(2)).sum::<f64>() / n;
869
870 let std_dev = gradient_variance.sqrt();
871 let gradient_skewness = if std_dev > 0.0 {
872 gradient_means
873 .iter()
874 .map(|&x| ((x - mean_gradient_norm) / std_dev).powi(3))
875 .sum::<f64>()
876 / n
877 } else {
878 0.0
879 };
880
881 let gradient_kurtosis = if std_dev > 0.0 {
882 gradient_means
883 .iter()
884 .map(|&x| ((x - mean_gradient_norm) / std_dev).powi(4))
885 .sum::<f64>()
886 / n
887 - 3.0
888 } else {
889 0.0
890 };
891
892 let mut layer_gradient_ratios = HashMap::new();
893 for (layer_name, details) in layer_details {
894 let ratio = if mean_gradient_norm > 0.0 {
895 details.gradient_statistics.mean / mean_gradient_norm
896 } else {
897 1.0
898 };
899 layer_gradient_ratios.insert(layer_name.clone(), ratio);
900 }
901
902 let distribution_type =
903 self.classify_distribution_type(gradient_skewness, gradient_kurtosis);
904
905 GradientDistribution {
906 mean_gradient_norm,
907 gradient_variance,
908 gradient_skewness,
909 gradient_kurtosis,
910 layer_gradient_ratios,
911 distribution_type,
912 }
913 }
914
915 fn classify_distribution_type(&self, skewness: f64, kurtosis: f64) -> DistributionType {
916 if skewness.abs() > 2.0 {
917 DistributionType::Skewed
918 } else if kurtosis > 3.0 {
919 DistributionType::HeavyTailed
920 } else if kurtosis < -1.0 {
921 DistributionType::Multimodal
922 } else {
923 DistributionType::Normal
924 }
925 }
926
927 fn analyze_layer_interactions(
928 &self,
929 layer_details: &HashMap<String, LayerGradientDetails>,
930 ) -> Vec<LayerInteraction> {
931 let mut interactions = Vec::new();
932
933 let layer_names: Vec<String> = layer_details.keys().cloned().collect();
934 for i in 0..layer_names.len() {
935 for j in (i + 1)..layer_names.len() {
936 let layer1 = &layer_names[i];
937 let layer2 = &layer_names[j];
938
939 if let (Some(details1), Some(details2)) =
940 (layer_details.get(layer1), layer_details.get(layer2))
941 {
942 let interaction_strength =
943 self.compute_interaction_strength(details1, details2);
944 let interaction_type = self.classify_interaction_type(details1, details2);
945 let impact_score = interaction_strength * 0.5; interactions.push(LayerInteraction {
948 layer1: layer1.clone(),
949 layer2: layer2.clone(),
950 interaction_strength,
951 interaction_type,
952 impact_score,
953 });
954 }
955 }
956 }
957
958 interactions
959 }
960
961 fn compute_interaction_strength(
962 &self,
963 details1: &LayerGradientDetails,
964 details2: &LayerGradientDetails,
965 ) -> f64 {
966 let mean_diff =
967 (details1.gradient_statistics.mean - details2.gradient_statistics.mean).abs();
968 let stability_diff = (details1.flow_characteristics.stability_measure
969 - details2.flow_characteristics.stability_measure)
970 .abs();
971
972 let combined_diff = mean_diff + stability_diff;
974 1.0 / (1.0 + combined_diff)
975 }
976
977 fn classify_interaction_type(
978 &self,
979 details1: &LayerGradientDetails,
980 details2: &LayerGradientDetails,
981 ) -> InteractionType {
982 let convergence_diff = (details1.health_metrics.convergence_indicator
983 - details2.health_metrics.convergence_indicator)
984 .abs();
985
986 if convergence_diff < 0.1 {
987 InteractionType::Cooperative
988 } else if convergence_diff > 0.5 {
989 InteractionType::Competitive
990 } else {
991 InteractionType::Neutral
992 }
993 }
994
995 fn analyze_convergence_indicators(
996 &self,
997 layer_details: &HashMap<String, LayerGradientDetails>,
998 ) -> ConvergenceIndicators {
999 let convergence_scores: Vec<f64> = layer_details
1000 .values()
1001 .map(|details| details.health_metrics.convergence_indicator)
1002 .collect();
1003
1004 let gradient_convergence_score =
1005 convergence_scores.iter().sum::<f64>() / convergence_scores.len().max(1) as f64;
1006 let parameter_convergence_score = gradient_convergence_score * 0.8; let loss_convergence_score = gradient_convergence_score * 0.9; let convergence_trend = if gradient_convergence_score > 0.8 {
1010 ConvergenceTrend::Converging
1011 } else if gradient_convergence_score > 0.6 {
1012 ConvergenceTrend::Stable
1013 } else if gradient_convergence_score < 0.3 {
1014 ConvergenceTrend::Diverging
1015 } else {
1016 ConvergenceTrend::Unknown
1017 };
1018
1019 let estimated_steps_to_convergence = if gradient_convergence_score > 0.1 {
1020 Some(((1.0 - gradient_convergence_score) * 1000.0) as usize)
1021 } else {
1022 None
1023 };
1024
1025 ConvergenceIndicators {
1026 gradient_convergence_score,
1027 parameter_convergence_score,
1028 loss_convergence_score,
1029 convergence_trend,
1030 estimated_steps_to_convergence,
1031 }
1032 }
1033
1034 fn analyze_training_dynamics(
1035 &self,
1036 layer_details: &HashMap<String, LayerGradientDetails>,
1037 ) -> TrainingDynamics {
1038 let avg_convergence = layer_details
1039 .values()
1040 .map(|details| details.health_metrics.convergence_indicator)
1041 .sum::<f64>()
1042 / layer_details.len().max(1) as f64;
1043
1044 let learning_phase = match avg_convergence {
1045 x if x < 0.2 => LearningPhase::InitialLearning,
1046 x if x < 0.4 => LearningPhase::RapidLearning,
1047 x if x < 0.6 => LearningPhase::Refinement,
1048 x if x < 0.8 => LearningPhase::Convergence,
1049 _ => LearningPhase::Plateau,
1050 };
1051
1052 let gradient_momentum = avg_convergence * 0.8; let learning_velocity = avg_convergence * 1.2; let adaptation_rate = 1.0 - avg_convergence; let plateau_detection = PlateauDetection {
1057 is_plateau: avg_convergence > 0.9,
1058 plateau_duration: if avg_convergence > 0.9 { 10 } else { 0 },
1059 plateau_severity: if avg_convergence > 0.95 {
1060 PlateauSeverity::Severe
1061 } else {
1062 PlateauSeverity::Mild
1063 },
1064 suggested_actions: if avg_convergence > 0.9 {
1065 vec![
1066 "Consider learning rate reduction".to_string(),
1067 "Add regularization".to_string(),
1068 ]
1069 } else {
1070 vec![]
1071 },
1072 };
1073
1074 TrainingDynamics {
1075 learning_phase,
1076 gradient_momentum,
1077 learning_velocity,
1078 adaptation_rate,
1079 plateau_detection,
1080 }
1081 }
1082
1083 fn assess_network_stability(
1084 &self,
1085 layer_details: &HashMap<String, LayerGradientDetails>,
1086 ) -> StabilityAssessment {
1087 let stability_scores: Vec<f64> = layer_details
1088 .values()
1089 .map(|details| details.flow_characteristics.stability_measure)
1090 .collect();
1091
1092 let overall_stability =
1093 stability_scores.iter().sum::<f64>() / stability_scores.len().max(1) as f64;
1094
1095 let stability_trend = if overall_stability > self.stability_threshold {
1096 StabilityTrend::Stable
1097 } else {
1098 StabilityTrend::Degrading
1099 };
1100
1101 let instability_sources = self.identify_instability_sources(layer_details);
1102
1103 let stability_forecast = StabilityForecast {
1104 short_term_outlook: if overall_stability > 0.7 {
1105 StabilityOutlook::Stable
1106 } else {
1107 StabilityOutlook::Deteriorating
1108 },
1109 long_term_outlook: if overall_stability > 0.8 {
1110 StabilityOutlook::Stable
1111 } else {
1112 StabilityOutlook::Uncertain
1113 },
1114 confidence_level: overall_stability,
1115 recommended_monitoring: vec![
1116 "Monitor gradient norms".to_string(),
1117 "Track convergence indicators".to_string(),
1118 ],
1119 };
1120
1121 StabilityAssessment {
1122 overall_stability,
1123 stability_trend,
1124 instability_sources,
1125 stability_forecast,
1126 }
1127 }
1128
1129 fn identify_instability_sources(
1130 &self,
1131 layer_details: &HashMap<String, LayerGradientDetails>,
1132 ) -> Vec<InstabilitySource> {
1133 let mut sources = Vec::new();
1134
1135 for (layer_name, details) in layer_details {
1136 if details.gradient_statistics.mean > 100.0 {
1137 sources.push(InstabilitySource {
1138 source_type: InstabilityType::GradientExplosion,
1139 affected_layers: vec![layer_name.clone()],
1140 severity: details.gradient_statistics.mean / 100.0,
1141 description: format!("High gradient magnitude in layer {}", layer_name),
1142 });
1143 }
1144
1145 if details.gradient_statistics.mean < 1e-5 {
1146 sources.push(InstabilitySource {
1147 source_type: InstabilityType::GradientVanishing,
1148 affected_layers: vec![layer_name.clone()],
1149 severity: 1.0 - (details.gradient_statistics.mean * 1e5),
1150 description: format!("Very low gradient magnitude in layer {}", layer_name),
1151 });
1152 }
1153
1154 if details.flow_characteristics.oscillation_frequency > 0.5 {
1155 sources.push(InstabilitySource {
1156 source_type: InstabilityType::Oscillation,
1157 affected_layers: vec![layer_name.clone()],
1158 severity: details.flow_characteristics.oscillation_frequency,
1159 description: format!("High oscillation frequency in layer {}", layer_name),
1160 });
1161 }
1162 }
1163
1164 sources
1165 }
1166
1167 fn build_gradient_hierarchy(
1168 &self,
1169 layer_details: &HashMap<String, LayerGradientDetails>,
1170 ) -> GradientHierarchy {
1171 let mut layer_groups = Vec::new();
1173 let mut hierarchy_levels = Vec::new();
1174 let cross_level_interactions = Vec::new(); let high_gradient_layers: Vec<String> = layer_details
1178 .iter()
1179 .filter(|(_, details)| details.gradient_statistics.mean > 1.0)
1180 .map(|(name, _)| name.clone())
1181 .collect();
1182
1183 let medium_gradient_layers: Vec<String> = layer_details
1184 .iter()
1185 .filter(|(_, details)| {
1186 details.gradient_statistics.mean >= 0.1 && details.gradient_statistics.mean <= 1.0
1187 })
1188 .map(|(name, _)| name.clone())
1189 .collect();
1190
1191 let low_gradient_layers: Vec<String> = layer_details
1192 .iter()
1193 .filter(|(_, details)| details.gradient_statistics.mean < 0.1)
1194 .map(|(name, _)| name.clone())
1195 .collect();
1196
1197 if !high_gradient_layers.is_empty() {
1198 layer_groups.push(LayerGroup {
1199 group_name: "High Gradient Layers".to_string(),
1200 layers: high_gradient_layers.clone(),
1201 group_characteristics: GroupCharacteristics {
1202 average_gradient_norm: 2.0, gradient_synchronization: 0.8,
1204 learning_rate_sensitivity: 0.9,
1205 optimization_difficulty: OptimizationDifficulty::Difficult,
1206 },
1207 internal_coherence: 0.7,
1208 });
1209
1210 hierarchy_levels.push(HierarchyLevel {
1211 level_id: 0,
1212 level_name: "High Gradient Level".to_string(),
1213 layer_groups: vec!["High Gradient Layers".to_string()],
1214 level_importance: 0.9,
1215 optimization_impact: 0.8,
1216 });
1217 }
1218
1219 if !medium_gradient_layers.is_empty() {
1220 layer_groups.push(LayerGroup {
1221 group_name: "Medium Gradient Layers".to_string(),
1222 layers: medium_gradient_layers,
1223 group_characteristics: GroupCharacteristics {
1224 average_gradient_norm: 0.5,
1225 gradient_synchronization: 0.6,
1226 learning_rate_sensitivity: 0.5,
1227 optimization_difficulty: OptimizationDifficulty::Moderate,
1228 },
1229 internal_coherence: 0.8,
1230 });
1231
1232 hierarchy_levels.push(HierarchyLevel {
1233 level_id: 1,
1234 level_name: "Medium Gradient Level".to_string(),
1235 layer_groups: vec!["Medium Gradient Layers".to_string()],
1236 level_importance: 0.7,
1237 optimization_impact: 0.6,
1238 });
1239 }
1240
1241 if !low_gradient_layers.is_empty() {
1242 layer_groups.push(LayerGroup {
1243 group_name: "Low Gradient Layers".to_string(),
1244 layers: low_gradient_layers,
1245 group_characteristics: GroupCharacteristics {
1246 average_gradient_norm: 0.05,
1247 gradient_synchronization: 0.4,
1248 learning_rate_sensitivity: 0.3,
1249 optimization_difficulty: OptimizationDifficulty::Easy,
1250 },
1251 internal_coherence: 0.5,
1252 });
1253
1254 hierarchy_levels.push(HierarchyLevel {
1255 level_id: 2,
1256 level_name: "Low Gradient Level".to_string(),
1257 layer_groups: vec!["Low Gradient Layers".to_string()],
1258 level_importance: 0.5,
1259 optimization_impact: 0.4,
1260 });
1261 }
1262
1263 GradientHierarchy {
1264 layer_groups,
1265 hierarchy_levels,
1266 cross_level_interactions,
1267 }
1268 }
1269
1270 fn rank_optimization_priorities(
1271 &self,
1272 layer_details: &HashMap<String, LayerGradientDetails>,
1273 network_analysis: &NetworkLevelAnalysis,
1274 ) -> Vec<OptimizationPriority> {
1275 let mut priorities = Vec::new();
1276
1277 for (layer_name, details) in layer_details {
1278 let priority_score = self.calculate_priority_score(details, network_analysis);
1279 let urgency_level = self.determine_urgency_level(details);
1280 let optimization_potential = details.comparative_analysis.optimization_potential;
1281 let recommended_actions = self.generate_prioritized_actions(details);
1282
1283 priorities.push(OptimizationPriority {
1284 target_name: layer_name.clone(),
1285 target_type: OptimizationTarget::IndividualLayer,
1286 priority_score,
1287 urgency_level,
1288 optimization_potential,
1289 recommended_actions,
1290 });
1291 }
1292
1293 priorities.sort_by(|a, b| {
1295 b.priority_score
1296 .partial_cmp(&a.priority_score)
1297 .unwrap_or(std::cmp::Ordering::Equal)
1298 });
1299
1300 priorities
1301 }
1302
1303 fn calculate_priority_score(
1304 &self,
1305 details: &LayerGradientDetails,
1306 network_analysis: &NetworkLevelAnalysis,
1307 ) -> f64 {
1308 let health_weight = match details.health_metrics.overall_health {
1309 LayerHealth::Critical => 1.0,
1310 LayerHealth::Warning => 0.7,
1311 LayerHealth::Healthy => 0.3,
1312 LayerHealth::Unknown => 0.5, };
1314
1315 let stability_weight = 1.0 - details.flow_characteristics.stability_measure;
1316 let optimization_weight = details.comparative_analysis.optimization_potential;
1317 let network_impact_weight = details.health_metrics.information_flow_rate
1318 / network_analysis.gradient_distribution.mean_gradient_norm.max(1e-8);
1319
1320 (health_weight * 0.4
1321 + stability_weight * 0.3
1322 + optimization_weight * 0.2
1323 + network_impact_weight * 0.1)
1324 .min(1.0)
1325 }
1326
1327 fn determine_urgency_level(&self, details: &LayerGradientDetails) -> UrgencyLevel {
1328 match details.health_metrics.overall_health {
1329 LayerHealth::Critical => UrgencyLevel::Critical,
1330 LayerHealth::Warning => {
1331 if details.flow_characteristics.stability_measure < 0.3 {
1332 UrgencyLevel::High
1333 } else {
1334 UrgencyLevel::Medium
1335 }
1336 },
1337 LayerHealth::Healthy => UrgencyLevel::Low,
1338 LayerHealth::Unknown => UrgencyLevel::Medium, }
1340 }
1341
1342 fn generate_prioritized_actions(
1343 &self,
1344 details: &LayerGradientDetails,
1345 ) -> Vec<PrioritizedAction> {
1346 let mut actions = Vec::new();
1347
1348 if details.gradient_statistics.mean < 1e-5 {
1349 actions.push(PrioritizedAction {
1350 action_name: "Weight Initialization Improvement".to_string(),
1351 action_type: ActionType::ParameterAdjustment,
1352 expected_impact: 0.8,
1353 implementation_effort: ImplementationEffort::Moderate,
1354 prerequisites: vec!["Model architecture review".to_string()],
1355 });
1356 }
1357
1358 if details.gradient_statistics.mean > 10.0 {
1359 actions.push(PrioritizedAction {
1360 action_name: "Learning Rate Reduction".to_string(),
1361 action_type: ActionType::LearningRateScheduling,
1362 expected_impact: 0.7,
1363 implementation_effort: ImplementationEffort::Minimal,
1364 prerequisites: vec![],
1365 });
1366 }
1367
1368 if details.flow_characteristics.stability_measure < 0.5 {
1369 actions.push(PrioritizedAction {
1370 action_name: "Gradient Clipping".to_string(),
1371 action_type: ActionType::OptimizationTechnique,
1372 expected_impact: 0.6,
1373 implementation_effort: ImplementationEffort::Low,
1374 prerequisites: vec!["Hyperparameter tuning".to_string()],
1375 });
1376 }
1377
1378 actions
1379 }
1380
1381 pub fn analyze_gradients(
1383 &self,
1384 gradient_histories: &HashMap<String, GradientHistory>,
1385 ) -> EnhancedLayerGradientAnalysis {
1386 self.generate_enhanced_analysis(gradient_histories)
1388 }
1389}