Beispiel #1
0
// UpdateOne updates model using a single weighted sample.
func (m *Model) UpdateOne(o model.Obs, w float64) {
	m.updateCount++
	// We create a chain of hmms to update stats for an obs sequence.
	// The chain is released once the update is done.
	// The assigner has the logic for mapping labels to a chain of models.
	chain, err := m.Set.chainFromAssigner(o, m.assigner)
	if err != nil {
		glog.Warningf("skipping, failed to update hmm model stats, oid:%s, error: %s", o.ID(), err)
		return
	}

	// Use the forward-backward algorithm to compute counts.
	if m.useAlignments {
		err = chain.updateFromAlignments()
		if err != nil {
			m.updateFailCount++
			if glog.V(6) {
				glog.Fatal(err)
			}
			glog.Warning(err)
			return
		}
	} else {
		err = chain.update()
		if err != nil {
			m.updateFailCount++
			if glog.V(6) {
				glog.Fatal(err)
			}
			glog.Warning(err)
			return
		}

		// Print log(prob(O/model))\
		p := chain.beta.At(0, 0, 0)
		m.logProb += p
		glog.V(1).Infof("update hmm stats, oid:%s, logProb:%.2f total:%.2f", o.ID(), p, m.logProb)
	}
}
Beispiel #2
0
// Use the label to create a chain of hmms.
// If model set only has one hmm, no need to use labels, simply assign the only hmm.
func (ms *Set) chainFromAssigner(obs model.Obs, assigner Assigner) (*chain, error) {

	var hmms []*Net
	var fos model.FloatObsSequence
	switch o := obs.(type) {
	case model.FloatObsSequence:
		fos = o
	case *model.FloatObsSequence:
		fos = *o
	default:
		return nil, fmt.Errorf("obs must be of type model.FloatObsSequence, found type %s which is not supported",
			reflect.TypeOf(obs))
	}
	if len(fos.ValueAsSlice()) == 0 {
		return nil, fmt.Errorf("obs sequence has no data")
	}

	if assigner == nil && ms.size() == 1 {
		hmms = append(hmms, ms.Nets[0])
		if glog.V(3) {
			glog.Warningf("assigner missing but model set has only one hmm network - assigning model [%s] to chain", ms.Nets[0].Name)
		}
	} else if assigner == nil {
		return nil, fmt.Errorf("need assigner to create hmm chain if model set is greater than one")
	} else {
		// Get the labeler and check that it is of type SimpleLabeler
		// otherwise return error.
		labeler, ok := obs.Label().(model.SimpleLabel)
		if !ok {
			return nil, fmt.Errorf("labeler must be of type model.SimpleLabel, found type %s which is not supported",
				reflect.TypeOf(obs.Label()))
		}
		// Now we need to assign hmms to the chain.
		// We will use the sequence of labels to lookup the models by name.
		labels := strings.Split(labeler.String(), ",")
		if len(labels) == 1 && len(labels[0]) == 0 {
			return nil, fmt.Errorf("no label found, can't assign models")
		}
		modelNames := assigner.Assign(labels)
		glog.V(5).Infof("obsid:%s, labels:%v", obs.ID(), labels)
		glog.V(5).Infof("obsid:%s, models:%v", obs.ID(), modelNames)

		for _, name := range modelNames {
			h, ok := ms.net(name)
			if !ok {
				return nil, fmt.Errorf("can't find model for name [%s] in set - assignment failed", name)
			}
			hmms = append(hmms, h)
		}
	}

	nq := len(hmms)
	if nq == 0 {
		return nil, fmt.Errorf("the assigner returned no models")
	}
	ch := &chain{
		hmms:    hmms,
		nq:      nq,
		ns:      make([]int, nq, nq),
		obs:     obs,
		vectors: fos.Value().([][]float64),
		nobs:    len(fos.Value().([][]float64)),
		ms:      ms,
	}

	for k, hmm := range hmms {
		if hmm.A.Shape[0] > ch.maxNS {
			ch.maxNS = hmm.A.Shape[0]
		}
		ch.ns[k] = hmm.A.Shape[0]
	}
	ch.alpha = narray.New(ch.nq, ch.maxNS, ch.nobs)
	ch.beta = narray.New(ch.nq, ch.maxNS, ch.nobs)
	ch.computeLikelihoods()

	// Validate.

	// Can't have models with transitions from entry to exit states
	// at the beginning or end of a chain.
	if isTeeModel(hmms[0]) {
		return nil, fmt.Errorf("the first model in the chain can't have a transition from entry to exit states - model name is [%s] with id [%d]", hmms[0].Name, hmms[0].id)
	}
	if isTeeModel(hmms[nq-1]) {
		return nil, fmt.Errorf("the last model in the chain can't have a transition from entry to exit states - model name is [%s] with id [%d]", hmms[nq-1].Name, hmms[nq-1].id)
	}

	return ch, nil
}