use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::numeric::Float;
use std::collections::{HashMap, VecDeque};
use std::time::{Duration, Instant};
#[allow(unused_imports)]
use crate::error::Result;
#[derive(Debug, Clone)]
pub enum PerformanceMetric<A: Float + Send + Sync> {
Loss(A),
Accuracy(A),
F1Score(A),
AUC(A),
Custom { name: String, value: A },
}
#[derive(Debug, Clone)]
pub struct EnhancedAdaptiveLRController<A: Float + Send + Sync> {
current_lr: A,
base_lr: A,
min_lr: A,
max_lr: A,
adaptation_strategy: MultiSignalAdaptationStrategy<A>,
gradient_adapter: GradientBasedAdapter<A>,
performance_adapter: PerformanceBasedAdapter<A>,
drift_adapter: DriftAwareAdapter<A>,
resource_adapter: ResourceAwareAdapter<A>,
meta_optimizer: MetaOptimizer<A>,
adaptation_history: VecDeque<AdaptationEvent<A>>,
config: AdaptiveLRConfig<A>,
}
#[derive(Debug, Clone)]
pub struct AdaptiveLRConfig<A: Float + Send + Sync> {
pub base_lr: A,
pub min_lr: A,
pub max_lr: A,
pub enable_gradient_adaptation: bool,
pub enable_performance_adaptation: bool,
pub enable_drift_adaptation: bool,
pub enable_resource_adaptation: bool,
pub enable_meta_learning: bool,
pub history_window_size: usize,
pub adaptation_frequency: usize,
pub adaptation_sensitivity: A,
pub use_ensemble_voting: bool,
}
#[derive(Debug, Clone)]
pub struct MultiSignalAdaptationStrategy<A: Float + Send + Sync> {
signal_weights: HashMap<AdaptationSignalType, A>,
voting_history: VecDeque<SignalVote<A>>,
conflict_resolution: ConflictResolution,
signal_reliability: HashMap<AdaptationSignalType, A>,
last_decision: Option<AdaptationDecision<A>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AdaptationSignalType {
GradientMagnitude,
GradientVariance,
LossProgression,
AccuracyTrend,
ConceptDrift,
ResourceUtilization,
ModelComplexity,
DataQuality,
}
#[derive(Debug, Clone)]
pub struct SignalVote<A: Float + Send + Sync> {
signal_type: AdaptationSignalType,
recommended_lr_change: A, confidence: A,
reasoning: String,
timestamp: Instant,
}
#[derive(Debug, Clone, Copy)]
pub enum ConflictResolution {
WeightedAverage,
HighestConfidence,
MajorityVote { threshold: f64 },
Conservative,
MetaLearned,
}
#[derive(Debug, Clone)]
pub struct AdaptationDecision<A: Float + Send + Sync> {
new_lr: A,
lr_multiplier: A,
contributing_signals: Vec<AdaptationSignalType>,
confidence: A,
rationale: String,
timestamp: Instant,
}
#[derive(Debug, Clone)]
pub struct GradientBasedAdapter<A: Float + Send + Sync> {
magnitude_history: VecDeque<A>,
direction_variance_history: VecDeque<A>,
norm_statistics: GradientNormStatistics<A>,
snr_estimator: SignalToNoiseEstimator<A>,
staleness_detector: GradientStalenessDetector<A>,
}
#[derive(Debug, Clone)]
pub struct PerformanceBasedAdapter<A: Float + Send + Sync> {
metric_history: HashMap<String, VecDeque<A>>,
trend_analyzer: PerformanceTrendAnalyzer<A>,
plateau_detector: PlateauDetector<A>,
overfitting_detector: OverfittingDetector<A>,
efficiency_tracker: LearningEfficiencyTracker<A>,
}
#[derive(Debug, Clone)]
pub struct DriftAwareAdapter<A: Float + Send + Sync> {
drift_detectors: Vec<ConceptDriftDetector<A>>,
distribution_tracker: DistributionTracker<A>,
adaptation_speed: AdaptationSpeedController<A>,
drift_severity: DriftSeverityAssessor<A>,
}
#[derive(Debug, Clone)]
pub struct ResourceAwareAdapter<A: Float + Send + Sync> {
memory_tracker: MemoryUsageTracker,
compute_tracker: ComputationTimeTracker,
energy_tracker: EnergyConsumptionTracker,
throughput_requirements: ThroughputRequirements<A>,
budget_manager: ResourceBudgetManager<A>,
}
#[derive(Debug, Clone)]
pub struct MetaOptimizer<A: Float + Send + Sync> {
lr_predictor: LearningRatePredictorNetwork<A>,
optimization_history: VecDeque<HyperparameterUpdate<A>>,
exploration_strategy: ExplorationStrategy<A>,
transfer_learner: TransferLearner<A>,
}
#[derive(Debug, Clone)]
pub struct AdaptationEvent<A: Float + Send + Sync> {
timestamp: Instant,
old_lr: A,
new_lr: A,
trigger_signals: Vec<AdaptationSignalType>,
adaptation_reason: String,
confidence: A,
effectiveness_score: Option<A>, }
#[derive(Debug, Clone)]
pub struct GradientNormStatistics<A: Float + Send + Sync> {
mean: A,
variance: A,
skewness: A,
kurtosis: A,
percentiles: Vec<A>, autocorrelation: A,
}
#[derive(Debug, Clone)]
pub struct SignalToNoiseEstimator<A: Float + Send + Sync> {
signal_estimate: A,
noise_estimate: A,
snr_history: VecDeque<A>,
estimation_method: SNREstimationMethod,
}
#[derive(Debug, Clone, Copy)]
pub enum SNREstimationMethod {
MovingAverage,
ExponentialSmoothing,
RobustEstimation,
WaveletDenoising,
}
#[derive(Debug, Clone)]
pub struct GradientStalenessDetector<A: Float + Send + Sync> {
staleness_threshold: Duration,
gradient_timestamps: VecDeque<Instant>,
staleness_impact_model: StalenessImpactModel<A>,
}
#[derive(Debug, Clone)]
pub struct StalenessImpactModel<A: Float + Send + Sync> {
staleness_penalty: A,
compensation_factor: A,
impact_history: VecDeque<A>,
}
#[derive(Debug, Clone)]
pub struct PerformanceTrendAnalyzer<A: Float + Send + Sync> {
trend_detection_window: usize,
trend_types: Vec<TrendType>,
trend_strength: A,
trend_duration: Duration,
}
#[derive(Debug, Clone, Copy)]
pub enum TrendType {
Improving,
Degrading,
Oscillating,
Plateau,
Volatile,
}
#[derive(Debug, Clone)]
pub struct PlateauDetector<A: Float + Send + Sync> {
plateau_threshold: A,
min_plateau_duration: usize,
current_plateau_length: usize,
plateau_confidence: A,
}
#[derive(Debug, Clone)]
pub struct OverfittingDetector<A: Float + Send + Sync> {
train_loss_history: VecDeque<A>,
val_loss_history: VecDeque<A>,
overfitting_threshold: A,
early_stopping_patience: usize,
}
#[derive(Debug, Clone)]
pub struct LearningEfficiencyTracker<A: Float + Send + Sync> {
loss_reduction_per_step: VecDeque<A>,
parameter_change_magnitude: VecDeque<A>,
efficiency_score: A,
efficiency_trend: TrendType,
}
#[derive(Debug, Clone)]
pub struct ConceptDriftDetector<A: Float + Send + Sync> {
detection_method: DriftDetectionMethod,
drift_threshold: A,
window_size: usize,
drift_confidence: A,
last_drift_time: Option<Instant>,
}
#[derive(Debug, Clone, Copy)]
pub enum DriftDetectionMethod {
ADWIN,
DDM,
EDDM,
PageHinkley,
KSWIN,
Statistical,
}
#[derive(Debug, Clone)]
pub struct DistributionTracker<A: Float + Send + Sync> {
feature_distributions: HashMap<usize, FeatureDistribution<A>>,
kl_divergence_threshold: A,
wasserstein_distance_threshold: A,
distribution_drift_score: A,
}
#[derive(Debug, Clone)]
pub struct FeatureDistribution<A: Float + Send + Sync> {
mean: A,
variance: A,
histogram: Vec<A>,
last_update: Instant,
}
#[derive(Debug, Clone)]
pub struct AdaptationSpeedController<A: Float + Send + Sync> {
base_adaptation_rate: A,
current_adaptation_rate: A,
acceleration_factor: A,
deceleration_factor: A,
momentum: A,
}
#[derive(Debug, Clone)]
pub struct DriftSeverityAssessor<A: Float + Send + Sync> {
severity_levels: Vec<DriftSeverityLevel<A>>,
current_severity: DriftSeverityLevel<A>,
severity_history: VecDeque<DriftSeverityLevel<A>>,
}
#[derive(Debug, Clone)]
pub struct DriftSeverityLevel<A: Float + Send + Sync> {
level: DriftSeverity,
magnitude: A,
recommended_lr_adjustment: A,
adaptation_urgency: A,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DriftSeverity {
None,
Mild,
Moderate,
Severe,
Critical,
}
#[derive(Debug, Clone, Default)]
pub struct MemoryUsageTracker {
current_usage_mb: f64,
peak_usage_mb: f64,
usage_history: VecDeque<f64>,
memory_pressure: f64,
}
#[derive(Debug, Clone, Default)]
pub struct ComputationTimeTracker {
step_times: VecDeque<Duration>,
average_step_time: Duration,
time_budget: Duration,
time_pressure: f64,
}
#[derive(Debug, Clone, Default)]
pub struct EnergyConsumptionTracker {
energy_per_step: VecDeque<f64>,
cumulative_energy: f64,
energy_budget: f64,
energy_efficiency: f64,
}
#[derive(Debug, Clone)]
pub struct ThroughputRequirements<A: Float + Send + Sync> {
min_samples_per_second: A,
target_samples_per_second: A,
current_throughput: A,
throughput_deficit: A,
}
#[derive(Debug, Clone)]
pub struct ResourceBudgetManager<A: Float + Send + Sync> {
memory_budget_mb: f64,
compute_budget_seconds: f64,
energy_budget_joules: f64,
budget_utilization: A,
budget_violations: usize,
}
#[derive(Debug, Clone)]
pub struct LearningRatePredictorNetwork<A: Float + Send + Sync> {
input_features: Vec<FeatureType>,
hidden_layers: Vec<usize>,
weights: Vec<Array2<A>>,
biases: Vec<Array1<A>>,
prediction_confidence: A,
}
#[derive(Debug, Clone, Copy)]
pub enum FeatureType {
GradientNorm,
LossValue,
LossGradient,
ParameterNorm,
UpdateMagnitude,
LearningProgress,
ResourceUtilization,
DataCharacteristics,
}
#[derive(Debug, Clone)]
pub struct HyperparameterUpdate<A: Float + Send + Sync> {
timestamp: Instant,
old_lr: A,
new_lr: A,
features: Array1<A>,
reward: A, exploration_bonus: A,
}
#[derive(Debug, Clone)]
pub struct ExplorationStrategy<A: Float + Send + Sync> {
strategy_type: ExplorationStrategyType,
exploration_rate: A,
exploitation_rate: A,
arm_rewards: HashMap<usize, A>,
arm_counts: HashMap<usize, usize>,
}
#[derive(Debug, Clone, Copy)]
pub enum ExplorationStrategyType {
EpsilonGreedy,
UCB1,
ThompsonSampling,
LinUCB,
ContextualBandit,
}
#[derive(Debug, Clone)]
pub struct TransferLearner<A: Float + Send + Sync> {
source_task_data: Vec<TaskData<A>>,
similarity_metrics: Vec<TaskSimilarityMetric<A>>,
transfer_weights: Array1<A>,
transfer_confidence: A,
}
#[derive(Debug, Clone)]
pub struct TaskData<A: Float + Send + Sync> {
task_id: String,
optimal_lr_sequence: Vec<A>,
task_features: Array1<A>,
performance_curve: Vec<A>,
}
#[derive(Debug, Clone)]
pub struct TaskSimilarityMetric<A: Float + Send + Sync> {
metric_type: SimilarityMetricType,
similarity_score: A,
weight: A,
}
#[derive(Debug, Clone, Copy)]
pub enum SimilarityMetricType {
DatasetSize,
ModelArchitecture,
LossFunction,
DataDistribution,
OptimizationLandscape,
}
#[derive(Debug, Clone, Default)]
pub struct AdaptationStatistics<A: Float + Send + Sync> {
pub total_adaptations: usize,
pub successful_adaptations: usize,
pub avg_adaptation_frequency: A,
pub lr_volatility: A,
pub signal_reliability_scores: HashMap<AdaptationSignalType, A>,
pub signal_effectiveness: HashMap<AdaptationSignalType, A>,
pub resource_efficiency_gains: A,
pub convergence_speed_improvement: A,
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> EnhancedAdaptiveLRController<A> {
pub fn new(config: AdaptiveLRConfig<A>) -> Result<Self> {
let adaptation_strategy = MultiSignalAdaptationStrategy::new(&config)?;
let gradient_adapter = GradientBasedAdapter::new(&config)?;
let performance_adapter = PerformanceBasedAdapter::new(&config)?;
let drift_adapter = DriftAwareAdapter::new(&config)?;
let resource_adapter = ResourceAwareAdapter::new(&config)?;
let meta_optimizer = MetaOptimizer::new(&config)?;
Ok(Self {
current_lr: config.base_lr,
base_lr: config.base_lr,
min_lr: config.min_lr,
max_lr: config.max_lr,
adaptation_strategy,
gradient_adapter,
performance_adapter,
drift_adapter,
resource_adapter,
meta_optimizer,
adaptation_history: VecDeque::with_capacity(config.history_window_size),
config,
})
}
pub fn update_learning_rate(
&mut self,
gradients: &Array1<A>,
loss: A,
metrics: &HashMap<String, A>,
step: usize,
) -> Result<A> {
let mut signals = Vec::new();
if self.config.enable_gradient_adaptation {
if let Ok(signal) = self.gradient_adapter.generate_signal(gradients, step) {
signals.push(signal);
}
}
if self.config.enable_performance_adaptation {
if let Ok(signal) = self
.performance_adapter
.generate_signal(loss, metrics, step)
{
signals.push(signal);
}
}
if self.config.enable_drift_adaptation {
if let Ok(signal) = self.drift_adapter.generate_signal(gradients, step) {
signals.push(signal);
}
}
if self.config.enable_resource_adaptation {
if let Ok(signal) = self.resource_adapter.generate_signal(step) {
signals.push(signal);
}
}
let decision = self.adaptation_strategy.resolve_signals(signals, step)?;
if self.config.enable_meta_learning {
let meta_adjustment = self.meta_optimizer.meta_optimize(&decision, step)?;
self.current_lr = self.apply_meta_adjustment(decision.new_lr, meta_adjustment);
} else {
self.current_lr = decision.new_lr;
}
self.current_lr = self
.current_lr
.clamp(self.config.min_lr, self.config.max_lr);
let event = AdaptationEvent {
timestamp: Instant::now(),
old_lr: decision.new_lr, new_lr: self.current_lr,
trigger_signals: decision.contributing_signals,
adaptation_reason: decision.rationale,
confidence: decision.confidence,
effectiveness_score: None, };
self.adaptation_history.push_back(event);
if self.adaptation_history.len() > self.config.history_window_size {
self.adaptation_history.pop_front();
}
Ok(self.current_lr)
}
pub fn get_current_lr(&self) -> A {
self.current_lr
}
pub fn get_adaptation_statistics(&self) -> AdaptationStatistics<A> {
let total_adaptations = self.adaptation_history.len();
let successful_adaptations = self
.adaptation_history
.iter()
.filter(|event| {
event
.effectiveness_score
.is_some_and(|score| score > A::zero())
})
.count();
let lr_volatility = if !self.adaptation_history.is_empty() {
let lr_values: Vec<A> = self
.adaptation_history
.iter()
.map(|event| event.new_lr)
.collect();
let mean_lr = lr_values.iter().fold(A::zero(), |acc, &lr| acc + lr)
/ A::from(lr_values.len()).expect("unwrap failed");
let variance = lr_values
.iter()
.map(|&lr| {
let diff = lr - mean_lr;
diff * diff
})
.fold(A::zero(), |acc, var| acc + var)
/ A::from(lr_values.len()).expect("unwrap failed");
variance.sqrt()
} else {
A::zero()
};
AdaptationStatistics {
total_adaptations,
successful_adaptations,
lr_volatility,
..Default::default()
}
}
fn apply_meta_adjustment(&self, base_lr: A, meta_adjustment: A) -> A {
let alpha = A::from(0.7).expect("unwrap failed"); let beta = A::from(0.3).expect("unwrap failed");
alpha * base_lr + beta * meta_adjustment
}
pub fn evaluate_adaptation_effectiveness(&mut self, performance_improvement: A) {
if let Some(last_event) = self.adaptation_history.back_mut() {
last_event.effectiveness_score = Some(performance_improvement);
for signal_type in &last_event.trigger_signals {
self.adaptation_strategy
.update_signal_reliability(*signal_type, performance_improvement);
}
}
}
pub fn reset(&mut self) {
self.current_lr = self.base_lr;
self.adaptation_history.clear();
self.gradient_adapter.reset();
self.performance_adapter.reset();
self.drift_adapter.reset();
self.resource_adapter.reset();
self.meta_optimizer.reset();
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> MultiSignalAdaptationStrategy<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
signal_weights: HashMap::new(),
voting_history: VecDeque::new(),
conflict_resolution: ConflictResolution::WeightedAverage,
signal_reliability: HashMap::new(),
last_decision: None,
})
}
fn resolve_signals(
&mut self,
signals: Vec<SignalVote<A>>,
_step: usize,
) -> Result<AdaptationDecision<A>> {
if signals.is_empty() {
return Ok(AdaptationDecision {
new_lr: A::from(0.001).expect("unwrap failed"),
lr_multiplier: A::one(),
contributing_signals: vec![],
confidence: A::zero(),
rationale: "No signals available".to_string(),
timestamp: Instant::now(),
});
}
let total_weight = signals
.iter()
.map(|s| s.confidence)
.fold(A::zero(), |acc, c| acc + c);
let weighted_change = signals
.iter()
.map(|s| s.recommended_lr_change * s.confidence)
.fold(A::zero(), |acc, change| acc + change)
/ total_weight;
let contributing_signals = signals.iter().map(|s| s.signal_type).collect();
Ok(AdaptationDecision {
new_lr: A::from(0.001).expect("unwrap failed") * weighted_change,
lr_multiplier: weighted_change,
contributing_signals,
confidence: total_weight / A::from(signals.len()).expect("unwrap failed"),
rationale: "Weighted average of adaptation signals".to_string(),
timestamp: Instant::now(),
})
}
fn update_signal_reliability(&mut self, signal_type: AdaptationSignalType, effectiveness: A) {
let reliability = self
.signal_reliability
.entry(signal_type)
.or_insert(A::from(0.5).expect("unwrap failed"));
let alpha = A::from(0.1).expect("unwrap failed");
*reliability = (*reliability) * (A::one() - alpha) + effectiveness * alpha;
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> GradientBasedAdapter<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
magnitude_history: VecDeque::new(),
direction_variance_history: VecDeque::new(),
norm_statistics: GradientNormStatistics::default(),
snr_estimator: SignalToNoiseEstimator::default(),
staleness_detector: GradientStalenessDetector::default(),
})
}
fn generate_signal(&mut self, gradients: &Array1<A>, step: usize) -> Result<SignalVote<A>> {
let magnitude = gradients
.iter()
.map(|&g| g * g)
.fold(A::zero(), |acc, x| acc + x)
.sqrt();
self.magnitude_history.push_back(magnitude);
if self.magnitude_history.len() > 100 {
self.magnitude_history.pop_front();
}
let recommended_change = if magnitude > A::from(1.0).expect("unwrap failed") {
A::from(0.9).expect("unwrap failed") } else if magnitude < A::from(0.01).expect("unwrap failed") {
A::from(1.1).expect("unwrap failed") } else {
A::one() };
Ok(SignalVote {
signal_type: AdaptationSignalType::GradientMagnitude,
recommended_lr_change: recommended_change,
confidence: A::from(0.7).expect("unwrap failed"),
reasoning: "Gradient magnitude-based adaptation".to_string(),
timestamp: Instant::now(),
})
}
fn reset(&mut self) {
self.magnitude_history.clear();
self.direction_variance_history.clear();
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> PerformanceBasedAdapter<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
metric_history: HashMap::new(),
trend_analyzer: PerformanceTrendAnalyzer::default(),
plateau_detector: PlateauDetector::default(),
overfitting_detector: OverfittingDetector::default(),
efficiency_tracker: LearningEfficiencyTracker::default(),
})
}
fn generate_signal(
&mut self,
loss: A,
metrics: &HashMap<String, A>,
_step: usize,
) -> Result<SignalVote<A>> {
let loss_history = self.metric_history.entry("loss".to_string()).or_default();
loss_history.push_back(loss);
if loss_history.len() > 50 {
loss_history.pop_front();
}
let recommended_change = if loss_history.len() >= 2 {
let recent_loss = loss_history.back().expect("unwrap failed");
let prev_loss = loss_history
.get(loss_history.len() - 2)
.expect("unwrap failed");
if *recent_loss > *prev_loss {
A::from(0.95).expect("unwrap failed") } else {
A::from(1.02).expect("unwrap failed") }
} else {
A::one()
};
Ok(SignalVote {
signal_type: AdaptationSignalType::LossProgression,
recommended_lr_change: recommended_change,
confidence: A::from(0.8).expect("unwrap failed"),
reasoning: "Loss progression analysis".to_string(),
timestamp: Instant::now(),
})
}
fn reset(&mut self) {
self.metric_history.clear();
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> DriftAwareAdapter<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
drift_detectors: vec![],
distribution_tracker: DistributionTracker::default(),
adaptation_speed: AdaptationSpeedController::default(),
drift_severity: DriftSeverityAssessor::default(),
})
}
fn generate_signal(&mut self, gradients: &Array1<A>, step: usize) -> Result<SignalVote<A>> {
Ok(SignalVote {
signal_type: AdaptationSignalType::ConceptDrift,
recommended_lr_change: A::one(),
confidence: A::from(0.5).expect("unwrap failed"),
reasoning: "No drift detected".to_string(),
timestamp: Instant::now(),
})
}
fn reset(&mut self) {
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> ResourceAwareAdapter<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
memory_tracker: MemoryUsageTracker::default(),
compute_tracker: ComputationTimeTracker::default(),
energy_tracker: EnergyConsumptionTracker::default(),
throughput_requirements: ThroughputRequirements {
min_samples_per_second: A::from(100.0).expect("unwrap failed"),
target_samples_per_second: A::from(1000.0).expect("unwrap failed"),
current_throughput: A::from(500.0).expect("unwrap failed"),
throughput_deficit: A::zero(),
},
budget_manager: ResourceBudgetManager {
memory_budget_mb: 1000.0,
compute_budget_seconds: 3600.0,
energy_budget_joules: 1000.0,
budget_utilization: A::from(0.5).expect("unwrap failed"),
budget_violations: 0,
},
})
}
fn generate_signal(&mut self, step: usize) -> Result<SignalVote<A>> {
let memory_pressure = self.memory_tracker.memory_pressure;
let recommended_change = if memory_pressure > 0.8 {
A::from(0.9).expect("unwrap failed") } else if memory_pressure < 0.3 {
A::from(1.05).expect("unwrap failed") } else {
A::one()
};
Ok(SignalVote {
signal_type: AdaptationSignalType::ResourceUtilization,
recommended_lr_change: recommended_change,
confidence: A::from(0.6).expect("unwrap failed"),
reasoning: format!("Memory pressure: {:.2}", memory_pressure),
timestamp: Instant::now(),
})
}
fn reset(&mut self) {
self.memory_tracker = MemoryUsageTracker::default();
self.compute_tracker = ComputationTimeTracker::default();
self.energy_tracker = EnergyConsumptionTracker::default();
}
}
impl<A: Float + Default + Clone + Send + Sync + Send + Sync> MetaOptimizer<A> {
fn new(config: &AdaptiveLRConfig<A>) -> Result<Self> {
Ok(Self {
lr_predictor: LearningRatePredictorNetwork::default(),
optimization_history: VecDeque::new(),
exploration_strategy: ExplorationStrategy::default(),
transfer_learner: TransferLearner::default(),
})
}
fn meta_optimize(&mut self, decision: &AdaptationDecision<A>, step: usize) -> Result<A> {
Ok(A::from(0.001).expect("unwrap failed"))
}
fn reset(&mut self) {
self.optimization_history.clear();
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for GradientNormStatistics<A> {
fn default() -> Self {
Self {
mean: A::default(),
variance: A::default(),
skewness: A::default(),
kurtosis: A::default(),
percentiles: vec![A::default(); 5],
autocorrelation: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for SignalToNoiseEstimator<A> {
fn default() -> Self {
Self {
signal_estimate: A::default(),
noise_estimate: A::default(),
snr_history: VecDeque::new(),
estimation_method: SNREstimationMethod::MovingAverage,
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for GradientStalenessDetector<A> {
fn default() -> Self {
Self {
staleness_threshold: Duration::from_secs(1),
gradient_timestamps: VecDeque::new(),
staleness_impact_model: StalenessImpactModel::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for StalenessImpactModel<A> {
fn default() -> Self {
Self {
staleness_penalty: A::default(),
compensation_factor: A::default(),
impact_history: VecDeque::new(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for PerformanceTrendAnalyzer<A> {
fn default() -> Self {
Self {
trend_detection_window: 10,
trend_types: vec![],
trend_strength: A::default(),
trend_duration: Duration::from_secs(0),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for PlateauDetector<A> {
fn default() -> Self {
Self {
plateau_threshold: A::default(),
min_plateau_duration: 5,
current_plateau_length: 0,
plateau_confidence: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for OverfittingDetector<A> {
fn default() -> Self {
Self {
train_loss_history: VecDeque::new(),
val_loss_history: VecDeque::new(),
overfitting_threshold: A::default(),
early_stopping_patience: 10,
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for LearningEfficiencyTracker<A> {
fn default() -> Self {
Self {
loss_reduction_per_step: VecDeque::new(),
parameter_change_magnitude: VecDeque::new(),
efficiency_score: A::default(),
efficiency_trend: TrendType::Improving,
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for DistributionTracker<A> {
fn default() -> Self {
Self {
feature_distributions: HashMap::new(),
kl_divergence_threshold: A::default(),
wasserstein_distance_threshold: A::default(),
distribution_drift_score: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for AdaptationSpeedController<A> {
fn default() -> Self {
Self {
base_adaptation_rate: A::from(0.1).unwrap_or_default(),
current_adaptation_rate: A::from(0.1).unwrap_or_default(),
acceleration_factor: A::from(1.1).unwrap_or_default(),
deceleration_factor: A::from(0.9).unwrap_or_default(),
momentum: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for DriftSeverityAssessor<A> {
fn default() -> Self {
Self {
severity_levels: vec![],
current_severity: DriftSeverityLevel::default(),
severity_history: VecDeque::new(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for DriftSeverityLevel<A> {
fn default() -> Self {
Self {
level: DriftSeverity::None,
magnitude: A::default(),
recommended_lr_adjustment: A::one(),
adaptation_urgency: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for LearningRatePredictorNetwork<A> {
fn default() -> Self {
Self {
input_features: vec![],
hidden_layers: vec![],
weights: vec![],
biases: vec![],
prediction_confidence: A::default(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for ExplorationStrategy<A> {
fn default() -> Self {
Self {
strategy_type: ExplorationStrategyType::EpsilonGreedy,
exploration_rate: A::from(0.1).unwrap_or_default(),
exploitation_rate: A::from(0.9).unwrap_or_default(),
arm_rewards: HashMap::new(),
arm_counts: HashMap::new(),
}
}
}
impl<A: Float + Default + Send + Sync + Send + Sync> Default for TransferLearner<A> {
fn default() -> Self {
Self {
source_task_data: vec![],
similarity_metrics: vec![],
transfer_weights: Array1::from_vec(vec![]),
transfer_confidence: A::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use scirs2_core::ndarray::Array1;
#[test]
fn test_enhanced_adaptive_lr_controller_creation() {
let config = AdaptiveLRConfig {
base_lr: 0.01,
min_lr: 1e-6,
max_lr: 1.0,
enable_gradient_adaptation: true,
enable_performance_adaptation: true,
enable_drift_adaptation: false,
enable_resource_adaptation: false,
enable_meta_learning: false,
history_window_size: 100,
adaptation_frequency: 10,
adaptation_sensitivity: 0.1,
use_ensemble_voting: true,
};
let controller = EnhancedAdaptiveLRController::<f32>::new(config);
assert!(controller.is_ok());
}
#[test]
fn test_learning_rate_update() {
let config = AdaptiveLRConfig {
base_lr: 0.01,
min_lr: 1e-6,
max_lr: 1.0,
enable_gradient_adaptation: true,
enable_performance_adaptation: true,
enable_drift_adaptation: false,
enable_resource_adaptation: false,
enable_meta_learning: false,
history_window_size: 100,
adaptation_frequency: 10,
adaptation_sensitivity: 0.1,
use_ensemble_voting: true,
};
let mut controller =
EnhancedAdaptiveLRController::<f32>::new(config).expect("unwrap failed");
let gradients = Array1::from_vec(vec![0.1, 0.2, 0.05]);
let loss = 0.5;
let metrics = HashMap::new();
let new_lr = controller.update_learning_rate(&gradients, loss, &metrics, 1);
assert!(new_lr.is_ok());
assert!(new_lr.expect("unwrap failed") > 0.0);
}
#[test]
fn test_adaptation_statistics() {
let config = AdaptiveLRConfig {
base_lr: 0.01,
min_lr: 1e-6,
max_lr: 1.0,
enable_gradient_adaptation: true,
enable_performance_adaptation: true,
enable_drift_adaptation: false,
enable_resource_adaptation: false,
enable_meta_learning: false,
history_window_size: 100,
adaptation_frequency: 10,
adaptation_sensitivity: 0.1,
use_ensemble_voting: true,
};
let controller = EnhancedAdaptiveLRController::<f32>::new(config).expect("unwrap failed");
let stats = controller.get_adaptation_statistics();
assert_eq!(stats.total_adaptations, 0);
assert_eq!(stats.successful_adaptations, 0);
}
}