spawn_access_control/
ml_metrics.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use std::time::Duration;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelMetrics {
    pub model_id: String,
    pub timestamp: DateTime<Utc>,
    pub accuracy: f64,
    pub precision: f64,
    pub recall: f64,
    pub f1_score: f64,
    pub confusion_matrix: ConfusionMatrix,
    pub feature_importance: HashMap<String, f64>,
    pub training_duration: Duration,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfusionMatrix {
    pub true_positives: u32,
    pub true_negatives: u32,
    pub false_positives: u32,
    pub false_negatives: u32,
}

impl ConfusionMatrix {
    pub fn new() -> Self {
        Self {
            true_positives: 0,
            true_negatives: 0,
            false_positives: 0,
            false_negatives: 0,
        }
    }

    pub fn update(&mut self, predicted: bool, actual: bool) {
        match (predicted, actual) {
            (true, true) => self.true_positives += 1,
            (false, false) => self.true_negatives += 1,
            (true, false) => self.false_positives += 1,
            (false, true) => self.false_negatives += 1,
        }
    }

    pub fn accuracy(&self) -> f64 {
        let total = self.total() as f64;
        if total == 0.0 {
            return 0.0;
        }
        (self.true_positives + self.true_negatives) as f64 / total
    }

    pub fn precision(&self) -> f64 {
        let predicted_positive = self.true_positives + self.false_positives;
        if predicted_positive == 0 {
            return 0.0;
        }
        self.true_positives as f64 / predicted_positive as f64
    }

    pub fn recall(&self) -> f64 {
        let actual_positive = self.true_positives + self.false_negatives;
        if actual_positive == 0 {
            return 0.0;
        }
        self.true_positives as f64 / actual_positive as f64
    }

    pub fn f1_score(&self) -> f64 {
        let precision = self.precision();
        let recall = self.recall();
        if precision + recall == 0.0 {
            return 0.0;
        }
        2.0 * (precision * recall) / (precision + recall)
    }

    fn total(&self) -> u32 {
        self.true_positives + self.true_negatives + 
        self.false_positives + self.false_negatives
    }
}