private List <RootCauseItem> LocalizeRootCauseByDimension(PointTree anomalyTree, PointTree pointTree, Dictionary <string, Object> anomalyDimension, List <string> aggDims) { BestDimension best = null; if (anomalyTree.ChildrenNodes.Count == 0) { //has no children node information, should use the leaves node(whose point has no aggrgated dimensions) information best = SelectBestDimension(pointTree.Leaves, anomalyTree.Leaves, aggDims); } else { //has no leaves information, should calculate the entropy information according to the children nodes best = SelectBestDimension(pointTree.ChildrenNodes, anomalyTree.ChildrenNodes, aggDims); } if (best == null) { return(new List <RootCauseItem>() { new RootCauseItem(anomalyDimension) }); } List <TimeSeriesPoint> children = null; if (anomalyTree.ChildrenNodes.ContainsKey(best.DimensionKey)) { //Use children node information to get top anomalies children = GetTopAnomaly(anomalyTree.ChildrenNodes[best.DimensionKey], anomalyTree.ParentNode, pointTree.ChildrenNodes[best.DimensionKey].Count > 0 ? pointTree.ChildrenNodes[best.DimensionKey] : pointTree.Leaves, best.DimensionKey, !(pointTree.ChildrenNodes[best.DimensionKey].Count > 0)); } else { //Use leaves node informatin to get top anomalies children = GetTopAnomaly(anomalyTree.Leaves, anomalyTree.ParentNode, pointTree.Leaves, best.DimensionKey, true); } if (children == null) { //As the cause couldn't be found, the root cause should be itself return(new List <RootCauseItem>() { new RootCauseItem(anomalyDimension) }); } else { List <RootCauseItem> causes = new List <RootCauseItem>(); // For the found causes, we return the result foreach (TimeSeriesPoint anomaly in children) { causes.Add(new RootCauseItem(UpdateDimensionValue(anomalyDimension, best.DimensionKey, anomaly.Dimension[best.DimensionKey]), new List <string>() { best.DimensionKey })); } return(causes); } }
private BestDimension GetBestDimension(BestDimension best, KeyValuePair <BestDimension, double> dimension, Dictionary <BestDimension, Double> valueRatioMap) { if (valueRatioMap[best].CompareTo(dimension.Value) == 0) { if (dimension.Key.AnomalyDis.Count != dimension.Key.PointDis.Count) { best = dimension.Key; } } else { best = dimension.Key; } return(best); }
public int CompareTo(object obj) { if (obj == null) { return(1); } BestDimension other = obj as BestDimension; if (other != null) { return(DimensionKey.CompareTo(other.DimensionKey)); } else { throw new ArgumentException("Object is not a BestDimension"); } }
/// <summary> /// Use children point information to select best dimension /// </summary> private BestDimension SelectBestDimension(Dictionary <string, List <TimeSeriesPoint> > pointChildren, Dictionary <string, List <TimeSeriesPoint> > anomalyChildren, List <string> aggDim) { SortedDictionary <BestDimension, double> entropyMap = new SortedDictionary <BestDimension, double>(); Dictionary <BestDimension, double> entropyRatioMap = new Dictionary <BestDimension, double>(); double sumGain = 0; foreach (string dimKey in aggDim) { BestDimension dimension = new BestDimension(); dimension.DimensionKey = dimKey; if (pointChildren.ContainsKey(dimKey)) { UpdateDistribution(dimension.PointDis, pointChildren[dimKey], dimKey); } if (anomalyChildren.ContainsKey(dimKey)) { UpdateDistribution(dimension.AnomalyDis, anomalyChildren[dimKey], dimKey); } double entropy = GetEntropy(dimension.PointDis.Count, dimension.AnomalyDis.Count); if (Double.IsNaN(entropy)) { entropy = Double.MaxValue; } entropyMap.Add(dimension, entropy); double gainRatio = entropy / GetDimensionIntrinsicValue(dimension.PointDis); if (Double.IsInfinity(gainRatio)) { gainRatio = 0; } entropyRatioMap.Add(dimension, gainRatio); sumGain += entropy; } double meanGain = sumGain / aggDim.Count; BestDimension best = FindBestDimension(entropyMap, entropyRatioMap, meanGain, false); return(best); }
private BestDimension FindBestDimension(SortedDictionary <BestDimension, double> valueMap, Dictionary <BestDimension, double> valueRatioMap, double meanGain, bool isLeavesLevel = true) { BestDimension best = null; foreach (KeyValuePair <BestDimension, double> dimension in valueMap) { if (dimension.Key.AnomalyDis.Count == 1 || (isLeavesLevel ? dimension.Value >= meanGain : dimension.Value <= meanGain)) { if (best == null) { best = dimension.Key; } else { bool isRatioNan = Double.IsNaN(valueRatioMap[best]); if (dimension.Key.AnomalyDis.Count > 1) { if (best.AnomalyDis.Count != 1 && !isRatioNan && (isLeavesLevel ? valueRatioMap[best].CompareTo(dimension.Value) <= 0 : valueRatioMap[best].CompareTo(dimension.Value) >= 0)) { best = GetBestDimension(best, dimension, valueRatioMap); } } else if (dimension.Key.AnomalyDis.Count == 1) { if (best.AnomalyDis.Count > 1) { best = dimension.Key; } else if (best.AnomalyDis.Count == 1) { if (!isRatioNan && (isLeavesLevel ? valueRatioMap[best].CompareTo(dimension.Value) <= 0 : valueRatioMap[best].CompareTo(dimension.Value) >= 0)) { best = GetBestDimension(best, dimension, valueRatioMap); } } } } } } return(best); }
/// <summary> /// Use leaves point information to select ordered dimensions /// </summary> protected IEnumerable <BestDimension> SelectOrderedDimension(List <TimeSeriesPoint> totalPoints, List <TimeSeriesPoint> anomalyPoints, List <string> aggDim) { double totalEntropy = GetEntropy(totalPoints.Count, anomalyPoints.Count); SortedDictionary <BestDimension, double> entropyGainMap = new SortedDictionary <BestDimension, double>(); Dictionary <BestDimension, double> entroyGainRatioMap = new Dictionary <BestDimension, double>(); double sumGain = 0; foreach (string dimKey in aggDim) { BestDimension dimension = new BestDimension(); dimension.DimensionKey = dimKey; UpdateDistribution(dimension.PointDis, totalPoints, dimKey); UpdateDistribution(dimension.AnomalyDis, anomalyPoints, dimKey); double relativeEntropy = GetDimensionEntropy(dimension.PointDis, dimension.AnomalyDis); double gain = totalEntropy - relativeEntropy; if (Double.IsNaN(gain)) { gain = 0; } entropyGainMap.Add(dimension, gain); dimension.Gain = gain; double gainRatio = gain / GetDimensionIntrinsicValue(dimension.PointDis); if (Double.IsInfinity(gainRatio)) { gainRatio = 0; } entroyGainRatioMap.Add(dimension, gainRatio); dimension.GainRatio = gainRatio; sumGain += gain; } double meanGain = sumGain / aggDim.Count(); return(OrderDimensions(entropyGainMap, entroyGainRatioMap, meanGain)); }