public AnomaliesReport detect(Data test, List <CorrelatedFeatures> cf) { List <Anomaly> arVec = new List <Anomaly>(); // vector of AnomalyReport s // int correlNum = this->cf.size(); // number of correlations found (above normal threshold) // for every correl of 2 features in this.cf for (int j = 0; j < cf.Count; j++) { // and for every row in TimeSeries: // check if in row i in TS 2 features of cf[j] // are deviated from their linearreg more then allowed (in cf[j].threshold) for (int i = 0; i < test.numOfLines; i++) { CorrelatedFeatures temp = cf[j]; double x = test.ts[temp.feature1][i]; double y = test.ts[temp.feature2][i]; // if at any time 2 features deviated more than allowed - report anomaly between them if (isAnomalous(x, y, temp)) { arVec.Add(new Anomaly(temp.feature1, temp.feature2, i + 1)); } } } return(unifySpans(arVec)); }
void learnNormal(Data data) { CorrelatedFeatures correlf = new CorrelatedFeatures(); foreach (var entry in data.ts) { // for every feature i correlf.feature1 = entry.Key; correlf.feature2 = ""; // init feature i (max)correlation with any other feature to be 0 correlf.correlation = 0; // check correlation with feature j (j > i, upper triangular matrix) foreach (var inner in data.ts) { if (entry.Key == inner.Key) { continue; } // if i correlate with j more than any previous j, // AND i,j correlation is above minimum threshold, update correlf double correlIJ = calcFeaturesCorrelation(data, entry.Value, inner.Value); if (correlIJ > correlf.correlation && correlIJ > 0.5) { correlf.correlation = correlIJ; correlf.feature2 = inner.Key; set_CF_threshold(correlf, data); } } // if correlation was found for feature i - push to cf vector if (correlf.feature2.Length != 0 && !this.cf.Contains(correlf)) { this.cf.Add(new CorrelatedFeatures(correlf)); } } }
bool isAnomalous(double x, double y, CorrelatedFeatures c) { if (this.isRegression) { if (Math.Abs(c.correlation) > Math.Abs(0.9 /*normal threshold*/)) { return(Math.Abs(y - (c.lin_reg.a * x + c.lin_reg.b)) > c.threshold); } } else { if (Math.Abs(c.correlation) > Math.Abs(0.9 /*normal threshold*/)) { return(Math.Abs(y - (c.lin_reg.a * x + c.lin_reg.b)) > c.threshold); } return(!isInCircle(c.MEC, new Point(x, y))); } return(false); }
// input is timeseries and a correlation of 2 features, // method sets linearreg line and max deviation (threshold) of all points from linearreg line void set_CF_threshold(CorrelatedFeatures correlf, Data train) { // set liner regression line and MEC // get features' vectors List <double> v1 = train.ts[correlf.feature1]; List <double> v2 = train.ts[correlf.feature2]; // points array in size of timeseries' entries (rows - 1) // each point represent (f1,f2) at given time List <Point> points = toPoints(v1, v2); // if 2 features correlation is above normal_threshold, // anomaly check by max deviation from linearreg Line // otherwise (0.5 < correl < normal_threshold), // anomaly can be checked by MEC correlf.lin_reg = linear_reg(points, points.Count); correlf.threshold = findThreshold(points, correlf.lin_reg, train) * 1.1; // * 110% correlf.MEC = new Circle(points); correlf.MEC.r *= 1.1; // * 110% //deletePoints(points, v1.size()); }