// Predict issues predictions. Each class-specific classifier is expected // to output a value between 0 (indicating that a given instance is not // a given class) and 1 (indicating that the given instance is definitely // that class). For each instance, the class with the highest value is chosen. // The result is undefined if several underlying models output the same value. func (m *OneVsAllModel) Predict(what base.FixedDataGrid) (base.FixedDataGrid, error) { ret := base.GeneratePredictionVector(what) vecs := make([]base.FixedDataGrid, m.maxClassVal+1) specs := make([]base.AttributeSpec, m.maxClassVal+1) for i := uint64(0); i <= m.maxClassVal; i++ { f := m.filters[i] c := base.NewLazilyFilteredInstances(what, f) p, err := m.classifiers[i].Predict(c) if err != nil { return nil, err } vecs[i] = p specs[i] = base.ResolveAttributes(p, p.AllClassAttributes())[0] } _, rows := ret.Size() spec := base.ResolveAttributes(ret, ret.AllClassAttributes())[0] for i := 0; i < rows; i++ { class := uint64(0) best := 0.0 for j := uint64(0); j <= m.maxClassVal; j++ { val := base.UnpackBytesToFloat(vecs[j].Get(specs[j], i)) if val > best { class = j best = val } } ret.Set(spec, i, base.PackU64ToBytes(class)) } return ret, nil }
// Transform returns the byte sequence after discretisation func (c *ChiMergeFilter) Transform(a base.Attribute, n base.Attribute, field []byte) []byte { // Do we use this Attribute? if !c.attrs[a] { return field } // Find the Attribute value in the table table := c.tables[a] dis := 0 val := base.UnpackBytesToFloat(field) for j, k := range table { if k.Value < val { dis = j continue } break } return base.PackU64ToBytes(uint64(dis)) }
// param base.IFixedDataGrid // return base.IFixedDataGrid func (p *AveragePerceptron) Predict(what base.FixedDataGrid) base.FixedDataGrid { if !p.trained { panic("Cannot call Predict on an untrained AveragePerceptron") } data := processData(what) allAttrs := base.CheckCompatible(what, p.TrainingData) if allAttrs == nil { // Don't have the same Attributes return nil } // Remove the Attributes which aren't numeric allNumericAttrs := make([]base.Attribute, 0) for _, a := range allAttrs { if fAttr, ok := a.(*base.FloatAttribute); ok { allNumericAttrs = append(allNumericAttrs, fAttr) } } ret := base.GeneratePredictionVector(what) classAttr := ret.AllClassAttributes()[0] classSpec, err := ret.GetAttribute(classAttr) if err != nil { panic(err) } for i, datum := range data { result := p.score(datum) if result > 0.0 { ret.Set(classSpec, i, base.PackU64ToBytes(1)) } else { ret.Set(classSpec, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0}) } } return ret }
// Transform takes an Attribute and byte sequence and returns // the transformed byte sequence. func (b *BinningFilter) Transform(a base.Attribute, n base.Attribute, field []byte) []byte { if !b.attrs[a] { return field } af, ok := a.(*base.FloatAttribute) if !ok { panic("Attribute is the wrong type") } minVal := b.minVals[a] maxVal := b.maxVals[a] disc := 0 // Casts to float64 to replicate a floating point precision error delta := float64(maxVal-minVal) / float64(b.bins) val := float64(af.GetFloatFromSysVal(field)) if val <= minVal { disc = 0 } else { disc = int(math.Floor(float64(float64(val-minVal)/delta + 0.0001))) } return base.PackU64ToBytes(uint64(disc)) }
// Predict uses the underlying network to produce predictions for the // class variables of X. // // Can only predict one CategoricalAttribute at a time, or up to n // FloatAttributes. Set or unset ClassAttributes to work around this // limitation. func (m *MultiLayerNet) Predict(X base.FixedDataGrid) base.FixedDataGrid { // Create the return vector ret := base.GeneratePredictionVector(X) // Make sure everything's a FloatAttribute insts := m.convertToFloatInsts(X) // Get the input/output Attributes inputAttrs := base.NonClassAttributes(insts) outputAttrs := ret.AllClassAttributes() // Compute layers layers := 2 + len(m.layers) // Check that we're operating in a singular mode floatMode := 0 categoricalMode := 0 for _, a := range outputAttrs { if _, ok := a.(*base.CategoricalAttribute); ok { categoricalMode++ } else if _, ok := a.(*base.FloatAttribute); ok { floatMode++ } else { panic("Unsupported output Attribute type!") } } if floatMode > 0 && categoricalMode > 0 { panic("Can't predict a mix of float and categorical Attributes") } else if categoricalMode > 1 { panic("Can't predict more than one categorical class Attribute") } // Create the activation vector a := mat64.NewDense(m.network.size, 1, make([]float64, m.network.size)) // Resolve the input AttributeSpecs inputAs := base.ResolveAttributes(insts, inputAttrs) // Resolve the output Attributespecs outputAs := base.ResolveAttributes(ret, outputAttrs) // Map over each input row insts.MapOverRows(inputAs, func(row [][]byte, rc int) (bool, error) { // Clear the activation vector for i := 0; i < m.network.size; i++ { a.Set(i, 0, 0.0) } // Build the activation vector for i, vb := range row { if cIndex, ok := m.attrs[inputAs[i].GetAttribute()]; !ok { panic("Can't resolve the Attribute!") } else { a.Set(cIndex, 0, base.UnpackBytesToFloat(vb)) } } // Robots, activate! m.network.Activate(a, layers) // Decide which class to set if floatMode > 0 { for _, as := range outputAs { cIndex := m.attrs[as.GetAttribute()] ret.Set(as, rc, base.PackFloatToBytes(a.At(cIndex, 0))) } } else { maxIndex := 0 maxVal := 0.0 for i := m.classAttrOffset; i < m.classAttrOffset+m.classAttrCount; i++ { val := a.At(i, 0) if val > maxVal { maxIndex = i maxVal = val } } maxIndex -= m.classAttrOffset ret.Set(outputAs[0], rc, base.PackU64ToBytes(uint64(maxIndex))) } return true, nil }) return ret }