1use crate::error::{OptimError, Result};
6use scirs2_core::ndarray::{Array1, Dimension};
7use scirs2_core::numeric::Float;
8use std::collections::{HashMap, VecDeque};
9use std::fmt::Debug;
10use std::time::Instant;
11
12#[derive(Debug, Clone)]
14pub struct AdaptationStep<T: Float + Debug + Send + Sync + 'static> {
15 pub step: usize,
17 pub loss: T,
19 pub gradient_norm: T,
21 pub parameter_change_norm: T,
23 pub learning_rate: T,
25}
26#[derive(Debug, Clone)]
28pub struct MetaTrainingMetrics<T: Float + Debug + Send + Sync + 'static> {
29 pub avg_adaptation_speed: T,
31 pub generalization_performance: T,
33 pub task_diversity: T,
35 pub gradient_alignment: T,
37}
38#[derive(Debug, Clone, Copy)]
40pub enum TaskIdentificationMethod {
41 Oracle,
42 Learned,
43 Clustering,
44 EntropyBased,
45 GradientBased,
46}
47#[derive(Debug, Clone)]
49pub struct QueryEvaluationMetrics<T: Float + Debug + Send + Sync + 'static> {
50 pub mse: Option<T>,
52 pub classification_accuracy: Option<T>,
54 pub auc: Option<T>,
56 pub uncertainty_quality: T,
58}
59#[derive(Debug, Clone)]
61pub struct MetaParameters<T: Float + Debug + Send + Sync + 'static> {
62 pub parameters: HashMap<String, Array1<T>>,
64 pub metadata: HashMap<String, String>,
66}
67pub struct MAMLLearner<T: Float + Debug + Send + Sync + 'static, D: Dimension> {
76 pub(super) config: MAMLConfig<T>,
78 pub(super) adaptation_history: VecDeque<TaskAdaptationResult<T>>,
80 pub(super) meta_steps: usize,
82 _phantom: std::marker::PhantomData<D>,
84}
85
86pub(super) const MAML_HISTORY_CAPACITY: usize = 1000;
88
89impl<
90 T: Float
91 + Default
92 + Clone
93 + Send
94 + Sync
95 + scirs2_core::ndarray::ScalarOperand
96 + std::fmt::Debug,
97 D: Dimension,
98 > MAMLLearner<T, D>
99{
100 pub fn new(config: MAMLConfig<T>) -> Result<Self> {
101 if config.inner_steps == 0 {
102 return Err(OptimError::InvalidConfig(
103 "MAML requires at least one inner step".to_string(),
104 ));
105 }
106 Ok(Self {
107 config,
108 adaptation_history: VecDeque::with_capacity(MAML_HISTORY_CAPACITY),
109 meta_steps: 0,
110 _phantom: std::marker::PhantomData,
111 })
112 }
113
114 pub fn adaptations_recorded(&self) -> usize {
116 self.adaptation_history.len()
117 }
118}
119impl<T: Float + Debug + Send + Sync + 'static + Default + Clone + std::iter::Sum, D: Dimension>
120 MAMLLearner<T, D>
121{
122 pub(super) fn compute_support_loss(
124 &self,
125 task: &MetaTask<T>,
126 parameters: &HashMap<String, Array1<T>>,
127 ) -> Result<T> {
128 super::linear_model::mse_loss(
129 &task.support_set.features,
130 &task.support_set.targets,
131 parameters,
132 )
133 }
134
135 pub(super) fn compute_support_gradients(
137 &self,
138 task: &MetaTask<T>,
139 parameters: &HashMap<String, Array1<T>>,
140 ) -> Result<HashMap<String, Array1<T>>> {
141 let mut grads = super::linear_model::mse_gradients(
142 &task.support_set.features,
143 &task.support_set.targets,
144 parameters,
145 )?;
146 if let Some(clip) = self.config.gradient_clip {
147 if let Some(max_norm) = scirs2_core::numeric::NumCast::from(clip) {
148 super::linear_model::clip_gradients(&mut grads, max_norm);
149 }
150 }
151 Ok(grads)
152 }
153
154 pub(super) fn compute_query_gradients(
156 &self,
157 task: &MetaTask<T>,
158 parameters: &HashMap<String, Array1<T>>,
159 ) -> Result<HashMap<String, Array1<T>>> {
160 super::linear_model::mse_gradients(
161 &task.query_set.features,
162 &task.query_set.targets,
163 parameters,
164 )
165 }
166}
167#[derive(Debug, Clone, Copy)]
169pub enum MemorySelectionCriteria {
170 Random,
171 GradientMagnitude,
172 LossBased,
173 Uncertainty,
174 Diversity,
175 TemporalProximity,
176}
177#[derive(Debug, Clone)]
179pub struct TaskMetadata {
180 pub name: String,
182 pub description: String,
184 pub properties: HashMap<String, String>,
186 pub created_at: Instant,
188 pub source: String,
190}
191#[derive(Debug, Clone)]
193pub struct MetaTrainingEpoch<T: Float + Debug + Send + Sync + 'static> {
194 pub epoch: usize,
195 pub training_result: MetaTrainingResult<T>,
196 pub validation_result: MetaValidationResult<T>,
197 pub meta_parameters: HashMap<String, Array1<T>>,
198}
199#[derive(Debug, Clone)]
201pub struct TaskDataset<T: Float + Debug + Send + Sync + 'static> {
202 pub features: Vec<Array1<T>>,
204 pub targets: Vec<T>,
206 pub weights: Vec<T>,
208 pub metadata: DatasetMetadata,
210}
211#[derive(Debug, Clone)]
213pub struct MAMLConfig<T: Float + Debug + Send + Sync + 'static> {
214 pub second_order: bool,
216 pub inner_lr: T,
218 pub outer_lr: T,
220 pub inner_steps: usize,
222 pub allow_unused: bool,
224 pub gradient_clip: Option<f64>,
226}
227#[derive(Debug, Clone)]
229pub struct MetaTrainingResult<T: Float + Debug + Send + Sync + 'static> {
230 pub meta_loss: T,
232 pub task_losses: Vec<T>,
234 pub meta_gradients: HashMap<String, Array1<T>>,
236 pub metrics: MetaTrainingMetrics<T>,
238 pub adaptation_stats: AdaptationStatistics<T>,
240}
241#[derive(Debug, Clone)]
243pub struct MetricLearningSettings {
244 pub distance_metric: DistanceMetric,
246 pub embedding_dim: usize,
248 pub learned_metric: bool,
250}
251#[derive(Debug, Clone)]
253pub struct MultiTaskResult<T: Float + Debug + Send + Sync + 'static> {
254 pub task_results: Vec<TaskResult<T>>,
255 pub coordination_overhead: T,
256 pub convergence_status: String,
257}
258#[derive(Debug, Clone)]
260pub struct MemoryReplaySettings {
261 pub buffer_size: usize,
263 pub replay_strategy: ReplayStrategy,
265 pub replay_frequency: usize,
267 pub selection_criteria: MemorySelectionCriteria,
269}
270#[derive(Debug, Clone, Copy)]
272pub enum TaskType {
273 Regression,
274 Classification,
275 Optimization,
276 ReinforcementLearning,
277 StructuredPrediction,
278 Generative,
279}
280#[derive(Debug, Clone, Copy)]
282pub enum InterferenceMitigationStrategy {
283 OrthogonalGradients,
284 TaskSpecificLayers,
285 AttentionMechanisms,
286 MetaGradients,
287}
288#[derive(Debug, Clone, Copy)]
290pub enum ReplayStrategy {
291 Random,
292 GradientBased,
293 UncertaintyBased,
294 DiversityBased,
295 Temporal,
296}
297#[derive(Debug, Clone)]
299pub struct TransferLearningSettings {
300 pub domain_adaptation: bool,
302 pub source_domain_weights: Vec<f64>,
304 pub strategies: Vec<TransferStrategy>,
306 pub similarity_measures: Vec<SimilarityMeasure>,
308 pub progressive_transfer: bool,
310}
311#[derive(Debug, Clone)]
313pub struct ValidationResult {
314 pub is_valid: bool,
316 pub validation_loss: f64,
318 pub metrics: HashMap<String, f64>,
320}
321#[derive(Debug, Clone)]
323pub struct TransferLearningResult<T: Float + Debug + Send + Sync + 'static> {
324 pub transfer_efficiency: T,
325 pub domain_adaptation_score: T,
326 pub source_task_retention: T,
327 pub target_task_performance: T,
328}
329#[derive(Debug, Clone, Copy)]
331pub enum AdaptationStrategy {
332 FullFineTuning,
334 LayerWiseFineTuning,
336 ParameterEfficient,
338 LearnedLearningRates,
340 GradientBased,
342 MemoryBased,
344 AttentionBased,
346 ModularAdaptation,
348}
349#[derive(Debug, Clone)]
351pub struct MetaTask<T: Float + Debug + Send + Sync + 'static> {
352 pub id: String,
354 pub support_set: TaskDataset<T>,
356 pub query_set: TaskDataset<T>,
358 pub metadata: TaskMetadata,
360 pub difficulty: T,
362 pub domain: String,
364 pub task_type: TaskType,
366}
367#[derive(Debug, Clone)]
369pub struct ContinualLearningResult<T: Float + Debug + Send + Sync + 'static> {
370 pub sequence_results: Vec<TaskResult<T>>,
371 pub forgetting_measure: T,
372 pub adaptation_efficiency: T,
373}
374#[derive(Debug, Clone, Copy)]
376pub enum AntiForgettingStrategy {
377 ElasticWeightConsolidation,
378 SynapticIntelligence,
379 MemoryReplay,
380 ProgressiveNetworks,
381 PackNet,
382 Piggyback,
383 HAT,
384}
385#[derive(Debug, Clone)]
387pub struct TrainingResult {
388 pub training_loss: f64,
390 pub metrics: HashMap<String, f64>,
392 pub steps: usize,
394}
395#[derive(Debug, Clone)]
397pub struct MetaTrainingResults<T: Float + Debug + Send + Sync + 'static> {
398 pub final_parameters: HashMap<String, Array1<T>>,
399 pub training_history: Vec<MetaTrainingEpoch<T>>,
400 pub best_performance: T,
401 pub total_epochs: usize,
402}
403#[derive(Debug, Clone)]
405pub struct DatasetMetadata {
406 pub num_samples: usize,
408 pub feature_dim: usize,
410 pub distribution_type: String,
412 pub noise_level: f64,
414}
415#[derive(Debug, Clone)]
417pub struct MetaLearningStatistics<T: Float + Debug + Send + Sync + 'static> {
418 pub algorithm: MetaLearningAlgorithm,
419 pub total_tasks_seen: usize,
420 pub adaptation_efficiency: T,
421 pub transfer_success_rate: T,
422 pub forgetting_measure: T,
423 pub multitask_interference: T,
424 pub few_shot_performance: T,
425}
426#[derive(Debug, Clone)]
428pub struct TaskAdaptationResult<T: Float + Debug + Send + Sync + 'static> {
429 pub adapted_parameters: HashMap<String, Array1<T>>,
431 pub adaptation_trajectory: Vec<AdaptationStep<T>>,
433 pub final_loss: T,
435 pub metrics: TaskAdaptationMetrics<T>,
437}
438#[derive(Debug, Clone, Copy)]
440pub enum TransferStrategy {
441 FeatureExtraction,
442 FineTuning,
443 DomainAdaptation,
444 MultiTask,
445 MetaTransfer,
446 Progressive,
447}
448#[derive(Debug, Clone, Copy)]
450pub enum AugmentationStrategy {
451 Geometric,
452 Color,
453 Noise,
454 Mixup,
455 CutMix,
456 Learned,
457}
458#[derive(Debug, Clone)]
460pub struct StabilityMetrics<T: Float + Debug + Send + Sync + 'static> {
461 pub parameter_stability: T,
463 pub performance_stability: T,
465 pub gradient_stability: T,
467 pub forgetting_measure: T,
469}
470#[derive(Debug, Clone)]
472pub struct TaskResult<T: Float + Debug + Send + Sync + 'static> {
473 pub task_id: String,
474 pub loss: T,
475 pub metrics: HashMap<String, T>,
476}
477#[derive(Debug, Clone, Copy)]
479pub enum MetaLearningAlgorithm {
480 MAML,
482 FOMAML,
484 Reptile,
486 MetaSGD,
488 L2L,
490 GBML,
492 IMaml,
494 ProtoNet,
496 MatchingNet,
498 RelationNet,
500 MANN,
502 WarpGrad,
504 LearnedGD,
506}
507#[derive(Debug, Clone, Copy)]
509pub enum GradientBalancingMethod {
510 Uniform,
511 GradNorm,
512 PCGrad,
513 CAGrad,
514 NashMTL,
515}
516#[derive(Debug, Clone)]
518pub struct QueryEvaluationResult<T: Float + Debug + Send + Sync + 'static> {
519 pub query_loss: T,
521 pub accuracy: T,
523 pub predictions: Vec<T>,
525 pub confidence_scores: Vec<T>,
527 pub metrics: QueryEvaluationMetrics<T>,
529}
530#[derive(Debug, Clone, Copy)]
532pub enum FewShotAlgorithm {
533 Prototypical,
534 Matching,
535 Relation,
536 MAML,
537 Reptile,
538 MetaOptNet,
539}
540#[derive(Debug, Clone, Copy)]
542pub enum ActivationFunction {
543 ReLU,
544 Sigmoid,
545 Tanh,
546 Softmax,
547 GELU,
548}
549#[derive(Debug, Clone)]
551pub struct AdaptationStatistics<T: Float + Debug + Send + Sync + 'static> {
552 pub convergence_steps: Vec<usize>,
554 pub final_losses: Vec<T>,
556 pub adaptation_efficiency: T,
558 pub stability_metrics: StabilityMetrics<T>,
560}
561#[derive(Debug, Clone)]
563pub struct MetaValidationResult<T: Float + Debug + Send + Sync + 'static> {
564 pub performance: T,
565 pub adaptation_speed: T,
566 pub generalization_gap: T,
567 pub task_specific_metrics: HashMap<String, T>,
568}
569#[derive(Debug, Clone)]
571pub struct ContinualLearningSettings {
572 pub anti_forgetting_strategies: Vec<AntiForgettingStrategy>,
574 pub memory_replay: MemoryReplaySettings,
576 pub task_identification: TaskIdentificationMethod,
578 pub plasticity_stability_balance: f64,
580}
581#[derive(Debug, Clone, Copy)]
583pub enum TaskWeightingStrategy {
584 Uniform,
585 UncertaintyBased,
586 GradientMagnitude,
587 PerformanceBased,
588 Adaptive,
589 Learned,
590}
591#[derive(Debug, Clone)]
593pub struct MultiTaskSettings {
594 pub task_weighting: TaskWeightingStrategy,
596 pub gradient_balancing: GradientBalancingMethod,
598 pub interference_mitigation: InterferenceMitigationStrategy,
600 pub shared_representation: SharedRepresentationStrategy,
602}
603#[derive(Debug, Clone, Copy)]
605pub enum SharedRepresentationStrategy {
606 HardSharing,
607 SoftSharing,
608 HierarchicalSharing,
609 AttentionBased,
610 Modular,
611}
612#[derive(Debug, Clone, Copy)]
614pub enum DistanceMetric {
615 Euclidean,
616 Cosine,
617 Mahalanobis,
618 Learned,
619}
620#[derive(Debug, Clone)]
622pub struct TaskAdaptationMetrics<T: Float + Debug + Send + Sync + 'static> {
623 pub convergence_speed: T,
625 pub final_performance: T,
627 pub efficiency: T,
629 pub robustness: T,
631}
632#[derive(Debug, Clone)]
634pub struct FewShotSettings {
635 pub num_shots: usize,
637 pub num_ways: usize,
639 pub algorithm: FewShotAlgorithm,
641 pub metric_learning: MetricLearningSettings,
643 pub augmentation_strategies: Vec<AugmentationStrategy>,
645}
646#[derive(Debug, Clone, Copy)]
648pub enum SimilarityMeasure {
649 CosineDistance,
650 KLDivergence,
651 WassersteinDistance,
652 CentralMomentDiscrepancy,
653 MaximumMeanDiscrepancy,
654}
655#[derive(Debug, Clone)]
657pub struct MetaLearningConfig {
658 pub algorithm: MetaLearningAlgorithm,
660 pub inner_steps: usize,
662 pub outer_steps: usize,
664 pub meta_learning_rate: f64,
666 pub inner_learning_rate: f64,
668 pub task_batch_size: usize,
670 pub support_set_size: usize,
672 pub query_set_size: usize,
674 pub second_order: bool,
676 pub gradient_clip: f64,
678 pub adaptation_strategies: Vec<AdaptationStrategy>,
680 pub transfer_settings: TransferLearningSettings,
682 pub continual_settings: ContinualLearningSettings,
684 pub multitask_settings: MultiTaskSettings,
686 pub few_shot_settings: FewShotSettings,
688 pub enable_meta_regularization: bool,
690 pub meta_regularization_strength: f64,
692 pub task_sampling_strategy: TaskSamplingStrategy,
694}
695#[derive(Debug, Clone, Copy)]
697pub enum TaskSamplingStrategy {
698 Uniform,
699 Curriculum,
700 DifficultyBased,
701 DiversityBased,
702 ActiveLearning,
703 Adversarial,
704}
705#[derive(Debug, Clone)]
707pub struct FewShotResult<T: Float + Debug + Send + Sync + 'static> {
708 pub accuracy: T,
709 pub confidence: T,
710 pub adaptation_steps: usize,
711 pub uncertainty_estimates: Vec<T>,
712}
713
714impl Default for MetaLearningConfig {
715 fn default() -> Self {
718 Self {
719 algorithm: MetaLearningAlgorithm::MAML,
720 inner_steps: 5,
721 outer_steps: 100,
722 meta_learning_rate: 0.3,
723 inner_learning_rate: 0.4,
724 task_batch_size: 8,
725 support_set_size: 6,
726 query_set_size: 6,
727 second_order: false,
728 gradient_clip: 10.0,
729 adaptation_strategies: vec![AdaptationStrategy::FullFineTuning],
730 transfer_settings: TransferLearningSettings {
731 domain_adaptation: true,
732 source_domain_weights: vec![1.0],
733 strategies: vec![TransferStrategy::FineTuning],
734 similarity_measures: vec![SimilarityMeasure::CosineDistance],
735 progressive_transfer: false,
736 },
737 continual_settings: ContinualLearningSettings {
738 anti_forgetting_strategies: vec![
739 AntiForgettingStrategy::ElasticWeightConsolidation,
740 ],
741 memory_replay: MemoryReplaySettings {
742 buffer_size: 256,
743 replay_strategy: ReplayStrategy::Random,
744 replay_frequency: 8,
745 selection_criteria: MemorySelectionCriteria::Random,
746 },
747 task_identification: TaskIdentificationMethod::Oracle,
748 plasticity_stability_balance: 0.5,
749 },
750 multitask_settings: MultiTaskSettings {
751 task_weighting: TaskWeightingStrategy::Uniform,
752 gradient_balancing: GradientBalancingMethod::Uniform,
753 interference_mitigation: InterferenceMitigationStrategy::OrthogonalGradients,
754 shared_representation: SharedRepresentationStrategy::HardSharing,
755 },
756 few_shot_settings: FewShotSettings {
757 num_shots: 5,
758 num_ways: 2,
759 algorithm: FewShotAlgorithm::MAML,
760 metric_learning: MetricLearningSettings {
761 distance_metric: DistanceMetric::Euclidean,
762 embedding_dim: 16,
763 learned_metric: false,
764 },
765 augmentation_strategies: Vec::new(),
766 },
767 enable_meta_regularization: false,
768 meta_regularization_strength: 0.0,
769 task_sampling_strategy: TaskSamplingStrategy::Uniform,
770 }
771 }
772}
773
774impl MetaLearningConfig {
775 pub fn validate(&self) -> Result<()> {
777 if self.inner_steps == 0 {
778 return Err(OptimError::InvalidConfig(
779 "inner_steps must be greater than zero".to_string(),
780 ));
781 }
782 if self.task_batch_size == 0 {
783 return Err(OptimError::InvalidConfig(
784 "task_batch_size must be greater than zero".to_string(),
785 ));
786 }
787 if !(self.meta_learning_rate.is_finite() && self.meta_learning_rate > 0.0) {
788 return Err(OptimError::InvalidConfig(
789 "meta_learning_rate must be finite and positive".to_string(),
790 ));
791 }
792 if !(self.inner_learning_rate.is_finite() && self.inner_learning_rate > 0.0) {
793 return Err(OptimError::InvalidConfig(
794 "inner_learning_rate must be finite and positive".to_string(),
795 ));
796 }
797 if !(self.gradient_clip.is_finite() && self.gradient_clip > 0.0) {
798 return Err(OptimError::InvalidConfig(
799 "gradient_clip must be finite and positive".to_string(),
800 ));
801 }
802 if !(0.0..=1.0).contains(&self.continual_settings.plasticity_stability_balance) {
803 return Err(OptimError::InvalidConfig(
804 "plasticity_stability_balance must lie in [0, 1]".to_string(),
805 ));
806 }
807 Ok(())
808 }
809}