sklears_gaussian_process/
kernel_trait.rs1use scirs2_core::ndarray::{Array2, ArrayView1};
7use sklears_core::error::Result as SklResult;
8
9pub trait Kernel: std::fmt::Debug + Send + Sync {
14 fn compute_kernel_matrix(
16 &self,
17 X1: &Array2<f64>,
18 X2: Option<&Array2<f64>>,
19 ) -> SklResult<Array2<f64>>;
20
21 fn kernel(&self, x1: &ArrayView1<f64>, x2: &ArrayView1<f64>) -> f64;
23
24 fn get_params(&self) -> Vec<f64>;
26
27 fn set_params(&mut self, params: &[f64]) -> SklResult<()>;
29
30 fn clone_box(&self) -> Box<dyn Kernel>;
32
33 fn compute_kernel_gradient(
36 &self,
37 X1: &Array2<f64>,
38 X2: Option<&Array2<f64>>,
39 ) -> SklResult<Vec<Array2<f64>>> {
40 let X2 = X2.unwrap_or(X1);
42 let params = self.get_params();
43 let n_params = params.len();
44 let mut gradients = Vec::with_capacity(n_params);
45
46 let epsilon = 1e-8;
47 let base_matrix = self.compute_kernel_matrix(X1, Some(X2))?;
48
49 for i in 0..n_params {
50 let mut kernel_copy = self.clone_box();
51 let mut params_plus = params.clone();
52 params_plus[i] += epsilon;
53 kernel_copy.set_params(¶ms_plus)?;
54
55 let matrix_plus = kernel_copy.compute_kernel_matrix(X1, Some(X2))?;
56 let gradient = (&matrix_plus - &base_matrix) / epsilon;
57 gradients.push(gradient);
58 }
59
60 Ok(gradients)
61 }
62
63 fn kernel_gradient(&self, x1: &ArrayView1<f64>, x2: &ArrayView1<f64>) -> SklResult<Vec<f64>> {
66 let params = self.get_params();
68 let n_params = params.len();
69 let mut gradients = Vec::with_capacity(n_params);
70
71 let epsilon = 1e-8;
72 let base_value = self.kernel(x1, x2);
73
74 for i in 0..n_params {
75 let mut kernel_copy = self.clone_box();
76 let mut params_plus = params.clone();
77 params_plus[i] += epsilon;
78 kernel_copy.set_params(¶ms_plus)?;
79
80 let value_plus = kernel_copy.kernel(x1, x2);
81 let gradient = (value_plus - base_value) / epsilon;
82 gradients.push(gradient);
83 }
84
85 Ok(gradients)
86 }
87}
88
89impl Clone for Box<dyn Kernel> {
90 fn clone(&self) -> Self {
91 self.clone_box()
92 }
93}