Example #1
0
def log_map(x, r, tangent_point=None):
    """
    Let \(\mathcal{M}\) be a CCM of radius `r` and \(T_{p}\mathcal{M}\) the
    tangent plane of the CCM at point \(p\) (`tangent_point`).
    This function maps a point `x` on the CCM to the tangent plane, using the
    Riemannian logarithmic map.
    :param x: np.array, point on the CCM (extrinsic coordinates);
    :param r: float, radius of the CCM;
    :param tangent_point: np.array, origin of the tangent plane on the CCM
    (extrinsic coordinates); if 'None', defaults to `[0., ..., 0., r]`.
    :return: the log-map of x to the tangent plane (intrinsic coordinates).
    """
    if not CDG_OK:
        raise ImportError('`log_map` requires CDG.')
    extrinsic_dim = x.shape[-1]
    if tangent_point is None:
        tangent_point = np.zeros((extrinsic_dim,))
        tangent_point[-1] = np.abs(r)
    if isinstance(tangent_point, np.ndarray):
        if tangent_point.shape != (extrinsic_dim,) and tangent_point.shape != (1, extrinsic_dim):
            raise ValueError('Expected tangent_point of shape ({0},) or (1, {0}), got {1}'.format(extrinsic_dim, tangent_point.shape))
        if tangent_point.ndim == 1:
            tangent_point = tangent_point[np.newaxis, ...]
        if not belongs(tangent_point, r)[0]:
            raise ValueError('Tangent point must belong to manifold {}'.format(tangent_point))
    else:
        raise TypeError('tangent_point must be np.ndarray or None')

    if r > 0.:
        return SphericalManifold.log_map(tangent_point, x)
    elif r < 0.:
        return HyperbolicManifold.log_map(tangent_point, x)
    else:
        return x
Example #2
0
def _d_cdt(_path, _c):
    _id = _path.split('/')[-2]
    tpr_avg = []
    fpr_avg = []
    auc_avg = []
    run = 0
    skipped = 0
    crashed = False
    while run < P['N_RUNS'] and (skipped < 100 or skipped /
                                 (run + skipped) < 0.9):
        # Read data
        data = dataset_load(_path)
        try:
            nominal, live, labels = data
        except:
            live, labels = data
            nominal = live[labels == 0].copy()
        live = live[(labels == 0) | (labels == _c)]
        labels = labels[(labels == 0) | (labels == _c)]
        labels[labels != 0] = 1
        CUSUM_WINDOW_SIZE = int(nominal.shape[0] * P['CUSUM_WINDOW_RATIO'])
        cut = CUSUM_WINDOW_SIZE * (nominal.shape[0] // CUSUM_WINDOW_SIZE)
        nominal = nominal[:cut]
        cut = CUSUM_WINDOW_SIZE * (labels.shape[0] // CUSUM_WINDOW_SIZE)
        live = live[:cut]
        labels = labels[:cut]
        live_n = live[labels == 0].copy()
        live_nn = live[labels == 1].copy()
        live = np.vstack((live_n, live_nn))

        # Compute distances
        distances_nom = []
        distances_test = []
        try:
            for i_, r_ in enumerate(P['radius']):
                start = i_ * P['latent_space']
                stop = start + P['latent_space']
                if r_ > 0.:
                    # Spherical
                    s_mean = SphericalManifold.sample_mean(nominal[:,
                                                                   start:stop],
                                                           radius=r_)
                    d_nom = SphericalManifold.distance(nominal[:, start:stop],
                                                       s_mean,
                                                       radius=r_)
                    d_test = SphericalManifold.distance(live[:, start:stop],
                                                        s_mean,
                                                        radius=r_)
                elif r_ < 0.:
                    # Hyperbolic
                    s_mean = HyperbolicManifold.sample_mean(
                        nominal[:, start:stop], radius=-r_)
                    d_nom = HyperbolicManifold.distance(nominal[:, start:stop],
                                                        s_mean,
                                                        radius=-r_)
                    d_test = HyperbolicManifold.distance(live[:, start:stop],
                                                         s_mean,
                                                         radius=-r_)
                else:
                    # Euclidean
                    s_mean = np.mean(nominal[:, start:stop], 0)
                    d_nom = np.linalg.norm(nominal[:, start:stop] - s_mean,
                                           axis=-1)[..., None]
                    d_test = np.linalg.norm(live[:, start:stop] - s_mean,
                                            axis=-1)[..., None]
                distances_nom.append(d_nom)
                distances_test.append(d_test)
        except FloatingPointError:
            print('D-CDT: FloatingPointError')
            skipped += 1
            continue

        # Combined
        distances_nom = np.concatenate(distances_nom, -1)
        distances_test = np.concatenate(distances_test, -1)

        # Change detection
        cdt = GaussianCusum(arl=P['CUSUM_ARL'], window_size=CUSUM_WINDOW_SIZE)
        cdt.fit(distances_nom,
                estimate_threshold=True,
                len_simulation=P['CUSUM_SIM_LEN'])

        pred, cum_sum = cdt.predict(distances_test, reset=True)
        pred = np.array(pred).astype(int)

        y_true = labels.reshape(-1,
                                CUSUM_WINDOW_SIZE).mean(-1).round().reshape(-1)
        y_pred = pred.reshape(-1,
                              CUSUM_WINDOW_SIZE).mean(-1).round().reshape(-1)

        tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
        tpr = tp / (tp + fn)
        fpr = fp / (fp + tn)
        auc, _ = detection_score(y_pred, y_true)

        if auc > 0.:
            tpr_avg.append(tpr)
            fpr_avg.append(fpr)
            auc_avg.append(auc)
            run += 1
        else:
            print('No true positive predictions')
            skipped += 1

    if len(auc_avg) == 0 or np.isnan(np.mean(auc_avg)):
        crashed = True

    result_str = 'crashed' if crashed else 'TPR: {:.5f} FPR: {:.5f} - AUC: {:.3f}'.format(
        np.mean(tpr_avg), np.mean(fpr_avg), np.mean(auc_avg))
    print('Done: {} {} - {}'.format(_id, _c, result_str))

    if not crashed:
        return (_id, _c, np.mean(tpr_avg), np.std(tpr_avg), np.mean(fpr_avg),
                np.std(fpr_avg), np.mean(auc_avg), np.std(auc_avg))
    else:
        return _id, _c, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan
Example #3
0
def _r_cdt(_path, _c):
    _id = _path.split('/')[-2]
    tpr_avg = []
    fpr_avg = []
    auc_avg = []
    run = 0
    skipped = 0
    crashed = False
    while run < P['N_RUNS'] and (skipped < 100 or skipped /
                                 (run + skipped) < 0.9):
        # Read data
        data = dataset_load(_path)
        try:
            nominal, live, labels = data
        except:
            live, labels = data
            nominal = live[labels == 0].copy()
        live = live[(labels == 0) | (labels == _c)]
        labels = labels[(labels == 0) | (labels == _c)]
        labels[labels != 0] = 1
        CUSUM_WINDOW_SIZE = int(nominal.shape[0] * P['CUSUM_WINDOW_RATIO'])
        cut = CUSUM_WINDOW_SIZE * (nominal.shape[0] // CUSUM_WINDOW_SIZE)
        nominal = nominal[:cut]
        cut = CUSUM_WINDOW_SIZE * (labels.shape[0] // CUSUM_WINDOW_SIZE)
        live = live[:cut]
        labels = labels[:cut]
        live_n = live[labels == 0].copy()
        live_nn = live[labels == 1].copy()
        live = np.vstack((live_n, live_nn))

        # Change detection
        cusum_list = []
        indices = []
        for i_, r_ in enumerate(P['radius']):
            start = i_ * P['latent_space']
            stop = start + P['latent_space']
            indices.append((start, stop))
            if r_ < 0.:
                # Hyperbolic
                man_tmp = HyperbolicManifold(radius=-r_)
                cusum_list.append(
                    ManifoldCLTCusum(arl=P['CUSUM_ARL'],
                                     manifold=man_tmp,
                                     window_size=CUSUM_WINDOW_SIZE))
            elif r_ > 0.:
                # Spherical
                man_tmp = SphericalManifold(radius=r_)
                cusum_list.append(
                    ManifoldCLTCusum(arl=P['CUSUM_ARL'],
                                     manifold=man_tmp,
                                     window_size=CUSUM_WINDOW_SIZE))
            else:
                # Euclidean
                cusum_list.append(
                    GaussianCusum(arl=P['CUSUM_ARL'],
                                  window_size=CUSUM_WINDOW_SIZE))

        # Bonferroni on different
        cdt = BonferroniCusum(cusum_list=cusum_list,
                              arl=P['CUSUM_ARL'] // len(P['radius']))
        try:
            cdt.fit([nominal[..., start:stop] for start, stop in indices],
                    estimate_threshold=True,
                    len_simulation=P['CUSUM_SIM_LEN'],
                    radia=P['radius'])
        except FloatingPointError:
            print('R-CDT: FloatingPointError')
            skipped += 1
            continue

        pred, cum_sum = cdt.predict(
            [live[..., start:stop] for start, stop in indices], reset=True)
        pred = np.array(pred).astype(int)

        y_true = labels.reshape(-1,
                                CUSUM_WINDOW_SIZE).mean(-1).round().reshape(-1)
        y_pred = pred.reshape(-1,
                              CUSUM_WINDOW_SIZE).mean(-1).round().reshape(-1)

        tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
        tpr = tp / (tp + fn)
        fpr = fp / (fp + tn)
        auc, _ = detection_score(y_pred, y_true)

        if auc > 0.:
            tpr_avg.append(tpr)
            fpr_avg.append(fpr)
            auc_avg.append(auc)
            run += 1
        else:
            print('No true positive predictions')
            skipped += 1

    if len(auc_avg) == 0 or np.isnan(np.mean(auc_avg)):
        crashed = True

    result_str = 'crashed' if crashed else 'TPR: {:.5f} FPR: {:.5f} - AUC: {:.3f}'.format(
        np.mean(tpr_avg), np.mean(fpr_avg), np.mean(auc_avg))
    print('Done: {} {} - {}'.format(_id, _c, result_str))

    if not crashed:
        return (_id, _c, np.mean(tpr_avg), np.std(tpr_avg), np.mean(fpr_avg),
                np.std(fpr_avg), np.mean(auc_avg), np.std(auc_avg))
    else:
        return _id, _c, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan