Skip to main content

irithyll/
sample.rs

1//! Core data types for streaming samples.
2
3use serde::{Deserialize, Serialize};
4
5// Re-export core observation types
6pub use irithyll_core::{Observation, SampleRef};
7
8// ---------------------------------------------------------------------------
9// Sample -- owned observation
10// ---------------------------------------------------------------------------
11
12/// A single observation with feature vector and target value.
13///
14/// For regression, `target` is the continuous value to predict.
15/// For binary classification, `target` is 0.0 or 1.0.
16/// For multi-class, `target` is the class index as f64 (0.0, 1.0, 2.0, ...).
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Sample {
19    /// Feature values for this observation.
20    pub features: Vec<f64>,
21    /// Target value (regression) or class label (classification).
22    pub target: f64,
23    /// Optional sample weight (default 1.0).
24    pub weight: f64,
25}
26
27impl Sample {
28    /// Create a new sample with unit weight.
29    #[inline]
30    pub fn new(features: Vec<f64>, target: f64) -> Self {
31        Self {
32            features,
33            target,
34            weight: 1.0,
35        }
36    }
37
38    /// Create a new sample with explicit weight.
39    #[inline]
40    pub fn weighted(features: Vec<f64>, target: f64, weight: f64) -> Self {
41        Self {
42            features,
43            target,
44            weight,
45        }
46    }
47
48    /// Number of features in this sample.
49    #[inline]
50    pub fn n_features(&self) -> usize {
51        self.features.len()
52    }
53}
54
55impl std::fmt::Display for Sample {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        write!(
58            f,
59            "Sample(features=[{}], target={})",
60            self.features
61                .iter()
62                .map(|v| format!("{:.4}", v))
63                .collect::<Vec<_>>()
64                .join(", "),
65            self.target
66        )
67    }
68}
69
70impl Observation for Sample {
71    #[inline]
72    fn features(&self) -> &[f64] {
73        &self.features
74    }
75    #[inline]
76    fn target(&self) -> f64 {
77        self.target
78    }
79    #[inline]
80    fn weight(&self) -> f64 {
81        self.weight
82    }
83}
84
85impl Observation for &Sample {
86    #[inline]
87    fn features(&self) -> &[f64] {
88        &self.features
89    }
90    #[inline]
91    fn target(&self) -> f64 {
92        self.target
93    }
94    #[inline]
95    fn weight(&self) -> f64 {
96        self.weight
97    }
98}
99
100// ---------------------------------------------------------------------------
101// From impls -- conversion convenience
102// ---------------------------------------------------------------------------
103
104impl From<(Vec<f64>, f64)> for Sample {
105    fn from((features, target): (Vec<f64>, f64)) -> Self {
106        Sample::new(features, target)
107    }
108}