Esempio n. 1
0
    def test_layer_database_working_dir(self):

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        meta_path = str('./temp_working_dir/')

        if not os.path.exists(meta_path):
            os.mkdir(meta_path)

        layer_db = LayerDatabase(model=sess, input_shape=(1, 28, 28, 1), working_dir=meta_path)
        copy_layer_db = copy.deepcopy(layer_db)

        shutil.rmtree(meta_path)

        tf.compat.v1.reset_default_graph()

        layer_db.model.close()
        copy_layer_db.model.close()
Esempio n. 2
0
    def test_total_model_cost(self):

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        layer_database = LayerDatabase(model=sess,
                                       input_shape=(1, 28, 28, 1),
                                       working_dir=None)

        cost_calc = cc.CostCalculator()
        network_cost = cost_calc.compute_model_cost(layer_database)

        self.assertEqual(800 + 51200 + 3211264 + 10240, network_cost.memory)
        self.assertEqual(627200 + 10035200 + 3211264 + 10240, network_cost.mac)

        tf.compat.v1.reset_default_graph()
        sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
Esempio n. 3
0
    def test_prune_model_2_layers(self):
        """ Punning two layers with 0.5 comp-ratio in MNIST"""

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        # Create a layer database
        orig_layer_db = LayerDatabase(model=sess,
                                      input_shape=(1, 28, 28, 1),
                                      working_dir=None)
        conv1 = orig_layer_db.find_layer_by_name('conv2d/Conv2D')
        conv2 = orig_layer_db.find_layer_by_name('conv2d_1/Conv2D')

        layer_comp_ratio_list = [
            LayerCompRatioPair(conv1, Decimal(0.5)),
            LayerCompRatioPair(conv2, Decimal(0.5))
        ]

        spatial_svd_pruner = SpatialSvdPruner()
        comp_layer_db = spatial_svd_pruner.prune_model(orig_layer_db,
                                                       layer_comp_ratio_list,
                                                       CostMetric.mac,
                                                       trainer=None)

        conv1_a = comp_layer_db.find_layer_by_name('conv2d_a/Conv2D')
        conv1_b = comp_layer_db.find_layer_by_name('conv2d_b/Conv2D')

        # Weights shape [kh, kw, Nic, Noc]
        self.assertEqual([5, 1, 1, 2],
                         conv1_a.module.inputs[1].get_shape().as_list())
        self.assertEqual([1, 5, 2, 32],
                         conv1_b.module.inputs[1].get_shape().as_list())

        conv2_a = comp_layer_db.find_layer_by_name('conv2d_1_a/Conv2D')
        conv2_b = comp_layer_db.find_layer_by_name('conv2d_1_b/Conv2D')

        self.assertEqual([5, 1, 32, 53],
                         conv2_a.module.inputs[1].get_shape().as_list())
        self.assertEqual([1, 5, 53, 64],
                         conv2_b.module.inputs[1].get_shape().as_list())

        for layer in comp_layer_db:
            print("Layer: " + layer.name)
            print("   Module: " + str(layer.module.name))

        tf.compat.v1.reset_default_graph()
        sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
Esempio n. 4
0
    def test_layer_database_with_mnist(self):

        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            # initialize the weights and biases with appropriate initializer
            sess.run(tf.compat.v1.global_variables_initializer())

        layer_db = LayerDatabase(model=sess, input_shape=(1, 28, 28, 1), working_dir=None)

        layers = list(layer_db._compressible_layers.values())

        # check output shapes
        self.assertEqual(layers[0].output_shape, [None, 32, 28, 28])
        self.assertEqual(layers[1].output_shape, [None, 64, 14, 14])
        self.assertEqual(layers[2].output_shape, [None, 1024, 1, 1])
        self.assertEqual(layers[3].output_shape, [None, 10, 1, 1])

        # check weight shapes
        # layer weight_shape is in common format [Noc, Nic, k_h, k_w]
        self.assertEqual(layers[0].weight_shape, [32, 1, 5, 5])
        self.assertEqual(layers[1].weight_shape, [64, 32, 5, 5])
        self.assertEqual(layers[2].weight_shape, [1024, 3136])
        self.assertEqual(layers[3].weight_shape, [10, 1024])

        # tensorflow weights are stored in [k_h, k_w, Nic, Noc]
        self.assertEqual(layers[0].module.inputs[1].eval(session=layer_db.model).shape, (5, 5, 1, 32))
        self.assertEqual(layers[1].module.inputs[1].eval(session=layer_db.model).shape, (5, 5, 32, 64))
        self.assertEqual(layers[2].module.inputs[1].eval(session=layer_db.model).shape, (3136, 1024))
        self.assertEqual(layers[3].module.inputs[1].eval(session=layer_db.model).shape, (1024, 10))

        tf.compat.v1.reset_default_graph()
        sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
Esempio n. 5
0
    def test_calculate_spatial_svd_cost_all_layers(self):

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        layer_database = LayerDatabase(model=sess,
                                       input_shape=(1, 28, 28, 1),
                                       working_dir=None)

        # Compress all layers by 50%

        # Create a list of tuples of (layer, comp_ratio)
        layer_ratio_list = []

        for layer in layer_database:

            if layer.module.type == 'Conv2D':
                layer_ratio_list.append(LayerCompRatioPair(
                    layer, Decimal(0.5)))
            else:
                layer_ratio_list.append(LayerCompRatioPair(layer, None))

        compressed_cost = cc.SpatialSvdCostCalculator.calculate_compressed_cost(
            layer_database, layer_ratio_list, CostMetric.mac)

        self.assertEqual(8466464, compressed_cost.mac)

        tf.compat.v1.reset_default_graph()
        sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
Esempio n. 6
0
    def test_layer_database_destroy(self):

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            init = tf.compat.v1.global_variables_initializer()

        sess.run(init)
        layer_db = LayerDatabase(model=sess, input_shape=(1, 28, 28, 1), working_dir=None)

        layer_db.destroy()

        self.assertRaises(RuntimeError, lambda: sess.run(init))
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
    def test_per_layer_eval_scores(self):

        pruner = unittest.mock.MagicMock()
        eval_func = unittest.mock.MagicMock()

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        # Create a layer database
        layer_db = LayerDatabase(model=sess,
                                 input_shape=(1, 28, 28, 1),
                                 working_dir=None)
        layer1 = layer_db.find_layer_by_name('conv2d/Conv2D')

        layer_db.mark_picked_layers([layer1])
        eval_func.side_effect = [90, 80, 70, 60, 50, 40, 30, 20, 10]

        url, process = start_bokeh_server_session(8006)
        bokeh_session = BokehServerSession(url=url, session_id="compression")

        # Instantiate child
        greedy_algo = comp_ratio_select.GreedyCompRatioSelectAlgo(
            layer_db=layer_db,
            pruner=pruner,
            cost_calculator=SpatialSvdCostCalculator(),
            eval_func=eval_func,
            eval_iterations=20,
            cost_metric=CostMetric.mac,
            target_comp_ratio=0.5,
            num_candidates=10,
            use_monotonic_fit=True,
            saved_eval_scores_dict=None,
            comp_ratio_rounding_algo=None,
            use_cuda=False,
            bokeh_session=bokeh_session)
        progress_bar = ProgressBar(1,
                                   "eval scores",
                                   "green",
                                   bokeh_session=bokeh_session)
        data_table = DataTable(num_columns=3,
                               num_rows=1,
                               column_names=[
                                   '0.1', '0.2', '0.3', '0.4', '0.5', '0.6',
                                   '0.7', '0.8', '0.9'
                               ],
                               row_index_names=[layer1.name],
                               bokeh_session=bokeh_session)

        pruner.prune_model.return_value = layer_db
        eval_dict = greedy_algo._compute_layerwise_eval_score_per_comp_ratio_candidate(
            data_table, progress_bar, layer1)

        self.assertEqual(90, eval_dict[Decimal('0.1')])

        tf.compat.v1.reset_default_graph()
        sess.close()

        bokeh_session.server_session.close("test complete")
        os.killpg(os.getpgid(process.pid), signal.SIGTERM)
    def test_select_per_layer_comp_ratios_with_spatial_svd_pruner(self):

        pruner = SpatialSvdPruner()
        eval_func = unittest.mock.MagicMock()
        rounding_algo = unittest.mock.MagicMock()
        eval_func.side_effect = [
            10, 20, 30, 40, 50, 60, 70, 80, 90, 11, 21, 31, 35, 40, 45, 50, 55,
            60
        ]
        rounding_algo.round.side_effect = [
            0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.2, 0.3, 0.4,
            0.5, 0.6, 0.7, 0.8, 0.9
        ]

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        # Create a layer database
        layer_db = LayerDatabase(model=sess,
                                 input_shape=(1, 28, 28, 1),
                                 working_dir=None)

        selected_layers = [
            layer for layer in layer_db if layer.module.type == 'Conv2D'
        ]
        layer_db.mark_picked_layers(selected_layers)

        url, process = start_bokeh_server_session(8006)
        bokeh_session = BokehServerSession(url=url, session_id="compression")

        # Instantiate child
        greedy_algo = comp_ratio_select.GreedyCompRatioSelectAlgo(
            layer_db=layer_db,
            pruner=pruner,
            cost_calculator=SpatialSvdCostCalculator(),
            eval_func=eval_func,
            eval_iterations=20,
            cost_metric=CostMetric.mac,
            target_comp_ratio=Decimal(0.4),
            num_candidates=10,
            use_monotonic_fit=True,
            saved_eval_scores_dict=None,
            comp_ratio_rounding_algo=rounding_algo,
            use_cuda=False,
            bokeh_session=bokeh_session)

        layer_comp_ratio_list, stats = greedy_algo.select_per_layer_comp_ratios(
        )

        original_cost = SpatialSvdCostCalculator.compute_model_cost(layer_db)

        for layer in layer_db:
            if layer not in selected_layers:
                layer_comp_ratio_list.append(LayerCompRatioPair(layer, None))
        compressed_cost = SpatialSvdCostCalculator.calculate_compressed_cost(
            layer_db, layer_comp_ratio_list, CostMetric.mac)

        actual_compression_ratio = compressed_cost.mac / original_cost.mac
        self.assertTrue(
            math.isclose(Decimal(0.3), actual_compression_ratio, abs_tol=0.8))

        print('\n')
        for pair in layer_comp_ratio_list:
            print(pair)

        tf.compat.v1.reset_default_graph()
        sess.close()

        bokeh_session.server_session.close("test complete")
        os.killpg(os.getpgid(process.pid), signal.SIGTERM)
    def test_eval_scores_with_spatial_svd_pruner(self):

        pruner = SpatialSvdPruner()
        eval_func = unittest.mock.MagicMock()
        eval_func.side_effect = [
            90, 80, 70, 60, 50, 40, 30, 20, 10, 91, 81, 71, 61, 51, 41, 31, 21,
            11
        ]

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        # Create a layer database
        layer_db = LayerDatabase(model=sess,
                                 input_shape=(1, 28, 28, 1),
                                 working_dir=None)
        layer1 = layer_db.find_layer_by_name('conv2d/Conv2D')
        layer2 = layer_db.find_layer_by_name('conv2d_1/Conv2D')

        layer_db.mark_picked_layers([layer1, layer2])

        url, process = start_bokeh_server_session(8006)
        bokeh_session = BokehServerSession(url=url, session_id="compression")

        # Instantiate child
        greedy_algo = comp_ratio_select.GreedyCompRatioSelectAlgo(
            layer_db=layer_db,
            pruner=pruner,
            cost_calculator=SpatialSvdCostCalculator(),
            eval_func=eval_func,
            eval_iterations=20,
            cost_metric=CostMetric.mac,
            target_comp_ratio=0.5,
            num_candidates=10,
            use_monotonic_fit=True,
            saved_eval_scores_dict=None,
            comp_ratio_rounding_algo=None,
            use_cuda=False,
            bokeh_session=bokeh_session)

        dict = greedy_algo._compute_eval_scores_for_all_comp_ratio_candidates()

        print()
        print(dict)
        self.assertEqual(90, dict['conv2d/Conv2D'][Decimal('0.1')])

        self.assertEqual(51, dict['conv2d_1/Conv2D'][Decimal('0.5')])
        self.assertEqual(21, dict['conv2d_1/Conv2D'][Decimal('0.8')])

        tf.compat.v1.reset_default_graph()
        sess.close()

        bokeh_session.server_session.close("test complete")
        os.killpg(os.getpgid(process.pid), signal.SIGTERM)
Esempio n. 10
0
    def test_prune_layer(self):
        """ Pruning single layer with 0.5 comp-ratio in MNIST"""

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        # Create a layer database
        orig_layer_db = LayerDatabase(model=sess,
                                      input_shape=(1, 28, 28, 1),
                                      working_dir=None)
        # Copy the db
        comp_layer_db = copy.deepcopy(orig_layer_db)
        conv1 = comp_layer_db.find_layer_by_name('conv2d/Conv2D')

        # before the splitting
        bias_op = get_succeeding_bias_op(conv1.module)
        for consumer in bias_op.outputs[0].consumers():
            self.assertEqual(consumer.name, "conv2d/Relu")

        spatial_svd_pruner = SpatialSvdPruner()
        spatial_svd_pruner._prune_layer(orig_layer_db, comp_layer_db, conv1,
                                        0.5, CostMetric.mac)
        conv2d_a_op = comp_layer_db.model.graph.get_operation_by_name(
            'conv2d_a/Conv2D')
        conv2d_b_op = comp_layer_db.model.graph.get_operation_by_name(
            'conv2d_b/Conv2D')
        conv2d_a_weight = WeightTensorUtils.get_tensor_as_numpy_data(
            comp_layer_db.model, conv2d_a_op)
        conv2d_b_weight = WeightTensorUtils.get_tensor_as_numpy_data(
            comp_layer_db.model, conv2d_b_op)

        conv1_a = comp_layer_db.find_layer_by_name('conv2d_a/Conv2D')
        conv1_b = comp_layer_db.find_layer_by_name('conv2d_b/Conv2D')

        # [Noc, Nic, kh, kw]
        self.assertEqual([2, 1, 5, 1], conv1_a.weight_shape)
        self.assertEqual([32, 2, 1, 5], conv1_b.weight_shape)

        # after the splitting
        bias_op = get_succeeding_bias_op(conv1_b.module)

        for consumer in bias_op.outputs[0].consumers():
            self.assertEqual(consumer.name, "conv2d/Relu")

        # original layer should be not there in the database
        self.assertRaises(
            KeyError,
            lambda: comp_layer_db.find_layer_by_name('conv2d/Conv2D'))

        # check if the layer replacement is done correctly
        orig_conv_op = comp_layer_db.model.graph.get_operation_by_name(
            'conv2d/Conv2D')
        bias_op = get_succeeding_bias_op(orig_conv_op)

        # consumers list should be empty
        consumers = [consumer for consumer in bias_op.outputs[0].consumers()]
        self.assertEqual(len(consumers), 0)

        # Check that weights loaded during svd pruning will stick after save and load
        new_sess = save_and_load_graph('./temp_meta/', comp_layer_db.model)
        conv2d_a_op = comp_layer_db.model.graph.get_operation_by_name(
            'conv2d_a/Conv2D')
        conv2d_b_op = comp_layer_db.model.graph.get_operation_by_name(
            'conv2d_b/Conv2D')
        conv2d_a_weight_after_save_load = WeightTensorUtils.get_tensor_as_numpy_data(
            comp_layer_db.model, conv2d_a_op)
        conv2d_b_weight_after_save_load = WeightTensorUtils.get_tensor_as_numpy_data(
            comp_layer_db.model, conv2d_b_op)
        self.assertTrue(
            np.array_equal(conv2d_a_weight, conv2d_a_weight_after_save_load))
        self.assertTrue(
            np.array_equal(conv2d_b_weight, conv2d_b_weight_after_save_load))

        tf.compat.v1.reset_default_graph()
        sess.close()
        new_sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))
Esempio n. 11
0
    def test_layer_database_deepcopy(self):

        # create tf.compat.v1.Session and initialize the weights and biases with zeros
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True

        # create session with graph
        sess = tf.compat.v1.Session(graph=tf.Graph(), config=config)

        with sess.graph.as_default():
            # by default, model will be constructed in default graph
            _ = mnist_tf_model.create_model(data_format='channels_last')
            sess.run(tf.compat.v1.global_variables_initializer())

        layer_db = LayerDatabase(model=sess, input_shape=(1, 28, 28, 1), working_dir=None)
        layers = list(layer_db._compressible_layers.values())

        # set the picked_for_compression for first two layers
        layers[0].picked_for_compression = True
        layers[1].picked_for_compression = True

        layer_db_copy = copy.deepcopy(layer_db)
        layers_copy = list(layer_db_copy._compressible_layers.values())

        # should be True
        self.assertTrue(layers_copy[0].picked_for_compression)
        self.assertTrue(layers_copy[1].picked_for_compression)

        # should be False
        self.assertFalse(layers_copy[2].picked_for_compression)
        self.assertFalse(layers_copy[3].picked_for_compression)

        # op reference should be different
        self.assertNotEqual(layers[0].module, layers_copy[0].module)
        self.assertNotEqual(layers[1].module, layers_copy[1].module)
        self.assertNotEqual(layers[2].module, layers_copy[2].module)
        self.assertNotEqual(layers[3].module, layers_copy[3].module)

        # layer reference should be different
        self.assertNotEqual(layers[0], layers_copy[0])
        self.assertNotEqual(layers[1], layers_copy[1])
        self.assertNotEqual(layers[2], layers_copy[2])
        self.assertNotEqual(layers[3], layers_copy[3])

        # op name should be same for both original and copy
        self.assertEqual(layers[0].name, layers_copy[0].name)
        self.assertEqual(layers[1].name, layers_copy[1].name)
        self.assertEqual(layers[2].name, layers_copy[2].name)
        self.assertEqual(layers[3].name, layers_copy[3].name)

        # session should be different
        self.assertNotEqual(layer_db.model, layer_db_copy.model)

        # check output shapes for layers in layer_db_copy
        self.assertEqual(layers_copy[0].output_shape, [None, 32, 28, 28])
        self.assertEqual(layers_copy[1].output_shape, [None, 64, 14, 14])
        self.assertEqual(layers_copy[2].output_shape, [None, 1024, 1, 1])
        self.assertEqual(layers_copy[3].output_shape, [None, 10, 1, 1])

        # check weight shapes for layers in layer_db_copy
        self.assertEqual(layers_copy[0].weight_shape, [32, 1, 5, 5])
        self.assertEqual(layers_copy[1].weight_shape, [64, 32, 5, 5])
        self.assertEqual(layers_copy[2].weight_shape, [1024, 3136])
        self.assertEqual(layers_copy[3].weight_shape, [10, 1024])

        # check the weight elements are equal in both data bases
        self.assertTrue(np.array_equal(layers[0].module.inputs[1].eval(session=layer_db.model),
                                       layers_copy[0].module.inputs[1].eval(session=layer_db_copy.model)))
        self.assertTrue(np.array_equal(layers[1].module.inputs[1].eval(session=layer_db.model),
                                       layers_copy[1].module.inputs[1].eval(session=layer_db_copy.model)))
        self.assertTrue(np.array_equal(layers[2].module.inputs[1].eval(session=layer_db.model),
                                       layers_copy[2].module.inputs[1].eval(session=layer_db_copy.model)))
        self.assertTrue(np.array_equal(layers[3].module.inputs[1].eval(session=layer_db.model),
                                       layers_copy[3].module.inputs[1].eval(session=layer_db_copy.model)))

        tf.compat.v1.reset_default_graph()
        sess.close()
        # delete temp directory
        shutil.rmtree(str('./temp_meta/'))