




import logging
import re

import pytorch_quantization
import pytorch_quantization.nn as quant_nn
import torch
from pytorch_quantization import calib
from pytorch_quantization.tensor_quant import QuantDescriptor


UpperCAmelCase_		:					Union[str, Any]          =  logging.getLogger(__name__)

UpperCAmelCase_		:					Optional[Any]          =  50  # max width of layer names
UpperCAmelCase_		:					Optional[int]          =  70  # max width of quantizer names




def 		lowerCAmelCase_ (						lowerCamelCase ):
				__magic_name__						:						Dict										=parser.add_argument_group("""quant_trainer arguments""" )
				group.add_argument("""--wprec"""						,  type=lowerCamelCase						,  default=8						,  help="""weight precision""" )
				group.add_argument("""--aprec"""						,  type=lowerCamelCase						,  default=8						,  help="""activation precision""" )
				group.add_argument("""--quant-per-tensor"""						,  action="""store_true"""						,  help="""per tensor weight scaling""" )
				group.add_argument("""--quant-disable"""						,  action="""store_true"""						,  help="""disable all quantizers""" )
				group.add_argument("""--quant-disable-embeddings"""						,  action="""store_true"""						,  help="""disable all embeddings quantizers""" )
				group.add_argument("""--quant-disable-keyword"""						,  type=lowerCamelCase						,  nargs="""+"""						,  help="""disable quantizers by keyword""" )
				group.add_argument("""--quant-disable-layer-module"""						,  type=lowerCamelCase						,  help="""disable quantizers by keyword under layer.""" )
				group.add_argument("""--quant-enable-layer-module"""						,  type=lowerCamelCase						,  help="""enable quantizers by keyword under layer""" )
				group.add_argument("""--calibrator"""						,  default="""max"""						,  help="""which quantization range calibrator to use""" )
				group.add_argument("""--percentile"""						,  default=lowerCamelCase						,  type=lowerCamelCase						,  help="""percentile for PercentileCalibrator""" )
				group.add_argument("""--fuse-qkv"""						,  action="""store_true"""						,  help="""use the same scale factor for qkv""" )
				group.add_argument("""--clip-gelu"""						,  metavar="""N"""						,  type=lowerCamelCase						,  help="""clip gelu output maximum value to N""" )
				group.add_argument(
				    """--recalibrate-weights"""						,  action="""store_true"""						,  help=(
				        """recalibrate weight amaxes by taking the max of the weights."""
				        """ amaxes will be computed with the current quantization granularity (axis)."""
				    )						,  )




def 		lowerCAmelCase_ (						lowerCamelCase ):

				if args.calibrator == "max":
								__magic_name__						:						str										="""max"""
				elif args.calibrator == "percentile":
								if args.percentile is None:
												raise ValueError("""Specify --percentile when using percentile calibrator""" )
								__magic_name__						:						str										="""histogram"""
				elif args.calibrator == "mse":
								__magic_name__						:						Dict										="""histogram"""
				else:
								raise ValueError(F"Invalid calibrator {args.calibrator}" )

				__magic_name__						:						Optional[Any]										=QuantDescriptor(num_bits=args.aprec						,  calib_method=lowerCamelCase )
				__magic_name__						:						int										=QuantDescriptor(num_bits=args.wprec						,  axis=(None if args.quant_per_tensor else (0,)) )
				quant_nn.QuantLinear.set_default_quant_desc_input(lowerCamelCase )
				quant_nn.QuantLinear.set_default_quant_desc_weight(lowerCamelCase )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase=False						,  lowerCamelCase=False ):
				logger.info("""Configuring Model for Quantization""" )
				logger.info(F"using quantization package {pytorch_quantization.__file__}" )

				if not calib:
								if args.quant_disable_embeddings:
												set_quantizer_by_name(lowerCamelCase						,  ["""embeddings"""]						,  which="""weight"""						,  _disabled=lowerCamelCase )

								if args.quant_disable:
												set_quantizer_by_name(lowerCamelCase						,  [""""""]						,  _disabled=lowerCamelCase )

								if args.quant_disable_keyword:
												set_quantizer_by_name(lowerCamelCase						,  args.quant_disable_keyword						,  _disabled=lowerCamelCase )

								if args.quant_disable_layer_module:
												set_quantizer_by_name(lowerCamelCase						,  [R"""layer.\d+.""" + args.quant_disable_layer_module]						,  _disabled=lowerCamelCase )

								if args.quant_enable_layer_module:
												set_quantizer_by_name(lowerCamelCase						,  [R"""layer.\d+.""" + args.quant_enable_layer_module]						,  _disabled=lowerCamelCase )

								if args.recalibrate_weights:
												recalibrate_weights(lowerCamelCase )

								if args.fuse_qkv:
												fuse_qkv(lowerCamelCase						,  lowerCamelCase )

				if args.clip_gelu:
								clip_gelu(lowerCamelCase						,  args.clip_gelu )

				# if args.local_rank in [-1, 0] and not calib:
				print_quant_summary(lowerCamelCase )




def 		lowerCAmelCase_ (						lowerCamelCase ):
				logger.info("""Enabling Calibration""" )
				for name, module in model.named_modules():
								if name.endswith("""_quantizer""" ):
												if module._calibrator is not None:
																module.disable_quant()
																module.enable_calib()
												else:
																module.disable()
												logger.info(F"{name:80}: {module}" )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase ):
				logger.info("""Loading calibrated amax""" )
				for name, module in model.named_modules():
								if name.endswith("""_quantizer""" ):
												if module._calibrator is not None:
																if isinstance(module._calibrator						,  calib.MaxCalibrator ):
																				module.load_calib_amax()
																else:
																				module.load_calib_amax("""percentile"""						,  percentile=args.percentile )
																module.enable_quant()
																module.disable_calib()
												else:
																module.enable()
				model.cuda()
				print_quant_summary(lowerCamelCase )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase ):

				def fusea(lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase ):
								for mod in [qq, qk, qv]:
												if not hasattr(lowerCamelCase						,  """_amax""" ):
																print("""          WARNING: NO AMAX BUFFER""" )
																return
								__magic_name__						:						Optional[int]										=qq._amax.detach().item()
								__magic_name__						:						List[str]										=qk._amax.detach().item()
								__magic_name__						:						List[Any]										=qv._amax.detach().item()

								__magic_name__						:						Optional[int]										=max(lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase )
								qq._amax.fill_(lowerCamelCase )
								qk._amax.fill_(lowerCamelCase )
								qv._amax.fill_(lowerCamelCase )
								logger.info(F"          q={q:5.2f} k={k:5.2f} v={v:5.2f} -> {amax:5.2f}" )

				for name, mod in model.named_modules():
								if name.endswith(""".attention.self""" ):
												logger.info(F"FUSE_QKV: {name:{name_width}}" )
												fusea(mod.matmul_q_input_quantizer						,  mod.matmul_k_input_quantizer						,  mod.matmul_v_input_quantizer )
												if args.quant_per_tensor:
																fusea(mod.query._weight_quantizer						,  mod.key._weight_quantizer						,  mod.value._weight_quantizer )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase ):

				for name, mod in model.named_modules():
								if name.endswith(""".output.dense""" ) and not name.endswith("""attention.output.dense""" ):
												__magic_name__						:						int										=mod._input_quantizer._amax.data.detach().item()
												mod._input_quantizer._amax.data.detach().clamp_(max=lowerCamelCase )
												__magic_name__						:						Optional[Any]										=mod._input_quantizer._amax.data.detach().item()
												logger.info(F"CLIP_GELU: {name:{name_width}} amax: {amax_init:5.2f} -> {amax:5.2f}" )




def 		lowerCAmelCase_ (						lowerCamelCase ):

				for name, mod in model.named_modules():
								if hasattr(lowerCamelCase						,  """_weight_quantizer""" ) and mod._weight_quantizer.axis is not None:
												__magic_name__						:						int										=mod.weight.shape[0]
												__magic_name__						:						int										=mod._weight_quantizer._amax.detach()
												__magic_name__						:						Tuple										=torch.ones(lowerCamelCase						,  dtype=amax.dtype						,  device=amax.device ) * amax
												print(F"expanding {name} {amax} -> {mod._weight_quantizer._amax}" )




def 		lowerCAmelCase_ (						lowerCamelCase ):

				for name, mod in model.named_modules():
								if hasattr(lowerCamelCase						,  """_weight_quantizer""" ):
												if not hasattr(mod.weight_quantizer						,  """_amax""" ):
																print("""RECALIB: {name:{name_width}} WARNING: NO AMAX BUFFER""" )
																continue

												# determine which axes to reduce across
												# e.g. a 4D tensor quantized per axis 0 should reduce over (1,2,3)
												__magic_name__						:						List[str]										=set() if mod._weight_quantizer.axis is None else set(mod._weight_quantizer.axis )
												__magic_name__						:						List[str]										=set(range(len(mod.weight.size() ) ) ) - axis_set
												__magic_name__						:						List[str]										=pytorch_quantization.utils.reduce_amax(mod.weight						,  axis=lowerCamelCase						,  keepdims=lowerCamelCase ).detach()
												logger.info(F"RECALIB: {name:{name_width}} {mod._weight_quantizer._amax.flatten()} -> {amax.flatten()}" )
												__magic_name__						:						Union[str, Any]										=amax




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase=25						,  lowerCamelCase=180						,  lowerCamelCase=None ):

				if ignore is None:
								__magic_name__						:						int										=[]
				elif not isinstance(lowerCamelCase						,  lowerCamelCase ):
								__magic_name__						:						Union[str, Any]										=[ignore]

				__magic_name__						:						Tuple										=0
				for name, mod in model.named_modules():
								if not hasattr(lowerCamelCase						,  """weight""" ):
												continue
								__magic_name__						:						Union[str, Any]										=max(lowerCamelCase						,  len(lowerCamelCase ) )

				for name, mod in model.named_modules():
								__magic_name__						:						int										=getattr(lowerCamelCase						,  """_input_quantizer"""						,  lowerCamelCase )
								__magic_name__						:						Tuple										=getattr(lowerCamelCase						,  """_weight_quantizer"""						,  lowerCamelCase )
								if not hasattr(lowerCamelCase						,  """weight""" ):
												continue
								if type(lowerCamelCase ) in ignore:
												continue
								if [True for s in ignore if type(lowerCamelCase ) is str and s in name]:
												continue
								__magic_name__						:						List[str]										=F"Act:{input_q.extra_repr()}"
								__magic_name__						:						Dict										=F"Wgt:{weight_q.extra_repr()}"
								__magic_name__						:						Optional[Any]										=F"{name:{name_width}} {act_str} {wgt_str}"
								if len(lowerCamelCase ) <= line_width:
												logger.info(lowerCamelCase )
								else:
												logger.info(F"{name:{name_width}} {act_str}" )
												logger.info(F"{'  ':{name_width}} {wgt_str}" )




def 		lowerCAmelCase_ (						lowerCamelCase ):
				__magic_name__						:						Union[str, Any]										=0
				for name, mod in model.named_modules():
								if isinstance(lowerCamelCase						,  pytorch_quantization.nn.TensorQuantizer ):
												print(F"{name:80} {mod}" )
												count += 1
				print(F"{count} TensorQuantizers found in model" )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase ):
				__magic_name__						:						List[str]										=getattr(lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase )
				if quantizer_mod is not None:
								assert hasattr(lowerCamelCase						,  lowerCamelCase )
								setattr(lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase )
				else:
								logger.warning(F"{name} has no {quantizer}" )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase="both"						,  **lowerCamelCase ):
				__magic_name__						:						str										=F"Warning: changing {which} quantizers of {name:{qname_width}}"
				for k, v in kwargs.items():
								s += F" {k}={v}"
								if which in ["input", "both"]:
												set_quantizer(lowerCamelCase						,  lowerCamelCase						,  """_input_quantizer"""						,  lowerCamelCase						,  lowerCamelCase )
								if which in ["weight", "both"]:
												set_quantizer(lowerCamelCase						,  lowerCamelCase						,  """_weight_quantizer"""						,  lowerCamelCase						,  lowerCamelCase )
				logger.info(lowerCamelCase )




def 		lowerCAmelCase_ (						lowerCamelCase						,  lowerCamelCase						,  **lowerCamelCase ):

				for name, mod in model.named_modules():
								if hasattr(lowerCamelCase						,  """_input_quantizer""" ) or hasattr(lowerCamelCase						,  """_weight_quantizer""" ):
												for n in names:
																if re.search(lowerCamelCase						,  lowerCamelCase ):
																				set_quantizers(lowerCamelCase						,  lowerCamelCase						,  **lowerCamelCase )
								elif name.endswith("""_quantizer""" ):
												for n in names:
																if re.search(lowerCamelCase						,  lowerCamelCase ):
																				__magic_name__						:						Tuple										=F"Warning: changing {name:{name_width}}"
																				for k, v in kwargs.items():
																								s += F" {k}={v}"
																								setattr(lowerCamelCase						,  lowerCamelCase						,  lowerCamelCase )
																				logger.info(lowerCamelCase )










from sklearn.metrics import matthews_corrcoef

import datasets


UpperCAmelCase_		:					Dict          =  "\nCompute the Matthews correlation coefficient (MCC)\n\nThe Matthews correlation coefficient is used in machine learning as a\nmeasure of the quality of binary and multiclass classifications. It takes\ninto account true and false positives and negatives and is generally\nregarded as a balanced measure which can be used even if the classes are of\nvery different sizes. The MCC is in essence a correlation coefficient value\nbetween -1 and +1. A coefficient of +1 represents a perfect prediction, 0\nan average random prediction and -1 an inverse prediction.  The statistic\nis also known as the phi coefficient. [source: Wikipedia]\n"

UpperCAmelCase_		:					Any          =  "\nArgs:\n    predictions (list of int): Predicted labels, as returned by a model.\n    references (list of int): Ground truth labels.\n    sample_weight (list of int, float, or bool): Sample weights. Defaults to `None`.\nReturns:\n    matthews_correlation (dict containing float): Matthews correlation.\nExamples:\n    Example 1, a basic example with only predictions and references as inputs:\n        >>> matthews_metric = datasets.load_metric(\"matthews_correlation\")\n        >>> results = matthews_metric.compute(references=[1, 3, 2, 0, 3, 2],\n        ...                                     predictions=[1, 2, 2, 0, 3, 3])\n        >>> print(round(results['matthews_correlation'], 2))\n        0.54\n\n    Example 2, the same example as above, but also including sample weights:\n        >>> matthews_metric = datasets.load_metric(\"matthews_correlation\")\n        >>> results = matthews_metric.compute(references=[1, 3, 2, 0, 3, 2],\n        ...                                     predictions=[1, 2, 2, 0, 3, 3],\n        ...                                     sample_weight=[0.5, 3, 1, 1, 1, 2])\n        >>> print(round(results['matthews_correlation'], 2))\n        0.1\n\n    Example 3, the same example as above, but with sample weights that cause a negative correlation:\n        >>> matthews_metric = datasets.load_metric(\"matthews_correlation\")\n        >>> results = matthews_metric.compute(references=[1, 3, 2, 0, 3, 2],\n        ...                                     predictions=[1, 2, 2, 0, 3, 3],\n        ...                                     sample_weight=[0.5, 1, 0, 0, 0, 1])\n        >>> print(round(results['matthews_correlation'], 2))\n        -0.25\n"

UpperCAmelCase_		:					Dict          =  "\\n@article{scikit-learn,\n  title={Scikit-learn: Machine Learning in {P}ython},\n  author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.\n         and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P.\n         and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and\n         Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.},\n  journal={Journal of Machine Learning Research},\n  volume={12},\n  pages={2825--2830},\n  year={2011}\n}\n"




@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION       ,    _KWARGS_DESCRIPTION      )
class 		__A   (      datasets.Metric      ):

						def      A__    (		self :List[str]			):
										'''simple docstring'''

										return datasets.MetricInfo(
										    description=_DESCRIPTION     ,			citation=_CITATION     ,			inputs_description=_KWARGS_DESCRIPTION     ,			features=datasets.Features(
										        {
										            """predictions""": datasets.Value("""int32"""			),
										            """references""": datasets.Value("""int32"""			),
										        }			)     ,			reference_urls=[
										        """https://scikit-learn.org/stable/modules/generated/sklearn.metrics.matthews_corrcoef.html"""
										    ]     ,			)


						def      A__    (		self :Tuple     ,			__snake_case :str     ,			__snake_case :Tuple     ,			__snake_case :List[str]=None			):
										'''simple docstring'''

										return {
										    "matthews_correlation": float(matthews_corrcoef(__snake_case     ,			__snake_case     ,			sample_weight=__snake_case			)			),
										}




