Пример #1
0
    def runTest(self):
        with tf.Graph().as_default():
            # Input shape: (2,3,4)
            inp = tf.constant(
                [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
                 [[-1, -2, -3, -4], [-5, -6, -7, -8], [-9, -10, -11, -12]]],
                dtype=tf.float32)

            # Output shape: (2, 12)
            out = tf.reshape(inp, [2, 12])

            # Calculate relevances
            expl = lrp.lrp(inp, out)

            with tf.Session() as s:
                output = s.run(out)
                explanation = s.run(expl)

                # Shape: (2,3,4)
                expected_explanation = np.array([[[0., 0., 0., 0.],
                                                  [0., 0., 0., 0.],
                                                  [0., 0., 0., 12.]],
                                                 [[-1., 0., 0., 0.],
                                                  [0., 0., 0., 0.],
                                                  [0., 0., 0., 0.]]])

                self.assertTrue(
                    np.allclose(expected_explanation, explanation),
                    "Explanation does not match expected explanation")
Пример #2
0
    def test_softmax(self):
        with tf.Graph().as_default():
            inp = tf.constant([[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]], dtype=tf.float32)

            out = tf.nn.softmax(inp)

            config = LRPConfiguration()
            config.set(LAYER.SOFTMAX, AlphaBetaConfiguration(alpha=2, beta=-1))
            expl = lrp.lrp(inp, out, config)

            with tf.Session() as s:
                explanation = s.run(expl)

                expected = np.array([[[[-0.05989202454, -0.162803402, 0.8879363823],
                                       [0, 0, 0]],

                                      [[0, 0, 0],
                                       [-0.05989202454, -0.162803402, 0.8879363823]]],

                                     [[[-0.05989202454, -0.162803402, 0.8879363823],
                                       [0, 0, 0]],

                                      [[0, 0, 0],
                                       [-0.05989202454, -0.162803402, 0.8879363823]]]])

                # Check if the relevance scores are correct (the correct values are found by
                # calculating the example by hand)
                self.assertTrue(
                    np.allclose(expected, explanation, rtol=1e-03, atol=1e-03),
                    msg="Should be a good explanation")
Пример #3
0
    def _do_test(self, expected_result, config=None):
        # Make sure that expected_result is an np array
        if not type(expected_result).__module__ == np.__name__:
            expected_result = np.array(expected_result)

        with tf.Graph().as_default():
            inputs, indices, _ = dense_to_sparse(self.input)
            sparse_tensor_reordered = tf.sparse_reorder(inputs)
            sparse_tensor_reshaped = tf.sparse_reshape(sparse_tensor_reordered, self.input.shape)

            W = tf.constant(self.W1, dtype=tf.float32)
            b = tf.constant(self.b1, dtype=tf.float32)

            # Sparse layer
            logits = tf.sparse_tensor_dense_matmul(sparse_tensor_reshaped, W) + b

            # Dense layer
            logits = logits @ tf.constant(self.W2, tf.float32) + tf.constant(self.b2, tf.float32)

            explanation = lrp.lrp(inputs, logits, config)

            with tf.Session() as s:
                expl = s.run(explanation)
                self.assertTrue(np.all(np.equal(indices, expl.indices)),
                                "expected indices did not equal actual indices")
                self.assertTrue(np.allclose(expl.values, expected_result.reshape((-1)), rtol=1.e-3, atol=1.e-3),
                                "expected indices did not equal actual indices")
Пример #4
0
    def test_different_consumers_for_each_output(self):
        with tf.Graph().as_default() as g:
            inp = tf.placeholder(tf.float32, shape=(3, 4))

            # Split input to construct path in lrp with two paths from
            # input to output.
            in1, in2 = tf.split(inp, 2, 1)

            # Do additional work on one of the paths
            w = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
            in1 = tf.matmul(in1, w)

            # Concatenate the paths again in order to end up with one output.
            out = tf.concat([in1, in2], 1, 'wtf')

            expl = lrp.lrp(inp, out)

            # Do some testing
            with tf.Session() as s:
                explanation = s.run(expl,
                                    feed_dict={
                                        inp: [[1, 1, 0, 1], [0, 0, 0, 0],
                                              [1, 0, 0, 0]]
                                    })

                self.assertTrue(
                    np.allclose(
                        np.array([[2, 4, 0, 0], [0, 0, 0, 0], [2, 0, 0, 0]]),
                        explanation), "Relevances should match")
Пример #5
0
    def runTest(self):
        with tf.Graph().as_default():
            # Create the input
            # Shape: (1,2,3)
            inp = tf.constant([[[1, 2, 3], [4, 5, 6]]], dtype=tf.float32)

            # Shape: (1, 4, 6)
            pred = tf.tile(inp, (1, 2, 2))

            # Calculate the explanation
            expl = lrp.lrp(inp, pred)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Calculate the explanation
                explanation = sess.run(expl)

                # Create the expected explanation
                # Shape: (1,4,2,3)
                expected_explanation = np.array([[[[0, 0, 3], [0, 0, 0]],
                                                  [[0, 0, 0], [0, 0, 6]],
                                                  [[0, 0, 3], [0, 0, 0]],
                                                  [[0, 0, 0], [0, 0, 6]]]])

                # Check if the calculated explanation matches the expected explanation
                self.assertTrue(
                    np.allclose(expected_explanation,
                                explanation,
                                rtol=1e-03,
                                atol=1e-03),
                    msg=
                    "The explanation does not match the expected explanation")
Пример #6
0
    def _do_linear_test(self, config, expected_result):
        if not type(expected_result).__module__ == np.__name__:
            expected_result = np.array(expected_result)

        with tf.Graph().as_default():
            inp = tf.constant([[
                0.61447761, -0.47432536, -0.29292757, -0.78589278, -0.86108047
            ], [
                0.28479454, -0.60827365, 0.86519678, -0.65091976, -0.6819959
            ], [-0.4422958, 0.55866813, -0.88997564, -0.87868751, -0.0389981]],
                              dtype=tf.float32)

            W1 = tf.constant(
                [[-0.70950127, -0.15957509, -0.607047, 0.13172],
                 [-0.9520821, -0.79133917, -0.03131101, -0.00217408],
                 [-0.35051205, 0.84566609, 0.22297791, 0.39139763],
                 [-0.05067179, 0.07747386, -0.89703108, 0.22393099],
                 [-0.43415774, 0.44243544, -0.17682024, -0.31072929]],
                dtype=tf.float32)
            b1 = tf.constant(
                [0.10282315, -0.07288911, -0.53922754, -0.3299993],
                dtype=tf.float32)

            out1 = tf.nn.relu(inp @ W1 + b1)

            W2 = tf.constant(
                [[-0.3378281, -0.03719562, -0.05190714, 0.3983907],
                 [-0.92650528, -0.97646332, 0.08498075, 0.37901429],
                 [-0.36540267, -0.26421945, -0.79152602, 0.73636482],
                 [0.59652669, 0.89863044, 0.02424345, 0.09883726]],
                dtype=tf.float32)
            b2 = tf.constant(
                [-0.26253957, 0.91930372, 0.11791677, -0.28088199],
                dtype=tf.float32)

            out2 = out1 @ W2 + b2

            out3 = tf.reshape(out2, (3, 2, 2))

            out = tf.nn.softmax(out3)

            expl = lrp.lrp(inp, out, config)

            with tf.Session() as s:
                explanation = s.run(expl)

                # Check if the explanation has the right shape
                self.assertEqual(explanation.shape,
                                 expected_result.shape,
                                 msg="Should be a wellformed explanation")

                # Check if the relevance scores are correct (the correct values are found by
                # calculating the example by hand)
                self.assertTrue(np.allclose(explanation,
                                            expected_result,
                                            rtol=1e-03,
                                            atol=1e-03),
                                msg="Should be a good explanation")
Пример #7
0
    def runTest(self):
        # Get a tensorflow graph
        g = tf.Graph()
        # Set the graph as default
        with g.as_default():
            # Create a placeholder for the input
            inp = tf.placeholder(tf.float32, shape=(1, 1, 4, 6))

            # Create max pooling layer
            activation = tf.nn.max_pool(inp, [1, 1, 2, 1], [1, 1, 2, 1],
                                        "SAME")

            # Reshape predictions to shape (batch_size, predictions_per_sample, classes) so they can be used
            # as input for the lrp framework
            pred = tf.reshape(activation, (1, 2, 6))

            # Calculate the relevance scores using lrp
            expl = lrp.lrp(inp, pred)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Run the operations of interest and feed an input to the network
                prediction, explanation = sess.run(
                    [pred, expl],
                    feed_dict={
                        inp: [[[[1, 2, 3, 4, 5, 6], [3, 4, 3, 5, 6, 7],
                                [5, 6, -1, -5, 0, -1], [-1, -2, 1, 1, 1, 1]]]]
                    })

                # Check if the predictions has the right shape
                self.assertEqual(
                    prediction.shape, (1, 2, 6),
                    msg="Should be able to do a linear forward pass")

                # Check if the explanation has the right shape
                self.assertEqual((1, 2, 1, 4, 6),
                                 explanation.shape,
                                 msg="Should be a wellformed explanation")

                # Expected explanation
                expected = np.array([[[[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 7],
                                        [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0,
                                                             0]]],
                                      [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                        [0, 6, 0, 0, 0, 0], [0, 0, 0, 0, 0,
                                                             0]]]]])

                # Check if the relevance scores are correct (the correct values
                # are found by calculating the example by hand)
                self.assertTrue(np.allclose(expected,
                                            explanation,
                                            rtol=1e-03,
                                            atol=1e-03),
                                msg="Should be a good explanation")
Пример #8
0
    def runTest(self):
        # Get a tensorflow graph
        g = tf.Graph()
        # Set the graph as default
        with g.as_default():
            # Create a placeholder for the input
            inp = tf.placeholder(tf.float32, shape=(1, 2, 2, 2))

            # Create the convolutional layer
            # Set the filters and biases
            filters = tf.constant(
                [[[[2., 1, 1], [1., 1, 0]], [[2., 2, 1], [1., 1, 1]]],
                 [[[1., -1, 1], [0., 1, 0]], [[2., 0, 0], [0., -1, 1]]]],
                dtype=tf.float32)
            bias = tf.constant([1, 2, -2], dtype=tf.float32)

            # Perform the convolution
            activation = tf.nn.conv2d(inp, filters, [1, 1, 1, 1], "SAME")

            # Add bias
            activation = tf.nn.bias_add(activation, bias)

            # Reshape predictions to (batch_size, pred. pr. sample, classes) to fit the required input shape of
            # the framework
            pred = tf.reshape(activation, (1, 2, 6))

            # Calculate the relevance scores using lrp
            expl = lrp.lrp(inp, pred)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Run the operations of interest and feed an input to the network
                prediction, explanation = sess.run([pred, expl],
                                                   feed_dict={
                                                       inp: [[[[1., 0.],
                                                               [-1., 2.]],
                                                              [[2., -1.],
                                                               [3., 0.]]]]
                                                   })

                # Check if the relevance scores are correct
                self.assertTrue(
                    np.allclose([[[[[1.692307692, 0], [0, 1.692307692]],
                                   [[1.692307692, 0], [5.076923077, 0]]],
                                  [[[0, 0], [0, 0]],
                                   [[3.636363636, 0], [5.454545455, 0]]]]],
                                explanation,
                                rtol=1e-03,
                                atol=1e-03),
                    msg=
                    "The calculated relevances do not match the expected relevances"
                )
Пример #9
0
    def test_flat(self):
        g = tf.Graph()
        with g.as_default():
            inp = tf.placeholder(tf.float32, (3, 5))

            W = tf.constant([[1.493394546, 0.5987773779],
                             [0.7321155851, 1.23063763],
                             [2.488971816, 0.9885881838],
                             [0.9965223115, 0.8397688134],
                             [2.089138346, 0.8398492639]]
                            , dtype=tf.float32)
            b = [[2.665864718, 0.8793648172]]

            to_normalize = inp @ W + b

            x = tf.contrib.layers.batch_norm(to_normalize, is_training=False, scale=True)
            vars = tf.global_variables()
            beta = next(i for i in vars if 'beta' in i.name)
            gamma = next(i for i in vars if 'gamma' in i.name)
            mean = next(i for i in vars if 'mean' in i.name)
            variance = next(i for i in vars if 'variance' in i.name)

            b = tf.constant([0.8481817169, -1.118752611], dtype=tf.float32)
            assign_beta = tf.assign(beta, b)
            g = tf.constant([0.1005506696, 0.308355701], dtype=tf.float32)
            assign_gamma = tf.assign(gamma, g)
            m = tf.constant([-0.8224766215, 0.9257031289], dtype=tf.float32)
            assign_mean = tf.assign(mean, m)
            v = tf.constant([0.7134228722, 1.065337135], dtype=tf.float32)
            assign_variance = tf.assign(variance, v)

            # Get the explanation
            config = LRPConfiguration()
            config.set(LAYER.LINEAR, EpsilonConfiguration(bias_strategy=BIAS_STRATEGY.NONE))
            config.set(LAYER.ELEMENTWISE_LINEAR, BaseConfiguration(RULE.IDENTITY))
            explanation = lrp.lrp(inp, x, config)

            with tf.Session() as s:
                s.run(tf.global_variables_initializer())
                s.run([assign_beta, assign_gamma, assign_mean, assign_variance])

                expected_relevances = np.array([[0.3331443396, 0.5080297851, 0.2213932963, 0.1821642756, 0.832728544],
                                                 [0.3800239444, 0.1179592254, 0.5207348458, 0.5280974564, 0.3505242006],
                                                 [0.5231591662, 0.0895191051, 0.6016423127, 0.423324388, -0.1957729137]]
)

                out, relevances = s.run([x, explanation],
                                   feed_dict={inp: [[1.187187323, 3.692928471, 0.4733755909, 0.9728313491, 2.121278175],
                                                    [1.302276662, 0.8245540266, 1.070689437, 2.712026357, 0.8586529453],
                                                    [1.57555465, 0.5499336234, 1.087157802, 1.910559011,
                                                     -0.4214631393]]})

                self.assertTrue(np.allclose(expected_relevances, relevances, rtol=1e-03, atol=1e-03),
                                msg="The relevances do not match the expected")
Пример #10
0
    def runTest(self):
        with tf.Graph().as_default() as g:
            # shape: (6,6)
            values = tf.constant([1], dtype=tf.float32, name="vals")
            inp = tf.SparseTensor([[5, 5]], values, [6, 6])
            inp_reordered = tf.sparse_reorder(inp)
            out = tf.sparse_reshape(inp_reordered, (9, 4))

            out_as_dense = tf.sparse_tensor_dense_matmul(
                out, tf.eye(4, dtype=tf.float32))

            writer = tf.summary.FileWriter("./tmp")
            writer.add_graph(g)

            # Calculate the explanation
            expl = lrp.lrp(inp, out_as_dense)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as s:
                s.run(inp)
                s.run(out)
                # Initialize the variables
                s.run(tf.global_variables_initializer())

                s.run(out)

                # Calculate the explanation
                explanation = s.run(expl)

                # Extract the indices of non-zero elements, the values of the non-zero elements and the dense shape of
                # the expected explanation
                calculated_indices = explanation[0]
                calculated_values = explanation[1]
                calculated_shape = explanation[2]

                # Create the expected explanation by creating an array that holds the indices of non-zero
                # elements, an array that holds the values of the non-zero elements and an array that holds
                # the dense shape of the expected explanation
                expected_indices = np.array([[5, 5]])
                expected_values = np.array([1])
                expected_shape = np.array([6, 6])

                # Check if the explanation matches the expected explanation
                self.assertTrue(np.array_equal(expected_indices,
                                               calculated_indices),
                                msg="The indicies do not match")
                self.assertTrue(np.allclose(expected_values,
                                            calculated_values,
                                            atol=1e-03,
                                            rtol=1e-03),
                                msg="The values do not match")
                self.assertTrue(np.array_equal(expected_shape,
                                               calculated_shape),
                                msg="The shapes do not match")
Пример #11
0
def do_lrp_pertubation_tests(configs, selected_model, model_file, destination,
                             **kwargs):
    result_writer = ResultWriter(destination)
    feed = DataFeed(False)

    iterations = kwargs['test_size'] // kwargs['batch_size']

    start = kwargs['start']
    end = kwargs['end']
    if end == -1:
        end = len(configs)

    for config_idx, config in enumerate(configs[start:end]):
        graph = tf.Graph()
        feed.reset_permutation()

        with graph.as_default():
            x = tf.placeholder(tf.float32, shape=[None, 784])
            y_ = tf.placeholder(tf.float32, shape=[None, 10])

            is_training = False

            y, _ = selected_model['nn'](x, y_, is_training)

            if isinstance(config, str):
                if config == 'random':
                    print("Testing random relevance")
                    explanation = get_random_relevance(x)
                else:
                    print("Testing sensitivity analysis")
                    explanation = get_sensitivity_relevance(x, y)
            else:
                print("Testing ({}/{}) {}".format(config_idx, end - start,
                                                  config))
                with tf.name_scope("LRP"):
                    explanation = lrp.lrp(x, y, config)

            init = get_initializer(False)

            important_variables = tf.trainable_variables()
            important_variables.extend(
                [v for v in tf.global_variables() if 'moving_' in v.name])

            saver = tf.train.Saver(important_variables)

            with tf.Session() as s:
                # Initialize stuff and restore model
                s.run(init)
                saver.restore(s, model_file)

                do_pertubations(config, s, feed, explanation, iterations,
                                kwargs['batch_size'], kwargs['pertubations'],
                                result_writer, x, y)
Пример #12
0
def do_nan_searching(configs, selected_model, model_file, model_name,
                     **kwargs):
    iterations = kwargs['test_size'] // kwargs['batch_size']
    feed = DataFeed()

    start = kwargs['start']
    end = kwargs['end']
    if end == -1:
        end = len(configs)

    found_nans = 0
    for config_idx, config in enumerate(configs[start:end]):
        graph = tf.Graph()
        feed.reset_permutation()

        with graph.as_default():
            x = tf.placeholder(tf.float32, shape=[None, 784])
            y_ = tf.placeholder(tf.float32, shape=[None, 10])

            is_training = False

            y, _ = selected_model['nn'](x, y_, is_training)

            print("Testing ({}/{}), Nan-cnt {}: {}".format(
                config_idx, end - start, found_nans, config))
            explanation = lrp.lrp(x, y, config)

            init = get_initializer(False)

            important_variables = tf.trainable_variables()
            important_variables.extend(
                [v for v in tf.global_variables() if 'moving_' in v.name])

            saver = tf.train.Saver(important_variables)

            with tf.Session() as s:
                # Initialize stuff and restore model
                s.run(init)
                saver.restore(s, model_file)

                found_nans += do_search(config, s, feed, explanation,
                                        iterations, kwargs['batch_size'], x)
    logger.info(
        "Found nans for {} configurations in total for model {}".format(
            found_nans, model_name))
    print("Found nans for {} configurations in total for model {}".format(
        found_nans, model_name))
    return model_name, found_nans
Пример #13
0
    def runTest(self):
        with tf.Graph().as_default():
            inp = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=tf.float32)

            w1 = tf.constant([[1, 1], [1, 1], [1, 1]], dtype=tf.float32)

            b1 = tf.constant([2, 4], dtype=tf.float32)
            activation = tf.matmul(inp, w1) + b1

            # Calculate relevances using lrp
            explanation = lrp.lrp(inp, activation)

            with tf.Session() as s:
                act, expl = s.run([activation, explanation])

                self.assertTrue(
                    np.allclose(np.array([[1, 2, 3], [4, 5, 6]]), expl))
Пример #14
0
    def runTest(self):
        with tf.Graph().as_default():
            inp = tf.constant([[[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]],
                               [[11, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
                               [[1, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]],
                              dtype=tf.float32)

            out = tf.slice(inp, [0, 0, 2], [-1, 3, 2])

            R = lrp.lrp(inp, out)
            with tf.Session() as s:
                expected_explanation = np.array([[[[0., 0., 0., 4.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 0., 8.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 0., 3.]]],
                                                 [[[0., 0., 1., 0.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 1., 0.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 1., 0.]]],
                                                 [[[0., 0., 2., 0.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 3., 0.],
                                                   [0., 0., 0., 0.]],
                                                  [[0., 0., 0., 0.],
                                                   [0., 0., 0., 0.],
                                                   [0., 0., 4., 0.]]]])
                explanation = s.run(R)
                self.assertTrue(
                    np.allclose(expected_explanation,
                                explanation,
                                atol=1e-03,
                                rtol=1e-03),
                    "The explanation does not match the expected explanation")
Пример #15
0
    def test_distribute(self):
        with tf.Graph().as_default():
            input = tf.constant([[0.3315922947, 1.053559579, 0.7477053648, 1.22290369,
                                  0.3730588596, -1.034354431, 0.9187013371, 1.478589349,
                                  -0.7325915066, -0.3569675024, -1.136600512, 0.5516666285,
                                  0.4834049101, -1.613833301, 0.1520745652, 0.117390006]],
                                dtype=tf.float32)
            i = tf.reshape(input, (1, 4, 4, 1))

            # Create max pooling layer
            # (1, 2, 2, 1)
            activation = tf.nn.max_pool(i, [1, 2, 2, 1], [1, 2, 2, 1], "SAME")

            # Reshape to get 1 p/s
            output = tf.reshape(activation, (1, 4))

            config = LRPConfiguration()
            config.set(LAYER.MAX_POOLING, EpsilonConfiguration())

            explanation = lrp.lrp(input, output, config)

            with tf.Session() as s:
                expl = s.run(explanation)

                # Check if the explanation has the right shape
                self.assertEqual((1, 16), expl.shape,
                                 msg="Should be a wellformed explanation")

                # Expected explanation
                expected = np.array(
                    [[0, 0, 0.2531077301, 0.4139683781, 0, 0, 0.3109920311, 0.50052121, 0, 0, 0, 0, 0, 0, 0, 0]])

                # Check if the relevance scores are correct (the correct values
                # are found by calculating the example by hand)
                self.assertTrue(
                    np.allclose(expected,
                                expl,
                                rtol=1e-03,
                                atol=1e-03),
                    msg="Should be a good explanation")

                self.assertTrue(True)
Пример #16
0
    def test_multiple_output_uses(self):
        with tf.Graph().as_default() as g:
            inp = tf.placeholder(tf.float32, shape=(3, 4))

            # Split input to construct path in lrp with two paths from
            # input to output.
            in1, in2 = tf.split(inp, 2, 1)

            # Concatenate the paths again in order to end up with one output
            out = tf.concat([in1, in2], 1)

            expl = lrp.lrp(inp, out)

            with tf.Session() as s:
                input_values = [[1, 1, 0, 1], [0, 0, 0, 0], [1, 0, 0, 0]]
                explanation = s.run(expl, feed_dict={inp: input_values})

                expected_output = [[1, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 0]]
                self.assertTrue(np.allclose(expected_output, explanation),
                                "Relevances should match")
    def test_distribute(self):
        with tf.Graph().as_default():
            input = tf.constant([[1., 2., 2., 3., 3., 3., 3., 2., 1]],
                                dtype=tf.float32)

            i = tf.reshape(input, (1, 3, 3, 1))

            # Create max pooling layer
            # (1, 2, 2, 1)
            activation = tf.nn.max_pool(i, [1, 2, 2, 1], [1, 2, 2, 1], "SAME")

            # Reshape to get 1 p/s
            output = tf.reshape(activation, (2, 2))

            config = LRPConfiguration()
            config.set(LAYER.MAX_POOLING,
                       BaseConfiguration(RULE.WINNER_TAKES_ALL))

            explanation = lrp.lrp(input, output, config)

            with tf.Session() as s:
                expl = s.run(explanation)

                # Check if the explanation has the right shape
                self.assertEqual((1, 9),
                                 expl.shape,
                                 msg="Should be a wellformed explanation")

                # Expected explanation
                expected = np.array([[0., 0., 0., 3., 0., 0., 3., 0., 0]])

                # Check if the relevance scores are correct (the correct values
                # are found by calculating the example by hand)
                self.assertTrue(np.allclose(expected,
                                            expl,
                                            rtol=1e-03,
                                            atol=1e-03),
                                msg="Should be a good explanation")

                self.assertTrue(True)
Пример #18
0
    def test_one_prediction_per_sample(self):
        g = tf.Graph()
        with g.as_default():
            inp = tf.placeholder(tf.float32, (2, 1, 5))

            x = tf.contrib.layers.batch_norm(inp, is_training=False, scale=True)
            vars = tf.global_variables()
            beta = next(i for i in vars if 'beta' in i.name)
            gamma = next(i for i in vars if 'gamma' in i.name)
            mean = next(i for i in vars if 'mean' in i.name)
            variance = next(i for i in vars if 'variance' in i.name)

            b = tf.constant([0, 1, 0, 1, 0], dtype=tf.float32)
            assign_beta = tf.assign(beta, b)
            g = tf.constant([0.1, 0.2, 0.3, 0.4, 0.5], dtype=tf.float32)
            assign_gamma = tf.assign(gamma, g)
            m = tf.constant([1, 2, 3, 4, 4.5], dtype=tf.float32)
            assign_mean = tf.assign(mean, m)
            v = tf.constant([0.2, 0.2, 0.2, 0.2, 0.2], dtype=tf.float32)
            assign_variance = tf.assign(variance, v)

            # Get the explanation
            config = LRPConfiguration()
            config.set(LAYER.ELEMENTWISE_LINEAR, AlphaBetaConfiguration())
            explanation = lrp.lrp(inp, x, config)

            with tf.Session() as s:
                s.run(tf.global_variables_initializer())
                s.run([assign_beta, assign_gamma, assign_mean, assign_variance])

                # Shape: (2, 1, 1, 5)
                expected_relevances = np.array(
                    [[[[0, 0, 0, 1, 0]]],
                     [[[0, 0.8921994513, 0, 0, 0]]]])
                relevances = s.run(explanation, feed_dict={inp: [[[1, 0, 3, 4, 5]],
                                                                 [[1, 2, 3, 0, 4]]]})

                self.assertTrue(np.allclose(expected_relevances, relevances, rtol=1e-03, atol=1e-03),
                                msg="The relevances do not match the expected")
Пример #19
0
    def test_ww_rule_sparse(self):
        with tf.Graph().as_default():
            indices = [[0, 2], [0, 5], [1, 0], [1, 6]]
            values = tf.constant([2, 1, 1, 2.], dtype=tf.float32)
            inp = tf.SparseTensor(indices, values, (3, 7))
            sparse_tensor_reordered = tf.sparse_reorder(inp)
            sparse_tensor_reshaped = tf.sparse_reshape(sparse_tensor_reordered,
                                                       (3, 7))

            W = tf.constant([[0.48237237, -2.17243375, -0.97473115],
                             [2.35669847, 3.11619017, 0.84322384],
                             [5.01346225, 1.69588809, -1.47801861],
                             [2.28595446, 0.24175502, -0.23067427],
                             [0.41892012, -1.44306815, 2.21516808],
                             [1.88990215, 1.46110879, 2.89949934],
                             [2.01381318, 2.12360494, 2.34057405]],
                            dtype=tf.float32)

            b = tf.constant([1.47436833, -0.27795767, 4.28945125],
                            dtype=tf.float32)
            out = tf.sparse_tensor_dense_matmul(sparse_tensor_reshaped, W) + b

            config = LRPConfiguration()
            config.set(LAYER.SPARSE_LINEAR, WWConfiguration())
            expl = lrp.lrp(inp, out, config)

            with tf.Session() as s:
                output, explanation = s.run([out, expl])

                expected_indices = indices
                expected_values = np.array(
                    [11.72503303, 1.666161958, 1.181770802, 6.814097394])

                self.assertTrue(
                    np.allclose(expected_indices, explanation.indices))
                self.assertTrue(
                    np.allclose(expected_values, explanation.values))
Пример #20
0
    def runTest(self):
        # Get a tensorflow graph
        g = tf.Graph()
        # Set the graph as default
        with g.as_default():
            # Create a placeholder for the input
            inp = tf.placeholder(tf.float32, shape=(1, 4, 4, 1))

            # Create max pooling layer
            activation = tf.nn.max_pool(inp, [1, 2, 2, 1], [1, 2, 2, 1],
                                        "VALID")

            # Reshape predictions to (batch_size, pred. pr. sample, classes)
            pred = tf.reshape(activation, (1, 4, 1))

            # Get the explanation tensor
            expl = lrp.lrp(inp, pred)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Run the operations of interest and feed an input to the network
                prediction, explanation = sess.run(
                    [pred, expl],
                    feed_dict={
                        inp: [[[[1], [2], [3], [4]], [[5], [6], [7], [8]],
                               [[9], [10], [11], [12]], [[13], [14], [15],
                                                         [16]]]]
                    })

                # Check if the predictions has the right shape
                self.assertEqual(
                    prediction.shape, (1, 4, 1),
                    msg="Should be able to do a linear forward pass")

                # Check if the explanation has the right shape
                self.assertEqual((1, 4, 4, 4, 1),
                                 explanation.shape,
                                 msg="Should be a wellformed explanation")

                # Expected output has shape
                # (batch_size, pred. pr. sample, input_size ...)
                expected = np.array([[[[[0], [0], [0], [0]],
                                       [[0], [6], [0], [0]],
                                       [[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]]],
                                      [[[0], [0], [0], [0]],
                                       [[0], [0], [0], [8]],
                                       [[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]]],
                                      [[[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]],
                                       [[0], [14], [0], [0]]],
                                      [[[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]],
                                       [[0], [0], [0], [0]],
                                       [[0], [0], [0], [16]]]]])

                # Check if the relevance scores are correct
                # (the correct values are found by calculating the example by hand)
                self.assertTrue(np.allclose(expected,
                                            explanation,
                                            rtol=1e-03,
                                            atol=1e-03),
                                msg="Should be a good explanation")
    def runTest(self):
        with tf.Graph().as_default():
            lstm_units = 2
            max_time_step = 3
            input_depth = 4
            TYPES_OF_GATES_IN_A_LSTM = 4

            # Create input
            inp = tf.constant(
                [[[-5, -4, -3, -2], [-1, 0, 1, 2], [3, 4, 5, 6]],
                 [[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]]],
                dtype=tf.float32)

            # Create mock weights
            LSTM_WEIGHTS = tf.constant(
                [[
                    0.19517923, 0.24883463, 0.65906681, 0.43171532, 0.30894309,
                    0.18143875, 0.9064917, 0.34376469
                ],
                 [
                     0.36688612, 0.41893102, 0.68622539, 0.92279857,
                     0.18437027, 0.7582207, 0.70674838, 0.8861974
                 ],
                 [
                     0.60149935, 0.84269909, 0.3129998, 0.75019745, 0.75946505,
                     0.76014145, 0.012957, 0.06685569
                 ],
                 [
                     0.09053277, 0.91693017, 0.11203575, 0.85798137,
                     0.14988363, 0.96619787, 0.63018615, 0.77663712
                 ],
                 [
                     0.18449367, 0.61801985, 0.07125719, 0.02529254,
                     0.42940272, 0.96136843, 0.95259111, 0.33910939
                 ],
                 [
                     0.88669326, 0.58888385, 0.11549774, 0.63704878,
                     0.85553019, 0.39069136, 0.56481662, 0.27301619
                 ]],
                dtype=tf.float32)

            # Create bias weights
            LSTM_BIAS = tf.constant([
                0.37282269, 0.16629956, 0.92285417, 0.86485604, -0.13370907,
                0.75214074, 0.72669859, -0.261183
            ],
                                    dtype=tf.float32)

            # Create lstm layer
            lstm = tf.contrib.rnn.LSTMCell(lstm_units, forget_bias=0.)

            # Put it into Multi RNN Cell
            lstm = tf.contrib.rnn.MultiRNNCell([lstm])

            # Let dynamic rnn setup the control flow (making while loops and stuff)
            lstm_output, _ = tf.nn.dynamic_rnn(lstm, inp, dtype=tf.float32)

            # Construct operation for assigning mock weights
            kernel = next(i for i in tf.global_variables()
                          if i.shape == (input_depth + lstm_units, lstm_units *
                                         TYPES_OF_GATES_IN_A_LSTM))
            assign_kernel = kernel.assign(LSTM_WEIGHTS)

            # Construct operation for assigning mock bias
            bias = next(i for i in tf.global_variables()
                        if i.shape == (lstm_units *
                                       TYPES_OF_GATES_IN_A_LSTM, ))
            assign_bias = bias.assign(LSTM_BIAS)

            # Get the explanation from the LRP framework
            R = lrp.lrp(inp, lstm_output)
            R_sum = tf.reduce_sum(R, [2, 3])

            with tf.Session() as s:
                # Initialize variables
                s.run(tf.global_variables_initializer())

                # Assign mock weights and mock bias
                s.run([assign_kernel, assign_bias])

                # Calculate the relevances
                explanation = s.run(R)

                # Create array with expected relevances
                expected_explanation = np.array(
                    [[[[
                        -0.00000000329187, -0.00000000579639,
                        -0.00000000344224, -0.00000000256858
                    ], [0, 0, 0, 0], [0, 0, 0, 0]],
                      [[
                          0.01917747822, 0.02132167498, 0.009472542897,
                          0.004885821672
                      ],
                       [
                           -0.05303456479, 0.02658300098, 0.1649355033,
                           0.3430433395
                       ], [0, 0, 0, 0]],
                      [[
                          0.01775032921, 0.01975440857, 0.008784149807,
                          0.004537977098
                      ],
                       [
                           -0.05051601016, 0.02468158083, 0.1500054205,
                           0.3081801763
                       ],
                       [
                           0.04747183272, 0.1265003211, 0.1284724633,
                           0.1745462303
                       ]]],
                     [[[
                         0.09064830212495, 0.21548798884060, 0.19743329647079,
                         0.24977081145921
                     ],
                       [
                           0.00000000000000, 0.00000000000000,
                           0.00000000000000, 0.00000000000000
                       ],
                       [
                           0.00000000000000, 0.00000000000000,
                           0.00000000000000, 0.00000000000000
                       ]],
                      [[
                          0.05894237044, 0.1393483447, 0.127375767,
                          0.1608060994
                      ],
                       [
                           0.06054255911, 0.1387999706, 0.1224546803,
                           0.1504080344
                       ], [0, 0, 0, 0]],
                      [[
                          0.04103863682, 0.09681307209, 0.08841408434,
                          0.1115271072
                      ],
                       [
                           0.04215389263, 0.09642979223, 0.0849954929,
                           0.1043121762
                       ],
                       [
                           0.04310312299, 0.09707452916, 0.08397782613,
                           0.1014948822
                       ]]]])

                self.assertTrue(
                    np.allclose(expected_explanation,
                                explanation,
                                rtol=1e-3,
                                atol=1e-3),
                    "The eplanation should match the expected explanation")
Пример #22
0
    def runTest(self):
        with tf.Graph().as_default():
            batch_size = 4
            sequence_length = 3
            units = 2

            # Shape: (4, 3, 2)
            inp = tf.constant(
                [[[0.25946831, 0.73117677], [-0.86958342, 0.71637971],
                  [1.37765705, -0.94898418]],
                 [[-1.58566558, 0.81390618], [-0.80477955, 0.93804462],
                  [-0.21492174, -0.84860344]],
                 [[1.14450824, 0.76930967], [0.05394846, 0.26253664],
                  [1.47991874, 1.5336967]],
                 [[0.75599386, 0.04976039], [1.37701431, 1.33116121],
                  [0.19442138, -0.2920729]]],
                dtype=tf.float32)

            # Make a reshape that changes the 'batch_size'
            # New shape: (12, 2)
            inp_reshaped = tf.reshape(inp, (-1, 2))

            # Shape back to the original batch_size: (4, 3, 2)
            out = tf.reshape(inp_reshaped,
                             (batch_size, sequence_length, units))

            # Perform lrp
            R = lrp.lrp(inp, out)

            with tf.Session() as s:
                explanation = s.run(R)

                expected_explanation = np.array([[[[0, 0.73117679], [0, 0],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0.7163797],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0],
                                                   [1.37765706, 0]]],
                                                 [[[0, 0.81390619], [0, 0],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0.93804461],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0],
                                                   [-0.21492174, 0]]],
                                                 [[[1.14450824, 0], [0, 0],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0.26253664],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0],
                                                   [0, 1.53369665]]],
                                                 [[[0.75599384, 0], [0, 0],
                                                   [0, 0]],
                                                  [[0, 0], [1.37701428, 0],
                                                   [0, 0]],
                                                  [[0, 0], [0, 0],
                                                   [0.19442138, 0]]]])

                self.assertTrue(
                    np.allclose(expected_explanation,
                                explanation,
                                atol=1e-03,
                                rtol=1e-03),
                    "Explanation does not match expected explanation")
Пример #23
0
    def runTest(self):
        # Construct tensorflow graph
        g = tf.Graph()
        # Use tensorflows default graph
        with g.as_default():
            # Create a placeholder for the input
            inp = tf.placeholder(tf.float32, shape=(1, 2, 2, 2))

            # Create first convolutional layer (simple layer that copies the
            # input to the next layer and copies relevances backwards in the
            # same manner (so we were able to reuse calculations from earlier
            # test case, `test_convolution_with_bias.py`)
            with tf.name_scope('conv1'):
                weights = tf.constant([[[[9, 5], [0, -2]], [[2, 0], [4, 0]]],
                                       [[[4, 6], [1, 0]], [[-8, 7], [2, 3]]]],
                                      dtype=tf.float32)
                activation = tf.nn.conv2d(inp, weights, [1, 1, 1, 1], "SAME")

            # Create the second convolutional layer equal to `test_convolution_with_bias.py`
            with tf.name_scope('conv2'):
                # Set the weights and biases
                weights = tf.constant(
                    [[[[2., 1, 1], [1., 1, 0]], [[2., 2, 1], [1., 1, 1]]],
                     [[[1., -1, 1], [0., 1, 0]], [[2., 0, 0], [0., -1, 1]]]],
                    dtype=tf.float32)
                bias = tf.constant([1, 2, -2], dtype=tf.float32)

                # Perform the convolution
                activation = tf.nn.conv2d(activation, weights, [1, 1, 1, 1],
                                          "SAME")

                # Add bias
                activation = tf.nn.bias_add(activation, bias)
                print(activation)

            # Flatten the activations to get something of the shape (batch_size, predictions_per_sample, classes)
            # as required by the lrp framework
            final_output = tf.reshape(activation, [1, 2, 6])

            # Calculate the relevance scores using lrp
            expl = lrp.lrp(inp, final_output)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Run the operations of interest and feed an input to the network
                prediction, explanation = sess.run([final_output, expl],
                                                   feed_dict={
                                                       inp: [[[[-1., 0.],
                                                               [1., 2.]],
                                                              [[12., 9.],
                                                               [13., 6.]]]]
                                                   })

                # The expected relevances (calculated in Google sheet)
                expected_explanation = np.array([[[[[0, 0], [20.77998952, 0]],
                                                   [[162.531828, 0],
                                                    [480.9247907,
                                                     48.85034831]]],
                                                  [[[0, 0], [0, 0]],
                                                   [[258, 0], [339, 48]]]]])

                # Check if the relevance scores are correct
                self.assertTrue(
                    np.allclose(expected_explanation,
                                explanation,
                                rtol=1e-03,
                                atol=1e-03),
                    msg="Should be a good convolutional explanation")
Пример #24
0
    def test_four_predictions_per_sample(self):
        g = tf.Graph()
        with g.as_default():
            inp = tf.placeholder(tf.float32, (2, 4, 5))

            x = tf.contrib.layers.batch_norm(inp, is_training=False, scale=True)
            vars = tf.global_variables()
            beta = next(i for i in vars if 'beta' in i.name)
            gamma = next(i for i in vars if 'gamma' in i.name)
            mean = next(i for i in vars if 'mean' in i.name)
            variance = next(i for i in vars if 'variance' in i.name)

            b = tf.constant([0, 1, 0, 1, 0], dtype=tf.float32)
            assign_beta = tf.assign(beta, b)
            g = tf.constant([0.1, 0.2, 0.3, 0.4, 0.5], dtype=tf.float32)
            assign_gamma = tf.assign(gamma, g)
            m = tf.constant([1, 2, 3, 4, 4.5], dtype=tf.float32)
            assign_mean = tf.assign(mean, m)
            v = tf.constant([0.2, 0.2, 0.2, 0.2, 0.2], dtype=tf.float32)
            assign_variance = tf.assign(variance, v)

            # Get the explanation
            config = LRPConfiguration()
            config.set(LAYER.ELEMENTWISE_LINEAR, AlphaBetaConfiguration())
            explanation = lrp.lrp(inp, x, config)

            with tf.Session() as s:
                s.run(tf.global_variables_initializer())
                s.run([assign_beta, assign_gamma, assign_mean, assign_variance])

                input = np.array([[[-0.3597203655, 2.416366089, -0.7543762749, 0.8718006654, -2.221761776],
                                   [1.099448308, 0.4108163696, 1.798067039, -0.6544576652, -0.6968107745],
                                   [-0.5612699962, -0.2597267932, 0.06325442832, -1.236885473, 0.9369620591],
                                   [-0.06784464057, -0.004403155247, -1.195337879, -0.528265092, -0.1020843691]],
                                  [[0.8766405077, 0.522839272, 0.4197016166, -1.497174712, 0.05348117451],
                                   [0.08739119149, -0.9997059536, -0.6212993685, 0.04027413639, 0.3979749684],
                                   [0.06180908495, -0.5322826252, -1.585670194, -0.5220654844, -1.096597863],
                                   [1.003261811, -1.865129316, -1.134796217, -0.1038509194, -0.8933464003]]])

                # Shape: (2, 4, 4, 5)
                expected_relevances = np.array(
                    [[[[0.0, 1.07794025, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],

                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.1832650698, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],

                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],

                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]]],
                     [[[0.0, 0.2332384558, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],
                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [-0.2035572695, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],
                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0]],
                      [[0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0, 0.0, 0.0, 0.0, 0.0],
                       [0.0007275465407, 0.0, 0.0, 0.0, 0.0]]]])
                relevances = s.run(explanation, feed_dict={inp: input})
                self.assertTrue(np.allclose(expected_relevances, relevances, rtol=1e-03, atol=1e-03),
                                msg="The relevances do not match the expected")
    def runTest(self):
        # Get a tensorflow graph
        g = tf.Graph()
        # Set the graph as default
        with g.as_default():
            # Create a placeholder for the input
            inp = tf.placeholder(tf.float32, shape=(1, 4))

            # --------------------- Linear layer -----------------------------
            # Setup the linear layer
            weights_1 = tf.constant(
                [[10, 1, 0], [-10, 1, 1], [5, 1, 0], [17, 1, -1]],
                dtype=tf.float32)
            bias_1 = tf.constant([-20, 13, 2], dtype=tf.float32)

            # Calculate the activations
            activation_1 = tf.matmul(inp, weights_1, name="MUL1") + bias_1

            # --------------------- Conv layer -----------------------------
            # Create the convolutional layer
            # Set the filters and biases
            filters = tf.constant([[[-3, 3]], [[3, 10]]], dtype=tf.float32)
            bias_2 = tf.constant([-9, 19], dtype=tf.float32)

            # Expand the dimensions of the output from the first layer,
            # since the 1dconv takes rank 3 tensors as input
            activation_1 = tf.expand_dims(activation_1, -1)

            # Perform the convolution and add bias
            activation_2 = tf.nn.conv1d(activation_1, filters, 1,
                                        "SAME") + bias_2

            # --------------------- Linear layer -----------------------------

            # Flatten the output from the conv layer so it can serve as input
            # to a linear layer
            activation_2_flattened = tf.reshape(activation_2, (1, 6))

            # Setup the linear layer
            weights_3 = tf.constant([[14], [14], [1], [3], [5], [-1]],
                                    dtype=tf.float32)
            bias_3 = tf.constant([0], dtype=tf.float32)

            # Calculate the activations
            activation_3 = tf.matmul(
                activation_2_flattened, weights_3, name="MUL3") + bias_3

            # Set the prediction to be equal to the activations of the last layer
            # (there is no softmax in this network)
            pred = activation_3

            # --------------------- Calculate relevances -----------------------------
            # Calculate the relevance scores using lrp

            expl = lrp.lrp(inp, pred)

            # Run a tensorflow session to evaluate the graph
            with tf.Session() as sess:
                # Initialize the variables
                sess.run(tf.global_variables_initializer())

                # Run the operations of interest and feed an input to the network
                prediction, explanation = sess.run(
                    [pred, expl], feed_dict={inp: [[-1, 3, 55, 0]]})

                # Check if the predictions has the right shape
                self.assertEqual(prediction.shape, (1, 1),
                                 msg="Should be able to do a forward pass")

                # Check if the explanation has the right shape
                self.assertEqual(explanation.shape,
                                 inp.shape,
                                 msg="Should be a wellformed explanation")

                # Check if the relevance scores are correct (the correct values are found by
                # calculating the example by hand)
                self.assertTrue(np.allclose(explanation[0],
                                            [[0, 353.58, 11466.76, 0]],
                                            rtol=1e-01,
                                            atol=1e-01),
                                msg="Should be a good explanation")
Пример #26
0
    def _test_configuration(self, config):
        # Start new graph for this configuration
        graph = tf.Graph()
        with graph.as_default():

            logger.debug(
                "Start of new test graph with config {}".format(config))

            X, X_reordered, self.features_batch, feed_dict = _construct_X_and_feed_dict(
                self.features_read)

            # Prepare template (that uses parameter sharing across calls to sirs_template)
            sirs_template = tf.make_template('', self.create_model)

            logger.debug("Building graph for forward pass")
            logger.debug(sirs_template)

            # Compute the DRN graph
            model = sirs_template(X_reordered)

            should_write_input = False
            if isinstance(config, str):
                # The config is either random or SA
                if config == 'random':
                    # Compute random relevances
                    logger.debug("Building random graph")
                    R = get_random_relevance(X)
                    should_write_input = True
                else:
                    # Compute sensitivity analysis
                    logger.debug("Building SA graph")
                    R = get_sensitivity_analysis(X, model['y_hat'])
            else:
                logger.debug('Building lrp graph')
                R = lrp.lrp(X, model['y_hat'], config)
                logger.debug('Done building lrp graph')

            logger.debug("Instantiating pertubation class")
            # Make pertuber for X and R that prepares a number of pertubations of X
            pertuber = Pertuber(X, R, self.batch_size, **self.confs)

            # Build the pertubation graph
            benchmark = pertuber.build_pertubation_graph(sirs_template)

            # Create a tf Saver that can be used to restore a pre-trained model below
            saver = tf.train.Saver()

            with tf.Session(graph=graph) as s:
                logger.debug("Initializing vars and restoring model")
                # Initialize the local variables and restore the model that was trained earlier
                s.run([tf.local_variables_initializer()])
                self.restore_checkpoint(s, saver)

                logger.debug("Restored model. Now starting threads.")

                # Create the threads that run the model
                coord = tf.train.Coordinator()
                threads = tf.train.start_queue_runners(coord=coord, sess=s)

                try:
                    # Run the benchmarks. Shapes:
                    # Benchmark_result: batch_size, pertubations, num_classes
                    # y                 batch_size, 1
                    # y_hat             batch_size, num_classes
                    logger.debug("Starting session for benchmarks")
                    benchmark_result, expl, y, y_hat = self.run_model(
                        [benchmark, R, model['y'], model['y_hat']],
                        model,
                        feed_dict=feed_dict,
                        session=s)
                    logger.debug("Session done")

                    # Remove extra dimension from y
                    # y shape: (batch_size,)
                    y = y[:, 0]

                    # Find argmax for y_hat
                    # y_hat shape: (batch_size,)
                    y_hat = np.argmax(y_hat, axis=1)

                    # Write results to file
                    logger.debug("Writing result to file")
                    self.writer.write_result(config, y, y_hat,
                                             benchmark_result)

                    logger.debug("Writing explanation to file")
                    self.writer.write_explanation(config, expl)

                    if should_write_input:
                        logger.debug("Writing input to file")
                        self.writer.write_input(self.features_read['features'])

                except tf.errors.OutOfRangeError:
                    logger.debug("Done with the testing")
                except KeyboardInterrupt:
                    logger.debug("Process interrupted by user. Wrapping up.")
                finally:
                    coord.request_stop()

                logger.debug("Joining threads")
                coord.join(threads)
                logger.info("Done with test")
Пример #27
0
    def _do_test_with_config_and_expected_result(self, config,
                                                 expected_result):
        with tf.Graph().as_default():
            lstm_units = 2

            # Make static input shape: (1, 2, 3)
            input = [[[0.42624769, -0.24526631, 2.6827445],
                      [1.50864387, 2.01764531, 0.49280675]]]

            inp = tf.constant(input, dtype=tf.float32)

            # Create lstm layer
            lstm = tf.contrib.rnn.LSTMCell(
                lstm_units,
                # initializer=tf.constant_initializer(1., dtype=tf.float32),
                forget_bias=0.)

            # Put it into Multi RNN Cell
            lstm = tf.contrib.rnn.MultiRNNCell([lstm])
            # Let dynamic rnn setup the control flow (making while loops and stuff)
            lstm_output, _ = tf.nn.dynamic_rnn(lstm, inp, dtype=tf.float32)

            # Construct operation for assigning mock weights
            kernel = next(i for i in tf.global_variables()
                          if i.shape == (5, 8))
            assign_kernel = kernel.assign(
                [[
                    1.48840206, -0.948746, 0.77125305, 2.55016428, 1.18691298,
                    -0.24476569, 2.56425766, 0.13880421
                ],
                 [
                     2.08840452, -0.46632275, 0.84440069, 0.98795753,
                     0.61527844, 2.7123294, 0.33261274, 1.86915179
                 ],
                 [
                     1.42373006, 1.23778513, 0.63839003, 0.68332758,
                     0.82368828, -0.11620465, 0.11787995, 1.58372134
                 ],
                 [
                     2.35450518, -0.41308389, 1.31977204, 0.91312955,
                     -0.13488139, 0.93544023, 0.0894083, 0.12383227
                 ],
                 [
                     0.0330369, 2.63521215, 1.48256475, -0.28661456,
                     1.70166103, 1.80855782, 1.35295711, 0.58774797
                 ]])

            # Construct operation for assigning mock bias
            bias = next(i for i in tf.global_variables() if i.shape == (8, ))
            assign_bias = bias.assign([
                1.39120539, -0.91791735, -1.02699767, 1.34115046, 0.19859183,
                0.73738726, 1.6626231, 2.31063315
            ])

            output = lstm_output

            # Get the explanation from the LRP framework.
            R = lrp.lrp(inp, output, config)

            with tf.Session() as s:
                # Initialize variables
                s.run(tf.global_variables_initializer())

                # Assign mock kernel and bias
                s.run([assign_kernel, assign_bias])

                # Calculate relevance
                relevances = s.run(R)

                # Check for shape and actual result
                self.assertEqual(
                    expected_result.shape, relevances.shape,
                    "Shapes of expected relevance and relevance should be equal"
                )
                self.assertTrue(
                    np.allclose(relevances,
                                expected_result,
                                rtol=1e-03,
                                atol=1e-03), "The relevances do not match")
Пример #28
0
    def runTest(self):
        with tf.Graph().as_default():
            lstm_units = 5

            # Make static input
            np_input = np.reshape(np.arange(-10, 14), (1, 8, 3))
            inp = tf.constant(np_input, dtype=tf.float32)

            # Create lstm layer
            lstm = tf.contrib.rnn.LSTMCell(lstm_units, forget_bias=0.)
            # Put it into Multi RNN Cell
            lstm = tf.contrib.rnn.MultiRNNCell([lstm])
            # Let dynamic rnn setup the control flow (making while loops and stuff)
            lstm_output, _ = tf.nn.dynamic_rnn(lstm, inp, dtype=tf.float32)

            # Construct operation for assigning mock weights
            kernel = next(i for i in tf.global_variables()
                          if i.shape == (8, 20))
            assign_kernel = kernel.assign(LSTM_WEIGHTS)

            # Slice the output to get shape (batch_size, 1, lstm_units) and then squueze the 2nd dimension to
            # get shape (batch_size, lstm_units) so we test if the framework if capable of handling starting point
            # predictions without the predictions_per_sample dimension
            output = tf.squeeze(
                tf.slice(lstm_output, [0, 7, 0], [1, 1, lstm_units]), 1)

            # Get the explanation from the LRP framework.
            # TODO The output of the lstm is not quite right.
            explanation = lrp.lrp(inp, output)

            with tf.Session() as s:
                # Initialize variables
                s.run(tf.global_variables_initializer())

                # Assign mock kernel
                s.run(assign_kernel)

                # Calculate relevance
                relevances = s.run(explanation)

                # Expected result calculated in
                # https://docs.google.com/spreadsheets/d/1_bmSEBSWVOkpdlZYEUckgrnUtxhEfnR84LZy1cU5fIw/edit?usp=sharing
                expected_result = np.array(
                    [[[-0.001298088358, 0.01145384055, 0.0006777067672],
                      [0.02191306626, 0.008657823488, -0.01480988454],
                      [0.05461008726, 0.0005180473113, -0.02527708783],
                      [0.02971554238, 0.0, 0.02727937854],
                      [-0.08685950242, 0.02556374875, 0.1572219068],
                      [-0.2561188815, 0.06659819392, 0.3236008156],
                      [-0.4212428569, 0.1028748125, 0.4771196328],
                      [-0.569597743, 0.1599460364, 0.5879939284]]])

                # Check for shape and actual result
                self.assertEqual(
                    expected_result.shape, relevances.shape,
                    "Shapes of expected relevance and actual relevance should be the same"
                )
                self.assertTrue(
                    np.allclose(relevances,
                                expected_result,
                                rtol=1e-03,
                                atol=1e-03), "The relevances do not match")
Пример #29
0
    def _do_convolutional_test(self, config, expected_result):
        if not type(expected_result).__module__ == np.__name__:
            expected_result = np.array(expected_result)

        with tf.Graph().as_default():
            # Shape (1, 3, 3, 2)
            inp = tf.constant(
                [[[[0.26327863, 1.34089666], [1.10478271, 1.52725762],
                   [-0.16542361, 0.9857486]],
                  [[0.59388839, 0.89302082], [-0.12325813, 1.37334976],
                   [1.70439274, 1.37814247]],
                  [[0.37915105, 0.89512656], [-0.12834121, 0.72336895],
                   [1.35641106, 1.76352144]]]],
                dtype=tf.float32)
            # Shape: (2, 2, 2, 1)
            kernel = tf.constant([[[[0.28530154], [-0.095688446]],
                                   [[-0.45116284], [0.87342771]]],
                                  [[[0.51163061], [-0.86481167]],
                                   [[-0.78022886], [-0.86212577]]]],
                                 dtype=tf.float32)

            bias = tf.constant([0.484489966914], dtype=tf.float32)

            # Shape: (1, 2, 2, 1)
            out1 = tf.nn.relu(
                tf.nn.bias_add(tf.nn.conv2d(inp, kernel, [1, 2, 2, 1], 'SAME'),
                               bias))

            # Shape: (1, 4)
            out2 = tf.reshape(out1, (1, 4))

            # Shape: (4, 2)
            weights = tf.constant(
                [[-0.93597473, -0.26599479], [-0.58296088, -0.05599708],
                 [-0.21809592, 0.93448646], [-0.36266413, -0.00806697]],
                dtype=tf.float32)

            # Shape: (2,)
            bias2 = tf.constant([0.0794559, -0.48629082], dtype=tf.float32)

            # Shape: (1, 2)
            out3 = out2 @ weights + bias2

            # Shape: (1, 2)
            out4 = tf.nn.softmax(out3)

            # Explanation shape: (1, 3, 3, 2)
            expl = lrp.lrp(inp, out4, config)

            with tf.Session() as s:
                explanation = s.run(expl)

                # Check if the explanation has the right shape
                self.assertEqual(explanation.shape,
                                 expected_result.shape,
                                 msg="Should be a wellformed explanation")

                print(expected_result)
                print()
                print(explanation)

                # Check if the relevance scores are correct (the correct values are found by
                # calculating the example by hand)
                self.assertTrue(np.allclose(explanation,
                                            expected_result,
                                            rtol=1e-06,
                                            atol=1e-06),
                                msg="Should be a good explanation")
Пример #30
0
    def runTest(self):
        # Build the computational graph
        with tf.Graph().as_default():
            # Make static input shape: (4, 6)
            inp = tf.constant([[0.49529851, -0.64648792, 0.18508197, -0.14201359, 0.29480708,
                                -0.23168202],
                               [0.03458613, -0.11823616, -0.67511888, -0.17805438, 0.7495242,
                                -0.29286811],
                               [-1.51681199, -1.05214575, -0.31338711, -0.14845488, 0.32269641,
                                2.08227179],
                               [0.18766482, 0.10273498, 0.93645419, -0.71804516, -0.92730127,
                                0.11013126]]

                              , dtype=tf.float32)

            # -------------------------------------------- FC 1--------------------------------------------
            # shape: (6, 10)
            weights_1 = tf.constant([[0.63023564, 0.72418477, -0.03827982, 0.48678625, 1.04275436,
                                      0.35443291, 0.92035296, -0.89705308, -0.90312034, 0.51454559],
                                     [-0.40643197, -0.19538514, 0.52029634, -0.43955133, -1.19634436,
                                      0.33259718, -0.21127183, 0.6793771, -0.72406187, 1.54054022],
                                     [-0.67484287, -1.14928279, 1.28560718, -0.02242465, 0.3377433,
                                      0.74823952, 2.18620002, 0.18857024, 0.6531554, 2.72489568],
                                     [-0.15728904, 0.28771674, -1.18420233, 2.17638949, -0.47370135,
                                      -0.02005775, 0.41663315, 0.60860928, 0.57529257, -0.104214],
                                     [-0.4055075, 0.8596076, -0.89655813, -1.39272219, 0.73927064,
                                      1.44179635, -1.01808758, 1.20547704, -1.30409662, 0.02295059],
                                     [0.80911711, 0.99273549, 0.31395664, 2.29630583, 0.58090097,
                                      -1.05635963, -0.90120138, 1.63487712, 2.27660196, 0.51776111]]

                                    ,
                                    dtype=tf.float32)

            # shape: (10,)
            bias_1 = tf.constant([-1.58876296, 1.44444094, 0.73600305, 0.99948251, -0.25653983,
                                  0.54555058, 0.80193129, -0.46552793, 0.30203156, -0.28628351]
                                 , dtype=tf.float32)

            # shape: (4, 10)
            output_1 = tf.matmul(inp, weights_1) + bias_1

            # Prepare the output for the convolutional layer
            # New shape: (4, 5, 2)
            output_1 = tf.reshape(output_1, (4, 5, 2))

            # -------------------------------------------- Convolution 1 --------------------------------------------
            # Create the filter which has shape [filter_width, in_channels, out_channels]
            # Shape: (2,2,1)
            filter_2 = tf.constant(
                [[[-0.41445586],
                  [1.26795033]],
                 [[-1.61688659],
                  [1.50628238]]]
                , dtype=tf.float32)

            # Shape: (1,)
            bias_2 = tf.constant([0.84705889], dtype=tf.float32)

            # Perform the convolution
            # Shape of output_2: (4, 5, 1)
            output_2 = tf.nn.conv1d(output_1, filter_2, 1, "SAME") + bias_2

            # Prepare output for the max pooling
            # Pooling is defined for 2d, so add dim of 1 (height)
            # New shape of output_2_reshaped: (4,1,5,1)
            output_2 = tf.expand_dims(output_2, 1)

            # -------------------------------------------- Max pooling --------------------------------------------

            # Kernel looks at 1 sample, 1 height, 2 width, and 1 depth
            ksize = [1, 1, 2, 1]

            # Move 1 sample, 1 height, 2 width, and 1 depth at a time
            strides = [1, 1, 2, 1]

            # Perform the max pooling
            # Shape of pool: (4, 1, 3, 1)
            pool = tf.nn.max_pool(output_2, ksize, strides, padding='SAME')

            # Remove the "height" dimension again
            # New shape: (4, 3, 1)
            output_3 = tf.squeeze(pool, 1)

            # -------------------------------------------- Convolution 2--------------------------------------------

            # Create the filter which has shape [filter_width, in_channels, out_channels]
            # Shape: (2,1,2)
            filter_4 = tf.constant(
                [[[0.19205464, -0.90562985]],
                 [[1.0016198, 0.89356491]]],
                dtype=tf.float32)

            # Shape: (2, )
            bias_4 = tf.constant([0.07450981, -0.14901961], dtype=tf.float32)

            # Perform the convolution
            # Shape: (4, 3, 2)
            output_4 = tf.nn.conv1d(output_3, filter_4, 1, "SAME") + bias_4

            # Prepare output for the max pooling
            # Pooling is defined for 2d, so add dim of 1 (height)
            # New shape of output_2_reshaped: (4,1,3,2)
            output_4 = tf.expand_dims(output_4, 1)

            # -------------------------------------------- Max pooling --------------------------------------------

            # Kernel looks at 1 sample, 1 height, 2 width, and 1 depth
            ksize = [1, 1, 2, 1]

            # Move 1 sample, 1 height, 2 width, and 1 depth at a time
            strides = [1, 1, 2, 1]

            # Perform the max pooling
            # Shape of pool: (4, 1, 2, 2)
            pool = tf.nn.max_pool(output_4, ksize, strides, padding='SAME')

            # Remove the "height" dimension again
            # New shape: (4, 2, 2)
            output_5 = tf.squeeze(pool, 1)

            # -------------------------------------------- LSTM --------------------------------------------
            lstm_units = 3

            # Shape of weights: (5, 12)
            LSTM_weights = [[-0.6774261, -1.77336803, 0.37789944, -1.47642675, -0.77326061,
                             -0.41624885, -0.80737161, -1.00830384, 0.80501084, -0.10506079,
                             -0.42341706, 1.61561637],
                            [0.65131449, -1.25813521, -1.01188983, 1.58355103, -0.55863594,
                             0.59259386, -1.15333092, 1.31657508, -0.3582473, -0.91620798,
                             1.30231276, 0.32319264],
                            [1.11120673, 0.60646556, -1.11294626, -0.26202266, -1.53741017,
                             -0.09405062, -0.82200596, -0.41727707, 0.69017403, -2.67866443,
                             1.08780302, -0.53820959],
                            [0.12222124, 0.17716194, -0.96654223, 0.64953949, 1.55478632,
                             -1.22787184, 0.67456202, 0.34234439, -2.42116309, 0.22752669,
                             -0.40613203, -0.42356035],
                            [0.9004432, 1.9286521, 1.04199918, 1.17486178, -1.30394625,
                             0.60571671, 1.30499515, 2.12358405, -1.82775648, 0.81019163,
                             0.20284197, 0.72304922]]
            # Shape: (12,)
            LSTM_bias = [-9.46940060e-01, 5.69888879e-02, -4.06483928e-05,
                         -9.60644436e-01, -1.18161660e+00, -2.04222054e+00,
                         -2.27343882e-02, 2.39842965e-01, -4.42784509e-01,
                         2.86647829e+00, 2.92904572e-02, -1.45679881e+00]

            # Create lstm layer
            lstm = tf.contrib.rnn.LSTMCell(lstm_units,
                                           forget_bias=0.)

            # Put it into Multi RNN Cell
            lstm = tf.contrib.rnn.MultiRNNCell([lstm])

            # Let dynamic rnn setup the control flow (making while loops and stuff)
            # Shape of output_6: (4, 2, 3)
            output_6, _ = tf.nn.dynamic_rnn(lstm, output_5, dtype=tf.float32)

            # Construct operation for assigning mock weights
            kernel = next(i for i in tf.global_variables() if i.shape == (5, 12))
            assign_kernel = kernel.assign(LSTM_weights)

            # Construct operation for assigning mock bias
            bias = next(i for i in tf.global_variables() if i.shape == (12,))
            assign_bias = bias.assign(LSTM_bias)

            # Prepare output for the linear layer by flattening the batch and timesteps
            # to be able to use linear layer on all predictions and all samples in batch at the same time
            # New shape of output_6: (8, 3)
            output_6 = tf.reshape(output_6, (-1, lstm_units))

            # -------------------------------------------- FC 2--------------------------------------------
            # Shape of weights_7: (3,2)
            weights_7 = tf.constant([[1.6295322, 1.54609607],
                                     [1.04818304, -0.98323105],
                                     [-1.35106161, -1.20737747]],
                                    dtype=tf.float32)

            bias_7 = tf.constant([0.85856544, 0.75856544], dtype=tf.float32)

            # Perform the matmul
            output_7 = tf.matmul(output_6, weights_7) + bias_7

            # Reshape to shape (4, 2, 2)
            output_7 = tf.reshape(output_7, (4, 2, 2))

            # -------------------------------------------- Softmax -------------------------------------------

            output_final = tf.nn.softmax(output_7)

            # -------------------------------------------- LRP -------------------------------------------

            # Get the explanation from the LRP framework.
            R = lrp.lrp(inp, output_final)

            # Run the computations
            with tf.Session() as s:
                # Initialize variables
                s.run(tf.global_variables_initializer())

                # Assign mock bias
                s.run([assign_kernel, assign_bias])

                relevances = s.run(R)

                # Expected result calculated in
                # https://docs.google.com/spreadsheets/d/1_bmSEBSWVOkpdlZYEUckgrnUtxhEfnR84LZy1cU5fIw/edit?usp=sharing
                expected_result = np.array([[0, 0.07404811231, 0.01912311052, 0, 0, 0],
                                            [0, 0.02956543224, 0.007635346947, 0, 0, 0],
                                            [0.002886748521, 0.002103478273, 0.00662006448, 0.00155415063, 0.042944841,
                                             0.02943967311],
                                            [-0.002340507274, 0.03042895035, -0.005880763452, -0.001369479592,
                                             -0.03478716069, -0.02364958506],
                                            [0.02778684373, 0.0235402653, 0.001067970707, 4.045956959e-06,
                                             0.008719875287, 0.09191818869],
                                            [-0.0004585283713, -0.0004082257816, -2.710138429e-05, -1.02672324e-07,
                                             -0.0001507774977, -0.001715578912],
                                            [0.00195132106, 0.003198257203, 0.05156540372, 0.001512167255, 0,
                                             0.001152290654],
                                            [0.008284077171, 0.01357778073, 0.2189141462, 0.006419707395, 0,
                                             0.00489189857]]
                                           ).reshape((4, 2, 6))

                self.assertTrue(np.allclose(relevances, expected_result, rtol=1e-03, atol=1e-03),
                                "The relevances do not match")