Closed nilgoyette closed 5 years ago
Thanks for working on this! I am bit busy at the moment, I'll try get back to this during the weekend (hopefully with some answers to the points you have raised).
- I moved all "summary statistic" tests. Sadly github shows them as a deleted and a new file. Sorry, I should have used
git mv
. Ctrl-fweighted_var
andweighted_std
to know what I actually changed.
No worries, not a big deal.
- I'm not too sure about ddof. I know that 0.0 and 1.0 work, but I don't actually know what others ddof do. ndarray's definition of ddof is different, so I'm probably wrong :)
I have yet to find a use for ddof
outside of 0
and 1
. In ndarray
we have been slightly more permissive (letting it range from >0
to <n
), but unless we have a concrete example I am actually ok to constrain it to [0,1]
.
- How can
A::from_usize(0)
fails? Anunwrap
would be safe, no?
Well, that's exactly what we are doing :grin:
We are just using expect
instead of unwrap
to provide a better error message in the unlikely (but still possible) event of a panic. We should use expect
also when doing A::from_usize(1)
and we should add this panic condition to documentation of the various new methods.
- I picked the first 1-pass+weights algorithm that I found. I don't know if there are better or faster algorithm around, or if it accepts other ddof than 0.0 and 1.0. All I know is that it does give the same results as the 2-pass algorithm.
To notice a difference you need to evaluate it on arrays with a lot of elements, even better if they lead to somewhat badly conditioned operations. The first issue there is the summing algorithm we are using, the naive one. Using pairwise summation would greatly improve numerical stability, but there are pros and cons at the moment, considering that we do not have specialization.
Overall it looks good to me :+1:
I have left a couple of comments. Could you add some benchmarks for these new methods?
I am curious to see if we can make them faster using azip
instead of zipping together using .iter
. There are also some opportunities to use mul_add
that we should probably leverage to make it faster and more precise.
I added a benchmark (azip! was slower) but I'm not sure about using mul_add because criterion tells me that it's slower. It's more precise though (from 1e-10 to 1e-11). I'll add it if you want.
That's interesting! Could you post criterion
's plot? I'll try to run them later on my machine as well.
I replace
mean += (w / weight_sum) * x_minus_mean;
s += w * x_minus_mean * (x - mean);
with
mean = (w / weight_sum).mul_add(x_minus_mean, mean);
s = (w * x_minus_mean).mul_add(x - mean, s);
cargo bench
gives something like
/10 Change within noise threshold.
/100 +2.6839%
/1000 +3.0680%
/10000 +1.9234%
The performance impact looks even more severe on my machine:
I'd say we can go without mul_add
for now and then revise if we find out we need to squeeze more precision.
Same story for Zip
(quite interesting actually):
I'd say we are good to go :muscle: Thanks for working on this!
Here's the var/std version.
git mv
. Ctrl-fweighted_var
andweighted_std
to know what I actually changed.A::from_usize(0)
fails? Anunwrap
would be safe, no?