public void RenderNode(Graphics graphics, GridCoordinate coordinate, DecisionTree.DecisionNode node) { var location = GetBitmapLocation(coordinate); graphics.DrawRectangle(Pens.Black, location.X, location.Y, ItemSize.Width, ItemSize.Height - 100); var font = new Font("Arial", 9); var message = node.IsLeaf ? node.Class : node.Children.First().Attribute + Environment.NewLine + "(" + node.Class + ")"; var size = graphics.MeasureString(message, font); var textWidth = size.Width; var textHeight = size.Height; var stringLocationX = ((location.X + location.X + ItemSize.Width) / (float)2) - (textWidth / 2); var stringLocationY = ((location.Y + location.Y + ItemSize.Height - 100) / (float)2) - (textHeight / 2); graphics.DrawString(message, font, Brushes.Black, stringLocationX, stringLocationY); }
private Dictionary <DecisionTree.DecisionNode, GridCoordinate> GetCoordinates(DecisionTree.DecisionNode root) { Dictionary <DecisionTree.DecisionNode, GridCoordinate> points = new Dictionary <DecisionTree.DecisionNode, GridCoordinate>(); var leavesNodes = new List <DecisionTree.DecisionNode>(); DecisionTree.LoadLeaves(root, leavesNodes); Func <DecisionTree.DecisionNode, GridCoordinate?> getPointFromChildren = node => { if (node.Children == null || !node.Children.Any()) { return(null); } var xValue = (int)node.Children.Average(item => { var point = points[item]; return(point.Column); }); return(new GridCoordinate { Column = xValue, Row = node.Depth }); }; var nextColumnIndex = 0; var nodesToProcess = leavesNodes; while (nodesToProcess.Count > 0) { var listNewNodesToProcess = new List <DecisionTree.DecisionNode>(); foreach (var node in nodesToProcess) { if (points.ContainsKey(node)) { continue; } if (node.IsLeaf) { points.Add(node, new GridCoordinate { Column = nextColumnIndex, Row = node.Depth }); nextColumnIndex = nextColumnIndex + 2; } else { var childrenResolved = node.Children.All(child => points.ContainsKey(child)); if (!childrenResolved) { continue; } var point = getPointFromChildren(node); if (point.HasValue) { points.Add(node, point.Value); } } if (node.Parent != null) { listNewNodesToProcess.Add(node.Parent); } } nodesToProcess = listNewNodesToProcess; } return(points); }
private void BuildConditionalNodes(IList <int> rows, IList <int> attributesIndexes, DecisionTree.DecisionNode parentNode) { var stack = new Stack <Iteration>(); stack.Push(new Iteration { Attributes = attributesIndexes, ParentNode = parentNode, Rows = rows, }); Iteration currentIteration = stack.Pop(); while (currentIteration != null) { var attributesList = currentIteration.Attributes.ToList(); if (attributesList.Count == 0) { currentIteration.ParentNode.Statistics = ComputeStatistics(currentIteration.Rows); currentIteration.ParentNode.Class = _data.ClassesValue[(int)currentIteration.ParentNode.Statistics.MostFrequentClass]; currentIteration = stack.Count > 0 ? stack.Pop() : null; continue; } var result = ComputeBestGain(currentIteration.Rows.ToArray(), currentIteration.Attributes); var statistics = result.Item3; currentIteration.ParentNode.Statistics = statistics; currentIteration.ParentNode.Class = _data.ClassesValue[(int)statistics.MostFrequentClass]; if (statistics.SameClass || (currentIteration.ParentNode.Depth == _options.MaxTreeDepth && _options.MaxTreeDepth > 0)) { currentIteration = stack.Count > 0 ? stack.Pop() : null; continue; } var attributeResult = result.Item2; var first = true; var children = new List <DecisionTree.DecisionNode>(); attributesList.Remove(attributeResult.AttributeIndex); if (attributeResult.InvalidAttributes.Any()) { foreach (var item in attributeResult.InvalidAttributes) { attributesList.Remove(item); } } var subsets = attributeResult.Subsets.Value.ToList(); attributeResult.Subsets = null; foreach (var subset in subsets) { var node = new DecisionTree.DecisionNode { Condition = attributeResult.IsNumeric ? first ? DecisionTree.PredicateCondition.LessThanOrEqual : DecisionTree.PredicateCondition.GreaterThan : DecisionTree.PredicateCondition.Equal, ThreshHold = subset.Value, Attribute = _data.Attributes[attributeResult.AttributeIndex], Depth = currentIteration.ParentNode.Depth + 1, Parent = currentIteration.ParentNode }; stack.Push(new Iteration { Rows = subset.Rows, Attributes = attributesList, ParentNode = node, }); first = false; children.Add(node); } currentIteration.ParentNode.Children = children.ToArray(); currentIteration = stack.Count > 0 ? stack.Pop() : null; } }
private void BuildConditionalNodesRecursive(int[] rows, IList <int> attributesIndexes, DecisionTree.DecisionNode parentNode) { var attributesList = attributesIndexes.ToList(); if (attributesList.Count == 0) { parentNode.Statistics = ComputeStatistics(rows); parentNode.Class = _data.ClassesValue[(int)parentNode.Statistics.MostFrequentClass]; return; } var result = ComputeBestGain(rows, attributesIndexes); var statistics = result.Item3; parentNode.Statistics = statistics; parentNode.Class = _data.ClassesValue[(int)statistics.MostFrequentClass]; if (statistics.SameClass || (parentNode.Depth == _options.MaxTreeDepth && _options.MaxTreeDepth > 0)) { return; } var attributeResult = result.Item2; var first = true; var children = new List <DecisionTree.DecisionNode>(); attributesList.Remove(attributeResult.AttributeIndex); if (attributeResult.InvalidAttributes.Any()) { foreach (var item in attributeResult.InvalidAttributes) { attributesList.Remove(item); } } var subsets = attributeResult.Subsets.Value; attributeResult.Subsets = null; foreach (var subset in subsets) { if (subset.Rows.Count < _options.MinItemsOnNode) { continue; } var node = new DecisionTree.DecisionNode { Condition = attributeResult.IsNumeric ? first ? DecisionTree.PredicateCondition.LessThanOrEqual : DecisionTree.PredicateCondition.GreaterThan : DecisionTree.PredicateCondition.Equal, ThreshHold = subset.Value, Attribute = _data.Attributes[attributeResult.AttributeIndex], Depth = parentNode.Depth + 1, Parent = parentNode }; BuildConditionalNodesRecursive(subset.Rows.ToArray(), attributesList, node); first = false; children.Add(node); } parentNode.Children = children.ToArray(); }