nncf/common/pruning/mask_propagation.py
def symbolic_mask_propagation(self, prunable_layers_types: List[str],
                                  can_prune_after_analysis: Dict[int, PruningAnalysisDecision]) \
            -> Dict[int, PruningAnalysisDecision]:
        """
        Check all nodes that were marked as prunable after the model analysis and compatibility check vs.
        pruning algo have a correct correspondent closing node on each path from self to outputs;
        the check entails verifying that every convolution prunable by the output channel dimension
        has a corresponding convolution that is prunable by its input channel dimension (output channel
        dimension equal to closing convolution input channel dimension) in every path from self to outputs.
        If the check fails, the entire groups containing such nodes will be marked as unprunable.
        If convolution symbolic mask mixes with other symbolic masks (by elementwise operation, for example)
        and mixing masks can't be mixed, all mask producers participated in this mixing will be marked as unprunable.
        If convolution output channel dimension reducing directly affect an output of the model -
        it will be marked as unprunable as well.


        :param prunable_layers_types: Types of operations with prunable filters.
        :param can_prune_after_analysis: Dict of node indices vs the decision made by previous steps;
            the decision is true only for the nodes that do not conflict with mask propagation and
            are supported by the NNCF pruning algorithm.
        :return: Dict of node indices vs the decision made by symbolic mask propagation algorithm.
        """

        can_be_closing_convs = {node.node_id for node in self._graph.get_all_nodes()
                                if node.node_type in prunable_layers_types and not is_grouped_conv(node)}
        can_prune_by_dim = {k: None for k in can_be_closing_convs}
        for node in self._graph.topological_sort():
            if node.node_id in can_be_closing_convs and can_prune_after_analysis[node.node_id]:
                # Set output mask
                node.data['output_mask'] = SymbolicMask(get_output_channels(node), [node.node_id])
            # Propagate masks
            cls = self.get_meta_operation_by_type_name(node.node_type)
            cls.mask_propagation(node, self._graph, SymbolicMaskProcessor)
            if node.node_id in can_be_closing_convs:
                # Check input mask producers out channel dimension
                input_masks = get_input_masks(node, self._graph)
                if any(input_masks):
                    assert len(input_masks) == 1
                    input_mask = input_masks[0] # type: SymbolicMask

                    for producer in input_mask.mask_producers:
                        previously_dims_equal = True if can_prune_by_dim[producer] is None \
                            else can_prune_by_dim[producer]

                        is_dims_equal = get_input_channels(node) == input_mask.shape[0]
                        decision = previously_dims_equal and is_dims_equal
                        can_prune_by_dim[producer] = PruningAnalysisDecision(
                            decision, PruningAnalysisReason.DIMENSION_MISMATCH)
        # Remove all convolutions with masks
        # that were propagated to output node
        for out_node in self._graph.get_output_nodes():
            for input_mask in get_input_masks(out_node, self._graph):
                if input_mask:
                    for producer in input_mask.mask_producers:
                        can_prune_by_dim[producer] = PruningAnalysisDecision(
                                False, PruningAnalysisReason.LAST_CONV)
        # Update decision for nodes which
        # have no closing convolution
        convs_without_closing_conv = {}
        for k, v in can_prune_by_dim.items():
            if v is None:
                convs_without_closing_conv[k] = \
                    PruningAnalysisDecision(False, PruningAnalysisReason.CLOSING_CONV_MISSING)
        can_prune_by_dim.update(convs_without_closing_conv)

        # Clean nodes masks
        for node in self._graph.get_all_nodes():
            node.data['output_mask'] = None

        return can_prune_by_dim

        Check all nodes that were marked as prunable after the model analysis and compatibility check vs.
        pruning algo have a correct correspondent closing node on each path from self to outputs;
        the check entails verifying that every convolution prunable by the output channel dimension
        has a corresponding convolution that is prunable by its input channel dimension (output channel
        dimension equal to closing convolution input channel dimension) in every path from self to outputs.
        If the check fails, the entire groups containing such nodes will be marked as unprunable.
        If convolution symbolic mask mixes with other symbolic masks (by elementwise operation, for example)
        and mixing masks can't be mixed, all mask producers participated in this mixing will be marked as unprunable.
        If convolution output channel dimension reducing directly affect an output of the model -
        it will be marked as unprunable as well.


        :param prunable_layers_types: Types of operations with prunable filters.
        :param can_prune_after_analysis: Dict of node indices vs the decision made by previous steps;
            the decision is true only for the nodes that do not conflict with mask propagation and
            are supported by the NNCF pruning algorithm.
        :return: Dict of node indices vs the decision made by symbolic mask propagation algorithm.
        
Check all nodes that were marked as prunable after the model analysis and compatibility check vs.
pruning algo have a correct correspondent closing node on each path from self to outputs;
the check entails verifying that every convolution prunable by the output channel dimension
has a corresponding convolution that is prunable by its input channel dimension (output channel
dimension equal to closing convolution input channel dimension) in every path from self to outputs.
If the check fails, the entire groups containing such nodes will be marked as unprunable.
If convolution symbolic mask mixes with other symbolic masks (by elementwise operation, for example)
and mixing masks can't be mixed, all mask producers participated in this mixing will be marked as unprunable.
If convolution output channel dimension reducing directly affect an output of the model
it will be marked as unprunable as well.
Check all nodes that were marked as prunable after the model analysis and compatibility check vs . pruning algo have a correct correspondent closing node on each path from self to outputs ; the check entails verifying that every convolution prunable by the output channel dimension has a corresponding convolution that is prunable by its input channel dimension ( output channel dimension equal to closing convolution input channel dimension ) in every path from self to outputs . If the check fails the entire groups containing such nodes will be marked as unprunable . If convolution symbolic mask mixes with other symbolic masks ( by elementwise operation for example ) and mixing masks can ' t be mixed all mask producers participated in this mixing will be marked as unprunable . If convolution output channel dimension reducing directly affect an output of the model it will be marked as unprunable as well .
def symbolic_mask_propagation(self, prunable_layers_types: List[str],
                                  can_prune_after_analysis: Dict[int, PruningAnalysisDecision]) \
            -> Dict[int, PruningAnalysisDecision]:
        can_be_closing_convs = {node.node_id for node in self._graph.get_all_nodes()
                                if node.node_type in prunable_layers_types and not is_grouped_conv(node)}
        can_prune_by_dim = {k: None for k in can_be_closing_convs}
        for node in self._graph.topological_sort():
            if node.node_id in can_be_closing_convs and can_prune_after_analysis[node.node_id]:
                node.data['output_mask'] = SymbolicMask(get_output_channels(node), [node.node_id])
            cls = self.get_meta_operation_by_type_name(node.node_type)
            cls.mask_propagation(node, self._graph, SymbolicMaskProcessor)
            if node.node_id in can_be_closing_convs:
                input_masks = get_input_masks(node, self._graph)
                if any(input_masks):
                    assert len(input_masks) == 1
                    input_mask = input_masks[0] 
                    for producer in input_mask.mask_producers:
                        previously_dims_equal = True if can_prune_by_dim[producer] is None \
                            else can_prune_by_dim[producer]
                        is_dims_equal = get_input_channels(node) == input_mask.shape[0]
                        decision = previously_dims_equal and is_dims_equal
                        can_prune_by_dim[producer] = PruningAnalysisDecision(
                            decision, PruningAnalysisReason.DIMENSION_MISMATCH)
        for out_node in self._graph.get_output_nodes():
            for input_mask in get_input_masks(out_node, self._graph):
                if input_mask:
                    for producer in input_mask.mask_producers:
                        can_prune_by_dim[producer] = PruningAnalysisDecision(
                                False, PruningAnalysisReason.LAST_CONV)
        convs_without_closing_conv = {}
        for k, v in can_prune_by_dim.items():
            if v is None:
                convs_without_closing_conv[k] = \
                    PruningAnalysisDecision(False, PruningAnalysisReason.CLOSING_CONV_MISSING)
        can_prune_by_dim.update(convs_without_closing_conv)
        for node in self._graph.get_all_nodes():
            node.data['output_mask'] = None
        return can_prune_by_dim
def symbolic_mask_propagation ( self , prunable_layers_types : List [ str ] , can_prune_after_analysis : Dict [ int , PruningAnalysisDecision ] ) -> Dict [ int , PruningAnalysisDecision ] : can_be_closing_convs = { node . node_id for node in self . _graph . get_all_nodes ( ) if node . node_type in prunable_layers_types and not is_grouped_conv ( node ) } can_prune_by_dim = { k : None for k in can_be_closing_convs } for node in self . _graph . topological_sort ( ) : if node . node_id in can_be_closing_convs and can_prune_after_analysis [ node . node_id ] : node . data [ 'output_mask' ] = SymbolicMask ( get_output_channels ( node ) , [ node . node_id ] ) cls = self . get_meta_operation_by_type_name ( node . node_type ) cls . mask_propagation ( node , self . _graph , SymbolicMaskProcessor ) if node . node_id in can_be_closing_convs : input_masks = get_input_masks ( node , self . _graph ) if any ( input_masks ) : assert len ( input_masks ) == 1 input_mask = input_masks [ 0 ] for producer in input_mask . mask_producers : previously_dims_equal = True if can_prune_by_dim [ producer ] is None else can_prune_by_dim [ producer ] is_dims_equal = get_input_channels ( node ) == input_mask . shape [ 0 ] decision = previously_dims_equal and is_dims_equal can_prune_by_dim [ producer ] = PruningAnalysisDecision ( decision , PruningAnalysisReason . DIMENSION_MISMATCH ) for out_node in self . _graph . get_output_nodes ( ) : for input_mask in get_input_masks ( out_node , self . _graph ) : if input_mask : for producer in input_mask . mask_producers : can_prune_by_dim [ producer ] = PruningAnalysisDecision ( False , PruningAnalysisReason . LAST_CONV ) convs_without_closing_conv = { } for k , v in can_prune_by_dim . items ( ) : if v is None : convs_without_closing_conv [ k ] = PruningAnalysisDecision ( False , PruningAnalysisReason . CLOSING_CONV_MISSING ) can_prune_by_dim . update ( convs_without_closing_conv ) for node in self . _graph . get_all_nodes ( ) : node . data [ 'output_mask' ] = None return can_prune_by_dim
Check all nodes that were marked as prunable after the model analysis and compatibility check vs.
pruning algo have a correct correspondent closing node on each path from self to outputs;
the check entails verifying that every convolution prunable by the output channel dimension
has a corresponding convolution that is prunable by its input channel dimension (output channel
dimension equal to closing convolution input channel dimension) in every path from self to outputs.
Check all nodes that were marked as prunable after the model analysis and compatibility check vs . pruning algo have a correct correspondent closing node on each path from self to outputs ; the check entails verifying that every convolution prunable by the output channel dimension has a corresponding convolution that is prunable by its input channel dimension ( output channel dimension equal to closing convolution input channel dimension ) in every path from self to outputs .
"""
        Check all nodes that were marked as prunable after the model analysis and compatibility check vs.
        pruning algo have a correct correspondent closing node on each path from self to outputs;
        the check entails verifying that every convolution prunable by the output channel dimension
        has a corresponding convolution that is prunable by its input channel dimension (output channel
        dimension equal to closing convolution input channel dimension) in every path from self to outputs.
        If the check fails, the entire groups containing such nodes will be marked as unprunable.
        If convolution symbolic mask mixes with other symbolic masks (by elementwise operation, for example)
        and mixing masks can't be mixed, all mask producers participated in this mixing will be marked as unprunable.
        If convolution output channel dimension reducing directly affect an output of the model -
        it will be marked as unprunable as well.


        :param prunable_layers_types: Types of operations with prunable filters.
        :param can_prune_after_analysis: Dict of node indices vs the decision made by previous steps;
            the decision is true only for the nodes that do not conflict with mask propagation and
            are supported by the NNCF pruning algorithm.
        :return: Dict of node indices vs the decision made by symbolic mask propagation algorithm.
        """ # Set output mask # Propagate masks # Check input mask producers out channel dimension # type: SymbolicMask # Remove all convolutions with masks # that were propagated to output node # Update decision for nodes which # have no closing convolution # Clean nodes masks
Dict of node indices vs the decision made by symbolic mask propagation algorithm.
Dict of node indices vs the decision made by symbolic mask propagation algorithm .
self
prunable_layers_types
List[str]
Types of operations with prunable filters.
Types of operations with prunable filters .
can_prune_after_analysis
Dict[int, PruningAnalysisDecision]
Dict of node indices vs the decision made by previous steps;
the decision is true only for the nodes that do not conflict with mask propagation and
are supported by the NNCF pruning algorithm.
Dict of node indices vs the decision made by previous steps ; the decision is true only for the nodes that do not conflict with mask propagation and are supported by the NNCF pruning algorithm .