def validate(loaded_json): try: jsonschema.validate(loaded_json, schema=ROOT_NNCF_CONFIG_SCHEMA) except jsonschema.ValidationError as e: logger.error("Invalid NNCF config supplied!") # The default exception's __str__ result will contain the entire schema, # which is too large to be readable. msg = e.message + ". See documentation or {} for an NNCF configuration file JSON schema definition".format( nncf.config_schema.__file__) raise jsonschema.ValidationError(msg) compression_section = loaded_json.get("compression") if compression_section is None: # No compression specified return try: if isinstance(compression_section, dict): validate_single_compression_algo_schema(compression_section) else: # Passed a list of dicts for compression_algo_dict in compression_section: validate_single_compression_algo_schema(compression_algo_dict) except jsonschema.ValidationError: # No need to trim the exception output here since only the compression algo # specific sub-schema will be shown, which is much shorter than the global schema logger.error("Invalid NNCF config supplied!") raise
def _paint_activation_quantizer_node( nncf_graph: NNCFGraph, quantizer_id: NonWeightQuantizerId, quantizer_info: 'NonWeightQuantizerInfo', bits_color_map: Dict[int, str], groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers): #pylint:disable=too-many-branches affected_insertion_infos_list = quantizer_info.affected_insertions # type: List[InsertionInfo] for insertion_info in affected_insertion_infos_list: input_agnostic_op_exec_context = insertion_info.op_exec_context.input_agnostic affected_nncf_node_key = nncf_graph.get_node_key_by_iap_context( input_agnostic_op_exec_context) affected_nx_node = nncf_graph.get_nx_node_by_key( affected_nncf_node_key) operator_name = affected_nx_node[ NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name node_id = affected_nx_node[NNCFGraph.ID_NODE_ATTR] affected_nncf_node = nncf_graph.get_node_by_id(node_id) affected_nx_node['label'] = '_#'.join( [operator_name, str(node_id)]) if insertion_info.is_input: # Module UpdateInputs pre-op used for activation quantization previous_nodes = nncf_graph.get_previous_nodes( affected_nncf_node) # Relying on the _quantize_inputs behaviour of only being able to quantize 0-th input # previous_nodes are either UpdateWeights, or UpdateWeights + UpdateInputs assert len(previous_nodes) == 2 or len(previous_nodes) == 1 if len(previous_nodes) == 2: if "UpdateInputs" in str( previous_nodes[0].op_exec_context.input_agnostic): target_node = previous_nodes[0] else: target_node = previous_nodes[1] else: target_node = previous_nodes[0] target_nncf_node_id = target_node.node_id target_nncf_node_key = nncf_graph.get_node_key_by_id( target_nncf_node_id) else: in_port_id = insertion_info.in_port_id if in_port_id is None: # Post-hooking used for activation quantization # Currently only a single post-hook can immediately follow an operation succs = list( nncf_graph.get_successors(affected_nncf_node_key)) assert len(succs) == 1 target_nncf_node_key = succs[0] else: # Pre-hooking used for activation quantization previous_nodes = nncf_graph.get_previous_nodes( affected_nncf_node) target_node = None for prev_node in previous_nodes: prev_edge = nncf_graph.get_nx_edge( prev_node, affected_nncf_node) if prev_edge[NNCFGraph. IN_PORT_NAME_EDGE_ATTR] == in_port_id: target_node = prev_node break assert target_node is not None, "Could not find a pre-hook quantizer node for a specific " \ "input port!" target_nncf_node_id = target_node.node_id target_nncf_node_key = nncf_graph.get_node_key_by_id( target_nncf_node_id) activation_fq_node = nncf_graph.get_nx_node_by_key( target_nncf_node_key) bits = quantizer_info.quantizer_module_ref.num_bits activation_fq_node['color'] = bits_color_map[bits] activation_fq_node['style'] = 'filled' node_id = activation_fq_node[NNCFGraph.ID_NODE_ATTR] activation_fq_node['label'] = 'AFQ_[{}]_#{}'.format( quantizer_info.quantizer_module_ref.get_current_config(), str(node_id)) grouped_mode = bool(groups_of_adjacent_quantizers) if grouped_mode: group_id_str = 'UNDEFINED' group_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer( quantizer_id) if node_id is None: nncf_logger.error( 'No group for activation quantizer: {}'.format( target_nncf_node_key)) else: group_id_str = str(group_id) activation_fq_node['label'] += "_G" + group_id_str
def get_bitwidth_graph(algo_ctrl, model, all_quantizers_per_full_scope, groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers) -> NNCFGraph: grouped_mode = bool(groups_of_adjacent_quantizers) nncf_graph = model.get_graph() for node_key in nncf_graph.get_all_node_keys(): node = nncf_graph.get_nx_node_by_key(node_key) color = '' if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]: operator_name = node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name scope = node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].input_agnostic.scope_in_model module = model.get_module_by_scope(scope) if isinstance(module, NNCFConv2d): color = 'lightblue' if module.groups == module.in_channels: operator_name = 'DW_Conv2d' color = 'purple' if not grouped_mode: operator_name += '_#{}'.format(str(node[NNCFGraph.ID_NODE_ATTR])) node['label'] = operator_name node['style'] = 'filled' if color: node['color'] = color non_weight_quantizers = algo_ctrl.non_weight_quantizers bits_color_map = {4: 'red', 8: 'green', 6: 'orange'} for quantizer_id, quantizer_info in non_weight_quantizers.items(): affected_iap_ctx_list = quantizer_info.affected_ia_op_exec_contexts for activation_iap_ctx in affected_iap_ctx_list: post_hooked_nx_node_key = nncf_graph.get_node_id_by_iap_context(activation_iap_ctx) post_hooked_module_node = nncf_graph.get_nx_node_by_key(post_hooked_nx_node_key) operator_name = post_hooked_module_node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name if not grouped_mode: operator_name += '_#{}'.format(str(post_hooked_module_node[NNCFGraph.ID_NODE_ATTR])) post_hooked_module_node['label'] = operator_name for next_nx_node_key in nncf_graph.get_successors(post_hooked_nx_node_key): activation_fq_node = nncf_graph.get_nx_node_by_key(next_nx_node_key) activation_quantizer = non_weight_quantizers[quantizer_id].quantizer_module_ref bits = activation_quantizer.num_bits activation_fq_node['color'] = bits_color_map[bits] activation_fq_node['style'] = 'filled' node_id = activation_fq_node[NNCFGraph.ID_NODE_ATTR] if grouped_mode: node_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(activation_quantizer) if node_id is None: nncf_logger.error('No group for activation quantizer: {}'.format(next_nx_node_key)) node_id = 'UNDEFINED' activation_fq_node['label'] = '{}_bit__AFQ_#{}'.format(bits, str(node_id)) for scope, quantizer in all_quantizers_per_full_scope.items(): if quantizer.is_weights: node = nncf_graph.find_node_in_nx_graph_by_scope(scope) if node is None: raise AttributeError('Failed to get node by scope={}'.format(str(scope))) if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]: bits = quantizer.num_bits node_id = node[NNCFGraph.ID_NODE_ATTR] if grouped_mode: node_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(quantizer) if node_id is None: nncf_logger.error('No group for weight quantizer: {}'.format(scope)) node_id = 'UNDEFINED' node['label'] = '{}_bit__WFQ_#{}'.format(bits, str(node_id)) node['color'] = bits_color_map[bits] node['style'] = 'filled' return nncf_graph
def get_bitwidth_graph( algo_ctrl, model, all_quantizers_per_full_scope, groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers ) -> NNCFGraph: # Overwrites nodes that were obtained during graph tracing and correspond to quantizer # nodes with the nodes whose 'label' attribute is set to a more display-friendly representation # of the quantizer's bitwidth. #pylint:disable=too-many-branches grouped_mode = bool(groups_of_adjacent_quantizers) nncf_graph = model.get_graph() for node_key in nncf_graph.get_all_node_keys(): node = nncf_graph.get_nx_node_by_key(node_key) color = '' if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]: operator_name = node[ NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name scope = node[ NNCFGraph. OP_EXEC_CONTEXT_NODE_ATTR].input_agnostic.scope_in_model module = model.get_module_by_scope(scope) if isinstance(module, NNCFConv2d): color = 'lightblue' if module.groups == module.in_channels: operator_name = 'DW_Conv2d' color = 'purple' operator_name += '_#{}'.format( str(node[NNCFGraph.ID_NODE_ATTR])) node['label'] = operator_name node['style'] = 'filled' if color: node['color'] = color non_weight_quantizers = algo_ctrl.non_weight_quantizers bits_color_map = {2: 'purple', 4: 'red', 8: 'green', 6: 'orange'} for quantizer_id, quantizer_info in non_weight_quantizers.items(): HAWQDebugger._paint_activation_quantizer_node( nncf_graph, quantizer_id, quantizer_info, bits_color_map, groups_of_adjacent_quantizers) for scope, quantizer in all_quantizers_per_full_scope.items(): if not quantizer.is_weights: continue node = nncf_graph.find_node_in_nx_graph_by_scope(scope) if node is None: raise AttributeError('Failed to get node by scope={}'.format( str(scope))) if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]: bits = quantizer.num_bits node_id = node[NNCFGraph.ID_NODE_ATTR] node['label'] = 'WFQ_[{}]_#{}'.format( quantizer.get_current_config(), str(node_id)) if grouped_mode: group_id_str = 'UNDEFINED' normalized_scope = deepcopy(scope) normalized_scope.pop() # SymmetricQuantizer normalized_scope.pop() # UpdateWeights normalized_scope.pop() # ModuleDict[pre_ops] for wq_id in algo_ctrl.weight_quantizers.keys(): if wq_id.get_scope() == normalized_scope: quantizer_id = wq_id break else: raise RuntimeError( "Could not associate a weight quantizer inside a model with any " "weight quantizer registered in the quantization controller!" ) group_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer( quantizer_id) if group_id is None: nncf_logger.error( 'No group for weight quantizer: {}'.format(scope)) else: group_id_str = str(group_id) node['label'] += '_G' + group_id_str node['color'] = bits_color_map[bits] node['style'] = 'filled' return nncf_graph