





'''simple docstring'''

import importlib.util
import json
import os
import warnings
from dataclasses import dataclass, field

import torch

from ..training_args import TrainingArguments
from ..utils import cached_property, is_sagemaker_dp_enabled, logging


lowercase__		:     Tuple			=							logging.get_logger(__name__)







def    a__							(							)						->						str:





     """simple docstring"""

     _UpperCamelCase							       =			os.getenv('''SM_HP_MP_PARAMETERS''',   '''{}''' )
     try:
          # Parse it and check the field "partitions" is included, it is required for model parallel.
          _UpperCamelCase							       =			json.loads(lowercase )
          if "partitions" not in smp_options:
               return False
     except json.JSONDecodeError:
          return False

     # Get the sagemaker specific framework parameters from mpi_options variable.
     _UpperCamelCase							       =			os.getenv('''SM_FRAMEWORK_PARAMS''',   '''{}''' )
     try:
          # Parse it and check the field "sagemaker_distributed_dataparallel_enabled".
          _UpperCamelCase							       =			json.loads(lowercase )
          if not mpi_options.get('''sagemaker_mpi_enabled''',   lowercase ):
               return False
     except json.JSONDecodeError:
          return False
     # Lastly, check if the `smdistributed` module is present.
     return importlib.util.find_spec('''smdistributed''' ) is not None


if is_sagemaker_model_parallel_available():
   import smdistributed.modelparallel.torch as smp

   smp.init()




@dataclass
class 							__lowerCAmelCase	(       __magic_name__					):






       """simple docstring"""
       _snake_case      :	str									=       field(
           default=''		,		metadata={'help': 'Used by the SageMaker launcher to send mp-specific args. Ignored in SageMakerTrainer'}		,		)





       def snake_case__		(				self  :						List[str]	)       ->	Any:

            '''simple docstring'''




            super().__post_init__()
            warnings.warn(
                '''`SageMakerTrainingArguments` is deprecated and will be removed in v5 of Transformers. You can use '''
                '''`TrainingArguments` instead.'''			,					lowerCAmelCase__			,					)





       @cached_property
       def snake_case__		(				self  :						Any	)       ->	"torch.device":

            '''simple docstring'''




            logger.info('''PyTorch: setting up devices'''	)
            if torch.distributed.is_available() and torch.distributed.is_initialized() and self.local_rank == -1:
                 logger.warning(
                     '''torch.distributed process group is initialized, but local_rank == -1. '''
                     '''In order to use Torch DDP, launch your script with `python -m torch.distributed.launch'''	)
            if self.no_cuda:
                 _UpperCamelCase							       =			torch.device('''cpu'''	)
                 _UpperCamelCase							       =			0
            elif is_sagemaker_model_parallel_available():
                 _UpperCamelCase							       =			smp.local_rank()
                 _UpperCamelCase							       =			torch.device('''cuda'''			,					lowerCAmelCase__	)
                 _UpperCamelCase							       =			1
            elif is_sagemaker_dp_enabled():
                 import smdistributed.dataparallel.torch.torch_smddp  # noqa: F401

                 torch.distributed.init_process_group(backend='''smddp'''			,					timeout=self.ddp_timeout_delta	)
                 _UpperCamelCase							       =			int(os.getenv('''SMDATAPARALLEL_LOCAL_RANK'''	)	)
                 _UpperCamelCase							       =			torch.device('''cuda'''			,					self.local_rank	)
                 _UpperCamelCase							       =			1
            elif self.local_rank == -1:
                 # if n_gpu is > 1 we'll use nn.DataParallel.
                 # If you only want to use a specific subset of GPUs use `CUDA_VISIBLE_DEVICES=0`
                 # Explicitly set CUDA to the first (index 0) CUDA device, otherwise `set_device` will
                 # trigger an error that a device index is missing. Index 0 takes into account the
                 # GPUs available in the environment, so `CUDA_VISIBLE_DEVICES=1,2` with `cuda:0`
                 # will use the first GPU in that env, i.e. GPU#1
                 _UpperCamelCase							       =			torch.device('''cuda:0''' if torch.cuda.is_available() else '''cpu'''	)
                 # Sometimes the line in the postinit has not been run before we end up here, so just checking we're not at
                 # the default value.
                 _UpperCamelCase							       =			torch.cuda.device_count()
            else:
                 # Here, we'll use torch.distributed.
                 # Initializes the distributed backend which will take care of synchronizing nodes/GPUs
                 if not torch.distributed.is_initialized():
                      torch.distributed.init_process_group(backend='''nccl'''			,					timeout=self.ddp_timeout_delta	)
                 _UpperCamelCase							       =			torch.device('''cuda'''			,					self.local_rank	)
                 _UpperCamelCase							       =			1

            if device.type == "cuda":
                 torch.cuda.set_device(lowerCAmelCase__	)

            return device





       @property
       def snake_case__		(				self  :						str	)       ->	Tuple:

            '''simple docstring'''




            if is_sagemaker_model_parallel_available():
                 return smp.dp_size()

            return super().world_size





       @property
       def snake_case__		(				self  :						Dict	)       ->	Optional[Any]:

            '''simple docstring'''




            return not is_sagemaker_model_parallel_available()







       @property
       def snake_case__		(				self  :						int	)       ->	List[Any]:

            '''simple docstring'''




            return False







import argparse
import json
from pathlib import Path

import requests
import torch
from huggingface_hub import hf_hub_download
from PIL import Image

from transformers import ViTConfig, ViTForImageClassification, ViTImageProcessor, ViTModel
from transformers.utils import logging


logging.set_verbosity_info()
A				:       int      =  logging.get_logger(__name__)





def 						_lowerCAmelCase							(     _lowerCAmelCase   ,						_lowerCAmelCase=False			)    ->						Optional[int]:


						'''simple docstring'''






						__snake_case				=		[]
						for i in range(config.num_hidden_layers			):
												# encoder layers: output projection, 2 feedforward neural networks and 2 layernorms
												rename_keys.append((F'''blocks.{i}.norm1.weight''', F'''vit.encoder.layer.{i}.layernorm_before.weight''')			)
												rename_keys.append((F'''blocks.{i}.norm1.bias''', F'''vit.encoder.layer.{i}.layernorm_before.bias''')			)
												rename_keys.append((F'''blocks.{i}.attn.proj.weight''', F'''vit.encoder.layer.{i}.attention.output.dense.weight''')			)
												rename_keys.append((F'''blocks.{i}.attn.proj.bias''', F'''vit.encoder.layer.{i}.attention.output.dense.bias''')			)
												rename_keys.append((F'''blocks.{i}.norm2.weight''', F'''vit.encoder.layer.{i}.layernorm_after.weight''')			)
												rename_keys.append((F'''blocks.{i}.norm2.bias''', F'''vit.encoder.layer.{i}.layernorm_after.bias''')			)
												rename_keys.append((F'''blocks.{i}.mlp.fc1.weight''', F'''vit.encoder.layer.{i}.intermediate.dense.weight''')			)
												rename_keys.append((F'''blocks.{i}.mlp.fc1.bias''', F'''vit.encoder.layer.{i}.intermediate.dense.bias''')			)
												rename_keys.append((F'''blocks.{i}.mlp.fc2.weight''', F'''vit.encoder.layer.{i}.output.dense.weight''')			)
												rename_keys.append((F'''blocks.{i}.mlp.fc2.bias''', F'''vit.encoder.layer.{i}.output.dense.bias''')			)

						# projection layer + position embeddings
						rename_keys.extend(
						    [
						        ("cls_token", "vit.embeddings.cls_token"),
						        ("patch_embed.proj.weight", "vit.embeddings.patch_embeddings.projection.weight"),
						        ("patch_embed.proj.bias", "vit.embeddings.patch_embeddings.projection.bias"),
						        ("pos_embed", "vit.embeddings.position_embeddings"),
						    ]			)

						if base_model:
												# layernorm + pooler
												rename_keys.extend(
												    [
												        ("norm.weight", "layernorm.weight"),
												        ("norm.bias", "layernorm.bias"),
												    ]			)

												# if just the base model, we should remove "vit" from all keys that start with "vit"
												__snake_case				=		[(pair[0], pair[1][4:]) if pair[1].startswith("vit"			) else pair for pair in rename_keys]
						else:
												# layernorm + classification head
												rename_keys.extend(
												    [
												        ("norm.weight", "vit.layernorm.weight"),
												        ("norm.bias", "vit.layernorm.bias"),
												        ("head.weight", "classifier.weight"),
												        ("head.bias", "classifier.bias"),
												    ]			)

						return rename_keys





def 						_lowerCAmelCase							(     _lowerCAmelCase   ,						_lowerCAmelCase   ,						_lowerCAmelCase=False			)    ->						int:


						'''simple docstring'''






						for i in range(config.num_hidden_layers			):
												if base_model:
																		__snake_case				=		""
												else:
																		__snake_case				=		"vit."
												# read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
												__snake_case				=		state_dict.pop(F'''blocks.{i}.attn.qkv.weight'''			)
												__snake_case				=		state_dict.pop(F'''blocks.{i}.attn.qkv.bias'''			)
												# next, add query, keys and values (in that order) to the state dict
												__snake_case				=		in_proj_weight[
												    : config.hidden_size, :
												]
												__snake_case				=		in_proj_bias[: config.hidden_size]
												__snake_case				=		in_proj_weight[
												    config.hidden_size : config.hidden_size * 2, :
												]
												__snake_case				=		in_proj_bias[
												    config.hidden_size : config.hidden_size * 2
												]
												__snake_case				=		in_proj_weight[
												    -config.hidden_size :, :
												]
												__snake_case				=		in_proj_bias[-config.hidden_size :]





def 						_lowerCAmelCase							(     _lowerCAmelCase			)    ->						List[str]:


						'''simple docstring'''






						__snake_case				=		["head.weight", "head.bias"]
						for k in ignore_keys:
												state_dict.pop(_lowerCAmelCase   ,						_lowerCAmelCase			)





def 						_lowerCAmelCase							(     _lowerCAmelCase   ,						_lowerCAmelCase   ,						_lowerCAmelCase			)    ->						Dict:


						'''simple docstring'''






						__snake_case				=		dct.pop(_lowerCAmelCase			)
						__snake_case				=		val





def 						_lowerCAmelCase							(     )    ->						Any:


						'''simple docstring'''






						__snake_case				=		"http://images.cocodataset.org/val2017/000000039769.jpg"
						__snake_case				=		Image.open(requests.get(_lowerCAmelCase   ,						stream=_lowerCAmelCase			).raw			)
						return im





@torch.no_grad()
def 						_lowerCAmelCase							(     _lowerCAmelCase   ,						_lowerCAmelCase   ,						_lowerCAmelCase=True			)    ->						int:


						'''simple docstring'''






						__snake_case				=		ViTConfig()
						# patch_size
						if model_name[-1] == "8":
												__snake_case				=		8
						# set labels if required
						if not base_model:
												__snake_case				=		1000
												__snake_case				=		"huggingface/label-files"
												__snake_case				=		"imagenet-1k-id2label.json"
												__snake_case				=		json.load(open(hf_hub_download(_lowerCAmelCase   ,						_lowerCAmelCase   ,						repo_type="dataset"			)   ,						"r"			)			)
												__snake_case				=		{int(_lowerCAmelCase			): v for k, v in idalabel.items()}
												__snake_case				=		idalabel
												__snake_case				=		{v: k for k, v in idalabel.items()}
						# size of the architecture
						if model_name in ["dino_vits8", "dino_vits16"]:
												__snake_case				=		384
												__snake_case				=		1536
												__snake_case				=		12
												__snake_case				=		6

						# load original model from torch hub
						__snake_case				=		torch.hub.load("facebookresearch/dino:main"   ,						_lowerCAmelCase			)
						original_model.eval()

						# load state_dict of original model, remove and rename some keys
						__snake_case				=		original_model.state_dict()
						if base_model:
												remove_classification_head_(_lowerCAmelCase			)
						__snake_case				=		create_rename_keys(_lowerCAmelCase   ,						base_model=_lowerCAmelCase			)
						for src, dest in rename_keys:
												rename_key(_lowerCAmelCase   ,						_lowerCAmelCase   ,						_lowerCAmelCase			)
						read_in_q_k_v(_lowerCAmelCase   ,						_lowerCAmelCase   ,						_lowerCAmelCase			)

						# load HuggingFace model
						if base_model:
												__snake_case				=		ViTModel(_lowerCAmelCase   ,						add_pooling_layer=_lowerCAmelCase			).eval()
						else:
												__snake_case				=		ViTForImageClassification(_lowerCAmelCase			).eval()
						model.load_state_dict(_lowerCAmelCase			)

						# Check outputs on an image, prepared by ViTImageProcessor
						__snake_case				=		ViTImageProcessor()
						__snake_case				=		image_processor(images=prepare_img()   ,						return_tensors="pt"			)
						__snake_case				=		encoding["pixel_values"]
						__snake_case				=		model(_lowerCAmelCase			)

						if base_model:
												__snake_case				=		original_model(_lowerCAmelCase			)
												assert torch.allclose(_lowerCAmelCase   ,						outputs.last_hidden_state[:, 0, :]   ,						atol=1E-1			)
						else:
												__snake_case				=		original_model(_lowerCAmelCase			)
												assert logits.shape == outputs.logits.shape
												assert torch.allclose(_lowerCAmelCase   ,						outputs.logits   ,						atol=1E-3			)

						Path(_lowerCAmelCase			).mkdir(exist_ok=_lowerCAmelCase			)
						print(F'''Saving model {model_name} to {pytorch_dump_folder_path}'''			)
						model.save_pretrained(_lowerCAmelCase			)
						print(F'''Saving image processor to {pytorch_dump_folder_path}'''			)
						image_processor.save_pretrained(_lowerCAmelCase			)


if __name__ == "__main__":
	A				:       str      =  argparse.ArgumentParser()
	# Required parameters
	parser.add_argument(
	    '--model_name',
	    default='dino_vitb16',
	    type=str,
	    help='Name of the model trained with DINO you\'d like to convert.',
	)
	parser.add_argument(
	    '--pytorch_dump_folder_path', default=None, type=str, help='Path to the output PyTorch model directory.'
	)
	parser.add_argument(
	    '--base_model',
	    action='store_true',
	    help='Whether to only convert the base model (no projection head weights).',
	)

	parser.set_defaults(base_model=True)
	A				:       Any      =  parser.parse_args()
	convert_vit_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.base_model)





