def transform(self, x): if len(x) == 0: return x if len(self.X) < self.MIN_HISTORY_SIZE: p_arr = [0.5 for i in range(len(x))] else: p_arr = [pvalue(x[i], self.X[:, i]) for i in range(len(x))] self.P = np.vstack([self.P, p_arr]) self.X = np.vstack([self.X, x]) z = [] for i in range(len(x)): z += self.aggregate(i) return z
def transform_pvalue(self, x, aggregate=True): if len(self.X) < self.MIN_HISTORY_SIZE: p_arr = [0.5 for _ in range(len(x))] else: p_arr = [pvalue(x[i], self.X[:, i]) for i in range(len(x))] self.P = np.vstack([self.P, p_arr]) self.X = np.vstack([self.X, x]) z = [] for i in range(len(x)): pvalues = self.P[-self.w:, i] if aggregate: z += [1. - np.mean(pvalues)] if len(pvalues) >= 1 else [0.5] else: z += [1. - pvalues[-1]] if len(pvalues) >= 1 else [0.5] return z
def predict(self, dtime, x, external=None): '''Update the deviation level based on the new test sample x Parameters: ----------- dtime : datetime datetime corresponding to the sample x x : array-like, shape (n_features,) Sample for which the strangeness, p-value and deviation level are computed external: float (default None) Used in case self.ref_group == "external" to construct the reference dataset from historical data Returns: -------- strangeness : float Strangeness of x with respect to samples in Xref pval : float, in [0, 1] p-value that represents the proportion of samples in Xref that are stranger than x. deviation : float, in [0, 1] Normalized deviation level updated based on the last w_martingale steps ''' self.T.append(dtime) self._fit(dtime, x, external) strangeness = self.strg.get(x) self.S.append(strangeness) pval = pvalue(strangeness, self.scores) self.P.append(pval) deviation = self._update_martingale(pval) self.M.append(deviation) is_deviating = deviation > self.dev_threshold return DeviationContext(strangeness, pval, deviation, is_deviating)
def test_pvalue_special(self): self.assertEqual(pvalue(0, [1, 2, 7, 9, 11]), 1) self.assertEqual(pvalue(20, [1, 2, 7, 9, 11]), 0)
def test_pvalue_general(self): self.assertEqual(pvalue(4, [1, 2, 7, 9, 11]), 3 / 5)
def test_pvalue_empty(self): with self.assertRaises(InputValidationError): pvalue(4, [])