Exemplo n.º 1
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
}