diff --git a/model_compression_toolkit/target_platform_capabilities/schema/v1.py b/model_compression_toolkit/target_platform_capabilities/schema/v1.py index 31ea36458..6675471b8 100644 --- a/model_compression_toolkit/target_platform_capabilities/schema/v1.py +++ b/model_compression_toolkit/target_platform_capabilities/schema/v1.py @@ -14,13 +14,13 @@ # ============================================================================== import pprint -from dataclasses import replace, dataclass, asdict, field from enum import Enum -from typing import Dict, Any, Union, Tuple, List, Optional +from typing import Dict, Any, Union, Tuple, List, Optional, Literal, Annotated from mct_quantizers import QuantizationMethod from model_compression_toolkit.constants import FLOAT_BITWIDTH from model_compression_toolkit.logger import Logger -from model_compression_toolkit.target_platform_capabilities.constants import OPS_SET_LIST +from pydantic import BaseModel, Field, root_validator, validator, PositiveInt, PrivateAttr + class OperatorSetNames(Enum): OPSET_CONV = "Conv" @@ -92,8 +92,7 @@ class Signedness(Enum): UNSIGNED = 2 -@dataclass(frozen=True) -class AttributeQuantizationConfig: +class AttributeQuantizationConfig(BaseModel): """ Holds the quantization configuration of a weight attribute of a layer. @@ -103,27 +102,22 @@ class AttributeQuantizationConfig: weights_per_channel_threshold (bool): Indicates whether to quantize the weights per-channel or per-tensor. enable_weights_quantization (bool): Indicates whether to quantize the model weights or not. lut_values_bitwidth (Optional[int]): Number of bits to use when quantizing in a look-up table. - If None, defaults to 8 in hptq; otherwise, it uses the provided value. + If None, defaults to 8 in hptq; otherwise, it uses the provided value. """ weights_quantization_method: QuantizationMethod = QuantizationMethod.POWER_OF_TWO - weights_n_bits: int = FLOAT_BITWIDTH + weights_n_bits: PositiveInt = FLOAT_BITWIDTH weights_per_channel_threshold: bool = False enable_weights_quantization: bool = False lut_values_bitwidth: Optional[int] = None - def __post_init__(self): - """ - Post-initialization processing for input validation. + class Config: + # Makes the model immutable (frozen) + frozen = True - Raises: - Logger critical if attributes are of incorrect type or have invalid values. - """ - if not isinstance(self.weights_n_bits, int) or self.weights_n_bits < 1: - Logger.critical("weights_n_bits must be a positive integer.") # pragma: no cover - if not isinstance(self.enable_weights_quantization, bool): - Logger.critical("enable_weights_quantization must be a boolean.") # pragma: no cover - if self.lut_values_bitwidth is not None and not isinstance(self.lut_values_bitwidth, int): - Logger.critical("lut_values_bitwidth must be an integer or None.") # pragma: no cover + @property + def field_names(self) -> list: + """Return a list of field names for the model.""" + return list(self.__fields__.keys()) def clone_and_edit(self, **kwargs) -> 'AttributeQuantizationConfig': """ @@ -135,11 +129,10 @@ def clone_and_edit(self, **kwargs) -> 'AttributeQuantizationConfig': Returns: AttributeQuantizationConfig: A new instance of AttributeQuantizationConfig with updated attributes. """ - return replace(self, **kwargs) + return self.copy(update=kwargs) -@dataclass(frozen=True) -class OpQuantizationConfig: +class OpQuantizationConfig(BaseModel): """ OpQuantizationConfig is a class to configure the quantization parameters of an operator. @@ -148,39 +141,45 @@ class OpQuantizationConfig: attr_weights_configs_mapping (Dict[str, AttributeQuantizationConfig]): A mapping between an op attribute name and its quantization configuration. activation_quantization_method (QuantizationMethod): Which method to use from QuantizationMethod for activation quantization. activation_n_bits (int): Number of bits to quantize the activations. - supported_input_activation_n_bits (int or Tuple[int]): Number of bits that operator accepts as input. + supported_input_activation_n_bits (Union[int, Tuple[int, ...]]): Number of bits that operator accepts as input. enable_activation_quantization (bool): Whether to quantize the model activations or not. quantization_preserving (bool): Whether quantization parameters should be the same for an operator's input and output. - fixed_scale (float): Scale to use for an operator quantization parameters. - fixed_zero_point (int): Zero-point to use for an operator quantization parameters. - simd_size (int): Per op integer representing the Single Instruction, Multiple Data (SIMD) width of an operator. It indicates the number of data elements that can be fetched and processed simultaneously in a single instruction. - signedness (bool): Set activation quantization signedness. - + fixed_scale (Optional[float]): Scale to use for an operator quantization parameters. + fixed_zero_point (Optional[int]): Zero-point to use for an operator quantization parameters. + simd_size (Optional[int]): Per op integer representing the Single Instruction, Multiple Data (SIMD) width of an operator. It indicates the number of data elements that can be fetched and processed simultaneously in a single instruction. + signedness (Signedness): Set activation quantization signedness. """ default_weight_attr_config: AttributeQuantizationConfig attr_weights_configs_mapping: Dict[str, AttributeQuantizationConfig] activation_quantization_method: QuantizationMethod activation_n_bits: int - supported_input_activation_n_bits: Union[int, Tuple[int]] + supported_input_activation_n_bits: Union[int, Tuple[int, ...]] enable_activation_quantization: bool quantization_preserving: bool - fixed_scale: float - fixed_zero_point: int - simd_size: int + fixed_scale: Optional[float] + fixed_zero_point: Optional[int] + simd_size: Optional[int] signedness: Signedness - def __post_init__(self): - """ - Post-initialization processing for input validation. + class Config: + frozen = True - Raises: - Logger critical if supported_input_activation_n_bits is not an int or a tuple of ints. + @validator('supported_input_activation_n_bits', pre=True, allow_reuse=True) + def validate_supported_input_activation_n_bits(cls, v): """ - if isinstance(self.supported_input_activation_n_bits, int): - object.__setattr__(self, 'supported_input_activation_n_bits', (self.supported_input_activation_n_bits,)) - elif not isinstance(self.supported_input_activation_n_bits, tuple): - Logger.critical( - f"Supported_input_activation_n_bits only accepts int or tuple of ints, but got {type(self.supported_input_activation_n_bits)}") # pragma: no cover + Validate and process the supported_input_activation_n_bits field. + Converts an int to a tuple containing that int. + Ensures that if a tuple is provided, all elements are ints. + """ + + if isinstance(v, int): + v = (v,) + + # When loading from JSON, lists are returned. If the value is a list, convert it to a tuple. + if isinstance(v, list): + v = tuple(v) + + return v def get_info(self) -> Dict[str, Any]: """ @@ -189,9 +188,13 @@ def get_info(self) -> Dict[str, Any]: Returns: dict: Information about the quantization configuration as a dictionary. """ - return asdict(self) # pragma: no cover + return self.dict() # pragma: no cover - def clone_and_edit(self, attr_to_edit: Dict[str, Dict[str, Any]] = {}, **kwargs) -> 'OpQuantizationConfig': + def clone_and_edit( + self, + attr_to_edit: Dict[str, Dict[str, Any]] = {}, + **kwargs: Any + ) -> 'OpQuantizationConfig': """ Clone the quantization config and edit some of its attributes. @@ -203,64 +206,87 @@ def clone_and_edit(self, attr_to_edit: Dict[str, Dict[str, Any]] = {}, **kwargs) Returns: OpQuantizationConfig: Edited quantization configuration. """ - # Clone and update top-level attributes - updated_config = replace(self, **kwargs) + updated_config = self.copy(update=kwargs) # Clone and update nested immutable dataclasses in `attr_weights_configs_mapping` updated_attr_mapping = { attr_name: (attr_cfg.clone_and_edit(**attr_to_edit[attr_name]) - if attr_name in attr_to_edit else attr_cfg) + if attr_name in attr_to_edit else attr_cfg) for attr_name, attr_cfg in updated_config.attr_weights_configs_mapping.items() } # Return a new instance with the updated attribute mapping - return replace(updated_config, attr_weights_configs_mapping=updated_attr_mapping) + return updated_config.copy(update={'attr_weights_configs_mapping': updated_attr_mapping}) -@dataclass(frozen=True) -class QuantizationConfigOptions: +class QuantizationConfigOptions(BaseModel): """ QuantizationConfigOptions wraps a set of quantization configurations to consider during the quantization of an operator. Attributes: - quantization_configurations (Tuple[OpQuantizationConfig]): Tuple of possible OpQuantizationConfig to gather. + quantization_configurations (Tuple[OpQuantizationConfig, ...]): Tuple of possible OpQuantizationConfig to gather. base_config (Optional[OpQuantizationConfig]): Fallback OpQuantizationConfig to use when optimizing the model in a non-mixed-precision manner. """ - quantization_configurations: Tuple[OpQuantizationConfig] + quantization_configurations: Tuple[OpQuantizationConfig, ...] base_config: Optional[OpQuantizationConfig] = None - def __post_init__(self): + class Config: + frozen = True + + @root_validator(pre=True, allow_reuse=True) + def validate_and_set_base_config(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ - Post-initialization processing for input validation. + Validate and set the base_config based on quantization_configurations. + + Args: + values (Dict[str, Any]): Input data. - Raises: - Logger critical if quantization_configurations is not a tuple, contains invalid elements, or if base_config is not set correctly. + Returns: + Dict[str, Any]: Modified input data with base_config set appropriately. """ - # Validate `quantization_configurations` - if not isinstance(self.quantization_configurations, tuple): + quantization_configurations = values.get('quantization_configurations', ()) + num_configs = len(quantization_configurations) + base_config = values.get('base_config') + + if not isinstance(quantization_configurations, (tuple, list)): Logger.critical( - f"'quantization_configurations' must be a tuple, but received: {type(self.quantization_configurations)}.") # pragma: no cover - for cfg in self.quantization_configurations: - if not isinstance(cfg, OpQuantizationConfig): - Logger.critical( - f"Each option must be an instance of 'OpQuantizationConfig', but found an object of type: {type(cfg)}.") # pragma: no cover - - # Handle base_config - if len(self.quantization_configurations) > 1: - if self.base_config is None: - Logger.critical(f"For multiple configurations, a 'base_config' is required for non-mixed-precision optimization.") # pragma: no cover - if not any(self.base_config == cfg for cfg in self.quantization_configurations): - Logger.critical(f"'base_config' must be included in the quantization config options.") # pragma: no cover - elif len(self.quantization_configurations) == 1: - if self.base_config is None: - object.__setattr__(self, 'base_config', self.quantization_configurations[0]) - elif self.base_config != self.quantization_configurations[0]: + f"'quantization_configurations' must be a list or tuple, but received: {type(quantization_configurations)}." + ) # pragma: no cover + + if num_configs == 0: + Logger.critical( + "'QuantizationConfigOptions' requires at least one 'OpQuantizationConfig'. The provided configurations are empty." + ) # pragma: no cover + + if base_config is None: + if num_configs > 1: Logger.critical( - "'base_config' should be the same as the sole item in 'quantization_configurations'.") # pragma: no cover + "For multiple configurations, a 'base_config' is required for non-mixed-precision optimization." + ) # pragma: no cover + else: + # Automatically set base_config to the sole configuration + base_config = quantization_configurations[0] - elif len(self.quantization_configurations) == 0: - Logger.critical("'QuantizationConfigOptions' requires at least one 'OpQuantizationConfig'. The provided configurations is empty.") # pragma: no cover + + if base_config not in quantization_configurations: + Logger.critical( + "'base_config' must be included in the quantization config options." + ) # pragma: no cover + + # if num_configs == 1: + # if base_config != quantization_configurations[0]: + # Logger.critical( + # "'base_config' should be the same as the sole item in 'quantization_configurations'." + # ) # pragma: no cover + + values['base_config'] = base_config + + # When loading from JSON, lists are returned. If the value is a list, convert it to a tuple. + if isinstance(quantization_configurations, list): + values['quantization_configurations'] = tuple(quantization_configurations) + + return values def clone_and_edit(self, **kwargs) -> 'QuantizationConfigOptions': """ @@ -270,46 +296,71 @@ def clone_and_edit(self, **kwargs) -> 'QuantizationConfigOptions': **kwargs: Keyword arguments to edit in each configuration. Returns: - A new instance of QuantizationConfigOptions with updated configurations. + QuantizationConfigOptions: A new instance with updated configurations. """ - updated_base_config = replace(self.base_config, **kwargs) - updated_configs = [ - replace(cfg, **kwargs) for cfg in self.quantization_configurations - ] - return replace(self, base_config=updated_base_config, quantization_configurations=tuple(updated_configs)) + # Clone and update base_config + updated_base_config = self.base_config.clone_and_edit(**kwargs) if self.base_config else None + + # Clone and update all configurations + updated_configs = tuple(cfg.clone_and_edit(**kwargs) for cfg in self.quantization_configurations) - def clone_and_edit_weight_attribute(self, attrs: List[str] = None, **kwargs) -> 'QuantizationConfigOptions': + return self.copy(update={ + 'base_config': updated_base_config, + 'quantization_configurations': updated_configs + }) + + def clone_and_edit_weight_attribute( + self, + attrs: Optional[List[str]] = None, + **kwargs + ) -> 'QuantizationConfigOptions': """ Clones the quantization configurations and edits some of their attributes' parameters. Args: - attrs (List[str]): Attributes names to clone and edit their configurations. If None, updates all attributes. - **kwargs: Keyword arguments to edit in the attributes configuration. + attrs (Optional[List[str]]): Attribute names to clone and edit their configurations. If None, updates all attributes. + **kwargs: Keyword arguments to edit in the attributes' configuration. Returns: - QuantizationConfigOptions: A new instance of QuantizationConfigOptions with edited attributes configurations. + QuantizationConfigOptions: A new instance with edited attributes configurations. """ updated_base_config = self.base_config updated_configs = [] + for qc in self.quantization_configurations: if attrs is None: attrs_to_update = list(qc.attr_weights_configs_mapping.keys()) else: attrs_to_update = attrs + # Ensure all attributes exist in the config for attr in attrs_to_update: if attr not in qc.attr_weights_configs_mapping: - Logger.critical(f"{attr} does not exist in {qc}.") # pragma: no cover + Logger.critical(f"Attribute '{attr}' does not exist in {qc}.") # pragma: no cover + + # Update the specified attributes updated_attr_mapping = { attr: qc.attr_weights_configs_mapping[attr].clone_and_edit(**kwargs) for attr in attrs_to_update } - if qc == updated_base_config: - updated_base_config = replace(updated_base_config, attr_weights_configs_mapping=updated_attr_mapping) - updated_configs.append(replace(qc, attr_weights_configs_mapping=updated_attr_mapping)) - return replace(self, base_config=updated_base_config, quantization_configurations=tuple(updated_configs)) - def clone_and_map_weights_attr_keys(self, layer_attrs_mapping: Optional[Dict[str, str]]) -> 'QuantizationConfigOptions': + # If the current config is the base_config, update it accordingly + if qc == self.base_config: + updated_base_config = qc.clone_and_edit(attr_weights_configs_mapping=updated_attr_mapping) + + # Update the current config with the new attribute mappings + updated_cfg = qc.clone_and_edit(attr_weights_configs_mapping=updated_attr_mapping) + updated_configs.append(updated_cfg) + + return self.copy(update={ + 'base_config': updated_base_config, + 'quantization_configurations': tuple(updated_configs) + }) + + def clone_and_map_weights_attr_keys( + self, + layer_attrs_mapping: Optional[Dict[str, str]] = None + ) -> 'QuantizationConfigOptions': """ Clones the quantization configurations and updates keys in attribute config mappings. @@ -317,22 +368,32 @@ def clone_and_map_weights_attr_keys(self, layer_attrs_mapping: Optional[Dict[str layer_attrs_mapping (Optional[Dict[str, str]]): A mapping between attribute names. Returns: - QuantizationConfigOptions: A new instance of QuantizationConfigOptions with updated attribute keys. + QuantizationConfigOptions: A new instance with updated attribute keys. """ - updated_configs = [] new_base_config = self.base_config + updated_configs = [] + for qc in self.quantization_configurations: if layer_attrs_mapping is None: - new_attr_mapping = {} + new_attr_mapping = qc.attr_weights_configs_mapping else: new_attr_mapping = { layer_attrs_mapping.get(attr, attr): cfg for attr, cfg in qc.attr_weights_configs_mapping.items() } + + # If the current config is the base_config, update it accordingly if qc == self.base_config: - new_base_config = replace(qc, attr_weights_configs_mapping=new_attr_mapping) - updated_configs.append(replace(qc, attr_weights_configs_mapping=new_attr_mapping)) - return replace(self, base_config=new_base_config, quantization_configurations=tuple(updated_configs)) + new_base_config = qc.clone_and_edit(attr_weights_configs_mapping=new_attr_mapping) + + # Update the current config with the new attribute mappings + updated_cfg = qc.clone_and_edit(attr_weights_configs_mapping=new_attr_mapping) + updated_configs.append(updated_cfg) + + return self.copy(update={ + 'base_config': new_base_config, + 'quantization_configurations': tuple(updated_configs) + }) def get_info(self) -> Dict[str, Any]: """ @@ -341,18 +402,16 @@ def get_info(self) -> Dict[str, Any]: Returns: dict: Information about the quantization configuration options as a dictionary. """ - return {f'option {i}': cfg.get_info() for i, cfg in enumerate(self.quantization_configurations)} - + return {f'option_{i}': cfg.get_info() for i, cfg in enumerate(self.quantization_configurations)} -@dataclass(frozen=True) -class TargetPlatformModelComponent: +class TargetPlatformModelComponent(BaseModel): """ Component of TargetPlatformModel (Fusing, OperatorsSet, etc.). """ - pass + class Config: + frozen = True -@dataclass(frozen=True) class OperatorsSetBase(TargetPlatformModelComponent): """ Base class to represent a set of a target platform model component of operator set types. @@ -361,91 +420,151 @@ class OperatorsSetBase(TargetPlatformModelComponent): pass -@dataclass(frozen=True) class OperatorsSet(OperatorsSetBase): """ Set of operators that are represented by a unique label. Attributes: - name (str): The set's label (must be unique within a TargetPlatformModel). - qc_options (QuantizationConfigOptions): Configuration options to use for this set of operations. - If None, it represents a fusing set. - is_default (bool): Indicates whether this set is the default quantization configuration - for the TargetPlatformModel or a fusing set. + name (Union[str, OperatorSetNames]): The set's label (must be unique within a TargetPlatformModel). + qc_options (Optional[QuantizationConfigOptions]): Configuration options to use for this set of operations. + If None, it represents a fusing set. + type (Literal["OperatorsSet"]): Fixed type identifier. """ name: Union[str, OperatorSetNames] - qc_options: QuantizationConfigOptions = None + qc_options: Optional[QuantizationConfigOptions] = None + + # Define a private attribute _type + type: Literal["OperatorsSet"] = "OperatorsSet" + + class Config: + frozen = True def get_info(self) -> Dict[str, Any]: """ Get information about the set as a dictionary. Returns: - Dict[str, Any]: A dictionary containing the set name and - whether it is the default quantization configuration. + Dict[str, Any]: A dictionary containing the set name. """ return {"name": self.name} -@dataclass(frozen=True) class OperatorSetConcat(OperatorsSetBase): """ Concatenate a tuple of operator sets to treat them similarly in different places (like fusing). Attributes: - operators_set (Tuple[OperatorsSet]): Tuple of operator sets to group. - qc_options (None): Configuration options for the set, always None for concatenated sets. - name (str): Concatenated name generated from the names of the operator sets. + operators_set (Tuple[OperatorsSet, ...]): Tuple of operator sets to group. + name (Optional[str]): Concatenated name generated from the names of the operator sets. """ - operators_set: Tuple[OperatorsSet] - qc_options: None = field(default=None, init=False) + operators_set: Tuple[OperatorsSet, ...] + name: Optional[str] = None # Will be set in the validator if not given - def __post_init__(self): + # Define a private attribute _type + type: Literal["OperatorSetConcat"] = "OperatorSetConcat" + + class Config: + frozen = True + + @root_validator(pre=True, allow_reuse=True) + def validate_and_set_name(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ - Post-initialization processing to generate the concatenated name and set it as the `name` attribute. + Validate the input and set the concatenated name based on the operators_set. + + Args: + values (Dict[str, Any]): Input data. + + Returns: + Dict[str, Any]: Modified input data with 'name' set. + """ + operators_set = values['operators_set'] + + if len(operators_set) < 1: + Logger.critical("'operators_set' must contain at least one OperatorsSet") # pragma: no cover - Calls the parent class's __post_init__ method and creates a concatenated name - by joining the names of all operator sets in `operators_set`. + if values.get('name') is None: + # Generate the concatenated name from the operator sets + concatenated_name = "_".join([ + op.name.value if isinstance(op.name, OperatorSetNames) else op.name + for op in operators_set + ]) + values['name'] = concatenated_name + + return values + + def get_info(self) -> Dict[str, Any]: """ - # Generate the concatenated name from the operator sets - concatenated_name = "_".join([op.name.value if hasattr(op.name, "value") else op.name for op in self.operators_set]) - # Set the inherited name attribute using `object.__setattr__` since the dataclass is frozen - object.__setattr__(self, "name", concatenated_name) + Get information about the concatenated operator sets as a dictionary. + Returns: + Dict[str, Any]: A dictionary containing the concatenated name and operator sets information. + """ + return { + "name": self.name, + "operators_set": [op.get_info() for op in self.operators_set] + } -@dataclass(frozen=True) class Fusing(TargetPlatformModelComponent): """ Fusing defines a tuple of operators that should be combined and treated as a single operator, hence no quantization is applied between them. Attributes: - operator_groups (Tuple[Union[OperatorsSet, OperatorSetConcat]]): A tuple of operator groups, + operator_groups (Tuple[Union[OperatorsSet, OperatorSetConcat], ...]): A tuple of operator groups, each being either an OperatorSetConcat or an OperatorsSet. - name (str): The name for the Fusing instance. If not provided, it is generated from the operator groups' names. + name (Optional[str]): The name for the Fusing instance. If not provided, it is generated from the operator groups' names. """ - operator_groups: Tuple[Union[OperatorsSet, OperatorSetConcat]] + operator_groups: Tuple[Annotated[Union[OperatorsSet, OperatorSetConcat], Field(discriminator='type')], ...] + name: Optional[str] = None # Will be set in the validator if not given. + + class Config: + frozen = True - def __post_init__(self): + @root_validator(pre=True, allow_reuse=True) + def validate_and_set_name(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ - Post-initialization processing for input validation and name generation. + Validate the operator_groups and set the name by concatenating operator group names. - Calls the parent class's __post_init__ method, validates the operator_groups, - and generates the name if not explicitly provided. + Args: + values (Dict[str, Any]): Input data. - Raises: - Logger critical if operator_groups is not a tuple or if it contains fewer than two operators. + Returns: + Dict[str, Any]: Modified input data with 'name' set. """ - # Validate the operator_groups - if not isinstance(self.operator_groups, tuple): - Logger.critical( - f"Operator groups should be of type 'tuple' but is {type(self.operator_groups)}.") # pragma: no cover - if len(self.operator_groups) < 2: - Logger.critical("Fusing cannot be created for a single operator.") # pragma: no cover + operator_groups = values.get('operator_groups') - # Generate the name from the operator groups if not provided - generated_name = '_'.join([x.name.value if hasattr(x.name, 'value') else x.name for x in self.operator_groups]) - object.__setattr__(self, 'name', generated_name) + # When loading from JSON, lists are returned. If the value is a list, convert it to a tuple. + if isinstance(operator_groups, list): + values['operator_groups'] = tuple(operator_groups) + + if values.get('name') is None: + # Generate the concatenated name from the operator groups + concatenated_name = "_".join([ + op.name.value if isinstance(op.name, OperatorSetNames) else op.name + for op in values['operator_groups'] + ]) + values['name'] = concatenated_name + + return values + + @root_validator(allow_reuse=True) + def validate_after_initialization(cls, values: Dict[str, Any]) -> Dict[str, Any]: + """ + Perform validation after the model has been instantiated. + + Args: + values (Dict[str, Any]): The instantiated fusing. + + Returns: + Dict[str, Any]: The validated values. + """ + operator_groups = values.get('operator_groups') + + # Validate that there are at least two operator groups + if len(operator_groups) < 2: + Logger.critical("Fusing cannot be created for a single operator.") # pragma: no cover + + return values def contains(self, other: Any) -> bool: """ @@ -483,56 +602,75 @@ def get_info(self) -> Union[Dict[str, str], str]: or just the sequence of operator groups if no name is set. """ if self.name is not None: - return {self.name: ' -> '.join([x.name for x in self.operator_groups])} - return ' -> '.join([x.name for x in self.operator_groups]) - + return { + self.name: ' -> '.join([ + x.name.value if isinstance(x.name, OperatorSetNames) else x.name + for x in self.operator_groups + ]) + } + return ' -> '.join([ + x.name.value if isinstance(x.name, OperatorSetNames) else x.name + for x in self.operator_groups + ]) -@dataclass(frozen=True) -class TargetPlatformModel: +class TargetPlatformModel(BaseModel): """ Represents the hardware configuration used for quantized model inference. Attributes: default_qco (QuantizationConfigOptions): Default quantization configuration options for the model. + operator_set (Optional[Tuple[OperatorsSet, ...]]): Tuple of operator sets within the model. + fusing_patterns (Optional[Tuple[Fusing, ...]]): Tuple of fusing patterns for the model. tpc_minor_version (Optional[int]): Minor version of the Target Platform Configuration. tpc_patch_version (Optional[int]): Patch version of the Target Platform Configuration. tpc_platform_type (Optional[str]): Type of the platform for the Target Platform Configuration. add_metadata (bool): Flag to determine if metadata should be added. name (str): Name of the Target Platform Model. - operator_set (Tuple[OperatorsSetBase]): Tuple of operator sets within the model. - fusing_patterns (Tuple[Fusing]): Tuple of fusing patterns for the model. is_simd_padding (bool): Indicates if SIMD padding is applied. SCHEMA_VERSION (int): Version of the schema for the Target Platform Model. """ default_qco: QuantizationConfigOptions + operator_set: Optional[Tuple[OperatorsSet, ...]] + fusing_patterns: Optional[Tuple[Fusing, ...]] tpc_minor_version: Optional[int] tpc_patch_version: Optional[int] tpc_platform_type: Optional[str] add_metadata: bool = True - name: str = "default_tp_model" - operator_set: Tuple[OperatorsSetBase] = None - fusing_patterns: Tuple[Fusing] = None + name: Optional[str] = "default_tp_model" is_simd_padding: bool = False SCHEMA_VERSION: int = 1 - def __post_init__(self): + class Config: + frozen = True + + @root_validator(allow_reuse=True) + def validate_after_initialization(cls, values: Dict[str, Any]) -> Dict[str, Any]: """ - Post-initialization processing for input validation. + Perform validation after the model has been instantiated. + + Args: + values (Dict[str, Any]): The instantiated target platform model. - Raises: - Logger critical if the default_qco is not an instance of QuantizationConfigOptions - or if it contains more than one quantization configuration. + Returns: + Dict[str, Any]: The validated values. """ # Validate `default_qco` - if not isinstance(self.default_qco, QuantizationConfigOptions): - Logger.critical("'default_qco' must be an instance of QuantizationConfigOptions.") # pragma: no cover - if len(self.default_qco.quantization_configurations) != 1: - Logger.critical("Default QuantizationConfigOptions must contain exactly one option.") # pragma: no cover - - opsets_names = [op.name.value if hasattr(op.name, "value") else op.name for op in self.operator_set] if self.operator_set else [] - if len(set(opsets_names)) != len(opsets_names): - Logger.critical("Operator Sets must have unique names.") # pragma: no cover + default_qco = values.get('default_qco') + if len(default_qco.quantization_configurations) != 1: + Logger.critical("Default QuantizationConfigOptions must contain exactly one option.") # pragma: no cover + + # Validate `operator_set` uniqueness + operator_set = values.get('operator_set') + if operator_set is not None: + opsets_names = [ + op.name.value if isinstance(op.name, OperatorSetNames) else op.name + for op in operator_set + ] + if len(set(opsets_names)) != len(opsets_names): + Logger.critical("Operator Sets must have unique names.") # pragma: no cover + + return values def get_info(self) -> Dict[str, Any]: """ @@ -547,11 +685,8 @@ def get_info(self) -> Dict[str, Any]: "Fusing patterns": [f.get_info() for f in self.fusing_patterns] if self.fusing_patterns else [], } - def show(self): """ - Display the TargetPlatformModel. - """ pprint.pprint(self.get_info(), sort_dicts=False) \ No newline at end of file diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1/tp_model.py index 5a80e258a..dd62cf03f 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1/tp_model.py @@ -153,10 +153,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -167,46 +167,46 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit(enable_activation_quantization=False) + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit(enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=1, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_lut/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_lut/tp_model.py index 267dd98ce..557bb8a45 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_lut/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_lut/tp_model.py @@ -151,10 +151,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -166,47 +166,47 @@ def generate_tp_model(default_config: OpQuantizationConfig, fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=1, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_pot/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_pot/tp_model.py index df17573f8..2669fe92c 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_pot/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v1_pot/tp_model.py @@ -147,10 +147,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -162,48 +162,48 @@ def generate_tp_model(default_config: OpQuantizationConfig, fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=1, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2/tp_model.py index 040b453ca..d9f5ad63a 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2/tp_model.py @@ -156,10 +156,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -170,46 +170,46 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False).clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=2, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2_lut/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2_lut/tp_model.py index 3797a7127..be420bf03 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2_lut/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v2_lut/tp_model.py @@ -153,10 +153,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -167,47 +167,47 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=2, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3/tp_model.py index 3ff560d5c..4f0512cc3 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3/tp_model.py @@ -156,7 +156,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create a QuantizationConfigOptions for quantizing constants in functional ops. # Constant configuration is similar to the default eight bit configuration except for PoT @@ -167,7 +167,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, default_weight_attr_config=default_config.default_weight_attr_config.clone_and_edit( enable_weights_quantization=True, weights_per_channel_threshold=True, weights_quantization_method=tp.QuantizationMethod.POWER_OF_TWO)) - const_configuration_options = schema.QuantizationConfigOptions(tuple([const_config])) + const_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config])) # 16 bits inputs and outputs. Currently, only defined for consts since they are used in operators that # support 16 bit as input and output. @@ -175,12 +175,12 @@ def generate_tp_model(default_config: OpQuantizationConfig, supported_input_activation_n_bits=(8, 16)) const_config_input16_output16 = const_config_input16.clone_and_edit( activation_n_bits=16, signedness=Signedness.SIGNED) - const_configuration_options_inout16 = schema.QuantizationConfigOptions(tuple([const_config_input16_output16, + const_configuration_options_inout16 = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config_input16_output16, const_config_input16]), base_config=const_config_input16) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -191,49 +191,49 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False, supported_input_activation_n_bits=(8, 16)) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) - operator_set.append(schema.OperatorsSet("Default16BitInout", const_configuration_options_inout16)) + operator_set.append(schema.OperatorsSet(name="Default16BitInout", qc_options=const_configuration_options_inout16)) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add", const_configuration_options_inout16) - sub = schema.OperatorsSet("Sub", const_configuration_options_inout16) - mul = schema.OperatorsSet("Mul", const_configuration_options_inout16) - div = schema.OperatorsSet("Div", const_configuration_options) - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add", qc_options=const_configuration_options_inout16) + sub = schema.OperatorsSet(name="Sub", qc_options=const_configuration_options_inout16) + mul = schema.OperatorsSet(name="Mul", qc_options=const_configuration_options_inout16) + div = schema.OperatorsSet(name="Div", qc_options=const_configuration_options) + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=3, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3_lut/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3_lut/tp_model.py index f1de8b6e0..438544c56 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3_lut/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v3_lut/tp_model.py @@ -153,7 +153,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Create a QuantizationConfigOptions for quantizing constants in functional ops. # Constant configuration is similar to the default eight bit configuration except for PoT @@ -164,10 +164,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, default_weight_attr_config=default_config.default_weight_attr_config.clone_and_edit( enable_weights_quantization=True, weights_per_channel_threshold=True, weights_quantization_method=tp.QuantizationMethod.POWER_OF_TWO)) - const_configuration_options = schema.QuantizationConfigOptions(tuple([const_config])) + const_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config])) # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) # Create an OperatorsSet to represent a set of operations. @@ -178,47 +178,47 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) # Define operations sets without quantization configuration # options (useful for creating fusing patterns, for example): - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add", const_configuration_options) - sub = schema.OperatorsSet("Sub", const_configuration_options) - mul = schema.OperatorsSet("Mul", const_configuration_options) - div = schema.OperatorsSet("Div", const_configuration_options) - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add", qc_options=const_configuration_options) + sub = schema.OperatorsSet(name="Sub", qc_options=const_configuration_options) + mul = schema.OperatorsSet(name="Mul", qc_options=const_configuration_options) + div = schema.OperatorsSet(name="Div", qc_options=const_configuration_options) + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, tanh]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh]) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=3, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v4/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v4/tp_model.py index 7a7e74c03..2038e6eba 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v4/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/imx500_tpc/v4/tp_model.py @@ -179,9 +179,9 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) default_config_input16 = default_config.clone_and_edit(supported_input_activation_n_bits=(8, 16)) - default_config_options_16bit = schema.QuantizationConfigOptions(tuple([default_config_input16, + default_config_options_16bit = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config_input16, default_config_input16.clone_and_edit( activation_n_bits=16, signedness=Signedness.SIGNED)]), @@ -190,7 +190,8 @@ def generate_tp_model(default_config: OpQuantizationConfig, qpreseving_config = default_config.clone_and_edit(enable_activation_quantization=False, quantization_preserving=True, supported_input_activation_n_bits=(8, 16)) - qpreseving_config_options = schema.QuantizationConfigOptions(tuple([qpreseving_config, + + qpreseving_config_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([qpreseving_config, qpreseving_config.clone_and_edit( activation_n_bits=16, signedness=Signedness.SIGNED)]), @@ -205,7 +206,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, default_weight_attr_config=default_config.default_weight_attr_config.clone_and_edit( enable_weights_quantization=True, weights_per_channel_threshold=True, weights_quantization_method=tp.QuantizationMethod.POWER_OF_TWO)) - const_configuration_options = schema.QuantizationConfigOptions(tuple([const_config])) + const_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config])) # 16 bits inputs and outputs. Currently, only defined for consts since they are used in operators that # support 16 bit as input and output. @@ -213,9 +214,10 @@ def generate_tp_model(default_config: OpQuantizationConfig, supported_input_activation_n_bits=(8, 16)) const_config_input16_output16 = const_config_input16.clone_and_edit( activation_n_bits=16, signedness=Signedness.SIGNED) - const_configuration_options_inout16 = schema.QuantizationConfigOptions(tuple([const_config_input16_output16, - const_config_input16]), - base_config=const_config_input16) + const_configuration_options_inout16 = schema.QuantizationConfigOptions( + quantization_configurations=tuple([const_config_input16_output16, + const_config_input16]), + base_config=const_config_input16) const_config_input16_per_tensor = const_config.clone_and_edit( supported_input_activation_n_bits=(8, 16), @@ -225,7 +227,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, ) const_config_input16_output16_per_tensor = const_config_input16_per_tensor.clone_and_edit( activation_n_bits=16, signedness=Signedness.SIGNED) - const_configuration_options_inout16_per_tensor = schema.QuantizationConfigOptions(tuple( + const_configuration_options_inout16_per_tensor = schema.QuantizationConfigOptions(quantization_configurations=tuple( [const_config_input16_output16_per_tensor, const_config_input16_per_tensor]), base_config=const_config_input16_per_tensor) @@ -234,13 +236,13 @@ def generate_tp_model(default_config: OpQuantizationConfig, quantization_preserving=True, default_weight_attr_config=const_config.default_weight_attr_config.clone_and_edit( weights_per_channel_threshold=False)) - qpreserving_const_config_options = schema.QuantizationConfigOptions(tuple([qpreserving_const_config])) + qpreserving_const_config_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([qpreserving_const_config])) mp_cfg_list_16bit = [mp_cfg.clone_and_edit(activation_n_bits=16, signedness=Signedness.SIGNED) for mp_cfg in mixed_precision_cfg_list] # Create Mixed-Precision quantization configuration options from the given list of OpQuantizationConfig objects - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple( + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list + mp_cfg_list_16bit), base_config=base_config) @@ -252,70 +254,72 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] # May suit for operations like: Dropout, Reshape, etc. - operator_set.append(schema.OperatorsSet(OPSET_NO_QUANTIZATION, - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name=OPSET_NO_QUANTIZATION, + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) - operator_set.append(schema.OperatorsSet(OPSET_QUANTIZATION_PRESERVING, - default_configuration_options.clone_and_edit( + operator_set.append(schema.OperatorsSet(name=OPSET_QUANTIZATION_PRESERVING, + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False, quantization_preserving=True) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) operator_set.append( - schema.OperatorsSet(OPSET_DIMENSION_MANIPULATION_OPS_WITH_WEIGHTS, qpreserving_const_config_options)) - operator_set.append(schema.OperatorsSet(OPSET_DIMENSION_MANIPULATION_OPS, - default_configuration_options.clone_and_edit( + schema.OperatorsSet(name=OPSET_DIMENSION_MANIPULATION_OPS_WITH_WEIGHTS, + qc_options=qpreserving_const_config_options)) + operator_set.append(schema.OperatorsSet(name=OPSET_DIMENSION_MANIPULATION_OPS, + qc_options=default_configuration_options.clone_and_edit( enable_activation_quantization=False, quantization_preserving=True, supported_input_activation_n_bits=(8, 16)) .clone_and_edit_weight_attribute(enable_weights_quantization=False))) - operator_set.append(schema.OperatorsSet(OPSET_SPLIT_OPS, qpreseving_config_options)) - operator_set.append(schema.OperatorsSet(OPSET_MERGE_OPS, const_configuration_options_inout16_per_tensor)) + + operator_set.append(schema.OperatorsSet(name=OPSET_SPLIT_OPS, qc_options=qpreseving_config_options)) + operator_set.append(schema.OperatorsSet(name=OPSET_MERGE_OPS, qc_options=const_configuration_options_inout16_per_tensor)) # Define operator sets that use mixed_precision_configuration_options: - conv = schema.OperatorsSet(OPSET_CONV, mixed_precision_configuration_options) - fc = schema.OperatorsSet(OPSET_FULLY_CONNECTED, mixed_precision_configuration_options) + conv = schema.OperatorsSet(name=OPSET_CONV, qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name=OPSET_FULLY_CONNECTED, qc_options=mixed_precision_configuration_options) - operator_set.append(schema.OperatorsSet(OPSET_BATCH_NORM, default_config_options_16bit)) + operator_set.append(schema.OperatorsSet(name=OPSET_BATCH_NORM, qc_options=default_config_options_16bit)) # Note: Operations sets without quantization configuration are useful for creating fusing patterns - any_relu = schema.OperatorsSet(OPSET_ANY_RELU, default_config_options_16bit) - add = schema.OperatorsSet(OPSET_ADD, const_configuration_options_inout16) - sub = schema.OperatorsSet(OPSET_SUB, const_configuration_options_inout16) - mul = schema.OperatorsSet(OPSET_MUL, const_configuration_options_inout16) - div = schema.OperatorsSet(OPSET_DIV, const_configuration_options) - min_max = schema.OperatorsSet(OPSET_MIN_MAX, const_configuration_options_inout16) - prelu = schema.OperatorsSet(OPSET_PRELU, default_config_options_16bit) - swish = schema.OperatorsSet(OPSET_SWISH, default_config_options_16bit) - sigmoid = schema.OperatorsSet(OPSET_SIGMOID, default_config_options_16bit) - tanh = schema.OperatorsSet(OPSET_TANH, default_config_options_16bit) - gelu = schema.OperatorsSet(OPSET_GELU, default_config_options_16bit) - hardsigmoid = schema.OperatorsSet(OPSET_HARDSIGMOID, default_config_options_16bit) - hardswish = schema.OperatorsSet(OPSET_HARDSWISH, default_config_options_16bit) + any_relu = schema.OperatorsSet(name=OPSET_ANY_RELU, qc_options=default_config_options_16bit) + add = schema.OperatorsSet(name=OPSET_ADD, qc_options=const_configuration_options_inout16) + sub = schema.OperatorsSet(name=OPSET_SUB, qc_options=const_configuration_options_inout16) + mul = schema.OperatorsSet(name=OPSET_MUL, qc_options=const_configuration_options_inout16) + div = schema.OperatorsSet(name=OPSET_DIV, qc_options=const_configuration_options) + min_max = schema.OperatorsSet(name=OPSET_MIN_MAX, qc_options=const_configuration_options_inout16) + prelu = schema.OperatorsSet(name=OPSET_PRELU, qc_options=default_config_options_16bit) + swish = schema.OperatorsSet(name=OPSET_SWISH, qc_options=default_config_options_16bit) + sigmoid = schema.OperatorsSet(name=OPSET_SIGMOID, qc_options=default_config_options_16bit) + tanh = schema.OperatorsSet(name=OPSET_TANH, qc_options=default_config_options_16bit) + gelu = schema.OperatorsSet(name=OPSET_GELU, qc_options=default_config_options_16bit) + hardsigmoid = schema.OperatorsSet(name=OPSET_HARDSIGMOID, qc_options=default_config_options_16bit) + hardswish = schema.OperatorsSet(name=OPSET_HARDSWISH, qc_options=default_config_options_16bit) operator_set.extend( [conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh, min_max, gelu, hardsigmoid, hardswish]) # Combine multiple operators into a single operator to avoid quantization between # them. To do this we define fusing patterns using the OperatorsSets that were created. # To group multiple sets with regard to fusing, an OperatorSetConcat can be created - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, prelu, sigmoid, + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, prelu, sigmoid, tanh, gelu, hardswish, hardsigmoid]) - activations_after_fc_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid, tanh, gelu, + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid, tanh, gelu, hardswish, hardsigmoid]) - any_binary = schema.OperatorSetConcat([add, sub, mul, div]) + any_binary = schema.OperatorSetConcat(operators_set=[add, sub, mul, div]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=4, tpc_patch_version=0, tpc_platform_type=IMX500_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/qnnpack_tpc/v1/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/qnnpack_tpc/v1/tp_model.py index 5a94c4ebf..58fd8b9d2 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/qnnpack_tpc/v1/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/qnnpack_tpc/v1/tp_model.py @@ -139,7 +139,7 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) # Combine operations/modules into a single module. # Pytorch supports the next fusing patterns: @@ -148,24 +148,24 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] - conv = schema.OperatorsSet("Conv") - batchnorm = schema.OperatorsSet("BatchNorm") - relu = schema.OperatorsSet("Relu") - linear = schema.OperatorsSet("Linear") + conv = schema.OperatorsSet(name="Conv") + batchnorm = schema.OperatorsSet(name="BatchNorm") + relu = schema.OperatorsSet(name="Relu") + linear = schema.OperatorsSet(name="Linear") operator_set.extend([conv, batchnorm, relu, linear]) # ------------------- # # Fusions # ------------------- # - fusing_patterns.append(schema.Fusing((conv, batchnorm, relu))) - fusing_patterns.append(schema.Fusing((conv, batchnorm))) - fusing_patterns.append(schema.Fusing((conv, relu))) - fusing_patterns.append(schema.Fusing((linear, relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, batchnorm, relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, batchnorm))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(linear, relu))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=1, tpc_patch_version=0, tpc_platform_type=QNNPACK_TP_MODEL, diff --git a/model_compression_toolkit/target_platform_capabilities/tpc_models/tflite_tpc/v1/tp_model.py b/model_compression_toolkit/target_platform_capabilities/tpc_models/tflite_tpc/v1/tp_model.py index 3d664ab97..0f2cd571e 100644 --- a/model_compression_toolkit/target_platform_capabilities/tpc_models/tflite_tpc/v1/tp_model.py +++ b/model_compression_toolkit/target_platform_capabilities/tpc_models/tflite_tpc/v1/tp_model.py @@ -18,7 +18,8 @@ import model_compression_toolkit.target_platform_capabilities.schema.mct_current_schema as schema from model_compression_toolkit.constants import FLOAT_BITWIDTH from model_compression_toolkit.target_platform_capabilities.constants import BIAS_ATTR, KERNEL_ATTR, TFLITE_TP_MODEL -from model_compression_toolkit.target_platform_capabilities.schema.mct_current_schema import TargetPlatformModel, Signedness, \ +from model_compression_toolkit.target_platform_capabilities.schema.mct_current_schema import TargetPlatformModel, \ + Signedness, \ AttributeQuantizationConfig, OpQuantizationConfig tp = mct.target_platform @@ -136,7 +137,8 @@ def generate_tp_model(default_config: OpQuantizationConfig, # of possible configurations to consider when quantizing a set of operations (in mixed-precision, for example). # If the QuantizationConfigOptions contains only one configuration, # this configuration will be used for the operation quantization: - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) + default_configuration_options = schema.QuantizationConfigOptions( + quantization_configurations=tuple([default_config])) # In TFLite, the quantized operator specifications constraint operators quantization # differently. For more details: @@ -144,59 +146,60 @@ def generate_tp_model(default_config: OpQuantizationConfig, operator_set = [] fusing_patterns = [] - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit( - quantization_preserving=True))) - - fc = schema.OperatorsSet("FullyConnected", - default_configuration_options.clone_and_edit_weight_attribute(weights_per_channel_threshold=False)) - - operator_set.append(schema.OperatorsSet("L2Normalization", - default_configuration_options.clone_and_edit( - fixed_zero_point=0, fixed_scale=1 / 128))) - operator_set.append(schema.OperatorsSet("LogSoftmax", - default_configuration_options.clone_and_edit( - fixed_zero_point=127, fixed_scale=16 / 256))) - operator_set.append(schema.OperatorsSet("Tanh", - default_configuration_options.clone_and_edit( - fixed_zero_point=0, fixed_scale=1 / 128))) - operator_set.append(schema.OperatorsSet("Softmax", - default_configuration_options.clone_and_edit( - fixed_zero_point=-128, fixed_scale=1 / 256))) - operator_set.append(schema.OperatorsSet("Logistic", - default_configuration_options.clone_and_edit( - fixed_zero_point=-128, fixed_scale=1 / 256))) - - conv2d = schema.OperatorsSet("Conv2d") - kernel = schema.OperatorSetConcat([conv2d, fc]) - - relu = schema.OperatorsSet("Relu") - elu = schema.OperatorsSet("Elu") - activations_to_fuse = schema.OperatorSetConcat([relu, elu]) - - batch_norm = schema.OperatorsSet("BatchNorm") - bias_add = schema.OperatorsSet("BiasAdd") - add = schema.OperatorsSet("Add") - squeeze = schema.OperatorsSet("Squeeze", - qc_options=default_configuration_options.clone_and_edit( - quantization_preserving=True)) - operator_set.extend([fc, conv2d, kernel, relu, elu, batch_norm, bias_add, add, squeeze]) + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( + quantization_preserving=True))) + + fc = schema.OperatorsSet(name="FullyConnected", + qc_options=default_configuration_options.clone_and_edit_weight_attribute( + weights_per_channel_threshold=False)) + + operator_set.append(schema.OperatorsSet(name="L2Normalization", + qc_options=default_configuration_options.clone_and_edit( + fixed_zero_point=0, fixed_scale=1 / 128))) + operator_set.append(schema.OperatorsSet(name="LogSoftmax", + qc_options=default_configuration_options.clone_and_edit( + fixed_zero_point=127, fixed_scale=16 / 256))) + operator_set.append(schema.OperatorsSet(name="Tanh", + qc_options=default_configuration_options.clone_and_edit( + fixed_zero_point=0, fixed_scale=1 / 128))) + operator_set.append(schema.OperatorsSet(name="Softmax", + qc_options=default_configuration_options.clone_and_edit( + fixed_zero_point=-128, fixed_scale=1 / 256))) + operator_set.append(schema.OperatorsSet(name="Logistic", + qc_options=default_configuration_options.clone_and_edit( + fixed_zero_point=-128, fixed_scale=1 / 256))) + + conv2d = schema.OperatorsSet(name="Conv2d") + kernel = schema.OperatorSetConcat(operators_set=[conv2d, fc]) + + relu = schema.OperatorsSet(name="Relu") + elu = schema.OperatorsSet(name="Elu") + activations_to_fuse = schema.OperatorSetConcat(operators_set=[relu, elu]) + + batch_norm = schema.OperatorsSet(name="BatchNorm") + bias_add = schema.OperatorsSet(name="BiasAdd") + add = schema.OperatorsSet(name="Add") + squeeze = schema.OperatorsSet(name="Squeeze", + qc_options=default_configuration_options.clone_and_edit( + quantization_preserving=True)) + operator_set.extend([fc, conv2d, relu, elu, batch_norm, bias_add, add, squeeze]) # ------------------- # # Fusions # ------------------- # # Source: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/grappler/optimizers/remapper - fusing_patterns.append(schema.Fusing((kernel, bias_add))) - fusing_patterns.append(schema.Fusing((kernel, bias_add, activations_to_fuse))) - fusing_patterns.append(schema.Fusing((conv2d, batch_norm, activations_to_fuse))) - fusing_patterns.append(schema.Fusing((conv2d, squeeze, activations_to_fuse))) - fusing_patterns.append(schema.Fusing((batch_norm, activations_to_fuse))) - fusing_patterns.append(schema.Fusing((batch_norm, add, activations_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(kernel, bias_add))) + fusing_patterns.append(schema.Fusing(operator_groups=(kernel, bias_add, activations_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv2d, batch_norm, activations_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv2d, squeeze, activations_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(batch_norm, activations_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(batch_norm, add, activations_to_fuse))) # Create a TargetPlatformModel and set its default quantization config. # This default configuration will be used for all operations # unless specified otherwise (see OperatorsSet, for example): generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=1, tpc_patch_version=0, operator_set=tuple(operator_set), diff --git a/requirements.txt b/requirements.txt index 59be4a24a..4c68dd252 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ matplotlib<3.10.0 scipy protobuf mct-quantizers==1.5.2 +pydantic<2.0 \ No newline at end of file diff --git a/tests/common_tests/helpers/generate_test_tp_model.py b/tests/common_tests/helpers/generate_test_tp_model.py index 56dde1c5b..765f65d0e 100644 --- a/tests/common_tests/helpers/generate_test_tp_model.py +++ b/tests/common_tests/helpers/generate_test_tp_model.py @@ -39,8 +39,7 @@ def generate_test_tp_model(edit_params_dict, name=""): base_config, op_cfg_list, default_config = get_op_quantization_configs() # separate weights attribute parameters from the requested param to edit - weights_params_names = [name for name in schema.AttributeQuantizationConfig.__init__.__code__.co_varnames if - name != 'self'] + weights_params_names = base_config.default_weight_attr_config.field_names weights_params = {k: v for k, v in edit_params_dict.items() if k in weights_params_names} rest_params = {k: v for k, v in edit_params_dict.items() if k not in list(weights_params.keys())} @@ -107,7 +106,7 @@ def generate_tp_model_with_activation_mp(base_cfg, default_config, mp_bitwidth_c mixed_precision_cfg_list=mp_op_cfg_list, name=name) - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mp_op_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mp_op_cfg_list), base_config=base_cfg) operator_sets_dict = {op_set.name: mixed_precision_configuration_options for op_set in base_tp_model.operator_set @@ -126,7 +125,7 @@ def generate_custom_test_tp_model(name: str, base_cfg: OpQuantizationConfig, base_tp_model: schema.TargetPlatformModel, operator_sets_dict: Dict[str, QuantizationConfigOptions] = None): - default_configuration_options = schema.QuantizationConfigOptions(tuple([base_cfg])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([base_cfg])) operator_set, fusing_patterns = [], [] @@ -137,19 +136,19 @@ def generate_custom_test_tp_model(name: str, else: qc_options = op_set.qc_options - operator_set.append(schema.OperatorsSet(op_set.name, qc_options)) + operator_set.append(schema.OperatorsSet(name=op_set.name, qc_options=qc_options)) existing_op_sets_names = [op_set.name for op_set in base_tp_model.operator_set] for op_set_name, op_set_qc_options in operator_sets_dict.items(): # Add new OperatorSets from the given operator_sets_dict if op_set_name not in existing_op_sets_names: - operator_set.append( schema.OperatorsSet(op_set_name, op_set_qc_options)) + operator_set.append( schema.OperatorsSet(name=op_set_name, qc_options=op_set_qc_options)) for fusion in base_tp_model.fusing_patterns: - fusing_patterns.append(schema.Fusing(fusion.operator_groups)) + fusing_patterns.append(schema.Fusing(operator_groups=fusion.operator_groups)) custom_tp_model = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, diff --git a/tests/common_tests/test_tp_model.py b/tests/common_tests/test_tp_model.py index b36320456..cee4c6787 100644 --- a/tests/common_tests/test_tp_model.py +++ b/tests/common_tests/test_tp_model.py @@ -12,14 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +import os import unittest import model_compression_toolkit as mct import model_compression_toolkit.target_platform_capabilities.schema.mct_current_schema as schema -from model_compression_toolkit.constants import FLOAT_BITWIDTH from model_compression_toolkit.core.common import BaseNode -from model_compression_toolkit.target_platform_capabilities.constants import KERNEL_ATTR, BIAS_ATTR +from model_compression_toolkit.target_platform_capabilities.constants import KERNEL_ATTR from model_compression_toolkit.target_platform_capabilities.schema.schema_functions import \ get_config_options_by_operators_set, is_opset_in_model from tests.common_tests.helpers.generate_test_tp_model import generate_test_attr_configs, generate_test_op_qc @@ -27,27 +27,61 @@ tp = mct.target_platform TEST_QC = generate_test_op_qc(**generate_test_attr_configs()) -TEST_QCO = schema.QuantizationConfigOptions(tuple([TEST_QC])) +TEST_QCO = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) class TargetPlatformModelingTest(unittest.TestCase): + def cleanup_file(self, file_path): + if os.path.exists(file_path): + os.remove(file_path) + print(f"Cleaned up: {file_path}") + + def test_dump_to_json(self): + op1 = schema.OperatorsSet(name="opset1") + op2 = schema.OperatorsSet(name="opset2") + op3 = schema.OperatorsSet(name="opset3") + op12 = schema.OperatorSetConcat(operators_set=[op1, op2]) + model = schema.TargetPlatformModel(default_qco=TEST_QCO, + operator_set=(op1, op2, op3), + fusing_patterns=(schema.Fusing(operator_groups=(op12, op3)), + schema.Fusing(operator_groups=(op1, op2))), + tpc_minor_version=1, + tpc_patch_version=0, + tpc_platform_type="dump_to_json", + add_metadata=False) + json_str = model.json() + # Define the output file path + file_path = "target_platform_model.json" + # Register cleanup to delete the file if it exists + self.addCleanup(self.cleanup_file, file_path) + + # Write the JSON string to the file + with open(file_path, "w") as f: + f.write(json_str) + + with open(file_path, "r") as f: + json_content = f.read() + + loaded_target_model = schema.TargetPlatformModel.parse_raw(json_content) + self.assertEqual(model, loaded_target_model) + def test_immutable_tp(self): with self.assertRaises(Exception) as e: - model = schema.TargetPlatformModel(TEST_QCO, - operator_set=tuple([schema.OperatorsSet("opset")]), + model = schema.TargetPlatformModel(default_qco=TEST_QCO, + operator_set=tuple([schema.OperatorsSet(name="opset")]), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, add_metadata=False) model.operator_set = tuple() - self.assertEqual("cannot assign to field 'operator_set'", str(e.exception)) + self.assertEqual('"TargetPlatformModel" is immutable and does not support item assignment', str(e.exception)) def test_default_options_more_than_single_qc(self): - test_qco = schema.QuantizationConfigOptions(tuple([TEST_QC, TEST_QC]), base_config=TEST_QC) + test_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC, TEST_QC]), base_config=TEST_QC) with self.assertRaises(Exception) as e: - schema.TargetPlatformModel(test_qco, + schema.TargetPlatformModel(default_qco=test_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -55,13 +89,13 @@ def test_default_options_more_than_single_qc(self): self.assertEqual('Default QuantizationConfigOptions must contain exactly one option.', str(e.exception)) def test_tp_model_show(self): - tpm = schema.TargetPlatformModel(TEST_QCO, + tpm = schema.TargetPlatformModel(default_qco=TEST_QCO, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("opA"), schema.OperatorsSet("opB")]), + operator_set=tuple([schema.OperatorsSet(name="opA"), schema.OperatorsSet(name="opB")]), fusing_patterns=tuple( - [schema.Fusing((schema.OperatorsSet("opA"), schema.OperatorsSet("opB")))]), + [schema.Fusing(operator_groups=(schema.OperatorsSet(name="opA"), schema.OperatorsSet(name="opB")))]), add_metadata=False) tpm.show() @@ -70,8 +104,8 @@ class OpsetTest(unittest.TestCase): def test_opset_qco(self): opset_name = "ops_3bit" qco_3bit = TEST_QCO.clone_and_edit(activation_n_bits=3) - operator_set = [schema.OperatorsSet(opset_name, qco_3bit)] - hm = schema.TargetPlatformModel(TEST_QCO, + operator_set = [schema.OperatorsSet(name=opset_name, qc_options=qco_3bit)] + hm = schema.TargetPlatformModel(default_qco=TEST_QCO, operator_set=tuple(operator_set), tpc_minor_version=None, tpc_patch_version=None, @@ -90,12 +124,12 @@ def test_opset_qco(self): def test_opset_concat(self): operator_set, fusing_patterns = [], [] - a = schema.OperatorsSet('opset_A') - b = schema.OperatorsSet('opset_B', - TEST_QCO.clone_and_edit(activation_n_bits=2)) - c = schema.OperatorsSet('opset_C') # Just add it without using it in concat + a = schema.OperatorsSet(name='opset_A') + b = schema.OperatorsSet(name='opset_B', + qc_options=TEST_QCO.clone_and_edit(activation_n_bits=2)) + c = schema.OperatorsSet(name='opset_C') # Just add it without using it in concat operator_set.extend([a, b, c]) - hm = schema.TargetPlatformModel(TEST_QCO, + hm = schema.TargetPlatformModel(default_qco=TEST_QCO, operator_set=tuple(operator_set), tpc_minor_version=None, tpc_patch_version=None, @@ -108,8 +142,8 @@ def test_opset_concat(self): def test_non_unique_opset(self): with self.assertRaises(Exception) as e: hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), - operator_set=tuple([schema.OperatorsSet("conv"), schema.OperatorsSet("conv")]), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), + operator_set=tuple([schema.OperatorsSet(name="conv"), schema.OperatorsSet(name="conv")]), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -122,17 +156,17 @@ class QCOptionsTest(unittest.TestCase): def test_empty_qc_options(self): with self.assertRaises(Exception) as e: - schema.QuantizationConfigOptions(tuple([])) + schema.QuantizationConfigOptions(quantization_configurations=tuple([])) self.assertEqual( - "'QuantizationConfigOptions' requires at least one 'OpQuantizationConfig'. The provided configurations is empty.", + "'QuantizationConfigOptions' requires at least one 'OpQuantizationConfig'. The provided configurations are empty.", str(e.exception)) def test_list_of_no_qc(self): with self.assertRaises(Exception) as e: - schema.QuantizationConfigOptions(tuple([TEST_QC, 3])) - self.assertEqual( - 'Each option must be an instance of \'OpQuantizationConfig\', but found an object of type: .', - str(e.exception)) + schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC, 3]), base_config=TEST_QC) + self.assertTrue( + "1 validation error for QuantizationConfigOptions\nquantization_configurations -> 1\n value is not a valid dict (type=type_error.dict)" in str( + e.exception)) def test_clone_and_edit_options(self): modified_options = TEST_QCO.clone_and_edit(activation_n_bits=3).clone_and_edit_weight_attribute( @@ -144,9 +178,9 @@ def test_clone_and_edit_options(self): modified_options.quantization_configurations[0].attr_weights_configs_mapping[KERNEL_ATTR].weights_n_bits, 5) def test_qco_without_base_config(self): - schema.QuantizationConfigOptions(tuple([TEST_QC])) # Should work fine as it has only one qc. + schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) # Should work fine as it has only one qc. with self.assertRaises(Exception) as e: - schema.QuantizationConfigOptions(tuple([TEST_QC, TEST_QC])) # Should raise exception as base_config was not passed + schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC, TEST_QC])) # Should raise exception as base_config was not passed self.assertEqual( 'For multiple configurations, a \'base_config\' is required for non-mixed-precision optimization.', str(e.exception)) @@ -161,12 +195,12 @@ def test_get_qco_for_none_tpc(self): class FusingTest(unittest.TestCase): def test_fusing_single_opset(self): - add = schema.OperatorsSet("add") + add = schema.OperatorsSet(name="add") with self.assertRaises(Exception) as e: hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), operator_set=tuple([add]), - fusing_patterns=tuple([schema.Fusing(tuple([add]))]), + fusing_patterns=tuple([schema.Fusing(operator_groups=tuple([add]))]), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -177,16 +211,16 @@ def test_fusing_contains(self): operator_set, fusing_patterns = [], [] - conv = schema.OperatorsSet("conv") - add = schema.OperatorsSet("add") - tanh = schema.OperatorsSet("tanh") + conv = schema.OperatorsSet(name="conv") + add = schema.OperatorsSet(name="add") + tanh = schema.OperatorsSet(name="tanh") operator_set.extend([conv, add, tanh]) - fusing_patterns.append(schema.Fusing((conv, add))) - fusing_patterns.append(schema.Fusing((conv, add, tanh))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, add))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, add, tanh))) hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), operator_set=tuple(operator_set), fusing_patterns=tuple(fusing_patterns), tpc_minor_version=None, @@ -203,18 +237,18 @@ def test_fusing_contains(self): def test_fusing_contains_with_opset_concat(self): operator_set, fusing_patterns = [], [] - conv = schema.OperatorsSet("conv") - add = schema.OperatorsSet("add") - tanh = schema.OperatorsSet("tanh") + conv = schema.OperatorsSet(name="conv") + add = schema.OperatorsSet(name="add") + tanh = schema.OperatorsSet(name="tanh") operator_set.extend([conv, add, tanh]) - add_tanh = schema.OperatorSetConcat((add, tanh)) - fusing_patterns.append(schema.Fusing((conv, add))) - fusing_patterns.append(schema.Fusing((conv, add_tanh))) - fusing_patterns.append(schema.Fusing((conv, add, tanh))) + add_tanh = schema.OperatorSetConcat(operators_set=[add, tanh]) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, add))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, add_tanh))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, add, tanh))) hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), operator_set=tuple(operator_set), fusing_patterns=tuple(fusing_patterns), tpc_minor_version=None, diff --git a/tests/keras_tests/exporter_tests/tflite_int8/imx500_int8_tp_model.py b/tests/keras_tests/exporter_tests/tflite_int8/imx500_int8_tp_model.py index 07e5f1dae..e40185c5e 100644 --- a/tests/keras_tests/exporter_tests/tflite_int8/imx500_int8_tp_model.py +++ b/tests/keras_tests/exporter_tests/tflite_int8/imx500_int8_tp_model.py @@ -66,44 +66,44 @@ def generate_tp_model(default_config: OpQuantizationConfig, base_config: OpQuantizationConfig, mixed_precision_cfg_list: List[OpQuantizationConfig], name: str) -> TargetPlatformModel: - default_configuration_options = schema.QuantizationConfigOptions(tuple( + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple( [default_config])) - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) operator_set, fusing_patterns = [], [] - operator_set.append(schema.OperatorsSet("NoQuantization", - default_configuration_options - .clone_and_edit(enable_activation_quantization=False) - .clone_and_edit_weight_attribute(enable_weights_quantization=False))) + operator_set.append(schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options + .clone_and_edit(enable_activation_quantization=False) + .clone_and_edit_weight_attribute(enable_weights_quantization=False))) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - sub = schema.OperatorsSet("Sub") - mul = schema.OperatorsSet("Mul") - div = schema.OperatorsSet("Div") - prelu = schema.OperatorsSet("PReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + sub = schema.OperatorsSet(name="Sub") + mul = schema.OperatorsSet(name="Mul") + div = schema.OperatorsSet(name="Div") + prelu = schema.OperatorsSet(name="PReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set.extend([conv, fc, any_relu, add, sub, mul, div, prelu, swish, sigmoid, tanh]) - activations_after_conv_to_fuse = schema.OperatorSetConcat((any_relu, swish, prelu, sigmoid, tanh)) - activations_after_fc_to_fuse = schema.OperatorSetConcat((any_relu, swish, sigmoid)) - any_binary = schema.OperatorSetConcat((add, sub, mul, div)) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=(any_relu, swish, prelu, sigmoid, tanh)) + activations_after_fc_to_fuse = schema.OperatorSetConcat(operators_set=(any_relu, swish, sigmoid)) + any_binary = schema.OperatorSetConcat(operators_set=(add, sub, mul, div)) - fusing_patterns.append(schema.Fusing((conv, activations_after_conv_to_fuse))) - fusing_patterns.append(schema.Fusing((fc, activations_after_fc_to_fuse))) - fusing_patterns.append(schema.Fusing((any_binary, any_relu))) + fusing_patterns.append(schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(fc, activations_after_fc_to_fuse))) + fusing_patterns.append(schema.Fusing(operator_groups=(any_binary, any_relu))) generated_tpc = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/activation_16bit_test.py b/tests/keras_tests/feature_networks_tests/feature_networks/activation_16bit_test.py index a43453d88..9db95aa7f 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/activation_16bit_test.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/activation_16bit_test.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - import numpy as np import tensorflow as tf @@ -39,7 +37,9 @@ def get_tpc(self): # Force Mul base_config to 16bit only mul_op_set = get_op_set('Mul', tpc.tp_model.operator_set) base_config = [l for l in mul_op_set.qc_options.quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[tf.multiply] = replace(tpc.layer2qco[tf.multiply], base_config=base_config) + tpc.layer2qco[tf.multiply] = tpc.layer2qco[tf.multiply].copy(update= + {'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) return tpc def create_networks(self): @@ -76,7 +76,8 @@ def get_tpc(self): quantization_configurations.extend([ tpc.layer2qco[tf.multiply].base_config.clone_and_edit(activation_n_bits=4), tpc.layer2qco[tf.multiply].base_config.clone_and_edit(activation_n_bits=2)]) - tpc.layer2qco[tf.multiply] = replace(tpc.layer2qco[tf.multiply], base_config=base_config, quantization_configurations=tuple(quantization_configurations)) + tpc.layer2qco[tf.multiply] = tpc.layer2qco[tf.multiply].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) return tpc def get_resource_utilization(self): diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/bn_attributes_quantization_test.py b/tests/keras_tests/feature_networks_tests/feature_networks/bn_attributes_quantization_test.py index 56de10dab..c15ddb199 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/bn_attributes_quantization_test.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/bn_attributes_quantization_test.py @@ -77,17 +77,17 @@ def _generate_bn_quantized_tpm(quantize_linear): simd_size=32, signedness=Signedness.AUTO) - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_op_qc])) - linear_configuration_options = schema.QuantizationConfigOptions(tuple([linear_op_qc])) - bn_configuration_options = schema.QuantizationConfigOptions(tuple([bn_op_qc])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_op_qc])) + linear_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([linear_op_qc])) + bn_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([bn_op_qc])) generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Conv", linear_configuration_options), - schema.OperatorsSet("BN", bn_configuration_options)]), + operator_set=tuple([schema.OperatorsSet(name="Conv", qc_options=linear_configuration_options), + schema.OperatorsSet(name="BN", qc_options=bn_configuration_options)]), add_metadata=False, name='bn_quantized_tpm') return generated_tpm diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/const_quantization_test.py b/tests/keras_tests/feature_networks_tests/feature_networks/const_quantization_test.py index 34dc569da..1e87d6fe5 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/const_quantization_test.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/const_quantization_test.py @@ -49,11 +49,11 @@ def create_const_quant_tpc(qmethod): default_weight_attr_config=default_cfg.default_weight_attr_config.clone_and_edit( enable_weights_quantization=True, weights_per_channel_threshold=True, weights_n_bits=16, weights_quantization_method=qmethod)) - const_configuration_options = schema.QuantizationConfigOptions(tuple([const_config])) + const_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config])) const_merge_config = default_cfg.clone_and_edit( default_weight_attr_config=default_cfg.default_weight_attr_config.clone_and_edit( weights_per_channel_threshold=False)) - const_merge_configuration_options = schema.QuantizationConfigOptions(tuple([const_merge_config])) + const_merge_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_merge_config])) operator_sets_dict = {} operator_sets_dict["Add"] = const_configuration_options diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/manual_bit_selection.py b/tests/keras_tests/feature_networks_tests/feature_networks/manual_bit_selection.py index e609275b4..a1ef4f410 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/manual_bit_selection.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/manual_bit_selection.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - import numpy as np import tensorflow as tf @@ -136,7 +134,9 @@ def get_tpc(self): # Force Mul base_config to 16bit only mul_op_set = get_op_set('Mul', tpc.tp_model.operator_set) base_config = [l for l in mul_op_set.qc_options.quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[tf.multiply] = replace(tpc.layer2qco[tf.multiply], base_config=base_config) + tpc.layer2qco[tf.multiply] = tpc.layer2qco[tf.multiply].copy( + update={'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) return tpc def create_networks(self): @@ -165,8 +165,8 @@ def get_tpc(self): quantization_configurations.extend([ tpc.layer2qco[tf.multiply].base_config.clone_and_edit(activation_n_bits=4), tpc.layer2qco[tf.multiply].base_config.clone_and_edit(activation_n_bits=2)]) - tpc.layer2qco[tf.multiply] = replace(tpc.layer2qco[tf.multiply], base_config=base_config, - quantization_configurations=tuple(quantization_configurations)) + tpc.layer2qco[tf.multiply] = tpc.layer2qco[tf.multiply].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) return tpc def get_resource_utilization(self): diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/mixed_precision_tests.py b/tests/keras_tests/feature_networks_tests/feature_networks/mixed_precision_tests.py index e8beae097..209a76653 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/mixed_precision_tests.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/mixed_precision_tests.py @@ -643,23 +643,23 @@ def get_tpc(self): [c.clone_and_edit(enable_activation_quantization=False) for c in mixed_precision_cfg_list] cfg = mixed_precision_cfg_list[0] - act_mixed_cfg = schema.QuantizationConfigOptions(tuple( + act_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( [act_eight_bit_cfg, act_four_bit_cfg, act_two_bit_cfg]), base_config=act_eight_bit_cfg, ) - weight_mixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) tp_model = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([cfg]), cfg), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([cfg]), base_config=cfg), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Activations", act_mixed_cfg), - schema.OperatorsSet("Weights", weight_mixed_cfg)]), + operator_set=tuple([schema.OperatorsSet(name="Activations", qc_options=act_mixed_cfg), + schema.OperatorsSet(name="Weights", qc_options=weight_mixed_cfg)]), add_metadata=False, name="mp_activation_conf_weights_test") diff --git a/tests/keras_tests/feature_networks_tests/feature_networks/weights_mixed_precision_tests.py b/tests/keras_tests/feature_networks_tests/feature_networks/weights_mixed_precision_tests.py index 45413118f..3a13d12b3 100644 --- a/tests/keras_tests/feature_networks_tests/feature_networks/weights_mixed_precision_tests.py +++ b/tests/keras_tests/feature_networks_tests/feature_networks/weights_mixed_precision_tests.py @@ -178,23 +178,23 @@ def get_tpc(self): two_bit_cfg = mixed_precision_cfg_list[2] - weight_mixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) - weight_fixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_fixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( [two_bit_cfg]), base_config=two_bit_cfg, ) tp_model = schema.TargetPlatformModel( - weight_fixed_cfg, + default_qco=weight_fixed_cfg, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Weights_mp", weight_mixed_cfg), - schema.OperatorsSet("Weights_fixed", weight_fixed_cfg)]), + operator_set=tuple([schema.OperatorsSet(name="Weights_mp", qc_options=weight_mixed_cfg), + schema.OperatorsSet(name="Weights_fixed", qc_options=weight_fixed_cfg)]), add_metadata=False, name="mp_part_weights_layers_test") @@ -511,23 +511,23 @@ def get_tpc(self): [c.clone_and_edit(enable_activation_quantization=False) for c in mixed_precision_cfg_list] cfg = mixed_precision_cfg_list[0] - act_mixed_cfg = schema.QuantizationConfigOptions(tuple( + act_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( [act_eight_bit_cfg, act_four_bit_cfg, act_two_bit_cfg]), base_config=act_eight_bit_cfg, ) - weight_mixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) tp_model = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([cfg]), cfg), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([cfg]), base_config=cfg), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Activations", act_mixed_cfg), - schema.OperatorsSet("Weights", weight_mixed_cfg)]), + operator_set=tuple([schema.OperatorsSet(name="Activations", qc_options=act_mixed_cfg), + schema.OperatorsSet(name="Weights", qc_options=weight_mixed_cfg)]), add_metadata=False, name="mp_weights_conf_act_test") diff --git a/tests/keras_tests/function_tests/test_custom_layer.py b/tests/keras_tests/function_tests/test_custom_layer.py index d01642b20..f31101b92 100644 --- a/tests/keras_tests/function_tests/test_custom_layer.py +++ b/tests/keras_tests/function_tests/test_custom_layer.py @@ -76,12 +76,13 @@ def get_tpc(): simd_size=32, signedness=Signedness.AUTO) - default_configuration_options = schema.QuantizationConfigOptions(tuple([base_cfg])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([base_cfg])) - operator_set = [schema.OperatorsSet("NoQuantization", - default_configuration_options.clone_and_edit(enable_activation_quantization=False) - .clone_and_edit_weight_attribute(enable_weights_quantization=False))] - tp_model = schema.TargetPlatformModel(default_configuration_options, + operator_set = [schema.OperatorsSet(name="NoQuantization", + qc_options=default_configuration_options.clone_and_edit( + enable_activation_quantization=False) + .clone_and_edit_weight_attribute(enable_weights_quantization=False))] + tp_model = schema.TargetPlatformModel(default_qco=default_configuration_options, operator_set=tuple(operator_set), tpc_minor_version=None, tpc_patch_version=None, diff --git a/tests/keras_tests/function_tests/test_hmse_error_method.py b/tests/keras_tests/function_tests/test_hmse_error_method.py index 8a0cf0673..82d895d8a 100644 --- a/tests/keras_tests/function_tests/test_hmse_error_method.py +++ b/tests/keras_tests/function_tests/test_hmse_error_method.py @@ -171,19 +171,19 @@ def test_threshold_selection_hmse_no_gptq(self): def test_threshold_selection_hmse_no_kernel_attr(self): def _generate_bn_quantization_tpc(quant_method, per_channel): cfg, _, _ = get_op_quantization_configs() - conv_qco = schema.QuantizationConfigOptions(tuple([cfg]), base_config=cfg) + conv_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([cfg]), base_config=cfg) # enable BN attributes quantization using the bn_qco = conv_qco.clone_and_edit(attr_weights_configs_mapping= {GAMMA: AttributeQuantizationConfig(weights_n_bits=8, enable_weights_quantization=True)}) - tp_model = schema.TargetPlatformModel(conv_qco, + tp_model = schema.TargetPlatformModel(default_qco=conv_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Linear", conv_qco), - schema.OperatorsSet("BN", bn_qco)]), + operator_set=tuple([schema.OperatorsSet(name="Linear", qc_options=conv_qco), + schema.OperatorsSet(name="BN", qc_options=bn_qco)]), add_metadata=False) tpc = tp.TargetPlatformCapabilities(tp_model) diff --git a/tests/keras_tests/function_tests/test_layer_fusing.py b/tests/keras_tests/function_tests/test_layer_fusing.py index 0cde794b9..1a2713a08 100644 --- a/tests/keras_tests/function_tests/test_layer_fusing.py +++ b/tests/keras_tests/function_tests/test_layer_fusing.py @@ -81,10 +81,10 @@ def create_network_4(input_shape): def generate_base_tpc(operator_set, fusing_patterns): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - default_configuration_options = schema.QuantizationConfigOptions(tuple( + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple( [default_config])) generated_tp = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -97,13 +97,13 @@ def generate_base_tpc(operator_set, fusing_patterns): def get_tpc_1(): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") operator_set = [conv, any_relu] # Define fusions - fusing_patterns = [schema.Fusing((conv, any_relu))] + fusing_patterns = [schema.Fusing(operator_groups=(conv, any_relu))] generated_tp = generate_base_tpc(operator_set, fusing_patterns) @@ -118,17 +118,17 @@ def get_tpc_1(): def get_tpc_2(): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") - swish = schema.OperatorsSet("Swish") - sigmoid = schema.OperatorsSet("Sigmoid") - tanh = schema.OperatorsSet("Tanh") + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") + swish = schema.OperatorsSet(name="Swish") + sigmoid = schema.OperatorsSet(name="Sigmoid") + tanh = schema.OperatorsSet(name="Tanh") operator_set = [conv, any_relu, swish, sigmoid, tanh] - activations_after_conv_to_fuse = schema.OperatorSetConcat([any_relu, swish, sigmoid, tanh]) + activations_after_conv_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish, sigmoid, tanh]) # Define fusions - fusing_patterns = [schema.Fusing((conv, activations_after_conv_to_fuse))] + fusing_patterns = [schema.Fusing(operator_groups=(conv, activations_after_conv_to_fuse))] generated_tp = generate_base_tpc(operator_set, fusing_patterns) @@ -146,13 +146,13 @@ def get_tpc_2(): def get_tpc_3(): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") operator_set = [conv, any_relu] # Define fusions - fusing_patterns = [schema.Fusing((conv, any_relu))] + fusing_patterns = [schema.Fusing(operator_groups=(conv, any_relu))] generated_tp = generate_base_tpc(operator_set, fusing_patterns) @@ -167,20 +167,20 @@ def get_tpc_3(): def get_tpc_4(): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - swish = schema.OperatorsSet("Swish") - activations_to_fuse = schema.OperatorSetConcat([any_relu, swish]) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + swish = schema.OperatorsSet(name="Swish") + activations_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish]) operator_set = [conv, fc, any_relu, add, swish] # Define fusions - fusing_patterns = [schema.Fusing((conv, activations_to_fuse)), - schema.Fusing((conv, add, activations_to_fuse)), - schema.Fusing((conv, activations_to_fuse, add)), - schema.Fusing((fc, activations_to_fuse))] + fusing_patterns = [schema.Fusing(operator_groups=(conv, activations_to_fuse)), + schema.Fusing(operator_groups=(conv, add, activations_to_fuse)), + schema.Fusing(operator_groups=(conv, activations_to_fuse, add)), + schema.Fusing(operator_groups=(fc, activations_to_fuse))] generated_tp = generate_base_tpc(operator_set, fusing_patterns) diff --git a/tests/keras_tests/function_tests/test_quant_config_filtering.py b/tests/keras_tests/function_tests/test_quant_config_filtering.py index b711b06b2..9a85527d3 100644 --- a/tests/keras_tests/function_tests/test_quant_config_filtering.py +++ b/tests/keras_tests/function_tests/test_quant_config_filtering.py @@ -12,18 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - import unittest -import numpy as np import model_compression_toolkit as mct -import model_compression_toolkit.core.common.quantization.quantization_config as qc from model_compression_toolkit.constants import THRESHOLD, TENSORFLOW from model_compression_toolkit.target_platform_capabilities.constants import IMX500_TP_MODEL -from model_compression_toolkit.core.common.quantization.quantization_params_generation.error_functions import _mse_error_histogram -from model_compression_toolkit.core.common.collectors.histogram_collector import HistogramCollector -from model_compression_toolkit.core.common.quantization.quantization_params_generation.power_of_two_selection import power_of_two_selection_tensor -from model_compression_toolkit.core.common.graph import BaseNode from model_compression_toolkit.core.common.graph.functional_node import FunctionalNode from model_compression_toolkit.core.keras.constants import FUNCTION @@ -45,7 +37,9 @@ def get_tpc_default_16bit(): # Force Mul base_config to 16bit only mul_op_set = get_op_set('Mul', tpc.tp_model.operator_set) base_config = [l for l in mul_op_set.qc_options.quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[tf.multiply] = replace(tpc.layer2qco[tf.multiply], base_config=base_config) + tpc.layer2qco[tf.multiply] = tpc.layer2qco[tf.multiply].copy( + update={'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) return tpc def test_config_filtering(self): diff --git a/tests/keras_tests/non_parallel_tests/test_keras_tp_model.py b/tests/keras_tests/non_parallel_tests/test_keras_tp_model.py index a018bdd80..23a57c13a 100644 --- a/tests/keras_tests/non_parallel_tests/test_keras_tp_model.py +++ b/tests/keras_tests/non_parallel_tests/test_keras_tp_model.py @@ -49,7 +49,7 @@ tp = mct.target_platform TEST_QC = generate_test_op_qc(**generate_test_attr_configs()) -TEST_QCO = schema.QuantizationConfigOptions(tuple([TEST_QC])) +TEST_QCO = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) def get_node(layer) -> BaseNode: @@ -104,10 +104,10 @@ def test_keras_layers_with_params(self): self.assertFalse(get_node(conv).is_match_filter_params(conv_filter_contains)) def test_get_layers_by_op(self): - op_obj = schema.OperatorsSet('opsetA') + op_obj = schema.OperatorsSet(name='opsetA') hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -122,11 +122,11 @@ def test_get_layers_by_op(self): self.assertEqual(fw_tp.get_layers_by_opset_name('nonExistingOpsetName'), None) def test_get_layers_by_opconcat(self): - op_obj_a = schema.OperatorsSet('opsetA') - op_obj_b = schema.OperatorsSet('opsetB') - op_concat = schema.OperatorSetConcat([op_obj_a, op_obj_b]) + op_obj_a = schema.OperatorsSet(name='opsetA') + op_obj_b = schema.OperatorsSet(name='opsetB') + op_concat = schema.OperatorSetConcat(operators_set=[op_obj_a, op_obj_b]) hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -144,12 +144,12 @@ def test_get_layers_by_opconcat(self): def test_layer_attached_to_multiple_opsets(self): hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet('opsetA'), - schema.OperatorsSet('opsetB')]), + operator_set=tuple([schema.OperatorsSet(name='opsetA'), + schema.OperatorsSet(name='opsetB')]), add_metadata=False) @@ -162,12 +162,12 @@ def test_layer_attached_to_multiple_opsets(self): def test_filter_layer_attached_to_multiple_opsets(self): hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet('opsetA'), - schema.OperatorsSet('opsetB')]), + operator_set=tuple([schema.OperatorsSet(name='opsetA'), + schema.OperatorsSet(name='opsetB')]), add_metadata=False) fw_tp = TargetPlatformCapabilities(hm) with self.assertRaises(Exception) as e: @@ -178,7 +178,7 @@ def test_filter_layer_attached_to_multiple_opsets(self): def test_qco_by_keras_layer(self): operator_set = [] - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) default_qco = default_qco.clone_and_edit(attr_weights_configs_mapping={}) mixed_precision_configuration_options = schema.QuantizationConfigOptions( quantization_configurations=tuple([TEST_QC, @@ -186,13 +186,13 @@ def test_qco_by_keras_layer(self): TEST_QC.clone_and_edit(attr_to_edit={KERNEL_ATTR: {WEIGHTS_N_BITS: 2}})]), base_config=TEST_QC) - operator_set.append(schema.OperatorsSet("conv", mixed_precision_configuration_options)) + operator_set.append(schema.OperatorsSet(name="conv", qc_options=mixed_precision_configuration_options)) sevenbit_qco = TEST_QCO.clone_and_edit(activation_n_bits=7, attr_weights_configs_mapping={}) - operator_set.append(schema.OperatorsSet("tanh", sevenbit_qco)) - operator_set.append(schema.OperatorsSet("relu")) + operator_set.append(schema.OperatorsSet(name="tanh", qc_options=sevenbit_qco)) + operator_set.append(schema.OperatorsSet(name="relu")) - tpm = schema.TargetPlatformModel(default_qco, + tpm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -226,12 +226,12 @@ def test_qco_by_keras_layer(self): self.assertEqual(relu_qco, default_qco) def test_opset_not_in_tp(self): - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) - hm = schema.TargetPlatformModel(default_qco, + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) + hm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("opA")]), + operator_set=tuple([schema.OperatorsSet(name="opA")]), add_metadata=False) hm_keras = tp.TargetPlatformCapabilities(hm) with self.assertRaises(Exception) as e: @@ -242,15 +242,15 @@ def test_opset_not_in_tp(self): str(e.exception)) def test_keras_fusing_patterns(self): - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) - a = schema.OperatorsSet("opA") - b = schema.OperatorsSet("opB") - c = schema.OperatorsSet("opC") + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) + a = schema.OperatorsSet(name="opA") + b = schema.OperatorsSet(name="opB") + c = schema.OperatorsSet(name="opC") operator_set = [a, b, c] - fusing_patterns = [schema.Fusing((a, b, c)), - schema.Fusing((a, c))] + fusing_patterns = [schema.Fusing(operator_groups=(a, b, c)), + schema.Fusing(operator_groups=(a, c))] - hm = schema.TargetPlatformModel(default_qco, + hm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -278,12 +278,12 @@ def test_keras_fusing_patterns(self): self.assertEqual(p1[1], LayerFilterParams(ReLU, Greater("max_value", 7), negative_slope=0)) def test_get_default_op_qc(self): - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) - tpm = schema.TargetPlatformModel(default_qco, + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) + tpm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("opA")]), + operator_set=tuple([schema.OperatorsSet(name="opA")]), add_metadata=False) tpc = tp.TargetPlatformCapabilities(tpm) diff --git a/tests/pytorch_tests/function_tests/layer_fusing_test.py b/tests/pytorch_tests/function_tests/layer_fusing_test.py index a83144819..390373f8d 100644 --- a/tests/pytorch_tests/function_tests/layer_fusing_test.py +++ b/tests/pytorch_tests/function_tests/layer_fusing_test.py @@ -63,15 +63,15 @@ def __init__(self, unit_test): def get_tpc(self): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") operator_set = [conv, any_relu] # Define fusions - fusing_patterns = [schema.Fusing((conv, any_relu))] - generated_tp = schema.TargetPlatformModel(default_configuration_options, + fusing_patterns = [schema.Fusing(operator_groups=(conv, any_relu))] + generated_tp = schema.TargetPlatformModel(default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -116,15 +116,15 @@ def __init__(self, unit_test): def get_tpc(self): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_act = schema.OperatorsSet("AnyAct") + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_act = schema.OperatorsSet(name="AnyAct") operator_set = [conv, any_act] # Define fusions - fusing_patterns = [schema.Fusing((conv, any_act))] - generated_tp = schema.TargetPlatformModel(default_configuration_options, + fusing_patterns = [schema.Fusing(operator_groups=(conv, any_act))] + generated_tp = schema.TargetPlatformModel(default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -179,15 +179,15 @@ def __init__(self, unit_test): def get_tpc(self): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - any_act = schema.OperatorsSet("AnyAct") + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + any_act = schema.OperatorsSet(name="AnyAct") operator_set = [conv, any_act] # Define fusions - fusing_patterns = [schema.Fusing((conv, any_act))] - generated_tp = schema.TargetPlatformModel(default_configuration_options, + fusing_patterns = [schema.Fusing(operator_groups=(conv, any_act))] + generated_tp = schema.TargetPlatformModel(default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -241,23 +241,23 @@ def __init__(self, unit_test): def get_tpc(self): base_config, mixed_precision_cfg_list, default_config = get_op_quantization_configs() - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple(mixed_precision_cfg_list), + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple(mixed_precision_cfg_list), base_config=base_config) - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_config])) - conv = schema.OperatorsSet("Conv", mixed_precision_configuration_options) - fc = schema.OperatorsSet("FullyConnected", mixed_precision_configuration_options) - any_relu = schema.OperatorsSet("AnyReLU") - add = schema.OperatorsSet("Add") - swish = schema.OperatorsSet("Swish") + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_config])) + conv = schema.OperatorsSet(name="Conv", qc_options=mixed_precision_configuration_options) + fc = schema.OperatorsSet(name="FullyConnected", qc_options=mixed_precision_configuration_options) + any_relu = schema.OperatorsSet(name="AnyReLU") + add = schema.OperatorsSet(name="Add") + swish = schema.OperatorsSet(name="Swish") operator_set = [conv, fc, any_relu, add, swish] - activations_to_fuse = schema.OperatorSetConcat([any_relu, swish]) + activations_to_fuse = schema.OperatorSetConcat(operators_set=[any_relu, swish]) # Define fusions - fusing_patterns = [schema.Fusing((conv, activations_to_fuse)), - schema.Fusing((conv, add, activations_to_fuse)), - schema.Fusing((conv, activations_to_fuse, add)), - schema.Fusing((fc, activations_to_fuse))] + fusing_patterns = [schema.Fusing(operator_groups=(conv, activations_to_fuse)), + schema.Fusing(operator_groups=(conv, add, activations_to_fuse)), + schema.Fusing(operator_groups=(conv, activations_to_fuse, add)), + schema.Fusing(operator_groups=(fc, activations_to_fuse))] - generated_tp = schema.TargetPlatformModel(default_configuration_options, + generated_tp = schema.TargetPlatformModel(default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, diff --git a/tests/pytorch_tests/function_tests/test_pytorch_tp_model.py b/tests/pytorch_tests/function_tests/test_pytorch_tp_model.py index 26dd513f5..fb693e9d4 100644 --- a/tests/pytorch_tests/function_tests/test_pytorch_tp_model.py +++ b/tests/pytorch_tests/function_tests/test_pytorch_tp_model.py @@ -42,7 +42,7 @@ tp = mct.target_platform TEST_QC = generate_test_op_qc(**generate_test_attr_configs()) -TEST_QCO = schema.QuantizationConfigOptions(tuple([TEST_QC])) +TEST_QCO = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) class TestPytorchTPModel(unittest.TestCase): @@ -84,28 +84,28 @@ def test_pytorch_layers_with_params(self): get_node(partial(torch.nn.functional.normalize, p=3.0)).is_match_filter_params(l2norm_tflite_opset)) def test_qco_by_pytorch_layer(self): - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) default_qco = default_qco.clone_and_edit(attr_weights_configs_mapping={}) - mixed_precision_configuration_options = schema.QuantizationConfigOptions(tuple( + mixed_precision_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple( [TEST_QC, TEST_QC.clone_and_edit(attr_to_edit={KERNEL_ATTR: {WEIGHTS_N_BITS: 4}}), TEST_QC.clone_and_edit(attr_to_edit={KERNEL_ATTR: {WEIGHTS_N_BITS: 2}})]), base_config=TEST_QC) operator_set = [] - operator_set.append(schema.OperatorsSet("conv", mixed_precision_configuration_options)) + operator_set.append(schema.OperatorsSet(name="conv", qc_options=mixed_precision_configuration_options)) sevenbit_qco = TEST_QCO.clone_and_edit(activation_n_bits=7, attr_weights_configs_mapping={}) - operator_set.append(schema.OperatorsSet("tanh", sevenbit_qco)) + operator_set.append(schema.OperatorsSet(name="tanh", qc_options=sevenbit_qco)) sixbit_qco = TEST_QCO.clone_and_edit(activation_n_bits=6, attr_weights_configs_mapping={}) - operator_set.append(schema.OperatorsSet("avg_pool2d_kernel_2", sixbit_qco)) + operator_set.append(schema.OperatorsSet(name="avg_pool2d_kernel_2", qc_options=sixbit_qco)) - operator_set.append(schema.OperatorsSet("avg_pool2d")) + operator_set.append(schema.OperatorsSet(name="avg_pool2d")) - tpm = schema.TargetPlatformModel(default_qco, + tpm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -145,10 +145,10 @@ def test_qco_by_pytorch_layer(self): self.assertEqual(avg_pool2d_qco, default_qco) def test_get_layers_by_op(self): - op_obj = schema.OperatorsSet('opsetA') + op_obj = schema.OperatorsSet(name='opsetA') hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -163,12 +163,12 @@ def test_get_layers_by_op(self): self.assertEqual(fw_tp.get_layers_by_opset(op_obj), opset_layers) def test_get_layers_by_opconcat(self): - op_obj_a = schema.OperatorsSet('opsetA') - op_obj_b = schema.OperatorsSet('opsetB') - op_concat = schema.OperatorSetConcat([op_obj_a, op_obj_b]) + op_obj_a = schema.OperatorsSet(name='opsetA') + op_obj_b = schema.OperatorsSet(name='opsetB') + op_concat = schema.OperatorSetConcat(operators_set=[op_obj_a, op_obj_b]) hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, @@ -186,13 +186,13 @@ def test_get_layers_by_opconcat(self): def test_layer_attached_to_multiple_opsets(self): hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, operator_set=tuple([ - schema.OperatorsSet('opsetA'), - schema.OperatorsSet('opsetB')]), + schema.OperatorsSet(name='opsetA'), + schema.OperatorsSet(name='opsetB')]), add_metadata=False) fw_tp = TargetPlatformCapabilities(hm) @@ -204,12 +204,12 @@ def test_layer_attached_to_multiple_opsets(self): def test_filter_layer_attached_to_multiple_opsets(self): hm = schema.TargetPlatformModel( - schema.QuantizationConfigOptions(tuple([TEST_QC])), + default_qco=schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])), tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet('opsetA'), - schema.OperatorsSet('opsetB')]), + operator_set=tuple([schema.OperatorsSet(name='opsetA'), + schema.OperatorsSet(name='opsetB')]), add_metadata=False) fw_tp = TargetPlatformCapabilities(hm) @@ -220,12 +220,12 @@ def test_filter_layer_attached_to_multiple_opsets(self): self.assertEqual('Found layer Softmax(dim=2) in more than one OperatorsSet', str(e.exception)) def test_opset_not_in_tp(self): - default_qco = schema.QuantizationConfigOptions(tuple([TEST_QC])) - hm = schema.TargetPlatformModel(default_qco, + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple([TEST_QC])) + hm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("opA")]), + operator_set=tuple([schema.OperatorsSet(name="opA")]), add_metadata=False) hm_pytorch = tp.TargetPlatformCapabilities(hm) with self.assertRaises(Exception) as e: @@ -236,15 +236,15 @@ def test_opset_not_in_tp(self): str(e.exception)) def test_pytorch_fusing_patterns(self): - default_qco = schema.QuantizationConfigOptions(tuple( + default_qco = schema.QuantizationConfigOptions(quantization_configurations=tuple( [TEST_QC])) - a = schema.OperatorsSet("opA") - b = schema.OperatorsSet("opB") - c = schema.OperatorsSet("opC") + a = schema.OperatorsSet(name="opA") + b = schema.OperatorsSet(name="opB") + c = schema.OperatorsSet(name="opC") operator_set = [a, b, c] - fusing_patterns = [schema.Fusing((a, b, c)), - schema.Fusing((a, c))] - hm = schema.TargetPlatformModel(default_qco, + fusing_patterns = [schema.Fusing(operator_groups=(a, b, c)), + schema.Fusing(operator_groups=(a, c))] + hm = schema.TargetPlatformModel(default_qco=default_qco, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, diff --git a/tests/pytorch_tests/function_tests/test_quant_config_filtering.py b/tests/pytorch_tests/function_tests/test_quant_config_filtering.py index 1f398c785..fc344f38f 100644 --- a/tests/pytorch_tests/function_tests/test_quant_config_filtering.py +++ b/tests/pytorch_tests/function_tests/test_quant_config_filtering.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - import unittest import model_compression_toolkit as mct from model_compression_toolkit.constants import PYTORCH @@ -35,7 +33,9 @@ def get_tpc_default_16bit(): # Force Mul base_config to 16bit only mul_op_set = get_op_set('Mul', tpc.tp_model.operator_set) base_config = [l for l in mul_op_set.qc_options.quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[torch.multiply] = replace(tpc.layer2qco[torch.multiply], base_config=base_config) + tpc.layer2qco[torch.multiply] = tpc.layer2qco[torch.multiply].copy( + update={'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) return tpc def test_config_filtering(self): diff --git a/tests/pytorch_tests/model_tests/feature_models/activation_16bit_test.py b/tests/pytorch_tests/model_tests/feature_models/activation_16bit_test.py index ce6cb345a..44eec1fc3 100644 --- a/tests/pytorch_tests/model_tests/feature_models/activation_16bit_test.py +++ b/tests/pytorch_tests/model_tests/feature_models/activation_16bit_test.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - from operator import mul import torch @@ -86,7 +84,9 @@ def forward(self, x): def set_16bit_as_default(tpc, required_op_set, required_ops_list): for op in required_ops_list: base_config = [l for l in tpc.layer2qco[op].quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[op] = replace(tpc.layer2qco[op], base_config=base_config) + tpc.layer2qco[op] = tpc.layer2qco[op].copy( + update={'quantization_configurations': tpc.layer2qco[op].quantization_configurations, + 'base_config': base_config}) class Activation16BitTest(BasePytorchFeatureNetworkTest): @@ -131,8 +131,10 @@ def get_tpc(self): quantization_configurations.extend([ tpc.layer2qco[torch.mul].base_config.clone_and_edit(activation_n_bits=4), tpc.layer2qco[torch.mul].base_config.clone_and_edit(activation_n_bits=2)]) - tpc.layer2qco[torch.mul] = replace(tpc.layer2qco[torch.mul], base_config=base_config, quantization_configurations=tuple(quantization_configurations)) - tpc.layer2qco[mul] = replace(tpc.layer2qco[mul], base_config=base_config, quantization_configurations=tuple(quantization_configurations)) + tpc.layer2qco[torch.mul] = tpc.layer2qco[torch.mul].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) + tpc.layer2qco[mul] = tpc.layer2qco[mul].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) return tpc def get_resource_utilization(self): diff --git a/tests/pytorch_tests/model_tests/feature_models/bn_attributes_quantization_test.py b/tests/pytorch_tests/model_tests/feature_models/bn_attributes_quantization_test.py index 88ab07933..111643ea6 100644 --- a/tests/pytorch_tests/model_tests/feature_models/bn_attributes_quantization_test.py +++ b/tests/pytorch_tests/model_tests/feature_models/bn_attributes_quantization_test.py @@ -76,17 +76,17 @@ def _generate_bn_quantized_tpm(quantize_linear): simd_size=32, signedness=Signedness.AUTO) - default_configuration_options = schema.QuantizationConfigOptions(tuple([default_op_qc])) - linear_configuration_options = schema.QuantizationConfigOptions(tuple([linear_op_qc])) - bn_configuration_options = schema.QuantizationConfigOptions(tuple([bn_op_qc])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([default_op_qc])) + linear_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([linear_op_qc])) + bn_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([bn_op_qc])) generated_tpm = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Conv", linear_configuration_options), - schema.OperatorsSet("BN", bn_configuration_options)]), + operator_set=tuple([schema.OperatorsSet(name="Conv", qc_options=linear_configuration_options), + schema.OperatorsSet(name="BN", qc_options=bn_configuration_options)]), add_metadata=False, name='bn_quantized_tpm') return generated_tpm diff --git a/tests/pytorch_tests/model_tests/feature_models/const_quantization_test.py b/tests/pytorch_tests/model_tests/feature_models/const_quantization_test.py index 7fd484a0c..13c7fb878 100644 --- a/tests/pytorch_tests/model_tests/feature_models/const_quantization_test.py +++ b/tests/pytorch_tests/model_tests/feature_models/const_quantization_test.py @@ -240,21 +240,21 @@ def get_tpc(self): simd_size=32, signedness=Signedness.AUTO) - default_configuration_options = schema.QuantizationConfigOptions(tuple([base_cfg])) + default_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([base_cfg])) const_config = base_cfg.clone_and_edit(enable_activation_quantization=False, default_weight_attr_config=base_cfg.default_weight_attr_config.clone_and_edit( enable_weights_quantization=True, weights_per_channel_threshold=False, weights_quantization_method=tp.QuantizationMethod.POWER_OF_TWO)) - const_configuration_options = schema.QuantizationConfigOptions(tuple([const_config])) + const_configuration_options = schema.QuantizationConfigOptions(quantization_configurations=tuple([const_config])) tp_model = schema.TargetPlatformModel( - default_configuration_options, + default_qco=default_configuration_options, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("WeightQuant", const_configuration_options)]), + operator_set=tuple([schema.OperatorsSet(name="WeightQuant", qc_options=const_configuration_options)]), add_metadata=False) tpc = tp.TargetPlatformCapabilities(tp_model) diff --git a/tests/pytorch_tests/model_tests/feature_models/manual_bit_selection.py b/tests/pytorch_tests/model_tests/feature_models/manual_bit_selection.py index a9752e142..57f83f80f 100644 --- a/tests/pytorch_tests/model_tests/feature_models/manual_bit_selection.py +++ b/tests/pytorch_tests/model_tests/feature_models/manual_bit_selection.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -from dataclasses import replace - from operator import mul import inspect @@ -190,8 +188,12 @@ def get_tpc(self): tpc = mct.get_target_platform_capabilities(PYTORCH, IMX500_TP_MODEL, 'v3') mul_op_set = get_op_set('Mul', tpc.tp_model.operator_set) base_config = [l for l in mul_op_set.qc_options.quantization_configurations if l.activation_n_bits == 16][0] - tpc.layer2qco[torch.mul] = replace(tpc.layer2qco[torch.mul], base_config=base_config) - tpc.layer2qco[mul] = replace(tpc.layer2qco[mul] , base_config=base_config) + tpc.layer2qco[torch.mul] = tpc.layer2qco[torch.mul].copy( + update={'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) + tpc.layer2qco[mul] = tpc.layer2qco[mul].copy( + update={'quantization_configurations': mul_op_set.qc_options.quantization_configurations, + 'base_config': base_config}) return {'mixed_precision_activation_model': tpc} def create_feature_network(self, input_shape): @@ -208,10 +210,10 @@ def get_tpc(self): quantization_configurations.extend( [mul_op_set.qc_options.base_config.clone_and_edit(activation_n_bits=4), mul_op_set.qc_options.base_config.clone_and_edit(activation_n_bits=2)]) - tpc.layer2qco[torch.mul] = replace(tpc.layer2qco[torch.mul], base_config=base_config, - quantization_configurations=tuple(quantization_configurations)) - tpc.layer2qco[mul] = replace(tpc.layer2qco[mul], base_config=base_config, - quantization_configurations=tuple(quantization_configurations)) + tpc.layer2qco[torch.mul] = tpc.layer2qco[torch.mul].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) + tpc.layer2qco[mul] = tpc.layer2qco[mul].copy( + update={'base_config': base_config, 'quantization_configurations': tuple(quantization_configurations)}) return {'mixed_precision_activation_model': tpc} def get_resource_utilization(self): diff --git a/tests/pytorch_tests/model_tests/feature_models/mixed_precision_activation_test.py b/tests/pytorch_tests/model_tests/feature_models/mixed_precision_activation_test.py index 8b10ac7e2..1d0576fad 100644 --- a/tests/pytorch_tests/model_tests/feature_models/mixed_precision_activation_test.py +++ b/tests/pytorch_tests/model_tests/feature_models/mixed_precision_activation_test.py @@ -294,25 +294,26 @@ def get_tpc(self): [c.clone_and_edit(enable_activation_quantization=False) for c in mixed_precision_cfg_list] cfg = mixed_precision_cfg_list[0] - act_mixed_cfg = QuantizationConfigOptions(tuple( + act_mixed_cfg = QuantizationConfigOptions(quantization_configurations=tuple( [act_eight_bit_cfg, act_four_bit_cfg, act_two_bit_cfg]), base_config=act_eight_bit_cfg, ) - weight_mixed_cfg = QuantizationConfigOptions(tuple( + weight_mixed_cfg = QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) - tp_model = TargetPlatformModel(QuantizationConfigOptions(tuple([cfg]), cfg), - tpc_minor_version=None, - tpc_patch_version=None, - tpc_platform_type=None, - operator_set=tuple([ - OperatorsSet("Activations", act_mixed_cfg), - OperatorsSet("Weights", weight_mixed_cfg)]), - add_metadata=False, - name="mp_activation_conf_weights_test") + tp_model = TargetPlatformModel( + default_qco=QuantizationConfigOptions(quantization_configurations=tuple([cfg]), base_config=cfg), + tpc_minor_version=None, + tpc_patch_version=None, + tpc_platform_type=None, + operator_set=tuple([ + OperatorsSet(name="Activations", qc_options=act_mixed_cfg), + OperatorsSet(name="Weights", qc_options=weight_mixed_cfg)]), + add_metadata=False, + name="mp_activation_conf_weights_test") torch_tpc = TargetPlatformCapabilities(tp_model) diff --git a/tests/pytorch_tests/model_tests/feature_models/mixed_precision_weights_test.py b/tests/pytorch_tests/model_tests/feature_models/mixed_precision_weights_test.py index 5468cf50e..4560e6614 100644 --- a/tests/pytorch_tests/model_tests/feature_models/mixed_precision_weights_test.py +++ b/tests/pytorch_tests/model_tests/feature_models/mixed_precision_weights_test.py @@ -141,23 +141,23 @@ def get_tpc(self): two_bit_cfg = mixed_precision_cfg_list[2] - weight_mixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_mixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) - weight_fixed_cfg = schema.QuantizationConfigOptions(tuple( + weight_fixed_cfg = schema.QuantizationConfigOptions(quantization_configurations=tuple( [two_bit_cfg]), base_config=two_bit_cfg, ) tp_model = schema.TargetPlatformModel( - weight_fixed_cfg, + default_qco=weight_fixed_cfg, tpc_minor_version=None, tpc_patch_version=None, tpc_platform_type=None, - operator_set=tuple([schema.OperatorsSet("Weights_mp", weight_mixed_cfg), - schema.OperatorsSet("Weights_fixed", weight_fixed_cfg)]), + operator_set=tuple([schema.OperatorsSet(name="Weights_mp", qc_options=weight_mixed_cfg), + schema.OperatorsSet(name="Weights_fixed", qc_options=weight_fixed_cfg)]), name="mp_part_weights_layers_test") @@ -308,24 +308,25 @@ def get_tpc(self): [c.clone_and_edit(enable_activation_quantization=False) for c in mixed_precision_cfg_list] cfg = mixed_precision_cfg_list[0] - act_mixed_cfg = QuantizationConfigOptions(tuple( + act_mixed_cfg = QuantizationConfigOptions(quantization_configurations=tuple( [act_eight_bit_cfg, act_four_bit_cfg, act_two_bit_cfg]), base_config=act_eight_bit_cfg, ) - weight_mixed_cfg = QuantizationConfigOptions(tuple( + weight_mixed_cfg = QuantizationConfigOptions(quantization_configurations=tuple( mixed_precision_cfg_list), base_config=cfg, ) - tp_model = TargetPlatformModel(QuantizationConfigOptions(tuple([cfg]), cfg), - tpc_minor_version=None, - tpc_patch_version=None, - tpc_platform_type=None, - operator_set=tuple([ - OperatorsSet("Activations", act_mixed_cfg), - OperatorsSet("Weights", weight_mixed_cfg)]), - name="mp_weights_conf_act_test") + tp_model = TargetPlatformModel( + default_qco=QuantizationConfigOptions(quantization_configurations=tuple([cfg]), base_config=cfg), + tpc_minor_version=None, + tpc_patch_version=None, + tpc_platform_type=None, + operator_set=tuple([ + OperatorsSet(name="Activations", qc_options=act_mixed_cfg), + OperatorsSet(name="Weights", qc_options=weight_mixed_cfg)]), + name="mp_weights_conf_act_test") torch_tpc = TargetPlatformCapabilities(tp_model)