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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! Core data types for streaming samples.
use serde::{Deserialize, Serialize};
// Re-export core observation types
pub use irithyll_core::{Observation, SampleRef};
// ---------------------------------------------------------------------------
// Sample -- owned observation
// ---------------------------------------------------------------------------
/// A single observation with feature vector and target value.
///
/// For regression, `target` is the continuous value to predict.
/// For binary classification, `target` is 0.0 or 1.0.
/// For multi-class, `target` is the class index as f64 (0.0, 1.0, 2.0, ...).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Sample {
/// Feature values for this observation.
pub features: Vec<f64>,
/// Target value (regression) or class label (classification).
pub target: f64,
/// Optional sample weight (default 1.0).
pub weight: f64,
}
impl Sample {
/// Create a new sample with unit weight.
#[inline]
pub fn new(features: Vec<f64>, target: f64) -> Self {
Self {
features,
target,
weight: 1.0,
}
}
/// Create a new sample with explicit weight.
#[inline]
pub fn weighted(features: Vec<f64>, target: f64, weight: f64) -> Self {
Self {
features,
target,
weight,
}
}
/// Number of features in this sample.
#[inline]
pub fn n_features(&self) -> usize {
self.features.len()
}
}
impl std::fmt::Display for Sample {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Sample(features=[{}], target={})",
self.features
.iter()
.map(|v| format!("{:.4}", v))
.collect::<Vec<_>>()
.join(", "),
self.target
)
}
}
impl Observation for Sample {
#[inline]
fn features(&self) -> &[f64] {
&self.features
}
#[inline]
fn target(&self) -> f64 {
self.target
}
#[inline]
fn weight(&self) -> f64 {
self.weight
}
}
impl Observation for &Sample {
#[inline]
fn features(&self) -> &[f64] {
&self.features
}
#[inline]
fn target(&self) -> f64 {
self.target
}
#[inline]
fn weight(&self) -> f64 {
self.weight
}
}
// ---------------------------------------------------------------------------
// From impls -- conversion convenience
// ---------------------------------------------------------------------------
impl From<(Vec<f64>, f64)> for Sample {
fn from((features, target): (Vec<f64>, f64)) -> Self {
Sample::new(features, target)
}
}