// Estimate computes model parameters using sufficient statistics. func (g *Model) Estimate() error { if g.NSamples > minNumSamples { /* Estimate the mean. */ floatx.Apply(floatx.ScaleFunc(1.0/g.NSamples), g.Sumx, g.Mean) /* * Estimate the variance. sigma_sq = 1/n (sumxsq - 1/n sumx^2) or * 1/n sumxsq - mean^2. */ tmp := g.variance // borrow as an intermediate array. // floatx.Apply(sq, g.Mean, g.tmpArray) floatx.Sq(g.tmpArray, g.Mean) floatx.Apply(floatx.ScaleFunc(1.0/g.NSamples), g.Sumxsq, tmp) floats.SubTo(g.variance, tmp, g.tmpArray) floatx.Apply(floatx.Floorv(smallVar), g.variance, nil) } else { /* Not enough training sample. */ glog.Warningf("not enough training samples, name [%s], num samples [%e]", g.ModelName, g.NSamples) floatx.Apply(floatx.SetValueFunc(smallVar), g.variance, nil) floatx.Apply(floatx.SetValueFunc(0), g.Mean, nil) } g.setVariance(g.variance) // to update varInv and stddev. /* Update log Gaussian constant. */ floatx.Log(g.tmpArray, g.variance) g.const2 = g.const1 - floats.Sum(g.tmpArray)/2.0 glog.V(6).Infof("gaussian reest, name:%s, mean:%v, sd:%v", g.ModelName, g.Mean, g.StdDev) return nil }
// UpdateOne updates sufficient statistics using one observation. func (g *Model) UpdateOne(o model.Obs, w float64) { glog.V(6).Infof("gaussian update, name:%s, obs:%v, weight:%e", g.ModelName, o, w) /* Update sufficient statistics. */ obs, _, _ := model.ObsToF64(o) floatx.Apply(floatx.ScaleFunc(w), obs, g.tmpArray) floats.Add(g.Sumx, g.tmpArray) floatx.Sq(g.tmpArray, obs) floats.Scale(w, g.tmpArray) floats.Add(g.Sumxsq, g.tmpArray) g.NSamples += w }
// Estimate computes model parameters using sufficient statistics. func (gmm *Model) Estimate() error { // Estimate mixture weights. floatx.Apply(floatx.ScaleFunc(1.0/gmm.NSamples), gmm.PosteriorSum, gmm.Weights) floatx.Log(gmm.LogWeights, gmm.Weights) // Estimate component density. for _, c := range gmm.Components { err := c.Estimate() if err != nil { return err } } gmm.Iteration++ return nil }