def testCalcScoreByThresholdReturnsExpectedScores(self): fnWeight = 5.0 o = Sweeper() o.fnWeight = fnWeight fakeInput = [ AnomalyPoint(0, 0.5, -1000, 'probationary'), # Should never contribute to score (probationary) AnomalyPoint(1, 0.5, -1000, 'probationary'), # Should never contribute to score (probationary) AnomalyPoint(2, 0.0, -3, None), # Should never contribute to score (anomaly == 0.0) AnomalyPoint(4, 0.2, 20, 'windowA'), # Should be used instead of next row when threshold <= 0.2 AnomalyPoint(5, 0.3, 10, 'windowA'), # Should be used for winowA _until_ threshold <= 0.2 AnomalyPoint(6, 0.5, 5, 'windowB'), # Only score for windowB, but won't be used until threshold <= 0.5 AnomalyPoint(7, 0.5, -3, None), ] expectedScoresByThreshold = [ ThresholdScore(1.1, -2 * fnWeight, 0, 2, 0, 3, 5), # two windows, both false negatives at this threshold ThresholdScore(0.5, 5 - 3 - fnWeight, 1, 1, 1, 2, 5), # Both 'anomalyScore == 0.5' score, windowA is still FN ThresholdScore(0.3, 5 - 3 + 10, 2, 1, 1, 1, 5), # Both windows now have a TP ThresholdScore(0.2, 5 - 3 + 20, 3, 1, 1, 0, 5), # windowA gets a new max value due to row 4 becoming active ThresholdScore(0.0, 5 - 3 + 20 - 3, 3, 0, 2, 0, 5), ] actual = o.calcScoreByThreshold(fakeInput) assert actual == expectedScoresByThreshold
def testPrepareScoreParts(self): fakeInput = [ AnomalyPoint(0, 0.5, 0, 'probationary'), AnomalyPoint(1, 0.5, 0, 'probationary'), AnomalyPoint(2, 0.0, 0, None), AnomalyPoint(4, 0.2, 0, 'windowA'), AnomalyPoint(5, 0.2, 0, 'windowA'), AnomalyPoint(6, 0.5, 0, 'windowB'), AnomalyPoint(7, 0.5, 0, None), ] fakeFNWeight = 33.0 o = Sweeper() o.fnWeight = fakeFNWeight # Expect one entry for all false positives and one entry per unique window name, # initialized to a starting score of `-self.fnWeight` expectedOutput = { "fp": 0, "windowA": -fakeFNWeight, "windowB": -fakeFNWeight } actualScoreParts = o._prepareScoreByThresholdParts(fakeInput) assert actualScoreParts == expectedOutput
def testCalcScoreByThresholdReturnsExpectedScores(self): fnWeight = 5.0 o = Sweeper() o.fnWeight = fnWeight fakeInput = [ AnomalyPoint(0, 0.5, -1000, 'probationary' ), # Should never contribute to score (probationary) AnomalyPoint(1, 0.5, -1000, 'probationary' ), # Should never contribute to score (probationary) AnomalyPoint( 2, 0.0, -3, None), # Should never contribute to score (anomaly == 0.0) AnomalyPoint( 4, 0.2, 20, 'windowA' ), # Should be used instead of next row when threshold <= 0.2 AnomalyPoint( 5, 0.3, 10, 'windowA' ), # Should be used for winowA _until_ threshold <= 0.2 AnomalyPoint( 6, 0.5, 5, 'windowB' ), # Only score for windowB, but won't be used until threshold <= 0.5 AnomalyPoint(7, 0.5, -3, None), ] expectedScoresByThreshold = [ ThresholdScore( 1.1, -2 * fnWeight, 0, 2, 0, 3, 5), # two windows, both false negatives at this threshold ThresholdScore( 0.5, 5 - 3 - fnWeight, 1, 1, 1, 2, 5), # Both 'anomalyScore == 0.5' score, windowA is still FN ThresholdScore(0.3, 5 - 3 + 10, 2, 1, 1, 1, 5), # Both windows now have a TP ThresholdScore( 0.2, 5 - 3 + 20, 3, 1, 1, 0, 5 ), # windowA gets a new max value due to row 4 becoming active ThresholdScore(0.0, 5 - 3 + 20 - 3, 3, 0, 2, 0, 5), ] actual = o.calcScoreByThreshold(fakeInput) assert actual == expectedScoresByThreshold