func (f *oneVsAllFilter) Transform(old, to base.Attribute, seq []byte) []byte { if !old.Equals(f.classAttr) { return seq } val := base.UnpackBytesToU64(seq) if val == f.classAttrVal { return base.PackFloatToBytes(1.0) } return base.PackFloatToBytes(0.0) }
// Fit creates n filtered datasets (where n is the number of values // a CategoricalAttribute can take) and uses them to train the // underlying classifiers. func (m *OneVsAllModel) Fit(using base.FixedDataGrid) { var classAttr *base.CategoricalAttribute // Do some validation classAttrs := using.AllClassAttributes() for _, a := range classAttrs { if c, ok := a.(*base.CategoricalAttribute); !ok { panic("Unsupported ClassAttribute type") } else { classAttr = c } } attrs := m.generateAttributes(using) // Find the highest stored value val := uint64(0) classVals := classAttr.GetValues() for _, s := range classVals { cur := base.UnpackBytesToU64(classAttr.GetSysValFromString(s)) if cur > val { val = cur } } if val == 0 { panic("Must have more than one class!") } m.maxClassVal = val // Create individual filtered instances for training filters := make([]*oneVsAllFilter, val+1) classifiers := make([]base.Classifier, val+1) for i := uint64(0); i <= val; i++ { f := &oneVsAllFilter{ attrs, classAttr, i, } filters[i] = f classifiers[i] = m.NewClassifierFunction(classVals[int(i)]) classifiers[i].Fit(base.NewLazilyFilteredInstances(using, f)) } m.filters = filters m.classifiers = classifiers }
// Transform converts the given byte sequence using the old Attribute into the new // byte sequence. // // If the old Attribute has a categorical value of at most two items, then a zero or // non-zero byte sequence is returned. // // If the old Attribute has a categorical value of at most n-items, then a non-zero // or zero byte sequence is returned based on the value of the new Attribute passed in. // // If the old Attribute is a float, it's value's unpacked and we check for non-zeroness // // If the old Attribute is a BinaryAttribute, just return the input func (b *BinaryConvertFilter) Transform(a base.Attribute, n base.Attribute, attrBytes []byte) []byte { ret := make([]byte, 1) // Check for CategoricalAttribute if _, ok := a.(*base.CategoricalAttribute); ok { // Unpack byte value val := base.UnpackBytesToU64(attrBytes) // If it's a two-valued one, check for non-zero if b.twoValuedCategoricalAttributes[a] { if val > 0 { ret[0] = 1 } else { ret[0] = 0 } } else if an, ok := b.nValuedCategoricalAttributeMap[a]; ok { // If it's an n-valued one, check the new Attribute maps onto // the unpacked value if af, ok := an[val]; ok { if af.Equals(n) { ret[0] = 1 } else { ret[0] = 0 } } else { panic("Categorical value not defined!") } } else { panic(fmt.Sprintf("Not a recognised Attribute %v", a)) } } else if _, ok := a.(*base.BinaryAttribute); ok { // Binary: just return the original value ret = attrBytes } else if _, ok := a.(*base.FloatAttribute); ok { // Float: check for non-zero val := base.UnpackBytesToFloat(attrBytes) if val > 0 { ret[0] = 1 } else { ret[0] = 0 } } else { panic(fmt.Sprintf("Unrecognised Attribute: %v", a)) } return ret }