



'''simple docstring'''





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()
lowercase_	 =						logging.get_logger(__name__)




def lowerCAmelCase						(__A						,			__A=False):



     """simple docstring"""



     _a											=						[]
     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"
          _a											=						[(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						(__A						,			__A						,			__A=False):



     """simple docstring"""



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




def lowerCAmelCase						(__A):



     """simple docstring"""



     _a											=						['''head.weight''', '''head.bias''']
     for k in ignore_keys:
          state_dict.pop(__A						,			__A)




def lowerCAmelCase						(__A						,			__A						,			__A):



     """simple docstring"""



     _a											=						dct.pop(__A)
     _a											=						val




def lowerCAmelCase						():



     """simple docstring"""



     _a											=						'''http://images.cocodataset.org/val2017/000000039769.jpg'''
     _a											=						Image.open(requests.get(__A						,			stream=__A).raw)
     return im




@torch.no_grad()
def lowerCAmelCase						(__A						,			__A						,			__A=True):



     """simple docstring"""



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

     # load original model from torch hub
     _a											=						torch.hub.load('''facebookresearch/dino:main'''						,			__A)
     original_model.eval()

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

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

     # Check outputs on an image, prepared by ViTImageProcessor
     _a											=						ViTImageProcessor()
     _a											=						image_processor(images=prepare_img()						,			return_tensors='''pt''')
     _a											=						encoding['''pixel_values''']
     _a											=						model(__A)

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

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


if __name__ == "__main__":
  lowercase_	 =						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)
  lowercase_	 =						parser.parse_args()
  convert_vit_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.base_model)








'''simple docstring'''





def lowerCAmelCase						(__A):



     """simple docstring"""



     _a											=						set()
     # To detect a back edge, keep track of vertices currently in the recursion stack
     _a											=						set()
     return any(
         node not in visited and depth_first_search(__A						,			__A						,			__A						,			__A)
         for node in graph)




def lowerCAmelCase						(__A						,			__A						,			__A						,			__A):



     """simple docstring"""



     visited.add(__A)
     rec_stk.add(__A)

     for node in graph[vertex]:
          if node not in visited:
               if depth_first_search(__A						,			__A						,			__A						,			__A):
                    return True
          elif node in rec_stk:
               return True

    # The node needs to be removed from recursion stack before function ends
     rec_stk.remove(__A)
     return False


if __name__ == "__main__":
  from doctest import testmod

  testmod()



