Change alg for computing variance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
bc88c632d1
commit
21148033e2
@ -232,21 +232,20 @@ func compStats(vals []float64) (float64, float64) {
|
|||||||
type stats struct {
|
type stats struct {
|
||||||
count float64
|
count float64
|
||||||
mean float64
|
mean float64
|
||||||
dSqr float64
|
m2 float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stats) AddPoint(value float64) {
|
func (s *stats) AddPoint(value float64) {
|
||||||
s.count++
|
// based on https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm
|
||||||
meanDiff := (value - s.mean) / s.count
|
s.count += 1
|
||||||
newMean := s.mean + meanDiff
|
delta := value - s.mean
|
||||||
|
s.mean += delta / s.count
|
||||||
dSqrtInc := (value - newMean) * (value - s.mean)
|
delta2 := value - s.mean
|
||||||
s.dSqr += dSqrtInc
|
s.m2 += delta * delta2
|
||||||
s.mean = newMean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stats) variance() float64 {
|
func (s *stats) variance() float64 {
|
||||||
return s.dSqr / (s.count - 1)
|
return s.m2 / (s.count - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s1 *stats) Combine(s2 *stats) {
|
func (s1 *stats) Combine(s2 *stats) {
|
||||||
@ -268,14 +267,12 @@ func (s1 *stats) Combine(s2 *stats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newCount := s1.count + s2.count
|
newCount := s1.count + s2.count
|
||||||
newMean := s1.count*s1.mean + s2.count*s2.mean
|
delta := s2.mean - s1.mean
|
||||||
newMean /= newCount
|
meanDelta := delta * s2.count / newCount
|
||||||
newVar := s1.count * (s1.variance() + (s1.mean-newMean)*(s1.mean-newMean))
|
m2 := s1.m2 + s2.m2 + delta*meanDelta*s1.count
|
||||||
newVar += s2.count * (s2.variance() + (s2.mean-newMean)*(s2.mean-newMean))
|
|
||||||
newVar /= newCount
|
|
||||||
s1.count = newCount
|
s1.count = newCount
|
||||||
s1.mean = newMean
|
s1.mean += meanDelta
|
||||||
s1.dSqr = newVar * (newCount - 1)
|
s1.m2 = m2
|
||||||
}
|
}
|
||||||
|
|
||||||
func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
|
func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
|
||||||
|
@ -9,12 +9,12 @@ import (
|
|||||||
func TestStats(t *testing.T) {
|
func TestStats(t *testing.T) {
|
||||||
N := 16
|
N := 16
|
||||||
ss := make([]*stats, N)
|
ss := make([]*stats, N)
|
||||||
|
rng := rand.New(rand.NewSource(1))
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
ss[i] = &stats{}
|
ss[i] = &stats{}
|
||||||
maxJ := rand.Intn(1000)
|
maxJ := rng.Intn(1000)
|
||||||
for j := 0; j < maxJ; j++ {
|
for j := 0; j < maxJ; j++ {
|
||||||
ss[i].AddPoint(rand.NormFloat64()*5 + 500)
|
ss[i].AddPoint(rng.NormFloat64()*5 + 500)
|
||||||
ss[i].AddPoint(rand.NormFloat64()*5 + 1000)
|
|
||||||
}
|
}
|
||||||
t.Logf("mean: %f, stddev: %f, count %f", ss[i].mean, math.Sqrt(ss[i].variance()), ss[i].count)
|
t.Logf("mean: %f, stddev: %f, count %f", ss[i].mean, math.Sqrt(ss[i].variance()), ss[i].count)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user