private static IDecisionNode NodeToDecisionTree(IDataNode node) { if (node is DataLeaf) { DataLeaf leaf = (DataLeaf)node; Tactic tactic = EnumUtils.GetEnumValues <Tactic>().MaxBy(t => leaf.ClassDistribution[(int)t]); return(new DecisionLeaf(tactic)); } else if (node is AttributeSplit) { AttributeSplit attributeSplit = (AttributeSplit)node; return(new DecisionNode { Partitioner = new ContinuousPartitioner((ContinuousAxis)attributeSplit.Axis, attributeSplit.SplitValue), Left = NodeToDecisionTree(attributeSplit.Left), Right = NodeToDecisionTree(attributeSplit.Right), }); } else if (node is CategoricalSplit) { CategoricalSplit categoricalSplit = (CategoricalSplit)node; return(new DecisionNode { Partitioner = new CategoricalPartitioner( (CategoricalAxis)categoricalSplit.Axis, PolicyHelper.BitsToCategories((CategoricalAxis)categoricalSplit.Axis, categoricalSplit.Categories).ToArray()), Left = NodeToDecisionTree(categoricalSplit.Left), Right = NodeToDecisionTree(categoricalSplit.Right), }); } else { throw new ArgumentException("Unknown node type: " + node); } }
private static DataLeaf Resolve(IDataNode node, DataPoint newDataPoint) { if (node is DataLeaf) { return((DataLeaf)node); } else if (node is AttributeSplit) { AttributeSplit attributeSplit = (AttributeSplit)node; if (newDataPoint.Attributes[attributeSplit.Axis] >= attributeSplit.SplitValue) { return(Resolve(attributeSplit.Right, newDataPoint)); } else { return(Resolve(attributeSplit.Left, newDataPoint)); } } else if (node is CategoricalSplit) { CategoricalSplit categoricalSplit = (CategoricalSplit)node; if ((newDataPoint.Categories[categoricalSplit.Axis] & categoricalSplit.Categories) != 0) { return(Resolve(categoricalSplit.Right, newDataPoint)); } else { return(Resolve(categoricalSplit.Left, newDataPoint)); } } else { throw new ArgumentException("Unknown node type: " + node); } }
public void TestSimpleAttributeSplit() { List <DataPoint> dataPoints = new List <DataPoint> { new DataPoint { Class = 0, Attributes = new float[] { 123 }, Categories = new uint[] { }, Weight = 1.0f, }, new DataPoint { Class = 1, Attributes = new float[] { 456 }, Categories = new uint[] { }, Weight = 1.0f, }, }; using (CudaManager cudaManager = Provider.CudaManagerPool.GetCudaManagerForThread(Provider.Logger)) using (DecisionLearner decisionLearner = new DecisionLearner(cudaManager, dataPoints)) { IDataNode root = decisionLearner.FitDecisionTree().Node; AttributeSplit attributeSplit = (AttributeSplit)root; Assert.AreEqual(0, attributeSplit.Axis); Assert.AreEqual(456, attributeSplit.SplitValue); DataLeaf left = (DataLeaf)attributeSplit.Left; Assert.AreEqual(1, left.ClassDistribution[0]); Assert.AreEqual(0, left.ClassDistribution[1]); DataLeaf right = (DataLeaf)attributeSplit.Right; Assert.AreEqual(0, right.ClassDistribution[0]); Assert.AreEqual(1, right.ClassDistribution[1]); Assert.AreEqual(1.0, Accuracy(root, dataPoints)); } }
private DataNodeAccuracy PruneDecisionTree(IDataNode node) { if (node is DataLeaf) { return(new DataNodeAccuracy { Node = node, CorrectWeight = node.ClassDistribution.Max(), TotalWeight = node.ClassDistribution.Sum(), }); } else if (node is IDataSplit) { IDataSplit split = (IDataSplit)node; DataNodeAccuracy leftAccuracy = PruneDecisionTree(split.Left); DataNodeAccuracy rightAccuracy = PruneDecisionTree(split.Right); float splitCorrect = leftAccuracy.CorrectWeight + rightAccuracy.CorrectWeight; float splitTotal = leftAccuracy.TotalWeight + rightAccuracy.TotalWeight; float leafCorrect = node.ClassDistribution.Max(); float leafTotal = node.ClassDistribution.Sum(); #if DEBUGCUDA Assert.AreEqual(leafTotal, splitTotal, 1.0f); #endif float accuracyIncrease = splitCorrect - leafCorrect; float requiredIncrease = Context.TotalWeight * GPUConstants.RequiredImprovementToSplit; if (accuracyIncrease < requiredIncrease) { // Split not justified, revert back to leaf at this level return(new DataNodeAccuracy { Node = new DataLeaf { ClassDistribution = node.ClassDistribution }, CorrectWeight = leafCorrect, TotalWeight = leafTotal, }); } else { // Take the split with the pruned nodes if (split is AttributeSplit) { AttributeSplit attributeSplit = (AttributeSplit)split; attributeSplit.Left = leftAccuracy.Node; attributeSplit.Right = rightAccuracy.Node; } else if (split is CategoricalSplit) { CategoricalSplit categoricalSplit = (CategoricalSplit)split; categoricalSplit.Left = leftAccuracy.Node; categoricalSplit.Right = rightAccuracy.Node; } else { throw new ArgumentException("Unknown split type: " + split); } return(new DataNodeAccuracy { Node = split, CorrectWeight = splitCorrect, TotalWeight = splitTotal, }); } } else { throw new ArgumentException("Unknown node type: " + node); } }