// 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 }
// NewModel creates a new Gaussian model. func NewModel(dim int, options ...Option) *Model { g := &Model{ ModelName: "Gaussian", ModelDim: dim, Diag: true, variance: make([]float64, dim), varianceInv: make([]float64, dim), tmpArray: make([]float64, dim), } g.Type = reflect.TypeOf(*g).String() // Set options. for _, option := range options { option(g) } if len(g.Sumx) == 0 { g.Sumx = make([]float64, dim) } if len(g.Sumxsq) == 0 { g.Sumxsq = make([]float64, dim) } if g.Mean == nil { g.Mean = make([]float64, dim) } if g.StdDev == nil { g.StdDev = make([]float64, dim) floatx.Apply(floatx.SetValueFunc(smallSD), g.StdDev, nil) } floatx.Sq(g.variance, g.StdDev) // Initializes variance, varianceInv, and StdDev. g.setVariance(g.variance) floatx.Log(g.tmpArray, g.variance) g.const1 = -float64(g.ModelDim) * math.Log(2.0*math.Pi) / 2.0 g.const2 = g.const1 - floats.Sum(g.tmpArray)/2.0 return g }