def test_upsample_get_op_product_graph(self):
        """ Test connected graph construction on a graph with upsample op
        Need to perform one round of winnowing first to insert the upsample op """
        tf.compat.v1.reset_default_graph()
        sess = tf.compat.v1.Session()
        module_zero_channels_list = []

        _ = upsample_model()
        init = tf.compat.v1.global_variables_initializer()
        sess.run(init)

        input_op_names = ['input_1']
        output_op_names = ['upsample_model/Softmax']

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name("conv2d_3/Conv2D")
        input_channels_to_winnow = [3, 5, 7]
        module_mask_pair = (tf_op, input_channels_to_winnow)
        module_zero_channels_list.append(module_mask_pair)

        new_sess, _ = winnow.winnow_tf_model(sess, input_op_names, output_op_names,
                                             list_of_modules_to_winnow=module_zero_channels_list,
                                             reshape=True, in_place=True, verbose=True)

        conn_graph = ConnectedGraph(tf.compat.v1.get_default_graph(), input_op_names, output_op_names)
        self.assertEqual(18, len(conn_graph.get_all_ops()))
        reduced_bn_1_op = conn_graph.get_op_from_module_name('reduced_batch_normalization_1/cond/FusedBatchNormV3_1')
        self.assertTrue(reduced_bn_1_op.output.consumers[0].type == 'Upsample')
        new_sess.close()
Ejemplo n.º 2
0
    def test_reducing_vgg16_slim(self):
        """ Test reducing vgg16 slim model """
        tf.compat.v1.reset_default_graph()
        sess = tf.compat.v1.Session()
        module_zero_channels_list = []

        inp = tf.compat.v1.placeholder(tf.float32, [1, 224, 224, 3])
        _ = vgg.vgg_16(inp)
        init = tf.compat.v1.global_variables_initializer()
        sess.run(init)

        input_op_names = ["Placeholder"]
        output_op_names = ['vgg_16/fc8/squeezed']

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "vgg_16/fc7/Conv2D")
        input_channels_to_winnow = [2, 3, 4]
        module_mask_pair = (tf_op, input_channels_to_winnow)
        module_zero_channels_list.append(module_mask_pair)

        new_sess, ordered_modules_list = winnow.winnow_tf_model(
            sess,
            input_op_names,
            output_op_names,
            module_zero_channels_list,
            reshape=True,
            in_place=True,
            verbose=True)
        # Save and reload modified graph to allow changes to take effect
        new_sess = save_and_load_graph('./saver', new_sess)

        # _ = tf.compat.v1.summary.FileWriter('./reduced_graph', new_sess.graph)

        with new_sess.graph.as_default():
            inp = tf.random.uniform(shape=(1, 224, 224, 3))
            inp_array = inp.eval(session=new_sess)
            model_input = new_sess.graph.get_tensor_by_name("Placeholder:0")
            model_output = new_sess.graph.get_tensor_by_name(
                "vgg_16/fc8/squeezed:0")

            # run through entire model to check no error is produced
            _ = new_sess.run(model_output, feed_dict={model_input: inp_array})
        self.assertEqual(4, len(ordered_modules_list))
        new_sess.close()
        sess.close()
Ejemplo n.º 3
0
    def prune_model(self, layer_db: LayerDatabase,
                    layer_comp_ratio_list: List[LayerCompRatioPair],
                    cost_metric: CostMetric, trainer):

        # sort all the layers in layer_comp_ratio_list based on occurrence
        layer_comp_ratio_list = self._sort_on_occurrence(
            layer_db.model, layer_comp_ratio_list)

        # Copy the db
        comp_layer_db = copy.deepcopy(layer_db)
        current_sess = comp_layer_db.model

        # Dictionary to map original layer name to list of most recent pruned layer name and output mask.
        # Masks remain at the original length and specify channels winnowed after each round of winnower.
        orig_layer_name_to_pruned_name_and_mask_dict = {}
        # Dictionary to map most recent pruned layer name to the original layer name
        pruned_name_to_orig_name_dict = {}
        # List to hold original layers to reconstruct
        layers_to_reconstruct = []
        detached_op_names = set()

        # Prune layers which have comp ratios less than 1
        for layer_comp_ratio in layer_comp_ratio_list:
            orig_layer = layer_db.find_layer_by_name(
                layer_comp_ratio.layer.name)
            if layer_comp_ratio.comp_ratio is not None and layer_comp_ratio.comp_ratio < 1.0:
                # 1) channel selection
                prune_indices = self._select_inp_channels(
                    orig_layer, layer_comp_ratio.comp_ratio)
                if not prune_indices:
                    continue

                # 2) Winnowing the model
                current_sess, ordered_modules_list = winnow.winnow_tf_model(
                    current_sess,
                    self._input_op_names,
                    self._output_op_names,
                    [(orig_layer.module, prune_indices)],
                    reshape=self._allow_custom_downsample_ops,
                    in_place=True,
                    verbose=False)
                if not ordered_modules_list:
                    continue

                layers_to_reconstruct.append(orig_layer)
                # Update dictionaries with new info about pruned ops and new masks
                self._update_pruned_ops_and_masks_info(
                    ordered_modules_list,
                    orig_layer_name_to_pruned_name_and_mask_dict,
                    pruned_name_to_orig_name_dict, detached_op_names)

        # Save and reload modified graph to allow changes to take effect
        # Need to initialize uninitialized variables first since only newly winnowed conv ops are initialized during
        # winnow_tf_model, and all other newly winnowed ops are not.
        with current_sess.graph.as_default():
            initialize_uninitialized_vars(current_sess)
        current_sess = save_and_load_graph('./saver', current_sess)
        comp_layer_db.update_database(current_sess,
                                      detached_op_names,
                                      update_model=True)

        # Perform reconstruction
        self._reconstruct_layers(layers_to_reconstruct,
                                 orig_layer_name_to_pruned_name_and_mask_dict,
                                 layer_db, comp_layer_db)

        return comp_layer_db
Ejemplo n.º 4
0
    def calculate_compressed_cost(
            self, layer_db: LayerDatabase,
            layer_comp_ratio_list: List[LayerCompRatioPair]) -> Cost:
        """
        Calculate cost of a compressed model given a set of layers and corresponding comp-ratios
        :param layer_db: Layer database for original model
        :param layer_comp_ratio_list: List of (layer + comp-ratio) pairs
        :return: Estimated cost of the compressed model
        """

        # sort all the layers in layer_comp_ratio_list based on occurrence
        layer_comp_ratio_list = self._sort_on_occurrence(
            layer_db.model, layer_comp_ratio_list)

        detached_op_names = set()

        # Copy the db
        comp_layer_db = copy.deepcopy(layer_db)
        current_sess = comp_layer_db.model

        for layer_comp_ratio in layer_comp_ratio_list:

            orig_layer = layer_db.find_layer_by_name(
                layer_comp_ratio.layer.name)
            comp_ratio = layer_comp_ratio.comp_ratio

            if comp_ratio is not None and comp_ratio < 1.0:

                # select input channels of conv2d op to winnow
                prune_indices = self._select_inp_channels(
                    orig_layer, comp_ratio)
                if not prune_indices:
                    continue

                # Winnow the selected op and modify it's upstream affected ops
                current_sess, ordered_modules_list = winnow.winnow_tf_model(
                    current_sess,
                    self._input_op_names,
                    self._output_op_names,
                    [(orig_layer.module, prune_indices)],
                    reshape=self._allow_custom_downsample_ops,
                    in_place=True,
                    verbose=False)
                if not ordered_modules_list:
                    continue

                # Get all the detached op names from updated session graph
                for orig_op_name, _, _, _ in ordered_modules_list:
                    detached_op_names.add(orig_op_name)

        # update layer database by excluding the detached ops
        comp_layer_db.update_database(current_sess,
                                      detached_op_names,
                                      update_model=False)

        # calculate the cost of this model
        compressed_model_cost = CostCalculator.compute_model_cost(
            comp_layer_db)

        # close the session associated with compressed layer database
        comp_layer_db.model.close()

        return compressed_model_cost
Ejemplo n.º 5
0
    def test_reducing_vgg16(self):
        """ This test winnows a VGG16 model"""

        tf.compat.v1.reset_default_graph()
        sess = tf.compat.v1.Session()
        module_zero_channels_list = []

        _ = VGG16(weights=None)
        init = tf.compat.v1.global_variables_initializer()
        sess.run(init)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "block5_conv1/Conv2D")
        input_channels_to_winnow = [3, 5, 7]
        module_mask_pair = (tf_op, input_channels_to_winnow)
        module_zero_channels_list.append(module_mask_pair)

        tf_op_2 = tf.compat.v1.get_default_graph().get_operation_by_name(
            "block3_conv1/Conv2D")
        input_channels_to_winnow_2 = [11, 13, 15, 17]
        module_mask_pair_2 = (tf_op_2, input_channels_to_winnow_2)
        module_zero_channels_list.append(module_mask_pair_2)

        tf_op_3 = tf.compat.v1.get_default_graph().get_operation_by_name(
            "block2_conv2/Conv2D")
        input_channels_to_winnow_3 = [1, 2, 3, 4, 5]
        module_mask_pair_3 = (tf_op_3, input_channels_to_winnow_3)
        module_zero_channels_list.append(module_mask_pair_3)

        tf_op_4 = tf.compat.v1.get_default_graph().get_operation_by_name(
            "block2_conv1/Conv2D")
        input_channels_to_winnow_4 = [20, 21, 22, 23]
        module_mask_pair_4 = (tf_op_4, input_channels_to_winnow_4)
        module_zero_channels_list.append(module_mask_pair_4)

        input_op_names = ["input_1"]
        output_op_names = ['predictions/Softmax']
        new_sess, ordered_modules_list = winnow.winnow_tf_model(
            sess,
            input_op_names,
            output_op_names,
            module_zero_channels_list,
            reshape=True,
            in_place=True,
            verbose=True)
        # Save and reload modified graph to allow changes to take effect
        new_sess = save_and_load_graph('./saver', new_sess)

        # uncomment the following to generate tensorboard viewable file
        # _ = tf.compat.v1.summary.FileWriter('./reduced_graph', new_sess.graph)

        # Check certain weight indices to ensure that weights were reduced correctly
        b4c3_kernel = new_sess.graph.get_tensor_by_name(
            "block4_conv3/kernel/Read/"
            "ReadVariableOp:0").eval(session=new_sess)
        red_b4c3_kernel = new_sess.graph.get_tensor_by_name(
            "reduced_block4_conv3/kernel/"
            "Read/ReadVariableOp:0").eval(session=new_sess)
        self.assertEqual(red_b4c3_kernel.shape, (3, 3, 512, 509))
        self.assertEqual(red_b4c3_kernel[0][0][0][2], b4c3_kernel[0][0][0][2])
        self.assertEqual(np.sum(red_b4c3_kernel[0][0][0][5:]),
                         np.sum(b4c3_kernel[0][0][0][8:]))

        # Test that evaluating the new session uses the newly reduced modules.
        # Do so by first evaluating a tensor in a module coming after a set of reduced modules.
        # Zero out weights and biases of one of the original unreduced modules preceding the tensor.
        # Reevaluate the tensor and expect to see no change, since the original unreduced module should not be used
        # anymore.
        # Then zero out weights and biases of one of the newly reduced modules.
        # Finally reevaluate the same tensor as before.  This time, we expect to see the result be zero.

        with new_sess.graph.as_default():
            inp = tf.random.uniform(shape=(1, 224, 224, 3))
            inp_array = inp.eval(session=new_sess)
            model_input = new_sess.graph.get_tensor_by_name("input_1:0")

            # run through entire model to check no error is produced
            model_output = new_sess.graph.get_tensor_by_name(
                "predictions/Softmax:0")
            _ = new_sess.run(model_output, feed_dict={model_input: inp_array})

        self.assertEqual(13, len(ordered_modules_list))
        new_sess.close()
        sess.close()
Ejemplo n.º 6
0
    def test_reducing_inceptionV3(self):
        """ Test module reduction in inceptionV3 """
        tf.compat.v1.reset_default_graph()
        sess = tf.compat.v1.Session()
        module_zero_channels_list = []

        _ = InceptionV3(weights=None)
        init = tf.compat.v1.global_variables_initializer()
        sess.run(init)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2d_12/Conv2D")
        input_channels_to_winnow = [0, 1, 64, 128, 224]
        module_mask_pair = (tf_op, input_channels_to_winnow)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2d_13/Conv2D")
        input_channels_to_winnow_1 = [0, 64, 65, 66, 128, 224]
        module_mask_pair = (tf_op, input_channels_to_winnow_1)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2d_15/Conv2D")
        input_channels_to_winnow_2 = [0, 64, 128, 129, 130, 131, 224]
        module_mask_pair = (tf_op, input_channels_to_winnow_2)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2d_18/Conv2D")
        input_channels_to_winnow_3 = [0, 64, 128, 224, 225, 226, 227, 228]
        module_mask_pair = (tf_op, input_channels_to_winnow_3)
        module_zero_channels_list.append(module_mask_pair)

        input_op_names = ["input_1"]
        output_op_names = ['predictions/Softmax']
        new_sess, ordered_modules_list = winnow.winnow_tf_model(
            sess,
            input_op_names,
            output_op_names,
            module_zero_channels_list,
            reshape=True,
            in_place=True,
            verbose=True)
        # Save and reload modified graph to allow changes to take effect
        # Need to initialize uninitialized variables first since only newly winnowed conv ops are initialized during
        # winnow_tf_model, and all other newly winnowed ops are not.
        with new_sess.graph.as_default():
            initialize_uninitialized_vars(new_sess)
        new_sess = save_and_load_graph('./saver', new_sess)

        # _ = tf.compat.v1.summary.FileWriter('./reduced_graph', new_sess.graph)

        with new_sess.graph.as_default():
            inp = tf.random.uniform(shape=(1, 299, 299, 3))
            inp_array = inp.eval(session=new_sess)
            model_input = new_sess.graph.get_tensor_by_name("input_1:0")
            model_output = new_sess.graph.get_tensor_by_name(
                "predictions/Softmax:0")

            # check that reduced tensor shapes are as expected
            reduced_conv2d_12_input = new_sess.graph.get_operation_by_name(
                "reduced_conv2d_12/Conv2D").inputs[0]
            reduced_conv2d_13_input = new_sess.graph.get_operation_by_name(
                "reduced_conv2d_13/Conv2D").inputs[0]
            reduced_conv2d_15_input = new_sess.graph.get_operation_by_name(
                "reduced_conv2d_15/Conv2D").inputs[0]
            reduced_conv2d_18_input = new_sess.graph.get_operation_by_name(
                "reduced_conv2d_18/Conv2D").inputs[0]
            reduced_conv2d_5_output = new_sess.graph.get_tensor_by_name(
                "reduced_conv2d_5/Conv2D:0")
            reduced_conv2d_7_output = new_sess.graph.get_tensor_by_name(
                "reduced_conv2d_7/Conv2D:0")
            reduced_conv2d_10_output = new_sess.graph.get_tensor_by_name(
                "reduced_conv2d_10/Conv2D:0")
            reduced_conv2d_11_output = new_sess.graph.get_tensor_by_name(
                "reduced_conv2d_11/Conv2D:0")
            self.assertEqual(251, reduced_conv2d_12_input.shape.as_list()[-1])
            self.assertEqual(250, reduced_conv2d_13_input.shape.as_list()[-1])
            self.assertEqual(249, reduced_conv2d_15_input.shape.as_list()[-1])
            self.assertEqual(248, reduced_conv2d_18_input.shape.as_list()[-1])
            self.assertEqual(63, reduced_conv2d_5_output.shape.as_list()[-1])
            self.assertEqual(63, reduced_conv2d_7_output.shape.as_list()[-1])
            self.assertEqual(95, reduced_conv2d_10_output.shape.as_list()[-1])
            self.assertEqual(31, reduced_conv2d_11_output.shape.as_list()[-1])
            self.assertEqual(17, len(ordered_modules_list))

            # run through entire model to check no error is produced
            _ = new_sess.run(model_output, feed_dict={model_input: inp_array})
        new_sess.close()
        sess.close()
Ejemplo n.º 7
0
    def test_reducing_resnet_50(self):
        """ Test module reduction in resnet_50 """
        tf.compat.v1.reset_default_graph()
        sess = tf.compat.v1.Session()
        module_zero_channels_list = []

        _ = ResNet50(weights=None)
        init = tf.compat.v1.global_variables_initializer()
        sess.run(init)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2_block1_1_conv/Conv2D")
        input_channels_to_winnow_1 = [3, 5, 7]
        module_mask_pair = (tf_op, input_channels_to_winnow_1)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv2_block1_0_conv/Conv2D")
        input_channels_to_winnow_2 = [3, 5, 7, 8]
        module_mask_pair = (tf_op, input_channels_to_winnow_2)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv3_block1_1_conv/Conv2D")
        input_channels_to_winnow_3 = [3, 5, 7]
        module_mask_pair = (tf_op, input_channels_to_winnow_3)
        module_zero_channels_list.append(module_mask_pair)

        tf_op = tf.compat.v1.get_default_graph().get_operation_by_name(
            "conv3_block1_0_conv/Conv2D")
        input_channels_to_winnow_4 = [3, 5, 7, 8]
        module_mask_pair = (tf_op, input_channels_to_winnow_4)
        module_zero_channels_list.append(module_mask_pair)

        input_op_names = ["input_1"]
        output_op_names = ['probs/Softmax']
        new_sess, ordered_modules_list = winnow.winnow_tf_model(
            sess,
            input_op_names,
            output_op_names,
            module_zero_channels_list,
            reshape=True,
            in_place=True,
            verbose=True)
        # Save and reload modified graph to allow changes to take effect
        # Need to initialize uninitialized variables first since only newly winnowed conv ops are initialized during
        # winnow_tf_model, and all other newly winnowed ops are not.
        with new_sess.graph.as_default():
            initialize_uninitialized_vars(new_sess)
        new_sess = save_and_load_graph('./saver', new_sess)

        # _ = tf.compat.v1.summary.FileWriter('./reduced_graph', new_sess.graph)
        with new_sess.graph.as_default():
            inp = tf.random.uniform(shape=(1, 224, 224, 3))
            inp_array = inp.eval(session=new_sess)
        model_input = new_sess.graph.get_tensor_by_name("input_1:0")
        model_output = new_sess.graph.get_tensor_by_name("probs/Softmax:0")

        # check that reduced tensor shapes are as expected
        reduced_conv3_block1_1_input = new_sess.graph.get_operation_by_name(
            "reduced_conv3_block1_1_conv/"
            "Conv2D").inputs[0]
        reduced_conv3_block1_0_input = new_sess.graph.get_operation_by_name(
            "reduced_conv3_block1_0_conv/"
            "Conv2D").inputs[0]
        reduced_conv2_block3_3_output = new_sess.graph.get_tensor_by_name(
            "reduced_conv2_block3_3_conv/"
            "Conv2D:0")
        reduced_conv2_block1_1_input = new_sess.graph.get_operation_by_name(
            "reduced_conv2_block1_1_conv/"
            "Conv2D").inputs[0]
        reduced_conv2_block1_0_input = new_sess.graph.get_operation_by_name(
            "reduced_conv2_block1_0_conv/"
            "Conv2D").inputs[0]
        reduced_conv1_output = new_sess.graph.get_tensor_by_name(
            "reduced_conv1_conv/Conv2D:0")
        self.assertEqual(253, reduced_conv3_block1_1_input.shape.as_list()[-1])
        self.assertEqual(252, reduced_conv3_block1_0_input.shape.as_list()[-1])
        self.assertEqual(253,
                         reduced_conv2_block3_3_output.shape.as_list()[-1])
        self.assertEqual(61, reduced_conv2_block1_1_input.shape.as_list()[-1])
        self.assertEqual(60, reduced_conv2_block1_0_input.shape.as_list()[-1])
        self.assertEqual(61, reduced_conv1_output.shape.as_list()[-1])

        # run through entire model to check no error is produced
        _ = new_sess.run(model_output, feed_dict={model_input: inp_array})
        self.assertEqual(11, len(ordered_modules_list))
        new_sess.close()
        sess.close()