private static void inferBounds(Node node, Hyperrectangle <float> bounds) { if (node == null) { return; } node.Bounds = bounds; if (node.NodeType == NodeType.Leaf) { return; } Threshold test = node.Threshold; float min = bounds.MinimumBound[test.Dimension]; float max = bounds.MaximumBound[test.Dimension]; Hyperrectangle <float> leftBounds = (Hyperrectangle <float>)bounds.Clone(); Hyperrectangle <float> rightBounds = (Hyperrectangle <float>)bounds.Clone(); leftBounds.MaximumBound[test.Dimension] = test.Value; rightBounds.MinimumBound[test.Dimension] = test.Value; inferBounds(node.Left, leftBounds); inferBounds(node.Right, rightBounds); }
private static Node split(List <int> indices, int NCount, Hyperrectangle <float> bounds) { _depth++; int YCount = indices.Count; if (YCount <= MinY) { _depth--; return(new Node { NodeType = NodeType.Leaf, Y = YCount, N = NCount, Bounds = bounds }); } if (NCount < YCount) { NCount = YCount; } int length = _numFeatures; float min, max; Dictionary <Threshold, float> thresholds = new Dictionary <Threshold, float>(); float[] values = new float[YCount]; for (int i = 0; i < length; i++) { float[] featureValues = _featureValues[i]; for (int j = 0; j < YCount; j++) { values[j] = featureValues[indices[j]]; } Array.Sort <float>(values); min = bounds.MinimumBound[i]; max = bounds.MaximumBound[i]; Threshold cut1 = findCut(new Region { Min = min, Max = max, YCount = YCount, NCount = NCount }, values); if (cut1 == null) { continue; } Region r0 = new Region { Min = min, Max = cut1.Value, IncludeLeft = true, IncludeRight = cut1.IsInclusive }; Region r1 = new Region { Min = cut1.Value, Max = max, IncludeLeft = !cut1.IsInclusive, IncludeRight = true }; r0.CalculateCounts(values, min, max, NCount); r1.CalculateCounts(values, min, max, NCount); Region L = r0.RelativeDensity < r1.RelativeDensity ? r0 : r1; float[] LValues = L.Limit(values); if (LValues.Length == 0) { cut1.Dimension = i; cut1.Feature = _buildFeatures[i]; thresholds[cut1] = L.RelativeDensity; continue; } Threshold cut2 = findCut(L, LValues); if (cut2 == null) { continue; } if (L == r0) { r0 = new Region { Min = r0.Min, Max = cut2.Value, IncludeLeft = true, IncludeRight = cut2.IsInclusive }; r1 = new Region { Min = cut2.Value, Max = cut1.Value, IncludeLeft = !cut2.IsInclusive, IncludeRight = cut1.IsInclusive }; r0.CalculateCounts(values, min, max, NCount); r1.CalculateCounts(values, min, max, NCount); if (r1.RelativeDensity > r0.RelativeDensity) { cut2.Dimension = i; cut2.Feature = _buildFeatures[i]; thresholds[cut2] = r0.RelativeDensity; continue; } } else { r0 = new Region { Min = cut1.Value, Max = cut2.Value, IncludeLeft = !cut1.IsInclusive, IncludeRight = cut2.IsInclusive }; r1 = new Region { Min = cut2.Value, Max = r1.Max, IncludeLeft = !cut2.IsInclusive, IncludeRight = true }; r0.CalculateCounts(values, min, max, NCount); r1.CalculateCounts(values, min, max, NCount); if (r0.RelativeDensity > r1.RelativeDensity) { cut2.Dimension = i; cut2.Feature = _buildFeatures[i]; thresholds[cut2] = r1.RelativeDensity; continue; } } L = r0.RelativeDensity < r1.RelativeDensity ? r0 : r1; LValues = L.Limit(LValues); if (LValues.Length == 0) { continue; } Threshold cut3 = findCut(L, LValues); if (cut3 == null) { continue; } if (cut1.Value < cut3.Value) { r0 = new Region { Min = cut1.Value, Max = cut3.Value, IncludeLeft = !cut1.IsInclusive, IncludeRight = cut3.IsInclusive } } ; else { r0 = new Region { Min = cut3.Value, Max = cut1.Value, IncludeLeft = !cut3.IsInclusive, IncludeRight = cut1.IsInclusive } }; if (cut2.Value < cut3.Value) { r1 = new Region { Min = cut2.Value, Max = cut3.Value, IncludeLeft = !cut2.IsInclusive, IncludeRight = cut3.IsInclusive } } ; else { r1 = new Region { Min = cut3.Value, Max = cut2.Value, IncludeLeft = !cut3.IsInclusive, IncludeRight = cut2.IsInclusive } }; r0.CalculateCounts(values, min, max, NCount); r1.CalculateCounts(values, min, max, NCount); cut3.Feature = _buildFeatures[i]; cut3.Dimension = i; thresholds[cut3] = Math.Min(r0.RelativeDensity, r1.RelativeDensity); } values = null; if (thresholds.Count() == 0) { _depth--; return(new Node { NodeType = NodeType.Leaf, Y = YCount, N = NCount, Bounds = bounds }); } Threshold best = thresholds.OrderBy(o => o.Value).First().Key; List <int> left = new List <int>(); List <int> right = new List <int>(); values = _featureValues[best.Dimension]; foreach (int index in indices) { float value = values[index]; if (best.IsLeft(value)) { left.Add(index); } else { right.Add(index); } } UpdateManager.WriteLine("Splitting at {0}: {1} {2}", best, left.Count, right.Count); min = bounds.MinimumBound[best.Dimension]; max = bounds.MaximumBound[best.Dimension]; Hyperrectangle <float> leftBounds = (Hyperrectangle <float>)bounds.Clone(); Hyperrectangle <float> rightBounds = (Hyperrectangle <float>)bounds.Clone(); leftBounds.MaximumBound[best.Dimension] = best.Value; rightBounds.MinimumBound[best.Dimension] = best.Value; int leftNCount = (int)(((best.Value - min) * NCount) / (max - min)); Node node = new Node { Threshold = best, NodeType = NodeType.Branch, Y = YCount, N = NCount, Bounds = bounds }; node.Left = split(left, leftNCount, leftBounds); node.Right = split(right, NCount - leftNCount, rightBounds); _depth--; return(node); } } }