Example #1
0
// NewModel creates a new Gaussian mixture model.
func NewModel(dim, numComponents int, options ...Option) *Model {

	gmm := &Model{
		ModelName:   "GMM", // default name
		ModelDim:    dim,
		NComponents: numComponents,
		Diag:        true,
		tmpProbs:    make([]float64, numComponents),
	}
	gmm.Type = reflect.TypeOf(*gmm).String()

	// Set options.
	for _, option := range options {
		option(gmm)
	}
	if len(gmm.PosteriorSum) == 0 {
		gmm.PosteriorSum = make([]float64, gmm.NComponents)
	}

	// Create components if not provided.
	if len(gmm.Components) == 0 {
		gmm.Components = make([]*gaussian.Model, numComponents, numComponents)
		for i := range gmm.Components {
			cname := componentName(gmm.ModelName, i, gmm.NComponents)
			gmm.Components[i] = gaussian.NewModel(gmm.ModelDim, gaussian.Name(cname))
		}
	}

	// Initialize weights.
	// Caller may pass weight, log(weights), or no weights.
	switch {

	case len(gmm.LogWeights) > 0 && len(gmm.Weights) > 0:
		glog.Fatal("options not allowed: provide only one of LogWeights or Weights")

	case len(gmm.LogWeights) == 0 && len(gmm.Weights) == 0:
		gmm.LogWeights = make([]float64, numComponents)
		logw := -math.Log(float64(gmm.NComponents))
		floatx.Apply(floatx.SetValueFunc(logw), gmm.LogWeights, nil)
		gmm.Weights = make([]float64, gmm.NComponents)
		floatx.Exp(gmm.Weights, gmm.LogWeights)
		glog.Infof("init weights with equal values: %.6f", gmm.Weights[0])

	case len(gmm.LogWeights) > 0:
		gmm.Weights = make([]float64, gmm.NComponents)
		floatx.Exp(gmm.Weights, gmm.LogWeights)

	case len(gmm.Weights) > 0:
		gmm.LogWeights = make([]float64, numComponents)
		floatx.Log(gmm.LogWeights, gmm.Weights)
	}
	return gmm
}
Example #2
0
// Estimate computes model parameters using sufficient statistics.
func (gmm *Model) UpdateOne(o model.Obs, w float64) {

	obs, _, _ := model.ObsToF64(o)
	maxProb := gmm.logProbInternal(obs, gmm.tmpProbs)
	gmm.Likelihood += maxProb
	floatx.Apply(floatx.AddScalarFunc(-maxProb+math.Log(w)), gmm.tmpProbs, nil)

	// Compute posterior probabilities.
	floatx.Exp(gmm.tmpProbs, gmm.tmpProbs)

	// Update posterior sum, needed to compute mixture weights.
	floats.Add(gmm.PosteriorSum, gmm.tmpProbs)

	// Update Gaussian components.
	for i, c := range gmm.Components {
		c.UpdateOne(o, gmm.tmpProbs[i])
	}

	// Count number of observations.
	gmm.NSamples += w
}