def _create_2D_plots(self, normalizer):

        self._test_init(normalizer)

        self.logger.info("Create 2-dimensional plot")

        self.clf_orig = self.classifier.deepcopy()
        pois_clf = self._clf_poisoning()[0]

        fig = CFigure(height=4, width=10, title=self.clf_idx)
        n_rows = 1
        n_cols = 2

        box = self._create_box()

        fig.subplot(n_rows, n_cols, grid_slot=1)
        fig.sp.title('Attacker objective and gradients')
        self._plot_func(fig, self.poisoning.objective_function)
        self._plot_obj_grads(fig, self.poisoning.objective_function_gradient)
        fig.sp.plot_ds(self.tr)
        fig.sp.plot_decision_regions(
            self.clf_orig,
            plot_background=False,
            grid_limits=self.grid_limits,
            n_grid_points=10,
        )

        fig.sp.plot_constraint(box,
                               grid_limits=self.grid_limits,
                               n_grid_points=10)
        fig.sp.plot_path(self.poisoning.x_seq,
                         start_facecolor='r' if self.yc == 1 else 'b')

        fig.subplot(n_rows, n_cols, grid_slot=2)
        fig.sp.title('Classification error on val')
        self._plot_func(fig, self.poisoning.objective_function, acc=True)
        fig.sp.plot_ds(self.tr)
        fig.sp.plot_decision_regions(
            pois_clf,
            plot_background=False,
            grid_limits=self.grid_limits,
            n_grid_points=10,
        )

        fig.sp.plot_constraint(box,
                               grid_limits=self.grid_limits,
                               n_grid_points=10)
        fig.sp.plot_path(self.poisoning.x_seq,
                         start_facecolor='r' if self.yc == 1 else 'b')

        fig.tight_layout()
        exp_idx = "2d_pois_"
        exp_idx += self.clf_idx
        if self.classifier.class_type == 'svm':
            if self.classifier.kernel.preprocess is not None:
                exp_idx += "_norm"
        else:
            if self.classifier.preprocess is not None:
                exp_idx += "_norm"
        fig.savefig(exp_idx + '.pdf', file_format='pdf')
    def _test_plot(self, evas):
        """Check if `stored_vars` is correctly populated.

        Parameters
        ----------
        evas : CAttackEvasionCleverhans

        """
        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        fig = CFigure()

        fig.sp.plot_path(evas.x_seq)
        fig.sp.plot_fun(evas.objective_function,
                        plot_levels=False,
                        multipoint=True,
                        n_grid_points=50)
        fig.sp.plot_decision_regions(self.clf,
                                     plot_background=False,
                                     n_grid_points=100)

        fig.title("ATTACK: {}, y_target: {}".format(
            evas._clvrh_attack_class.__name__, self.y_target))

        name_file = '{}_evasion2D_target_{}.pdf'.format(
            evas._clvrh_attack_class.__name__, self.y_target)
        fig.savefig(fm.join(self.images_folder, name_file), file_format='pdf')
 def _save_fig(self):
     """Visualizing the function being optimized with line search."""
     x_range = CArray.arange(-5, 20, 0.5, )
     score_range = x_range.T.apply_along_axis(self.fun.fun, axis=1)
     ref_line = CArray.zeros(x_range.size)
     fig = CFigure(height=6, width=12)
     fig.sp.plot(x_range, score_range, color='b')
     fig.sp.plot(x_range, ref_line, color='k')
     filename = fm.join(fm.abspath(__file__), 'test_line_search_bisect.pdf')
     fig.savefig(filename)
示例#4
0
    def _plot_2d_evasion(self, evas, ds, x0, filename, th=0, grid_limits=None):
        """Plot evasion attack results for 2D data.

        Parameters
        ----------
        evas : CAttackEvasion
        ds : CDataset
        x0 : CArray
            Initial attack point.
        filename : str
            Name of the output pdf file.
        th : scalar, optional
            Scores threshold of the classifier. Default 0.
        grid_limits : list of tuple or None, optional
            If not specified, will be set as [(-1.5, 1.5), (-1.5, 1.5)].

        """
        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        fig = CFigure(height=6, width=6)

        if grid_limits is None:
            grid_limits = [(-1.5, 1.5), (-1.5, 1.5)]

        fig.sp.plot_ds(ds)
        fig.sp.plot_fun(func=evas.objective_function,
                        grid_limits=grid_limits,
                        colorbar=False,
                        n_grid_points=50,
                        plot_levels=False)

        fig.sp.plot_decision_regions(clf=evas.classifier,
                                     plot_background=False,
                                     grid_limits=grid_limits,
                                     n_grid_points=50)

        fig.sp.plot_constraint(self._box(evas),
                               n_grid_points=20,
                               grid_limits=grid_limits)

        fig.sp.plot_fun(func=lambda z: self._constr(evas, x0).constraint(z),
                        plot_background=False,
                        n_grid_points=50,
                        grid_limits=grid_limits,
                        levels=[0],
                        colorbar=False)

        fig.sp.plot_path(evas.x_seq)

        fig.savefig(fm.join(self.images_folder, filename), file_format='pdf')
    def _create_params_grad_plot(self, normalizer):
        """
        Show the gradient of the classifier parameters w.r.t the poisoning
        point
        """
        self.logger.info("Create 2-dimensional plot of the poisoning "
                         "gradient")

        self._test_init(normalizer)

        pois_clf = self._clf_poisoning()[0]

        if self.n_features == 2:
            debug_pois_obj = _CAttackPoisoningLinTest(self.poisoning)

            fig = CFigure(height=8, width=10)
            n_rows = 2
            n_cols = 2

            fig.title(self.clf_idx)

            fig.subplot(n_rows, n_cols, grid_slot=1)
            fig.sp.title('w1 wrt xc')
            self._plot_param_sub(fig, debug_pois_obj.w1,
                                 debug_pois_obj.gradient_w1_xc, pois_clf)

            fig.subplot(n_rows, n_cols, grid_slot=2)
            fig.sp.title('w2 wrt xc')
            self._plot_param_sub(fig, debug_pois_obj.w2,
                                 debug_pois_obj.gradient_w2_xc, pois_clf)

            fig.subplot(n_rows, n_cols, grid_slot=3)
            fig.sp.title('b wrt xc')
            self._plot_param_sub(fig, debug_pois_obj.b,
                                 debug_pois_obj.gradient_b_xc, pois_clf)

            fig.tight_layout()
            exp_idx = "2d_grad_pois_"
            exp_idx += self.clf_idx
            if self.classifier.preprocess is not None:
                exp_idx += "_norm"
            fig.savefig(exp_idx + '.pdf', file_format='pdf')
示例#6
0
    def test_margin(self):

        self.logger.info("Testing margin separation of SGD...")

        # we create 50 separable points
        dataset = CDLRandomBlobs(n_samples=50,
                                 centers=2,
                                 random_state=0,
                                 cluster_std=0.60).load()

        # fit the model
        clf = CClassifierSGD(loss=CLossHinge(),
                             regularizer=CRegularizerL2(),
                             alpha=0.01,
                             max_iter=200,
                             random_state=0)
        clf.fit(dataset.X, dataset.Y)

        # plot the line, the points, and the nearest vectors to the plane
        xx = CArray.linspace(-1, 5, 10)
        yy = CArray.linspace(-1, 5, 10)

        X1, X2 = np.meshgrid(xx.tondarray(), yy.tondarray())
        Z = CArray.empty(X1.shape)
        for (i, j), val in np.ndenumerate(X1):
            x1 = val
            x2 = X2[i, j]
            Z[i, j] = clf.decision_function(CArray([x1, x2]), y=1)
        levels = [-1.0, 0.0, 1.0]
        linestyles = ['dashed', 'solid', 'dashed']
        colors = 'k'
        fig = CFigure(linewidth=1)
        fig.sp.contour(X1, X2, Z, levels, colors=colors, linestyles=linestyles)
        fig.sp.scatter(dataset.X[:, 0].ravel(),
                       dataset.X[:, 1].ravel(),
                       c=dataset.Y,
                       s=40)

        fig.savefig(
            fm.join(fm.abspath(__file__), 'figs',
                    'test_c_classifier_sgd2.pdf'))
    def _show_adv(self, x0, y0, x_opt, y_pred, attack_idx, y_target):
        """Show the original and the modified sample.

        Parameters
        ----------
        x0 : CArray
            Initial attack point.
        y0 : CArray
            Label of the initial attack point.
        x_opt : CArray
            Final optimal point.
        y_pred : CArray
            Predicted label of the final optimal point.
        attack_idx : str
            Identifier of the attack algorithm.
        y_target : int or None
            Attack target class.

        """
        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        added_noise = abs(x_opt - x0)  # absolute value of noise image

        fig = CFigure(height=5.0, width=15.0)

        fig.subplot(1, 3, 1)
        fig.sp.title(self.digits[y0.item()])
        fig.sp.imshow(x0.reshape((self.img_h, self.img_w)), cmap='gray')

        fig.subplot(1, 3, 2)
        fig.sp.imshow(added_noise.reshape((self.img_h, self.img_w)),
                      cmap='gray')

        fig.subplot(1, 3, 3)
        fig.sp.title(self.digits[y_pred.item()])
        fig.sp.imshow(x_opt.reshape((self.img_h, self.img_w)), cmap='gray')

        name_file = "{:}_MNIST_target-{:}.pdf".format(attack_idx, y_target)
        fig.savefig(fm.join(self.images_folder, name_file), file_format='pdf')
示例#8
0
    def test_margin(self):
        self.logger.info("Testing margin separation of SVM...")

        import numpy as np

        # we create 40 separable points
        rng = np.random.RandomState(0)
        n_samples_1 = 1000
        n_samples_2 = 100
        X = np.r_[1.5 * rng.randn(n_samples_1, 2),
                  0.5 * rng.randn(n_samples_2, 2) + [2, 2]]
        y = [0] * (n_samples_1) + [1] * (n_samples_2)

        dataset = CDataset(X, y)

        # fit the model
        clf = CClassifierSVM()
        clf.fit(dataset.X, dataset.Y)

        w = clf.w
        a = -w[0] / w[1]

        xx = CArray.linspace(-5, 5)
        yy = a * xx - clf.b / w[1]

        wclf = CClassifierSVM(class_weight={0: 1, 1: 10})
        wclf.fit(dataset.X, dataset.Y)

        ww = wclf.w
        wa = -ww[0] / ww[1]
        wyy = wa * xx - wclf.b / ww[1]

        fig = CFigure(linewidth=1)
        fig.sp.plot(xx, yy.ravel(), 'k-', label='no weights')
        fig.sp.plot(xx, wyy.ravel(), 'k--', label='with weights')
        fig.sp.scatter(X[:, 0].ravel(), X[:, 1].ravel(), c=y)
        fig.sp.legend()

        fig.savefig(
            fm.join(fm.abspath(__file__), 'figs', 'test_c_classifier_svm.pdf'))
示例#9
0
    def _show_adv(self, x0, y0, x_opt, y_pred):
        """Show the original and the modified sample.

        Parameters
        ----------
        x0 : CArray
            Initial attack point.
        y0 : CArray
            Label of the initial attack point.
        x_opt : CArray
            Final optimal point.
        y_pred : CArray
            Predicted label of the final optimal point.

        """
        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        added_noise = abs(x_opt - x0)  # absolute value of noise image

        fig = CFigure(height=5.0, width=15.0)
        fig.subplot(1, 3, 1)
        fig.sp.title(self._digits[y0.item()])
        fig.sp.imshow(x0.reshape(
            (self._tr.header.img_h, self._tr.header.img_w)),
                      cmap='gray')
        fig.subplot(1, 3, 2)
        fig.sp.imshow(added_noise.reshape(
            (self._tr.header.img_h, self._tr.header.img_w)),
                      cmap='gray')
        fig.subplot(1, 3, 3)
        fig.sp.title(self._digits[y_pred.item()])
        fig.sp.imshow(x_opt.reshape(
            (self._tr.header.img_h, self._tr.header.img_w)),
                      cmap='gray')
        fig.savefig(fm.join(self.images_folder, self.filename),
                    file_format='pdf')
示例#10
0
    def test_draw(self):
        """ Compare the classifiers graphically"""
        self.logger.info("Testing classifiers graphically")

        # generate 2D synthetic data
        dataset = CDLRandom(n_features=2,
                            n_redundant=1,
                            n_informative=1,
                            n_clusters_per_class=1).load()
        dataset.X = CNormalizerMinMax().fit_transform(dataset.X)

        self.sgds[0].fit(dataset.X, dataset.Y)

        svm = CClassifierSVM()
        svm.fit(dataset.X, dataset.Y)

        fig = CFigure(width=10, markersize=8)
        fig.subplot(2, 1, 1)
        # Plot dataset points
        fig.sp.plot_ds(dataset)
        # Plot objective function
        fig.sp.plot_fun(svm.decision_function,
                        grid_limits=dataset.get_bounds(),
                        y=1)
        fig.sp.title('SVM')

        fig.subplot(2, 1, 2)
        # Plot dataset points
        fig.sp.plot_ds(dataset)
        # Plot objective function
        fig.sp.plot_fun(self.sgds[0].decision_function,
                        grid_limits=dataset.get_bounds(),
                        y=1)
        fig.sp.title('SGD Classifier')

        fig.savefig(
            fm.join(fm.abspath(__file__), 'figs',
                    'test_c_classifier_sgd1.pdf'))
示例#11
0
    def _test_2D(self,
                 fun,
                 grid_limits=None,
                 levels=None,
                 vmin=None,
                 vmax=None,
                 fun_args=()):
        """2D plot of the function.

        Parameters
        ----------
        fun : CFunction
        grid_limits : list of tuple or None, optional
        levels : list or None, optional
        vmin, vmax : scalar or None, optional
        fun_args : tuple

        """
        fun_name = fun.__class__.__name__

        self.logger.info("Plotting 2D of {:}".format(fun_name))

        fig = CFigure(width=7)
        fig.sp.plot_fun(func=fun.fun,
                        plot_levels=True,
                        grid_limits=grid_limits,
                        levels=levels,
                        n_grid_points=50,
                        n_colors=200,
                        vmin=vmin,
                        vmax=vmax,
                        func_args=fun_args)

        fig.sp.title(fun_name)
        fig.savefig(
            fm.join(fm.abspath(__file__),
                    'test_function_{:}.pdf'.format(fun.class_type)))
示例#12
0
    def _test_plot(self, c, *points):
        """Visualize the constraint.

        Parameters
        ----------
        c : CConstraint
        *points : CArray
            A series of point to plot. Each point will be plotted before
            and after cosntraint projection.

        """
        self.logger.info("Plotting constrain {:}".format(c.class_type))

        grid_limits = [(-1, 2.5), (-1, 2.5)]

        fig = CFigure(height=6, width=6)

        fig.sp.plot_fun(func=c.constraint,
                        grid_limits=grid_limits,
                        n_grid_points=40,
                        levels=[0],
                        levels_linewidth=1.5)

        colors = ['g', 'r', 'c', 'm', 'y', 'k', 'w']
        for p_i, p in enumerate(points):
            self.logger.info("Plotting point (color {:}): {:}".format(
                colors[p_i], p))
            fig.sp.scatter(*p, c=colors[p_i], zorder=10)
            p_proj = c.projection(p)
            self.logger.info("Plotting point (color {:}): {:}".format(
                colors[p_i], p_proj))
            fig.sp.scatter(*p_proj, c=colors[p_i], zorder=10)

        filename = "test_constraint_{:}.pdf".format(c.class_type)

        fig.savefig(fm.join(fm.abspath(__file__), filename))
示例#13
0
fig.sp.plot_ds(tr, markers=".")
# fig.sp.plot_path(pois_attack.x_seq)
fig.sp.set_axisbelow(True)
fig.sp._sp.set_aspect("equal")
fig.sp.title("Bi-level Objective")

fig.subplot(1, 2, 2)
fig.sp.plot_fun(
    loss.loss,
    plot_levels=False,
    colorbar=False,
    multipoint=False,
    n_grid_points=50,
    grid_limits=[(lb, ub), (lb, ub)],
)
# fig.sp.plot_fgrads(pois_attack._objective_function_gradient,
#                   n_grid_points=20, grid_limits=[(-20, 20), (-20, 20)])
fig.sp.plot_decision_regions(clf,
                             plot_background=False,
                             n_grid_points=500,
                             grid_limits=[(lb, ub), (lb, ub)])
fig.sp.grid(grid_on=True, linestyle=":", linewidth=0.5)
fig.sp.plot_ds(tr, markers=".")
# fig.sp.plot_path(pois_attack.x_seq)
fig.sp.set_axisbelow(True)
fig.sp._sp.set_aspect("equal")
fig.sp.title("Our Objective")

fig.savefig("poison_objectives.png")
fig.close()
示例#14
0
                n_grid_points=200,
                grid_limits=[(-20, 20), (-20, 20)])
# fig.sp.plot_fgrads(pois_attack._objective_function_gradient,
#                   n_grid_points=20, grid_limits=[(-20, 20), (-20, 20)])
fig.sp.plot_decision_regions(clf,
                             plot_background=False,
                             n_grid_points=500,
                             grid_limits=[(-20, 20), (-20, 20)])
fig.sp.grid(grid_on=True, linestyle=':', linewidth=0.5)
plot_data(fig, training_set)
fig.sp.plot_path(pois_attack.x_seq)
fig.sp.set_axisbelow(True)
fig.sp._sp.set_aspect('equal')
fig.sp.title("Attacker's Loss")
fig.sp.legend()
fig.savefig("loss.pdf")
fig.close()

fig = CFigure(width=width, height=height)
fig.sp.plot_fun(disp_impact.objective_function,
                plot_levels=False,
                multipoint=False,
                n_grid_points=200,
                cmap='jet',
                vmin=0.158,
                vmax=0.178,
                grid_limits=[(-20, 20), (-20, 20)],
                yc=1)
fig.sp.plot_decision_regions(clf,
                             plot_background=False,
                             n_grid_points=500,
    def _plot_optimization(self,
                           solver,
                           x_0,
                           g_min,
                           grid_limits,
                           method=None,
                           vmin=None,
                           vmax=None,
                           label=None):
        """Plots the optimization problem.

        Parameters
        ----------
        solver : COptimizer
        x_0 : CArray
            Starting point.
        g_min : CArray
            Final point (after optimization).
        grid_limits : list of tuple
        vmin, vmax : int or None, optional
        label : str or None, optional

        """
        fig = CFigure(markersize=12)

        # Plot objective function
        fig.sp.plot_fun(func=CArray.apply_along_axis,
                        plot_background=True,
                        n_grid_points=30,
                        n_colors=25,
                        grid_limits=grid_limits,
                        levels=[0.5],
                        levels_color='gray',
                        levels_style='--',
                        colorbar=True,
                        func_args=(
                            solver.f.fun,
                            1,
                        ),
                        vmin=vmin,
                        vmax=vmax)

        if solver.bounds is not None:  # Plot box constraint
            fig.sp.plot_fun(func=lambda x: solver.bounds.constraint(x),
                            plot_background=False,
                            n_grid_points=20,
                            grid_limits=grid_limits,
                            levels=[0],
                            colorbar=False)

        if solver.constr is not None:  # Plot distance constraint
            fig.sp.plot_fun(func=lambda x: solver.constr.constraint(x),
                            plot_background=False,
                            n_grid_points=20,
                            grid_limits=grid_limits,
                            levels=[0],
                            colorbar=False)

        # Plot optimization trace
        if solver.x_seq is not None:
            fig.sp.plot_path(solver.x_seq)
        else:
            fig.sp.plot_path(x_0.append(g_min, axis=0))

        fig.sp.title("{:}(fun={:}) - Glob Min @ {:}".format(
            solver.class_type, solver.f.class_type,
            solver.f.global_min_x().round(2).tolist()))

        test_img_fold_name = 'test_images'
        test_img_fold_path = fm.join(fm.abspath(__file__), test_img_fold_name)
        if not fm.folder_exist(test_img_fold_path):
            fm.make_folder(test_img_fold_path)

        if method is None:
            filename = fm.join(test_img_fold_path,
                               solver.class_type + '-' + solver.f.class_type)
        else:
            filename = fm.join(
                test_img_fold_path,
                solver.class_type + '-' + method + '-' + solver.f.class_type)

        filename += '-' + label if label is not None else ''

        test_img_fold_name = 'test_images'
        if not fm.folder_exist(test_img_fold_name):
            fm.make_folder(test_img_fold_name)

        fig.savefig('{:}.pdf'.format(filename))
示例#16
0
    def _make_plots(self, x_seq, dmax, eva, x0, scores, f_seq):

        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        fig = CFigure(height=9, width=10, markersize=6, fontsize=12)

        # Get plot bounds, taking into account ds and evaded point path
        bounds_x, bounds_y = self.ds.get_bounds()
        min_x, max_x = bounds_x
        min_y, max_y = bounds_y
        min_x = min(min_x, x_seq[:, 0].min())
        max_x = max(max_x, x_seq[:, 0].max())
        min_y = min(min_y, x_seq[:, 1].min())
        max_y = max(max_y, x_seq[:, 1].max())
        ds_bounds = [(min_x, max_x), (min_y, max_y)]

        # Plotting multiclass decision regions
        fig.subplot(2, 2, 1)
        fig = self._plot_decision_function(fig, plot_background=True)

        fig.sp.plot_path(x_seq,
                         path_style='-',
                         start_style='o',
                         start_facecolor='w',
                         start_edgewidth=2,
                         final_style='o',
                         final_facecolor='k',
                         final_edgewidth=2)

        # plot distance constraint
        fig.sp.plot_fun(func=self._rescaled_distance,
                        multipoint=True,
                        plot_background=False,
                        n_grid_points=20,
                        levels_color='k',
                        grid_limits=ds_bounds,
                        levels=[0],
                        colorbar=False,
                        levels_linewidth=2.0,
                        levels_style=':',
                        alpha_levels=.4,
                        c=x0,
                        r=dmax)

        fig.sp.grid(linestyle='--', alpha=.5, zorder=0)

        # Plotting multiclass evasion objective function
        fig.subplot(2, 2, 2)

        fig = self._plot_decision_function(fig)

        fig.sp.plot_fgrads(eva._objective_function_gradient,
                           grid_limits=ds_bounds,
                           n_grid_points=20,
                           color='k',
                           alpha=.5)

        fig.sp.plot_path(x_seq,
                         path_style='-',
                         start_style='o',
                         start_facecolor='w',
                         start_edgewidth=2,
                         final_style='o',
                         final_facecolor='k',
                         final_edgewidth=2)

        # plot distance constraint
        fig.sp.plot_fun(func=self._rescaled_distance,
                        multipoint=True,
                        plot_background=False,
                        n_grid_points=20,
                        levels_color='w',
                        grid_limits=ds_bounds,
                        levels=[0],
                        colorbar=False,
                        levels_style=':',
                        levels_linewidth=2.0,
                        alpha_levels=.5,
                        c=x0,
                        r=dmax)

        fig.sp.plot_fun(lambda z: eva._objective_function(z),
                        multipoint=True,
                        grid_limits=ds_bounds,
                        colorbar=False,
                        n_grid_points=20,
                        plot_levels=False)

        fig.sp.grid(linestyle='--', alpha=.5, zorder=0)

        fig.subplot(2, 2, 3)
        if self.y_target is not None:
            fig.sp.title("Classifier Score for Target Class (Targ. Evasion)")
        else:
            fig.sp.title("Classifier Score for True Class (Indiscr. Evasion)")
        fig.sp.plot(scores)

        fig.sp.grid()
        fig.sp.xlim(0, dmax)
        fig.sp.xlabel("dmax")

        fig.subplot(2, 2, 4)
        fig.sp.title("Objective Function")
        fig.sp.plot(f_seq)

        fig.sp.grid()
        fig.sp.xlim(0, dmax)
        fig.sp.xlabel("dmax")

        fig.tight_layout()

        k_name = self.kernel.class_type if self.kernel is not None else 'lin'
        fig.savefig(
            fm.join(
                self.images_folder,
                "pgd_ls_multiclass_{:}c_kernel-{:}_target-{:}.pdf".format(
                    self.ds.num_classes, k_name, self.y_target)))
示例#17
0
    def _make_plot(self, p_idx, eva, dmax):

        if self.make_figures is False:
            self.logger.debug("Skipping figures...")
            return

        x0 = self.ds.X[p_idx, :]
        y0 = self.ds.Y[p_idx].item()

        x_seq = CArray.empty((0, x0.shape[1]))
        scores = CArray([])
        f_seq = CArray([])

        x = x0
        for d_idx, d in enumerate(range(0, dmax + 1)):

            self.logger.info("Evasion at dmax: " + str(d))

            eva.dmax = d
            x, f_opt = eva._run(x0=x0, y0=y0, x_init=x)
            y_pred, score = self.multiclass.predict(
                x, return_decision_function=True)
            f_seq = f_seq.append(f_opt)
            # not considering all iterations, just values at dmax
            # for all iterations, you should bring eva.x_seq and eva.f_seq
            x_seq = x_seq.append(x, axis=0)

            s = score[:, y0 if self.y_target is None else self.y_target]

            scores = scores.append(s)

        self.logger.info("Predicted label after evasion: {:}".format(y_pred))
        self.logger.info("Score after evasion: {:}".format(s))
        self.logger.info("Objective function after evasion: {:}".format(f_opt))

        fig = CFigure(height=9, width=10, markersize=6, fontsize=12)

        # Get plot bounds, taking into account ds and evaded point path
        bounds_x, bounds_y = self.ds.get_bounds()
        min_x, max_x = bounds_x
        min_y, max_y = bounds_y
        min_x = min(min_x, x_seq[:, 0].min())
        max_x = max(max_x, x_seq[:, 0].max())
        min_y = min(min_y, x_seq[:, 1].min())
        max_y = max(max_y, x_seq[:, 1].max())
        ds_bounds = [(min_x, max_x), (min_y, max_y)]

        # Plotting multiclass decision regions
        fig.subplot(2, 2, 1)
        fig = self._plot_decision_function(fig, plot_background=True)

        fig.sp.plot_path(x_seq,
                         path_style='-',
                         start_style='o',
                         start_facecolor='w',
                         start_edgewidth=2,
                         final_style='o',
                         final_facecolor='k',
                         final_edgewidth=2)

        # plot distance constraint
        fig.sp.plot_fun(func=self._rescaled_distance,
                        multipoint=True,
                        plot_background=False,
                        n_grid_points=20,
                        levels_color='k',
                        grid_limits=ds_bounds,
                        levels=[0],
                        colorbar=False,
                        levels_linewidth=2.0,
                        levels_style=':',
                        alpha_levels=.4,
                        c=x0,
                        r=dmax)

        fig.sp.grid(linestyle='--', alpha=.5, zorder=0)

        # Plotting multiclass evasion objective function
        fig.subplot(2, 2, 2)

        fig = self._plot_decision_function(fig)

        fig.sp.plot_fgrads(eva.objective_function_gradient,
                           grid_limits=ds_bounds,
                           n_grid_points=20,
                           color='k',
                           alpha=.5)

        fig.sp.plot_path(x_seq,
                         path_style='-',
                         start_style='o',
                         start_facecolor='w',
                         start_edgewidth=2,
                         final_style='o',
                         final_facecolor='k',
                         final_edgewidth=2)

        # plot distance constraint
        fig.sp.plot_fun(func=self._rescaled_distance,
                        multipoint=True,
                        plot_background=False,
                        n_grid_points=20,
                        levels_color='w',
                        grid_limits=ds_bounds,
                        levels=[0],
                        colorbar=False,
                        levels_style=':',
                        levels_linewidth=2.0,
                        alpha_levels=.5,
                        c=x0,
                        r=dmax)

        fig.sp.plot_fun(lambda z: eva.objective_function(z),
                        multipoint=True,
                        grid_limits=ds_bounds,
                        colorbar=False,
                        n_grid_points=20,
                        plot_levels=False)

        fig.sp.grid(linestyle='--', alpha=.5, zorder=0)

        fig.subplot(2, 2, 3)
        if self.y_target is not None:
            fig.sp.title("Classifier Score for Target Class (Targ. Evasion)")
        else:
            fig.sp.title("Classifier Score for True Class (Indiscr. Evasion)")
        fig.sp.plot(scores)

        fig.sp.grid()
        fig.sp.xlim(0, dmax)
        fig.sp.xlabel("dmax")

        fig.subplot(2, 2, 4)
        fig.sp.title("Objective Function")
        fig.sp.plot(f_seq)

        fig.sp.grid()
        fig.sp.xlim(0, dmax)
        fig.sp.xlabel("dmax")

        fig.tight_layout()

        k_name = self.kernel.class_type if self.kernel is not None else 'lin'
        fig.savefig(
            fm.join(
                self.images_folder,
                "pgd_ls_reject_threshold_{:}c_kernel-{:}_target-{:}.pdf".
                format(self.ds.num_classes, k_name, self.y_target)))