Example #1
0
    def predict(self, X, confidence_level=None):
        """
        Estimates the importance of the inputs in __X__ towards the __self.explained_model__'s decision.
        Provides confidence intervals if __confidence_level__ is not None.

        :param X: The data samples to be evaluated. The first dimension must be the number of samples.
        :param confidence_level: The confidence level used to report the confidence intervals, i.e. a
                                 confidence level of 0.95 would indicate that you wish to obtain the
                                 0.025 and 0.975 quantiles of the output distribution. If None,
                                 no confidence is returned. The CXPlain instance must have been
                                 initialised with __num_models__ > 1 in order to be able to
                                 compute confidence intervals. (Optional, default: None).
        :return: (i) An array of predictions that estimate the importace of each input feature in __X__
                 based on the sample data __X__. The first dimension of the returned array will be the sample dimension
                 and it will match that of __X__, if confidence_level is None,
                 or
                 (ii) a tuple of two entries with the first entry being the predictions and the second entry being
                 the confidence interval (CI) for each provided feature importance estimate reported in the first entry.
                 The last dimension of the confidence interval reported is (2,) and the entries are
                 (CI lower bound, CI upper bound) if confidence_level is not None
        :exception AssertionError Thrown if __predict__ was called without first fitting the explanation model
                                  using __fit__.
        :exception ValueError Thrown if the value of __confidence_level__ was not in the range [0, 1].

        """
        if self.prediction_model is None:
            raise AssertionError(
                "Model must be initialised when calling __predict__. "
                "Did you forget to __fit__ the explanation model?")

        if confidence_level is not None and \
                (confidence_level <= 0.0 or confidence_level >= 1.0 or \
                 np.isclose(confidence_level, 0.) or \
                 np.isclose(confidence_level, 1.)):
            raise ValueError(
                "The __confidence_level__ must be a value between 0 (exclusive) and 1 (exclusive)."
            )

        if self.num_models == 1:
            ret_val = self._predict_single(self.prediction_model, X)
        else:
            ret_val = self._predict_multiple(X,
                                             confidence_level=confidence_level)

        target_shape = Validation.get_attribution_shape(X)

        if len(target_shape) >= 4:
            confidence_shape = target_shape[:-1] + (2, )
        else:
            confidence_shape = target_shape + (2, )

        if isinstance(ret_val, tuple):
            ret_val = ret_val[0].reshape(target_shape), ret_val[1].reshape(
                confidence_shape)
        else:
            ret_val = ret_val.reshape(target_shape)

        return ret_val
Example #2
0
    def test_get_attribution_shape_multi_channel(self):
        num_samples, intermediary_dimensions, num_channels = [1, 2, 100], [0, 1, 2, 3], [0, 1, 2, 3]

        for samples in num_samples:
            for num_dims in intermediary_dimensions:
                for channels in num_channels:
                    source_size = (samples,) + (2,)*num_dims
                    if channels != 0:
                        source_size += (channels,)

                    data = np.random.normal(0, 1, size=source_size)

                    if num_dims == 0 and channels == 0:
                        with self.assertRaises(ValueError):
                            Validation.get_attribution_shape(data)
                        continue
                    else:
                        attribution_shape = Validation.get_attribution_shape(data)

                    if len(source_size) >= 3:
                        adjusted_source_size = source_size[:-1] + (1,)
                        self.assertEqual(attribution_shape, adjusted_source_size)
                    else:
                        self.assertEqual(attribution_shape, source_size)
Example #3
0
    def check_plot_input(x, attribution, confidence=None):
        # Add sample dim - inputs to __check_plot_input__ are passed without sample dim,
        # but __get_attribution_shape__ expects a sample dim.
        x_with_sample_dim = np.expand_dims(x, axis=0)
        attribution_with_sample_dim = np.expand_dims(attribution, axis=0)
        expected_attribution_shape = Validation.get_attribution_shape(
            x_with_sample_dim)
        if not np.array_equal(attribution_with_sample_dim.shape,
                              expected_attribution_shape):
            raise ValueError("__attribution__ was not of the expected shape. "
                             "__attribution__.shape = {}, "
                             "expected shape = {}.".format(
                                 attribution.shape,
                                 expected_attribution_shape))

        if confidence is not None:
            numel_a, numel_c = np.prod(attribution.shape), np.prod(
                confidence.shape)
            if 2 * numel_a != numel_c:
                raise ValueError(
                    "__confidence__ must have exactly two times as many features as __attribution__. "
                    "Found number of elements (__attribution__) = {},"
                    "Found number of elements (__confidence__) = {}".format(
                        numel_a, numel_c))