fetish_lib/
fourier_feature_collection.rs1extern crate ndarray;
2extern crate ndarray_linalg;
3
4use ndarray::*;
5
6use crate::feature_collection::*;
7use crate::linalg_utils::*;
8use rand::prelude::*;
9use crate::params::*;
10
11#[derive(Clone)]
13pub struct FourierFeatureCollection {
14 in_dimensions : usize,
15 num_features : usize,
16 alpha : f32,
17 ws : Array2<f32> }
19
20impl FourierFeatureCollection {
21 pub fn new(in_dimensions: usize, num_features : usize,
27 alpha : f32,
28 generator : fn(&mut ThreadRng, usize) -> Array1<f32>) -> FourierFeatureCollection {
29
30 let mut ws = Array::zeros((num_features, in_dimensions));
31 let mut rng = rand::thread_rng();
32 for i in 0..num_features {
33 let feature = generator(&mut rng, in_dimensions);
34 for j in 0..in_dimensions {
35 ws[[i, j]] = feature[[j,]];
36 }
37 }
38
39 FourierFeatureCollection {
40 in_dimensions,
41 num_features,
42 alpha,
43 ws
44 }
45 }
46}
47
48impl FeatureCollection for FourierFeatureCollection {
49 fn get_features(&self, in_vec: ArrayView1<f32>) -> Array1<f32> {
50 let dotted = self.ws.dot(&in_vec);
51 let sine = dotted.mapv(f32::sin);
52 let cosine = dotted.mapv(f32::cos);
53
54 let result = stack(Axis(0), &[sine.view(), cosine.view()]).unwrap();
55
56 self.alpha * result
57 }
58
59 fn get_jacobian(&self, in_vec: ArrayView1<f32>) -> Array2<f32> {
60 let dotted = self.ws.dot(&in_vec);
64 let cos = dotted.mapv(f32::cos);
65 let neg_sine = -dotted.mapv(f32::sin);
66
67 let part_one = scale_rows(self.ws.view(), cos.view());
68 let part_two = scale_rows(self.ws.view(), neg_sine.view());
69
70 let result = stack(Axis(0), &[part_one.view(), part_two.view()]).unwrap()
71 .into_dimensionality::<Ix2>().unwrap();
72
73 self.alpha * result
74 }
75
76 fn get_in_dimensions(&self) -> usize {
77 self.in_dimensions
78 }
79
80 fn get_dimension(&self) -> usize {
81 self.num_features * 2
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::test_utils::*;
89 use crate::rand_utils::*;
90
91 #[test]
92 fn empirical_jacobian_is_jacobian() {
93 let mut successes : usize = 0;
94 for _ in 0..10 {
95 let fourier_feature_collection = FourierFeatureCollection::new(10, 15, 1.0f32, gen_nsphere_random);
96 let in_vec = random_vector(10);
97 let jacobian = fourier_feature_collection.get_jacobian(in_vec.view());
98 let empirical_jacobian = empirical_jacobian(|x| fourier_feature_collection.get_features(x),
99 in_vec.view());
100 let test = are_equal_matrices_to_within(jacobian.view(), empirical_jacobian.view(), 1.0f32, false);
101 if (test) {
102 successes += 1;
103 }
104 }
105 if (successes < 5) {
106 panic!();
107 }
108 }
109}