// 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 }