Ejemplo n.º 1
0
    def test_get_set_state(self):
        """Test for `.get_state` and `.set_state` methods."""
        x = self.ds.X[0, :]
        self.norm.out_layer = None
        out_norm = self.norm.transform(x)

        self.logger.info(
            "Normalized sample before restoring state:\n{:}".format(out_norm))
        state = self.norm.get_state(return_optimizer=False)

        model = mlp(input_dims=20, hidden_dims=(40,), output_dims=3)
        net = CClassifierPyTorch(model=model, pretrained=True)
        norm_new = CNormalizerDNN(net)

        # Restore state
        norm_new.set_state(state)

        post_out_norm = self.norm.transform(x)
        self.logger.info(
            "Normalized sample after restoring state:\n{:}".format(post_out_norm))

        self.assert_array_equal(out_norm, post_out_norm)
Ejemplo n.º 2
0
    def setUpClass(cls):
        cls.ds = CDLRandom(n_samples=40, n_classes=3,
                           n_features=20, n_informative=15,
                           random_state=0).load()

        model = mlp(input_dims=20, hidden_dims=(40,), output_dims=3)
        loss = nn.CrossEntropyLoss()
        optimizer = optim.SGD(model.parameters(), lr=1e-1)
        cls.net = CClassifierPyTorch(model=model, loss=loss,
                                     optimizer=optimizer, random_state=0,
                                     epochs=10, pretrained=True)
        cls.net.fit(cls.ds.X, cls.ds.Y)
        cls.norm = CNormalizerDNN(net=cls.net)

        CPreProcessTestCases.setUpClass()
Ejemplo n.º 3
0
    def test_preprocess_dnn(self):
        """Test using a `CNormalizerDNN` as preprocessor."""
        # Create a new clf which will have the unittest's Net as preprocessor
        # We use 3 as the number of features as it is the output size of
        # the standard Net used in this unittest
        new_clf = self._create_clf(3, self.n_classes, self.batch_size)
        new_clf.preprocess = CNormalizerDNN(self.clf)

        # Train the new classifier
        new_clf.fit(self.tr.X, self.tr.Y)

        # Test forward and backward
        self._test_predict(new_clf, self.ts)
        self._test_accuracy(new_clf, self.ts)

        self._test_gradient_numerical(new_clf,
                                      self.ts.X[0, :],
                                      th=1e-2,
                                      epsilon=1e-3)
Ejemplo n.º 4
0
    def __init__(self, combiner, layer_clf, dnn, layers, threshold, n_jobs=1):

        self.n_jobs = n_jobs
        super(CClassifierDNR, self).__init__(combiner, threshold)

        if not isinstance(dnn, CClassifierDNN):
            raise TypeError("`dnn` must be an instance of `CClassifierDNN`")
        if not isinstance(layers, list):
            raise TypeError("`layers` must be a list")
        if isinstance(layer_clf, dict):
            if not sorted(layers) == sorted(layer_clf.keys()):
                raise ValueError("`layer_clf` dict must contain `layers` "
                                 "values as keys")
            if not all(isinstance(c, CClassifier) for c in layer_clf.values()):
                raise TypeError("`layer_clf` dict must contain `CClassifier` "
                                "instances as values")
        elif not isinstance(layer_clf, CClassifier):
            raise TypeError("`layer_clf` must be an instance of either"
                            "`CClassifier` or `dict`")

        self._layers = layers
        self._layer_clfs = {}
        for layer in self._layers:
            if isinstance(layer_clf, dict):
                self._layer_clfs[layer] = layer_clf[layer]
            else:
                self._layer_clfs[layer] = layer_clf.deepcopy()
            # search for nested preprocess modules until the inner is reached
            module = self._layer_clfs[layer]
            while module.preprocess is not None:
                module = module.preprocess
            # once the inner preprocess is found, append the dnn to it
            module.preprocess = CNormalizerDNN(net=dnn, out_layer=layer)
            # this allows to access inner classifiers using the
            # respective layer name
            add_readwrite(self, layer, self._layer_clfs[layer])
Ejemplo n.º 5
0
 def test_chain(self):
     """Test for preprocessors chain."""
     # Inner preprocessors should be passed to the pytorch clf
     with self.assertRaises(ValueError):
         CNormalizerDNN(net=self.net, preprocess='min-max')
Ejemplo n.º 6
0
    def test_aspreprocess(self):
        """Test for normalizer used as preprocess."""
        from secml.ml.classifiers import CClassifierSVM
        from secml.ml.classifiers.multiclass import CClassifierMulticlassOVA

        model = mlp(input_dims=20, hidden_dims=(40,), output_dims=3)
        loss = nn.CrossEntropyLoss()
        optimizer = optim.SGD(model.parameters(), lr=1e-1)
        net = CClassifierPyTorch(model=model, loss=loss,
                                 optimizer=optimizer, random_state=0,
                                 epochs=10, preprocess='min-max')
        net.fit(self.ds.X, self.ds.Y)

        norm = CNormalizerDNN(net=net)

        clf = CClassifierMulticlassOVA(
            classifier=CClassifierSVM, preprocess=norm)

        self.logger.info("Testing last layer")

        clf.fit(self.ds.X, self.ds.Y)

        y_pred, scores = clf.predict(
            self.ds.X, return_decision_function=True)
        self.logger.info("TRUE:\n{:}".format(self.ds.Y.tolist()))
        self.logger.info("Predictions:\n{:}".format(y_pred.tolist()))
        self.logger.info("Scores:\n{:}".format(scores))

        x = self.ds.X[0, :]

        self.logger.info("Testing last layer gradient")

        for c in self.ds.classes:
            self.logger.info("Gradient w.r.t. class {:}".format(c))

            grad = clf.grad_f_x(x, y=c)

            self.logger.info("Output of grad_f_x:\n{:}".format(grad))

            check_grad_val = CFunction(
                clf.decision_function, clf.grad_f_x).check_grad(
                    x, y=c, epsilon=1e-1)
            self.logger.info(
                "norm(grad - num_grad): %s", str(check_grad_val))
            self.assertLess(check_grad_val, 1e-3)

            self.assertTrue(grad.is_vector_like)
            self.assertEqual(x.size, grad.size)

        layer = 'linear1'
        norm.out_layer = layer

        self.logger.info("Testing layer {:}".format(norm.out_layer))

        clf.fit(self.ds.X, self.ds.Y)

        y_pred, scores = clf.predict(
            self.ds.X, return_decision_function=True)
        self.logger.info("TRUE:\n{:}".format(self.ds.Y.tolist()))
        self.logger.info("Predictions:\n{:}".format(y_pred.tolist()))
        self.logger.info("Scores:\n{:}".format(scores))

        self.logger.info("Testing 'linear1' layer gradient")
        grad = clf.grad_f_x(x, y=0)  # y is required for multiclassova
        self.logger.info("Output of grad_f_x:\n{:}".format(grad))

        self.assertTrue(grad.is_vector_like)
        self.assertEqual(x.size, grad.size)