]>
git.proxmox.com Git - rustc.git/blob - vendor/criterion/src/stats/univariate/kde/mod.rs
c54de55a211e21a5d7368b2ba787be7500e66393
1 //! Kernel density estimation
5 use self::kernel
::Kernel
;
6 use crate::stats
::float
::Float
;
7 use crate::stats
::univariate
::Sample
;
8 #[cfg(feature = "rayon")]
11 /// Univariate kernel density estimator
12 pub struct Kde
<'a
, A
, K
>
19 sample
: &'a Sample
<A
>,
22 impl<'a
, A
, K
> Kde
<'a
, A
, K
>
27 /// Creates a new kernel density estimator from the `sample`, using a kernel and estimating
28 /// the bandwidth using the method `bw`
29 pub fn new(sample
: &'a Sample
<A
>, kernel
: K
, bw
: Bandwidth
) -> Kde
<'a
, A
, K
> {
31 bandwidth
: bw
.estimate(sample
),
37 /// Returns the bandwidth used by the estimator
38 pub fn bandwidth(&self) -> A
{
42 /// Maps the KDE over `xs`
45 pub fn map(&self, xs
: &[A
]) -> Box
<[A
]> {
46 #[cfg(feature = "rayon")]
47 let iter
= xs
.par_iter();
49 #[cfg(not(feature = "rayon"))]
52 iter
.map(|&x
| self.estimate(x
))
57 /// Estimates the probability density of `x`
58 pub fn estimate(&self, x
: A
) -> A
{
60 let slice
= self.sample
;
61 let h
= self.bandwidth
;
62 let n
= A
::cast(slice
.len());
66 .fold(_0
, |acc
, &x_i
| acc
+ self.kernel
.evaluate((x
- x_i
) / h
));
72 /// Method to estimate the bandwidth
74 /// Use Silverman's rule of thumb to estimate the bandwidth from the sample
79 fn estimate
<A
: Float
>(self, sample
: &Sample
<A
>) -> A
{
81 Bandwidth
::Silverman
=> {
82 let factor
= A
::cast(4. / 3.);
83 let exponent
= A
::cast(1. / 5.);
84 let n
= A
::cast(sample
.len());
85 let sigma
= sample
.std_dev(None
);
87 sigma
* (factor
/ n
).powf(exponent
)
97 use approx
::relative_eq
;
98 use quickcheck
::quickcheck
;
99 use quickcheck
::TestResult
;
101 use crate::stats
::univariate
::kde
::kernel
::Gaussian
;
102 use crate::stats
::univariate
::kde
::{Bandwidth, Kde}
;
103 use crate::stats
::univariate
::Sample
;
105 // The [-inf inf] integral of the estimated PDF should be one
107 fn integral(size
: u8, start
: u8) -> TestResult
{
108 let size
= size
as usize;
109 let start
= start
as usize;
110 const DX
: $ty
= 1e
-3;
112 if let Some(v
) = crate::stats
::test
::vec
::<$ty
>(size
, start
) {
113 let slice
= &v
[start
..];
114 let data
= Sample
::new(slice
);
115 let kde
= Kde
::new(data
, Gaussian
, Bandwidth
::Silverman
);
116 let h
= kde
.bandwidth();
117 // NB Obviously a [-inf inf] integral is not feasible, but this range works
119 let (a
, b
) = (data
.min() - 5. * h
, data
.max() + 5. * h
);
123 let mut y
= kde
.estimate(a
);
134 TestResult
::from_bool(relative_eq
!(acc
, 1., epsilon
= 2e
-5))
136 TestResult
::discard()