예제 #1
0
    def build_leaf(self, sample_indice):

        if (self.y[sample_indice].std() == 0) | (self.y[sample_indice].sum() < 5) | ((1 - self.y[sample_indice]).sum() < 5):
            best_estimator = None
            predict_func = lambda x: np.ones(x.shape[0]) * self.y[sample_indice].mean()
            best_impurity = self.get_loss(self.y[sample_indice], predict_func(self.x[sample_indice]))
        else:
            best_estimator = LogisticRegressionCV(Cs=self.reg_lambda, penalty="l1", solver="liblinear", scoring="roc_auc",
                                      cv=5, random_state=self.random_state)
            mx = self.x[sample_indice].mean(0)
            sx = self.x[sample_indice].std(0) + self.EPSILON
            nx = (self.x[sample_indice] - mx) / sx
            best_estimator.fit(nx, self.y[sample_indice])
            best_estimator.coef_ = best_estimator.coef_ / sx
            best_estimator.intercept_ = best_estimator.intercept_ - np.dot(mx, best_estimator.coef_.T)
            xmin = np.min(np.dot(self.x[sample_indice], best_estimator.coef_.ravel()))
            xmax = np.max(np.dot(self.x[sample_indice], best_estimator.coef_.ravel()))
            predict_func = lambda x: 1 / (1 + np.exp(- np.clip(np.dot(x, best_estimator.coef_.ravel()), xmin, xmax) - best_estimator.intercept_))
            best_impurity = self.get_loss(self.y[sample_indice], best_estimator.predict_proba(self.x[sample_indice])[:, 1])
        return predict_func, best_estimator, best_impurity
예제 #2
0
def create_reduced_linear_classifier(clf, x, transformable_feature_idxs):
    r"""Construct a reduced-dimension classifier based on the original one for a given example.

    The reduced-dimension classifier should behave the same way as the original one, but operate in
    a smaller feature space. This is done by fixing the score of the classifier on a static part of
    ``x``, and integrating it into the bias parameter of the reduced classifier.

    For example, let $$x = [1, 2, 3]$$, weights of the classifier $$w = [1, 1, 1]$$ and bias term $$b =
    0$$, and the only transformable feature index is 0. Then the reduced classifier has weights $$w' =
    [1]$$, and the bias term incorporates the non-transformable part of $$x$$: $$b' = -1 \cdot 2 + 1
    \cdot 3$$.

    :param clf: Original logistic regression classifier
    :param x: An example
    :param transformable_feature_idxs: List of features that can be changed in the given example.
    """

    if not isinstance(clf, LogisticRegressionCV) or not isinstance(
            clf, LogisticRegression):
        raise ValueError(
            "Only logistic regression classifiers can be reduced.")

    # Establish non-transformable feature indexes.
    feature_idxs = np.arange(x.size)
    non_transformable_feature_idxs = np.setdiff1d(feature_idxs,
                                                  transformable_feature_idxs)

    # Create the reduced classifier.
    clf_reduced = LogisticRegressionCV()
    clf_reduced.coef_ = clf.coef_[:, transformable_feature_idxs]
    clf_reduced.intercept_ = np.dot(
        clf.coef_[0, non_transformable_feature_idxs],
        x[non_transformable_feature_idxs])
    clf_reduced.intercept_ += clf.intercept_

    assert np.allclose(
        clf.predict_proba([x]),
        clf_reduced.predict_proba([x[transformable_feature_idxs]]),
    )
    return clf_reduced
예제 #3
0
def find_adv_examples(
    X,
    clf,
    target_confidence,
    confidence_margin,
    feat_count,
    epsilon,
    p_norm=1,
    q_norm=np.inf,
):
    # Define the file location to store results for given epsilon and feature count.
    file_path = "results/malware_{}_{}.pickle".format(epsilon, feat_count)

    # List for storing the results.
    results = []

    # Indices of examples classified in the (target_confidence, target_confidence+0.1) range.
    neg_indices, = np.where((clf.predict_proba(X)[:, 1] > target_confidence)
                            & (clf.predict_proba(X)[:, 1] <=
                               target_confidence + confidence_margin))

    # Specify how many different subsets of features to choose.
    sampling_count = 25

    for i in range(sampling_count):

        batch_msg = "(Batch: {}; Feats: {}; Epsilon: {})".format(
            i, feat_count, epsilon)
        logger.info(
            ">> {} Using JSMA to find adversarial examples for {} samples.".
            format(batch_msg, len(neg_indices)))

        # Choose randomly 'feat_count' features to perturb.
        manifest_subset = np.random.choice((list(MANIFEST_SET)),
                                           size=feat_count,
                                           replace=False)
        assert set(manifest_subset).issubset(MANIFEST_SET)

        # Oracle required by the JSMA algorithm.
        oracle = LogisticRegressionScikitSaliencyOracle(clf)

        # Start by finding adversarial examples using JSMA and record their costs.
        jsma_results = jsma_wrapper(
            X,
            neg_indices,
            clf,
            oracle,
            manifest_subset,
            target_confidence,
            k=1000,
            debug=batch_msg,
        )

        logger.info(
            ">> {} JSMA found adversarial examples for {} samples.".format(
                batch_msg, len(jsma_results)))

        # Skip this batch if no results are found by JSMA.
        if not len(jsma_results):
            logger.warning(
                ">> {} WARN! Insufficient adversarial examples returned by JSMA. Skipping..."
                .format(batch_msg))
            continue

        # Keep only those results that have path_costs > 2.
        jsma_results = {k: v for k, v in jsma_results.items() if v[1] > 2}

        if not len(jsma_results):
            logger.warning(
                ">> {} WARN! JSMA did not find adversarial examples with required path cost. Skipping..."
                .format(batch_msg))
            continue

        # Now only look at the malware samples with lowest path cost according to JSMA.
        jsma_results_sorted = sorted(jsma_results.items(),
                                     key=lambda d: d[1][1])[:10]

        logger.info(
            ">> {} Using IDA* search with heuristic to find adversarial examples for {} samples."
            .format(batch_msg, len(jsma_results_sorted)))

        for idx, (x_adv_jsma, cost_jsma,
                  runtime_jsma) in tqdm(jsma_results_sorted, ascii=True):

            x = X[idx].toarray()[0]

            # Instantiate a counter for expanded nodes, and a profiler.
            expanded_counter = Counter()
            per_example_profiler = Profiler()

            logger.debug(
                ">> {} Locating adversarial example for sample at index: {}..."
                .format(batch_msg, idx))

            with expanded_counter.as_default(
            ), per_example_profiler.as_default():
                try:
                    x_adv, cost = find_adversarial(
                        x,
                        clf,
                        ida_star_search,
                        manifest_subset,
                        epsilon,
                        p_norm=1,
                        q_norm=np.inf,
                        target_confidence=target_confidence,
                    )

                except Exception as e:
                    logger.debug(
                        ">> {} WARN! IDA* search failed for sample at index {} with the following message:\n{}"
                        .format(batch_msg, idx, e))
                    continue

            nodes_expanded = expanded_counter.count()
            runtime = per_example_profiler.compute_stats(
            )["find_adversarial"]["tot"]
            print("RUNTIME (normal CLF) IS {}".format(runtime))

            # Construct a new lightweight classifier.
            clf_light = LogisticRegressionCV()
            non_feature_subset = np.setdiff1d(np.arange(X.shape[1]),
                                              manifest_subset)
            clf_light.coef_ = clf.coef_[:, manifest_subset]
            clf_light.intercept_ = clf.intercept_ + np.dot(
                clf.coef_[0, non_feature_subset], x[non_feature_subset])
            import pdb

            pdb.set_trace()

            with expanded_counter.as_default(
            ), per_example_profiler.as_default():
                try:
                    x_adv, cost = find_adversarial(
                        x[manifest_subset],
                        clf_light,
                        ida_star_search,
                        manifest_subset,
                        epsilon,
                        p_norm=1,
                        q_norm=np.inf,
                        target_confidence=target_confidence,
                    )

                except Exception as e:
                    logger.debug(
                        ">> {} WARN! IDA* search failed for sample at index {} with the following message:\n{}"
                        .format(batch_msg, idx, e))
                    continue

            nodes_expanded = expanded_counter.count()
            runtime = per_example_profiler.compute_stats(
            )["find_adversarial"]["tot"]
            print("RUNTIME (reduced CLF) IS {}".format(runtime))
            pdb.set_trace()

            confidence_jsma = clf.predict_proba([x_adv_jsma])[0, 1]
            confidence = clf.predict_proba([x_adv])[0, 1]

            result = {
                "index": idx,
                "feat_count": feat_count,
                "manifest_subset": manifest_subset,
                "x_adv_jsma": x_adv_jsma,
                "path_cost_jsma": cost_jsma,
                "confidence_jsma": confidence_jsma,
                "runtime_jsma": runtime_jsma,
                "x_adv": x_adv,
                "path_cost": cost,
                "confidence": confidence,
                "nodes_expanded": nodes_expanded,
                "epsilon": epsilon,
                "runtime": runtime,
                "sampling_count": i,
            }

            results.append(result)

            logger.debug(">> {} Saving intermediary results to '{}'.".format(
                batch_msg, file_path))

            with open(file_path, "wb") as f:
                pickle.dump(results, f)

            logger.debug(">> {} Intermediary results saved to '{}'.".format(
                batch_msg, file_path))

    return results
예제 #4
0
        else:
            assert False, 'Not supported model arch'

        eval_ood_detector(args.base_dir, args.in_dataset, out_datasets,
                          args.batch_size, args.method, method_args, args.name,
                          args.epochs, args.adv, args.corrupt,
                          args.adv_corrupt, adv_args, mode_args)
    elif args.method == 'mahalanobis':
        sample_mean, precision, lr_weights, lr_bias, magnitude = np.load(
            os.path.join('output/hyperparams/', args.in_dataset, args.name,
                         'results.npy'),
            allow_pickle=True)
        regressor = LogisticRegressionCV(cv=2).fit(
            [[0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1], [1, 1, 1, 1]],
            [0, 0, 1, 1])
        regressor.coef_ = lr_weights
        regressor.intercept_ = lr_bias

        method_args['sample_mean'] = sample_mean
        method_args['precision'] = precision
        method_args['magnitude'] = magnitude
        method_args['regressor'] = regressor

        eval_ood_detector(args.base_dir, args.in_dataset, out_datasets,
                          args.batch_size, args.method, method_args, args.name,
                          args.epochs, args.adv, args.corrupt,
                          args.adv_corrupt, adv_args, mode_args)
    elif args.method == 'sofl':
        eval_ood_detector(args.base_dir, args.in_dataset, out_datasets,
                          args.batch_size, args.method, method_args, args.name,
                          args.epochs, args.adv, args.corrupt,
예제 #5
0
def run_eval(model, in_loader, out_loader, logger, args, num_classes):
    # switch to evaluate mode
    model.eval()

    logger.info("Running test...")
    logger.flush()

    if args.score == 'MSP':
        logger.info("Processing in-distribution data...")
        in_scores = iterate_data_msp(in_loader, model)
        logger.info("Processing out-of-distribution data...")
        out_scores = iterate_data_msp(out_loader, model)
    elif args.score == 'ODIN':
        logger.info("Processing in-distribution data...")
        in_scores = iterate_data_odin(in_loader, model, args.epsilon_odin,
                                      args.temperature_odin, logger)
        logger.info("Processing out-of-distribution data...")
        out_scores = iterate_data_odin(out_loader, model, args.epsilon_odin,
                                       args.temperature_odin, logger)
    elif args.score == 'Energy':
        logger.info("Processing in-distribution data...")
        in_scores = iterate_data_energy(in_loader, model,
                                        args.temperature_energy)
        logger.info("Processing out-of-distribution data...")
        out_scores = iterate_data_energy(out_loader, model,
                                         args.temperature_energy)
    elif args.score == 'Mahalanobis':
        sample_mean, precision, lr_weights, lr_bias, magnitude = np.load(
            os.path.join(args.mahalanobis_param_path, 'results.npy'),
            allow_pickle=True)
        sample_mean = [s.cuda() for s in sample_mean]
        precision = [p.cuda() for p in precision]

        regressor = LogisticRegressionCV(cv=2).fit(
            [[0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1], [1, 1, 1, 1]],
            [0, 0, 1, 1])

        regressor.coef_ = lr_weights
        regressor.intercept_ = lr_bias

        temp_x = torch.rand(2, 3, 480, 480)
        temp_x = Variable(temp_x).cuda()
        temp_list = model(x=temp_x, layer_index='all')[1]
        num_output = len(temp_list)

        logger.info("Processing in-distribution data...")
        in_scores = iterate_data_mahalanobis(in_loader, model, num_classes,
                                             sample_mean, precision,
                                             num_output, magnitude, regressor,
                                             logger)
        logger.info("Processing out-of-distribution data...")
        out_scores = iterate_data_mahalanobis(out_loader, model, num_classes,
                                              sample_mean, precision,
                                              num_output, magnitude, regressor,
                                              logger)
    elif args.score == 'KL_Div':
        logger.info("Processing in-distribution data...")
        in_dist_logits, in_labels = iterate_data_kl_div(in_loader, model)
        logger.info("Processing out-of-distribution data...")
        out_dist_logits, _ = iterate_data_kl_div(out_loader, model)

        class_mean_logits = []
        for c in range(num_classes):
            selected_idx = (in_labels == c)
            selected_logits = in_dist_logits[selected_idx]
            class_mean_logits.append(np.mean(selected_logits, axis=0))
        class_mean_logits = np.array(class_mean_logits)

        logger.info("Compute distance for in-distribution data...")
        in_scores = []
        for i, logit in enumerate(in_dist_logits):
            if i % 100 == 0:
                logger.info('{} samples processed...'.format(i))
            min_div = float('inf')
            for c_mean in class_mean_logits:
                cur_div = kl(logit, c_mean)
                if cur_div < min_div:
                    min_div = cur_div
            in_scores.append(-min_div)
        in_scores = np.array(in_scores)

        logger.info("Compute distance for out-of-distribution data...")
        out_scores = []
        for i, logit in enumerate(out_dist_logits):
            if i % 100 == 0:
                logger.info('{} samples processed...'.format(i))
            min_div = float('inf')
            for c_mean in class_mean_logits:
                cur_div = kl(logit, c_mean)
                if cur_div < min_div:
                    min_div = cur_div
            out_scores.append(-min_div)
        out_scores = np.array(out_scores)
    else:
        raise ValueError("Unknown score type {}".format(args.score))

    in_examples = in_scores.reshape((-1, 1))
    out_examples = out_scores.reshape((-1, 1))

    auroc, aupr_in, aupr_out, fpr95 = get_measures(in_examples, out_examples)

    logger.info('============Results for {}============'.format(args.score))
    logger.info('AUROC: {}'.format(auroc))
    logger.info('AUPR (In): {}'.format(aupr_in))
    logger.info('AUPR (Out): {}'.format(aupr_out))
    logger.info('FPR95: {}'.format(fpr95))

    logger.flush()