Пример #1
0
class Conductor:
    """
    Conductor that applies a RNN classifier to the sequence of ensemble member predictions
    """
    def __init__(self, base_rnn_classifier):
        """

        :param base_rnn_classifier: Prototype RNN classifier
        """

        self._rnn_clf = BaseClassifier(base_rnn_classifier)

    def fit(self, sequence, y):
        """ Fit the Conductor

        :param sequence: np.array(n_samples, n_ensemble_members, n_features), Sequence to tbe classified
        :param y: np.array(n_samples), Class labels
        :return:
        """

        # check if new classes appeared in the environment and add new outputs to the RNN classifier if necessary
        if self._rnn_clf.is_compiled:
            self._check_for_new_classes(y)

        self._rnn_clf.partial_fit(sequence, y)

    def predict(self, sequence):
        """ Returns the conductor classification given the ensemble members predictions

        :param sequence: np.array(n_samples, n_ensemble_members, n_features), Sequence to tbe classified
        :return: np.array(n_samples), Prediction
        """

        return self._rnn_clf.predict(sequence)

    def _check_for_new_classes(self, y):
        tmp_classes = np.unique(y)
        new_classes = tmp_classes[~np.isin(tmp_classes, self._rnn_clf.classes)]

        if len(new_classes) != 0:
            self._rnn_clf.add_new_classes(new_classes)
Пример #2
0
class Patch:
    """
    Patch that covers some classes for which the black-box classifier errs
    """
    def __init__(self, base_clf, classes, base_drift_detector):
        """

        :param base_clf: prototype for the patch classifier
        :param classes: classes on which the patch classifier gets trained on
        :param base_drift_detector: Prototype for the class based BD3 instance
                                    Checks whether the patch is suitable for some new input data
        """

        self._clf = BaseClassifier(base_clf)
        self._classes = classes
        self._drift_detector = base_drift_detector.clone()

    def fit(self, train_data, validation_data):
        """

        :param train_data: tuple(data, labels), training data for the patch classifier
        :param validation_data: tuple(data, labels), validation data for the patch classifier
        :return:
        """

        # fit the patch classifier on the training data
        self._clf.partial_fit(train_data[0],
                              train_data[1],
                              classes=self._classes,
                              validation_data=validation_data)

        # update the patches concept
        self._update_concept(validation_data)

    def predict(self, data):
        return self._clf.predict(data)

    def _update_concept(self, valdiation_data):
        # validate patch classifier on the validation data
        prediction = self._clf.predict(valdiation_data[0])

        # update the patch concept modeled by the drift detector based on the validation result
        self._drift_detector.add_element(prediction,
                                         valdiation_data[1],
                                         classifier_changed=True)

    def check_concept_similarity(self, data, labels):
        """ Checks whether the patch is suitable for some new input data

        :param data: test_data
        :param labels: test_labels
        :return: list, Classes in the test data that can not be covered by the patch
        """

        # predict the test data
        prediction = self.predict(data)

        # add the test data to the drift detector without changing the distribution
        self._drift_detector.add_element(prediction,
                                         labels,
                                         classifier_changed=False)

        # check whether the drift detector detects differing classes or not
        differing_classes = self._drift_detector.drifting_classes
        return differing_classes

    @property
    def classes(self):
        return self._classes