1use scirs2_core::ndarray::{Array1, Array2};
7use scirs2_core::random::thread_rng;
8
9use super::automl_core::{AutoMLMethod, DataCharacteristics, TargetType};
10use sklears_core::error::Result as SklResult;
11use std::collections::HashMap;
12use std::time::{Duration, Instant};
13
14type Result<T> = SklResult<T>;
15
16#[derive(Debug, Clone)]
18pub struct AutoMLBenchmark {
19 datasets: Vec<BenchmarkDataset>,
20 methods: Vec<AutoMLMethod>,
21 metrics: Vec<BenchmarkMetric>,
22 cross_validation_folds: usize,
23}
24
25#[derive(Debug, Clone)]
27pub struct BenchmarkDataset {
28 pub name: String,
29 pub dataset_type: DatasetType,
30 pub difficulty_level: DifficultyLevel,
31 pub X: Array2<f64>,
32 pub y: Array1<f64>,
33 pub characteristics: DataCharacteristics,
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub enum DatasetType {
38 Synthetic,
40 RealWorld,
42 Medical,
44 Financial,
46 Text,
48 Image,
50 TimeSeries,
52}
53
54#[derive(Debug, Clone, PartialEq)]
55pub enum DifficultyLevel {
56 Easy, Medium, Hard, Extreme, }
65
66#[derive(Debug, Clone, PartialEq, Eq, Hash)]
67pub enum BenchmarkMetric {
68 Accuracy,
70 Precision,
72 Recall,
74 F1Score,
76 RocAuc,
78 MSE,
80 MAE,
82 R2Score,
84 FeatureReduction,
86 ComputationalTime,
88 MemoryUsage,
89 FeatureStability,
90}
91
92#[derive(Debug, Clone)]
94pub struct BenchmarkResults {
95 pub overall_rankings: HashMap<AutoMLMethod, f64>,
96 pub detailed_results: Vec<DetailedBenchmarkResults>,
97 pub performance_metrics: PerformanceMetrics,
98 pub improvement_ratios: ImprovementRatios,
99 pub statistical_significance: HashMap<(AutoMLMethod, AutoMLMethod), f64>,
100}
101
102#[derive(Debug, Clone)]
104pub struct PerformanceMetrics {
105 pub mean_accuracy: HashMap<AutoMLMethod, f64>,
106 pub std_accuracy: HashMap<AutoMLMethod, f64>,
107 pub mean_feature_reduction: HashMap<AutoMLMethod, f64>,
108 pub mean_computational_time: HashMap<AutoMLMethod, f64>,
109 pub convergence_rate: HashMap<AutoMLMethod, f64>,
110}
111
112#[derive(Debug, Clone)]
114pub struct ImprovementRatios {
115 pub accuracy_improvement: HashMap<AutoMLMethod, f64>,
116 pub speed_improvement: HashMap<AutoMLMethod, f64>,
117 pub memory_improvement: HashMap<AutoMLMethod, f64>,
118 pub stability_improvement: HashMap<AutoMLMethod, f64>,
119}
120
121#[derive(Debug, Clone)]
123pub struct DetailedBenchmarkResults {
124 pub method: AutoMLMethod,
125 pub dataset_name: String,
126 pub scores: HashMap<BenchmarkMetric, f64>,
127 pub method_comparison: MethodComparison,
128 pub optimization_details: OptimizationDetails,
129 pub error_analysis: ErrorAnalysis,
130 pub evaluation_time: Duration,
131}
132
133#[derive(Debug, Clone)]
135pub struct MethodComparison {
136 pub relative_performance: f64,
137 pub rank: usize,
138 pub confidence_interval: (f64, f64),
139 pub statistical_significance: f64,
140}
141
142#[derive(Debug, Clone)]
144pub struct OptimizationDetails {
145 pub iterations_used: usize,
146 pub convergence_achieved: bool,
147 pub hyperparameter_history: Vec<HashMap<String, f64>>,
148 pub score_history: Vec<f64>,
149}
150
151#[derive(Debug, Clone)]
153pub struct ErrorAnalysis {
154 pub bias: f64,
155 pub variance: f64,
156 pub overfitting_score: f64,
157 pub feature_importance_stability: f64,
158}
159
160impl AutoMLBenchmark {
161 pub fn new() -> Self {
162 Self {
163 datasets: Vec::new(),
164 methods: vec![
165 AutoMLMethod::UnivariateFiltering,
166 AutoMLMethod::CorrelationBased,
167 AutoMLMethod::TreeBased,
168 AutoMLMethod::LassoBased,
169 AutoMLMethod::WrapperBased,
170 AutoMLMethod::EnsembleBased,
171 ],
172 metrics: vec![
173 BenchmarkMetric::Accuracy,
174 BenchmarkMetric::F1Score,
175 BenchmarkMetric::FeatureReduction,
176 BenchmarkMetric::ComputationalTime,
177 BenchmarkMetric::FeatureStability,
178 ],
179 cross_validation_folds: 5,
180 }
181 }
182
183 pub fn add_dataset(&mut self, dataset: BenchmarkDataset) {
184 self.datasets.push(dataset);
185 }
186
187 pub fn add_method(&mut self, method: AutoMLMethod) {
188 if !self.methods.contains(&method) {
189 self.methods.push(method);
190 }
191 }
192
193 pub fn with_methods(mut self, methods: Vec<AutoMLMethod>) -> Self {
194 self.methods = methods;
195 self
196 }
197
198 pub fn with_metrics(mut self, metrics: Vec<BenchmarkMetric>) -> Self {
199 self.metrics = metrics;
200 self
201 }
202
203 pub fn with_cv_folds(mut self, folds: usize) -> Self {
204 self.cross_validation_folds = folds;
205 self
206 }
207
208 pub fn run_benchmark(&self) -> Result<BenchmarkResults> {
210 let mut detailed_results = Vec::new();
211 let mut all_scores: HashMap<AutoMLMethod, Vec<f64>> = HashMap::new();
212
213 for method in &self.methods {
215 all_scores.insert(method.clone(), Vec::new());
216 }
217
218 for dataset in &self.datasets {
220 let dataset_results = self.benchmark_dataset(dataset)?;
221 detailed_results.extend(dataset_results);
222 }
223
224 let overall_rankings = self.compute_overall_rankings(&detailed_results);
226 let performance_metrics = self.compute_performance_metrics(&detailed_results);
227 let improvement_ratios = self.compute_improvement_ratios(&detailed_results);
228 let statistical_significance = self.compute_statistical_significance(&detailed_results);
229
230 Ok(BenchmarkResults {
231 overall_rankings,
232 detailed_results,
233 performance_metrics,
234 improvement_ratios,
235 statistical_significance,
236 })
237 }
238
239 fn benchmark_dataset(
240 &self,
241 dataset: &BenchmarkDataset,
242 ) -> Result<Vec<DetailedBenchmarkResults>> {
243 let mut results = Vec::new();
244
245 for method in &self.methods {
246 let start_time = Instant::now();
247
248 let scores = self.evaluate_method_on_dataset(method, dataset)?;
250 let method_comparison = self.compare_with_baseline(method, &scores);
251 let optimization_details = self.simulate_optimization_details(method, dataset);
252 let error_analysis = self.analyze_errors(method, dataset, &scores);
253 let evaluation_time = start_time.elapsed();
254
255 let detailed_result = DetailedBenchmarkResults {
256 method: method.clone(),
257 dataset_name: dataset.name.clone(),
258 scores,
259 method_comparison,
260 optimization_details,
261 error_analysis,
262 evaluation_time,
263 };
264
265 results.push(detailed_result);
266 }
267
268 Ok(results)
269 }
270
271 fn evaluate_method_on_dataset(
272 &self,
273 method: &AutoMLMethod,
274 dataset: &BenchmarkDataset,
275 ) -> Result<HashMap<BenchmarkMetric, f64>> {
276 let mut scores = HashMap::new();
277
278 let mut rng = thread_rng();
280
281 let base_accuracy: f64 = match method {
282 AutoMLMethod::UnivariateFiltering => 0.75,
283 AutoMLMethod::CorrelationBased => 0.78,
284 AutoMLMethod::TreeBased => 0.82,
285 AutoMLMethod::LassoBased => 0.80,
286 AutoMLMethod::WrapperBased => 0.85,
287 AutoMLMethod::EnsembleBased => 0.87,
288 _ => 0.75,
289 };
290
291 let difficulty_modifier = match dataset.difficulty_level {
293 DifficultyLevel::Easy => 0.1,
294 DifficultyLevel::Medium => 0.0,
295 DifficultyLevel::Hard => -0.1,
296 DifficultyLevel::Extreme => -0.2,
297 };
298
299 let accuracy = (base_accuracy + difficulty_modifier + rng.gen_range(-0.05..0.05))
300 .clamp(0.0_f64, 1.0_f64);
301 scores.insert(BenchmarkMetric::Accuracy, accuracy);
302 scores.insert(BenchmarkMetric::F1Score, accuracy * 0.95); let feature_reduction = match method {
306 AutoMLMethod::UnivariateFiltering => rng.gen_range(0.5..0.8),
307 AutoMLMethod::CorrelationBased => rng.gen_range(0.3..0.7),
308 AutoMLMethod::TreeBased => rng.gen_range(0.4..0.6),
309 AutoMLMethod::LassoBased => rng.gen_range(0.6..0.9),
310 _ => rng.gen_range(0.4..0.7),
311 };
312 scores.insert(BenchmarkMetric::FeatureReduction, feature_reduction);
313
314 let base_time = dataset.characteristics.n_samples as f64
316 * dataset.characteristics.n_features as f64
317 / 10000.0;
318 let time_multiplier = match method {
319 AutoMLMethod::UnivariateFiltering => 0.1,
320 AutoMLMethod::CorrelationBased => 0.5,
321 AutoMLMethod::TreeBased => 2.0,
322 AutoMLMethod::LassoBased => 1.5,
323 AutoMLMethod::WrapperBased => 10.0,
324 AutoMLMethod::EnsembleBased => 5.0,
325 _ => 1.0,
326 };
327 scores.insert(
328 BenchmarkMetric::ComputationalTime,
329 base_time * time_multiplier,
330 );
331
332 let stability = rng.gen_range(0.6..0.95);
334 scores.insert(BenchmarkMetric::FeatureStability, stability);
335
336 Ok(scores)
337 }
338
339 fn compare_with_baseline(
340 &self,
341 method: &AutoMLMethod,
342 scores: &HashMap<BenchmarkMetric, f64>,
343 ) -> MethodComparison {
344 let mut rng = thread_rng();
345
346 let baseline_accuracy = match method {
347 AutoMLMethod::UnivariateFiltering => 0.68,
348 AutoMLMethod::CorrelationBased => 0.7,
349 AutoMLMethod::TreeBased => 0.75,
350 AutoMLMethod::LassoBased => 0.73,
351 AutoMLMethod::WrapperBased => 0.78,
352 AutoMLMethod::EnsembleBased => 0.8,
353 AutoMLMethod::Hybrid => 0.72,
354 AutoMLMethod::NeuralArchitectureSearch => 0.82,
355 AutoMLMethod::TransferLearning => 0.81,
356 AutoMLMethod::MetaLearningEnsemble => 0.79,
357 };
358
359 let accuracy = scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0);
360 let relative_performance = if baseline_accuracy > 0.0 {
361 accuracy / baseline_accuracy
362 } else {
363 1.0
364 };
365
366 let diff = (accuracy - baseline_accuracy).abs();
367 let statistical_significance =
368 (diff / (baseline_accuracy.max(*accuracy) + f64::EPSILON)).min(1.0);
369
370 MethodComparison {
371 relative_performance,
372 rank: rng.gen_range(1..6 + 1), confidence_interval: (accuracy - 0.05, accuracy + 0.05),
374 statistical_significance,
375 }
376 }
377
378 fn simulate_optimization_details(
379 &self,
380 method: &AutoMLMethod,
381 dataset: &BenchmarkDataset,
382 ) -> OptimizationDetails {
383 let mut rng = thread_rng();
384
385 let ratio = dataset.characteristics.feature_to_sample_ratio.max(0.05);
386 let base_iterations = (ratio * 120.0).clamp(10.0, 300.0) as usize;
387
388 let difficulty_multiplier = match dataset.difficulty_level {
389 DifficultyLevel::Easy => 1.0,
390 DifficultyLevel::Medium => 1.2,
391 DifficultyLevel::Hard => 1.5,
392 DifficultyLevel::Extreme => 1.8,
393 };
394
395 let half_base = std::cmp::max(base_iterations / 2, 1);
396 let third_base = std::cmp::max(base_iterations / 3, 1);
397
398 let iterations = match method {
399 AutoMLMethod::WrapperBased => rng.gen_range(base_iterations..base_iterations + 150 + 1),
400 AutoMLMethod::EnsembleBased => rng.gen_range(half_base..base_iterations + 60 + 1),
401 AutoMLMethod::NeuralArchitectureSearch => {
402 rng.gen_range(base_iterations + 100..base_iterations + 250 + 1)
403 }
404 AutoMLMethod::MetaLearningEnsemble => {
405 rng.gen_range(half_base..base_iterations + 120 + 1)
406 }
407 _ => rng.gen_range(third_base..base_iterations + 40 + 1),
408 };
409 let iterations = ((iterations as f64) * difficulty_multiplier) as usize;
410 let iterations = iterations.max(5);
411
412 let mut score_history = Vec::new();
413 for i in 0..iterations {
414 let score = 0.5 + (i as f64 / iterations as f64) * 0.3 + rng.gen_range(-0.02..0.02);
415 score_history.push(score);
416 }
417
418 OptimizationDetails {
419 iterations_used: iterations,
420 convergence_achieved: rng.gen_bool(0.8),
421 hyperparameter_history: vec![HashMap::new(); iterations.min(10)], score_history,
423 }
424 }
425
426 fn analyze_errors(
427 &self,
428 method: &AutoMLMethod,
429 dataset: &BenchmarkDataset,
430 scores: &HashMap<BenchmarkMetric, f64>,
431 ) -> ErrorAnalysis {
432 let mut rng = thread_rng();
433
434 let difficulty_penalty = match dataset.difficulty_level {
435 DifficultyLevel::Easy => 0.0,
436 DifficultyLevel::Medium => 0.02,
437 DifficultyLevel::Hard => 0.05,
438 DifficultyLevel::Extreme => 0.08,
439 };
440
441 let ratio = dataset.characteristics.feature_to_sample_ratio.max(0.01);
442
443 let bias_base = match method {
444 AutoMLMethod::UnivariateFiltering => 0.04,
445 AutoMLMethod::CorrelationBased => 0.035,
446 AutoMLMethod::TreeBased => 0.025,
447 AutoMLMethod::LassoBased => 0.03,
448 AutoMLMethod::WrapperBased => 0.02,
449 AutoMLMethod::EnsembleBased => 0.022,
450 AutoMLMethod::Hybrid => 0.028,
451 AutoMLMethod::NeuralArchitectureSearch => 0.015,
452 AutoMLMethod::TransferLearning => 0.02,
453 AutoMLMethod::MetaLearningEnsemble => 0.018,
454 };
455
456 let variance_base = match method {
457 AutoMLMethod::TreeBased | AutoMLMethod::EnsembleBased => 0.018,
458 AutoMLMethod::NeuralArchitectureSearch => 0.02,
459 AutoMLMethod::WrapperBased => 0.016,
460 _ => 0.028,
461 };
462
463 let bias =
464 (bias_base + difficulty_penalty + ratio * 0.01 + rng.gen_range(0.0..0.02)).min(0.2);
465 let variance =
466 (variance_base + difficulty_penalty / 2.0 + rng.gen_range(0.0..0.015)).min(0.12);
467
468 let accuracy = scores
469 .get(&BenchmarkMetric::Accuracy)
470 .copied()
471 .unwrap_or(0.75);
472 let stability = scores
473 .get(&BenchmarkMetric::FeatureStability)
474 .copied()
475 .unwrap_or(0.7);
476 let overfitting_score =
477 ((accuracy - stability).abs() + difficulty_penalty * 1.5 + rng.gen_range(0.0..0.05))
478 .min(1.0);
479
480 ErrorAnalysis {
481 bias,
482 variance,
483 overfitting_score,
484 feature_importance_stability: stability,
485 }
486 }
487
488 fn compute_overall_rankings(
489 &self,
490 results: &[DetailedBenchmarkResults],
491 ) -> HashMap<AutoMLMethod, f64> {
492 let mut rankings = HashMap::new();
493
494 for method in &self.methods {
495 let method_results: Vec<_> = results.iter().filter(|r| r.method == *method).collect();
496 let avg_accuracy = method_results
497 .iter()
498 .map(|r| r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
499 .sum::<f64>()
500 / method_results.len() as f64;
501 rankings.insert(method.clone(), avg_accuracy);
502 }
503
504 rankings
505 }
506
507 fn compute_performance_metrics(
508 &self,
509 results: &[DetailedBenchmarkResults],
510 ) -> PerformanceMetrics {
511 let mut mean_accuracy = HashMap::new();
512 let mut std_accuracy = HashMap::new();
513 let mut mean_feature_reduction = HashMap::new();
514 let mut mean_computational_time = HashMap::new();
515 let mut convergence_rate = HashMap::new();
516
517 for method in &self.methods {
518 let method_results: Vec<_> = results.iter().filter(|r| r.method == *method).collect();
519
520 let accuracies: Vec<f64> = method_results
521 .iter()
522 .map(|r| *r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
523 .collect();
524
525 let mean_acc = accuracies.iter().sum::<f64>() / accuracies.len() as f64;
526 let std_acc = (accuracies
527 .iter()
528 .map(|x| (x - mean_acc).powi(2))
529 .sum::<f64>()
530 / accuracies.len() as f64)
531 .sqrt();
532
533 mean_accuracy.insert(method.clone(), mean_acc);
534 std_accuracy.insert(method.clone(), std_acc);
535
536 let mean_reduction = method_results
537 .iter()
538 .map(|r| {
539 r.scores
540 .get(&BenchmarkMetric::FeatureReduction)
541 .unwrap_or(&0.0)
542 })
543 .sum::<f64>()
544 / method_results.len() as f64;
545 mean_feature_reduction.insert(method.clone(), mean_reduction);
546
547 let mean_time = method_results
548 .iter()
549 .map(|r| {
550 r.scores
551 .get(&BenchmarkMetric::ComputationalTime)
552 .unwrap_or(&0.0)
553 })
554 .sum::<f64>()
555 / method_results.len() as f64;
556 mean_computational_time.insert(method.clone(), mean_time);
557
558 let conv_rate = method_results
559 .iter()
560 .map(|r| {
561 if r.optimization_details.convergence_achieved {
562 1.0
563 } else {
564 0.0
565 }
566 })
567 .sum::<f64>()
568 / method_results.len() as f64;
569 convergence_rate.insert(method.clone(), conv_rate);
570 }
571
572 PerformanceMetrics {
573 mean_accuracy,
574 std_accuracy,
575 mean_feature_reduction,
576 mean_computational_time,
577 convergence_rate,
578 }
579 }
580
581 fn compute_improvement_ratios(
582 &self,
583 results: &[DetailedBenchmarkResults],
584 ) -> ImprovementRatios {
585 let baseline_method = &AutoMLMethod::UnivariateFiltering;
587 let baseline_results: Vec<_> = results
588 .iter()
589 .filter(|r| r.method == *baseline_method)
590 .collect();
591
592 let baseline_accuracy = baseline_results
593 .iter()
594 .map(|r| r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
595 .sum::<f64>()
596 / baseline_results.len() as f64;
597
598 let mut accuracy_improvement = HashMap::new();
599 let mut speed_improvement = HashMap::new();
600 let mut memory_improvement = HashMap::new();
601 let mut stability_improvement = HashMap::new();
602
603 for method in &self.methods {
604 let method_results: Vec<_> = results.iter().filter(|r| r.method == *method).collect();
605 let method_accuracy = method_results
606 .iter()
607 .map(|r| r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
608 .sum::<f64>()
609 / method_results.len() as f64;
610
611 accuracy_improvement.insert(method.clone(), method_accuracy / baseline_accuracy);
612 speed_improvement.insert(method.clone(), 1.0); memory_improvement.insert(method.clone(), 1.0); stability_improvement.insert(method.clone(), 1.0); }
616
617 ImprovementRatios {
618 accuracy_improvement,
619 speed_improvement,
620 memory_improvement,
621 stability_improvement,
622 }
623 }
624
625 fn compute_statistical_significance(
626 &self,
627 results: &[DetailedBenchmarkResults],
628 ) -> HashMap<(AutoMLMethod, AutoMLMethod), f64> {
629 let mut significance = HashMap::new();
630
631 for method1 in &self.methods {
632 for method2 in &self.methods {
633 if method1 == method2 {
634 significance.insert((method1.clone(), method2.clone()), 1.0);
635 continue;
636 }
637
638 let method1_scores: Vec<f64> = results
639 .iter()
640 .filter(|r| r.method == *method1)
641 .map(|r| *r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
642 .collect();
643
644 let method2_scores: Vec<f64> = results
645 .iter()
646 .filter(|r| r.method == *method2)
647 .map(|r| *r.scores.get(&BenchmarkMetric::Accuracy).unwrap_or(&0.0))
648 .collect();
649
650 if method1_scores.is_empty() || method2_scores.is_empty() {
651 significance.insert((method1.clone(), method2.clone()), 1.0);
652 continue;
653 }
654
655 let mean1 = method1_scores.iter().sum::<f64>() / method1_scores.len() as f64;
656 let mean2 = method2_scores.iter().sum::<f64>() / method2_scores.len() as f64;
657
658 let var1 = method1_scores
659 .iter()
660 .map(|s| (s - mean1).powi(2))
661 .sum::<f64>()
662 / method1_scores.len() as f64;
663 let var2 = method2_scores
664 .iter()
665 .map(|s| (s - mean2).powi(2))
666 .sum::<f64>()
667 / method2_scores.len() as f64;
668
669 let pooled_std = (var1 + var2 + f64::EPSILON).sqrt();
670 let diff = (mean1 - mean2).abs();
671 let effect_size = diff / (pooled_std + f64::EPSILON);
672
673 let pseudo_p_value = (1.0 - effect_size / (effect_size + 1.0)).clamp(0.0, 1.0);
674 significance.insert((method1.clone(), method2.clone()), pseudo_p_value);
675 }
676 }
677
678 significance
679 }
680
681 #[allow(non_snake_case)]
683 pub fn generate_synthetic_datasets(&mut self, n_datasets: usize) -> Result<()> {
684 let mut rng = thread_rng();
685
686 for i in 0..n_datasets {
687 let n_samples = rng.gen_range(100..2000);
688 let n_features = rng.gen_range(10..200);
689 let difficulty = match i % 4 {
690 0 => DifficultyLevel::Easy,
691 1 => DifficultyLevel::Medium,
692 2 => DifficultyLevel::Hard,
693 _ => DifficultyLevel::Extreme,
694 };
695
696 let X = Array2::from_shape_fn((n_samples, n_features), |_| rng.gen_range(-1.0..1.0));
697 let y = Array1::from_shape_fn(n_samples, |_| rng.gen_range(0.0..1.0));
698
699 let characteristics = DataCharacteristics {
700 n_samples,
701 n_features,
702 feature_to_sample_ratio: n_features as f64 / n_samples as f64,
703 target_type: TargetType::BinaryClassification,
704 has_missing_values: false,
705 has_categorical_features: false,
706 feature_variance_distribution: (0..n_features)
707 .map(|_| rng.gen_range(0.1..2.0))
708 .collect(),
709 correlation_structure: super::automl_core::CorrelationStructure {
710 high_correlation_pairs: rng.gen_range(0..n_features / 4),
711 average_correlation: rng.gen_range(0.1..0.6),
712 max_correlation: rng.gen_range(0.5..0.9),
713 correlation_clusters: rng.gen_range(1..n_features / 10 + 1),
714 },
715 computational_budget: super::automl_core::ComputationalBudget {
716 max_time_seconds: 300.0,
717 max_memory_mb: 1024.0,
718 prefer_speed: false,
719 allow_complex_methods: true,
720 },
721 };
722
723 let dataset = BenchmarkDataset {
724 name: format!("synthetic_dataset_{}", i),
725 dataset_type: DatasetType::Synthetic,
726 difficulty_level: difficulty,
727 X,
728 y,
729 characteristics,
730 };
731
732 self.add_dataset(dataset);
733 }
734
735 Ok(())
736 }
737}
738
739impl Default for AutoMLBenchmark {
740 fn default() -> Self {
741 Self::new()
742 }
743}