


import argparse
import json
import os

import numpy as np
import PIL
import requests
import tensorflow.keras.applications.efficientnet as efficientnet
import torch
from huggingface_hub import hf_hub_download
from PIL import Image
from tensorflow.keras.preprocessing import image

from transformers import (
    EfficientNetConfig,
    EfficientNetForImageClassification,
    EfficientNetImageProcessor,
)
from transformers.utils import logging


logging.set_verbosity_info()
snake_case__				:	Optional[Any]					       =					logging.get_logger(__name__)

snake_case__				:	Any					       =					{
    'b0': efficientnet.EfficientNetBa,
    'b1': efficientnet.EfficientNetBa,
    'b2': efficientnet.EfficientNetBa,
    'b3': efficientnet.EfficientNetBa,
    'b4': efficientnet.EfficientNetBa,
    'b5': efficientnet.EfficientNetBa,
    'b6': efficientnet.EfficientNetBa,
    'b7': efficientnet.EfficientNetBa,
}

snake_case__				:	Union[str, Any]					       =					{
    'b0': {
        'hidden_dim': 1280,
        'width_coef': 1.0,
        'depth_coef': 1.0,
        'image_size': 224,
        'dropout_rate': 0.2,
        'dw_padding': [],
    },
    'b1': {
        'hidden_dim': 1280,
        'width_coef': 1.0,
        'depth_coef': 1.1,
        'image_size': 240,
        'dropout_rate': 0.2,
        'dw_padding': [16],
    },
    'b2': {
        'hidden_dim': 1408,
        'width_coef': 1.1,
        'depth_coef': 1.2,
        'image_size': 260,
        'dropout_rate': 0.3,
        'dw_padding': [5, 8, 16],
    },
    'b3': {
        'hidden_dim': 1536,
        'width_coef': 1.2,
        'depth_coef': 1.4,
        'image_size': 300,
        'dropout_rate': 0.3,
        'dw_padding': [5, 18],
    },
    'b4': {
        'hidden_dim': 1792,
        'width_coef': 1.4,
        'depth_coef': 1.8,
        'image_size': 380,
        'dropout_rate': 0.4,
        'dw_padding': [6],
    },
    'b5': {
        'hidden_dim': 2048,
        'width_coef': 1.6,
        'depth_coef': 2.2,
        'image_size': 456,
        'dropout_rate': 0.4,
        'dw_padding': [13, 27],
    },
    'b6': {
        'hidden_dim': 2304,
        'width_coef': 1.8,
        'depth_coef': 2.6,
        'image_size': 528,
        'dropout_rate': 0.5,
        'dw_padding': [31],
    },
    'b7': {
        'hidden_dim': 2560,
        'width_coef': 2.0,
        'depth_coef': 3.1,
        'image_size': 600,
        'dropout_rate': 0.5,
        'dw_padding': [18],
    },
}


def    __lowerCamelCase   (      A__						: Optional[int]					)     ->    Optional[int]:
   lowerCamelCase_						:   List[str]		= EfficientNetConfig()
   lowerCamelCase_						:   List[Any]		= CONFIG_MAP[model_name]["""hidden_dim"""]
   lowerCamelCase_						:   List[Any]		= CONFIG_MAP[model_name]["""width_coef"""]
   lowerCamelCase_						:   Union[str, Any]		= CONFIG_MAP[model_name]["""depth_coef"""]
   lowerCamelCase_						:   Tuple		= CONFIG_MAP[model_name]["""image_size"""]
   lowerCamelCase_						:   Dict		= CONFIG_MAP[model_name]["""dropout_rate"""]
   lowerCamelCase_						:   int		= CONFIG_MAP[model_name]["""dw_padding"""]

   lowerCamelCase_						:   Any		= """huggingface/label-files"""
   lowerCamelCase_						:   Optional[int]		= """imagenet-1k-id2label.json"""
   lowerCamelCase_						:   Optional[int]		= 1000
   lowerCamelCase_						:   int		= json.load(open(hf_hub_download(A__						,						A__						,						repo_type="""dataset"""					)						,						"""r"""					)					)
   lowerCamelCase_						:   Optional[int]		= {int(A__					): v for k, v in idalabel.items()}

   lowerCamelCase_						:   int		= idalabel
   lowerCamelCase_						:   List[Any]		= {v: k for k, v in idalabel.items()}
   return config


def    __lowerCamelCase   (      )     ->    Optional[Any]:
   lowerCamelCase_						:   List[Any]		= """http://images.cocodataset.org/val2017/000000039769.jpg"""
   lowerCamelCase_						:   List[str]		= Image.open(requests.get(A__						,						stream=A__					).raw					)
   return im


def    __lowerCamelCase   (      A__						: str					)     ->    Optional[int]:
   lowerCamelCase_						:   Optional[Any]		= CONFIG_MAP[model_name]["""image_size"""]
   lowerCamelCase_						:   Any		= EfficientNetImageProcessor(
       size={"""height""": size, """width""": size}						,						image_mean=[0.485, 0.456, 0.406]						,						image_std=[0.4785_3944, 0.473_2864, 0.4743_4163]						,						do_center_crop=A__						,						)
   return preprocessor


def    __lowerCamelCase   (      A__						: Union[str, Any]					)     ->    List[Any]:
   lowerCamelCase_						:   int		= [v.split("""_"""					)[0].split("""block"""					)[1] for v in original_param_names if v.startswith("""block"""					)]
   lowerCamelCase_						:   Tuple		= sorted(set(A__					)					)
   lowerCamelCase_						:   Union[str, Any]		= len(A__					)
   lowerCamelCase_						:   str		= {b: str(A__					) for b, i in zip(A__						,						range(A__					)					)}

   lowerCamelCase_						:   Union[str, Any]		= []
   rename_keys.append(("""stem_conv/kernel:0""", """embeddings.convolution.weight""")					)
   rename_keys.append(("""stem_bn/gamma:0""", """embeddings.batchnorm.weight""")					)
   rename_keys.append(("""stem_bn/beta:0""", """embeddings.batchnorm.bias""")					)
   rename_keys.append(("""stem_bn/moving_mean:0""", """embeddings.batchnorm.running_mean""")					)
   rename_keys.append(("""stem_bn/moving_variance:0""", """embeddings.batchnorm.running_var""")					)

   for b in block_names:
      lowerCamelCase_						:   List[str]		= block_name_mapping[b]
      rename_keys.append((f'''block{b}_expand_conv/kernel:0''', f'''encoder.blocks.{hf_b}.expansion.expand_conv.weight''')					)
      rename_keys.append((f'''block{b}_expand_bn/gamma:0''', f'''encoder.blocks.{hf_b}.expansion.expand_bn.weight''')					)
      rename_keys.append((f'''block{b}_expand_bn/beta:0''', f'''encoder.blocks.{hf_b}.expansion.expand_bn.bias''')					)
      rename_keys.append(
          (f'''block{b}_expand_bn/moving_mean:0''', f'''encoder.blocks.{hf_b}.expansion.expand_bn.running_mean''')					)
      rename_keys.append(
          (f'''block{b}_expand_bn/moving_variance:0''', f'''encoder.blocks.{hf_b}.expansion.expand_bn.running_var''')					)
      rename_keys.append(
          (f'''block{b}_dwconv/depthwise_kernel:0''', f'''encoder.blocks.{hf_b}.depthwise_conv.depthwise_conv.weight''')					)
      rename_keys.append((f'''block{b}_bn/gamma:0''', f'''encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.weight''')					)
      rename_keys.append((f'''block{b}_bn/beta:0''', f'''encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.bias''')					)
      rename_keys.append(
          (f'''block{b}_bn/moving_mean:0''', f'''encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_mean''')					)
      rename_keys.append(
          (f'''block{b}_bn/moving_variance:0''', f'''encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_var''')					)

      rename_keys.append((f'''block{b}_se_reduce/kernel:0''', f'''encoder.blocks.{hf_b}.squeeze_excite.reduce.weight''')					)
      rename_keys.append((f'''block{b}_se_reduce/bias:0''', f'''encoder.blocks.{hf_b}.squeeze_excite.reduce.bias''')					)
      rename_keys.append((f'''block{b}_se_expand/kernel:0''', f'''encoder.blocks.{hf_b}.squeeze_excite.expand.weight''')					)
      rename_keys.append((f'''block{b}_se_expand/bias:0''', f'''encoder.blocks.{hf_b}.squeeze_excite.expand.bias''')					)
      rename_keys.append(
          (f'''block{b}_project_conv/kernel:0''', f'''encoder.blocks.{hf_b}.projection.project_conv.weight''')					)
      rename_keys.append((f'''block{b}_project_bn/gamma:0''', f'''encoder.blocks.{hf_b}.projection.project_bn.weight''')					)
      rename_keys.append((f'''block{b}_project_bn/beta:0''', f'''encoder.blocks.{hf_b}.projection.project_bn.bias''')					)
      rename_keys.append(
          (f'''block{b}_project_bn/moving_mean:0''', f'''encoder.blocks.{hf_b}.projection.project_bn.running_mean''')					)
      rename_keys.append(
          (f'''block{b}_project_bn/moving_variance:0''', f'''encoder.blocks.{hf_b}.projection.project_bn.running_var''')					)

   rename_keys.append(("""top_conv/kernel:0""", """encoder.top_conv.weight""")					)
   rename_keys.append(("""top_bn/gamma:0""", """encoder.top_bn.weight""")					)
   rename_keys.append(("""top_bn/beta:0""", """encoder.top_bn.bias""")					)
   rename_keys.append(("""top_bn/moving_mean:0""", """encoder.top_bn.running_mean""")					)
   rename_keys.append(("""top_bn/moving_variance:0""", """encoder.top_bn.running_var""")					)

   lowerCamelCase_						:   Optional[Any]		= {}
   for item in rename_keys:
      if item[0] in original_param_names:
         lowerCamelCase_						:   Any		= """efficientnet.""" + item[1]

   lowerCamelCase_						:   str		= """classifier.weight"""
   lowerCamelCase_						:   Optional[int]		= """classifier.bias"""
   return key_mapping


def    __lowerCamelCase   (      A__						: str						,						A__						: List[Any]						,						A__						: List[str]					)     ->    Any:
   for key, value in tf_params.items():
      if "normalization" in key:
         continue

      lowerCamelCase_						:   Dict		= key_mapping[key]
      if "_conv" in key and "kernel" in key:
         lowerCamelCase_						:   int		= torch.from_numpy(A__					).permute(3						,						2						,						0						,						1					)
      elif "depthwise_kernel" in key:
         lowerCamelCase_						:   Optional[Any]		= torch.from_numpy(A__					).permute(2						,						3						,						0						,						1					)
      elif "kernel" in key:
         lowerCamelCase_						:   Union[str, Any]		= torch.from_numpy(np.transpose(A__					)					)
      else:
         lowerCamelCase_						:   Any		= torch.from_numpy(A__					)

      # Replace HF parameters with original TF model parameters
      assert hf_params[hf_key].shape == new_hf_value.shape
      hf_params[hf_key].copy_(A__					)


@torch.no_grad()
def    __lowerCamelCase   (      A__						: Union[str, Any]						,						A__						: Optional[int]						,						A__						: Optional[int]						,						A__						: str					)     ->    Dict:
   lowerCamelCase_						:   List[Any]		= model_classes[model_name](
       include_top=A__						,						weights="""imagenet"""						,						input_tensor=A__						,						input_shape=A__						,						pooling=A__						,						classes=1000						,						classifier_activation="""softmax"""						,						)

   lowerCamelCase_						:   str		= original_model.trainable_variables
   lowerCamelCase_						:   Any		= original_model.non_trainable_variables
   lowerCamelCase_						:   Union[str, Any]		= {param.name: param.numpy() for param in tf_params}
   for param in tf_non_train_params:
      lowerCamelCase_						:   str		= param.numpy()
   lowerCamelCase_						:   int		= list(tf_params.keys()					)

   # Load HuggingFace model
   lowerCamelCase_						:   Tuple		= get_efficientnet_config(A__					)
   lowerCamelCase_						:   Optional[Any]		= EfficientNetForImageClassification(A__					).eval()
   lowerCamelCase_						:   int		= hf_model.state_dict()

   # Create src-to-dst parameter name mapping dictionary
   print("""Converting parameters..."""					)
   lowerCamelCase_						:   Tuple		= rename_keys(A__					)
   replace_params(A__						,						A__						,						A__					)

   # Initialize preprocessor and preprocess input image
   lowerCamelCase_						:   Optional[int]		= convert_image_processor(A__					)
   lowerCamelCase_						:   int		= preprocessor(images=prepare_img()						,						return_tensors="""pt"""					)

   # HF model inference
   hf_model.eval()
   with torch.no_grad():
      lowerCamelCase_						:   List[Any]		= hf_model(**A__					)
   lowerCamelCase_						:   Dict		= outputs.logits.detach().numpy()

   # Original model inference
   lowerCamelCase_						:   str		= False
   lowerCamelCase_						:   str		= CONFIG_MAP[model_name]["""image_size"""]
   lowerCamelCase_						:   Dict		= prepare_img().resize((image_size, image_size)						,						resample=PIL.Image.NEAREST					)
   lowerCamelCase_						:   Union[str, Any]		= image.img_to_array(A__					)
   lowerCamelCase_						:   Optional[Any]		= np.expand_dims(A__						,						axis=0					)
   lowerCamelCase_						:   Any		= original_model.predict(A__					)

   # Check whether original and HF model outputs match  -> np.allclose
   assert np.allclose(A__						,						A__						,						atol=1e-3					), "The predicted logits are not the same."
   print("""Model outputs match!"""					)

   if save_model:
      # Create folder to save model
      if not os.path.isdir(A__					):
         os.mkdir(A__					)
      # Save converted model and image processor
      hf_model.save_pretrained(A__					)
      preprocessor.save_pretrained(A__					)

   if push_to_hub:
      # Push model and image processor to hub
      print(f'''Pushing converted {model_name} to the hub...'''					)
      lowerCamelCase_						:   Tuple		= f'''efficientnet-{model_name}'''
      preprocessor.push_to_hub(A__					)
      hf_model.push_to_hub(A__					)


if __name__ == "__main__":
      snake_case__				:	int					       =					argparse.ArgumentParser()
      # Required parameters
      parser.add_argument(
          '--model_name',
          default='b0',
          type=str,
          help='Version name of the EfficientNet model you want to convert, select from [b0, b1, b2, b3, b4, b5, b6, b7].',
      )
      parser.add_argument(
          '--pytorch_dump_folder_path',
          default='hf_model',
          type=str,
          help='Path to the output PyTorch model directory.',
      )
      parser.add_argument('--save_model', action='store_true', help='Save model to local')
      parser.add_argument('--push_to_hub', action='store_true', help='Push model and image processor to the hub')

      snake_case__				:	Dict					       =					parser.parse_args()
      convert_efficientnet_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.save_model, args.push_to_hub)









import argparse
import json
from pathlib import Path

import requests
import torch
from huggingface_hub import hf_hub_download
from PIL import Image
from timm import create_model
from timm.data import resolve_data_config
from timm.data.transforms_factory import create_transform

from transformers import BitConfig, BitForImageClassification, BitImageProcessor
from transformers.image_utils import PILImageResampling
from transformers.utils import logging


logging.set_verbosity_info()
snake_case__				:	Dict					       =					logging.get_logger(__name__)


def    __lowerCamelCase   (      A__						: Optional[Any]					)     ->    List[str]:
   lowerCamelCase_						:   int		= """huggingface/label-files"""
   lowerCamelCase_						:   Dict		= """imagenet-1k-id2label.json"""
   lowerCamelCase_						:   Optional[Any]		= json.load(open(hf_hub_download(A__						,						A__						,						repo_type="""dataset"""					)						,						"""r"""					)					)
   lowerCamelCase_						:   str		= {int(A__					): v for k, v in idalabel.items()}
   lowerCamelCase_						:   List[Any]		= {v: k for k, v in idalabel.items()}

   lowerCamelCase_						:   str		= """std_conv""" if """bit""" in model_name else False

   # note that when using BiT as backbone for ViT-hybrid checkpoints,
   # one needs to additionally set config.layer_type = "bottleneck", config.stem_type = "same",
   # config.conv_layer = "std_conv_same"
   lowerCamelCase_						:   Optional[Any]		= BitConfig(
       conv_layer=A__						,						num_labels=1000						,						idalabel=A__						,						labelaid=A__						,						)

   return config


def    __lowerCamelCase   (      A__						: str					)     ->    Any:
   if "stem.conv" in name:
      lowerCamelCase_						:   Any		= name.replace("""stem.conv"""						,						"""bit.embedder.convolution"""					)
   if "blocks" in name:
      lowerCamelCase_						:   Dict		= name.replace("""blocks"""						,						"""layers"""					)
   if "head.fc" in name:
      lowerCamelCase_						:   Optional[Any]		= name.replace("""head.fc"""						,						"""classifier.1"""					)
   if name.startswith("""norm"""					):
      lowerCamelCase_						:   int		= """bit.""" + name
   if "bit" not in name and "classifier" not in name:
      lowerCamelCase_						:   str		= """bit.encoder.""" + name

   return name


def    __lowerCamelCase   (      )     ->    List[Any]:
   lowerCamelCase_						:   List[Any]		= """http://images.cocodataset.org/val2017/000000039769.jpg"""
   lowerCamelCase_						:   Optional[Any]		= Image.open(requests.get(A__						,						stream=A__					).raw					)
   return im


@torch.no_grad()
def    __lowerCamelCase   (      A__						: List[Any]						,						A__						: List[str]						,						A__						: Tuple=False					)     ->    List[str]:
   lowerCamelCase_						:   Optional[Any]		= get_config(A__					)

   # load original model from timm
   lowerCamelCase_						:   Optional[Any]		= create_model(A__						,						pretrained=A__					)
   timm_model.eval()

   # load state_dict of original model
   lowerCamelCase_						:   Optional[int]		= timm_model.state_dict()
   for key in state_dict.copy().keys():
      lowerCamelCase_						:   int		= state_dict.pop(A__					)
      lowerCamelCase_						:   Union[str, Any]		= val.squeeze() if """head""" in key else val

   # load HuggingFace model
   lowerCamelCase_						:   Tuple		= BitForImageClassification(A__					)
   model.eval()
   model.load_state_dict(A__					)

   # create image processor
   lowerCamelCase_						:   Optional[Any]		= create_transform(**resolve_data_config({}						,						model=A__					)					)
   lowerCamelCase_						:   List[Any]		= transform.transforms

   lowerCamelCase_						:   List[Any]		= {
       """bilinear""": PILImageResampling.BILINEAR,
       """bicubic""": PILImageResampling.BICUBIC,
       """nearest""": PILImageResampling.NEAREST,
   }

   lowerCamelCase_						:   List[str]		= BitImageProcessor(
       do_resize=A__						,						size={"""shortest_edge""": timm_transforms[0].size}						,						resample=pillow_resamplings[timm_transforms[0].interpolation.value]						,						do_center_crop=A__						,						crop_size={"""height""": timm_transforms[1].size[0], """width""": timm_transforms[1].size[1]}						,						do_normalize=A__						,						image_mean=timm_transforms[-1].mean.tolist()						,						image_std=timm_transforms[-1].std.tolist()						,						)

   lowerCamelCase_						:   int		= prepare_img()
   lowerCamelCase_						:   int		= transform(A__					).unsqueeze(0					)
   lowerCamelCase_						:   List[str]		= processor(A__						,						return_tensors="""pt"""					).pixel_values

   # verify pixel values
   assert torch.allclose(A__						,						A__					)

   # verify logits
   with torch.no_grad():
      lowerCamelCase_						:   str		= model(A__					)
      lowerCamelCase_						:   int		= outputs.logits

   print("""Logits:"""						,						logits[0, :3]					)
   print("""Predicted class:"""						,						model.config.idalabel[logits.argmax(-1					).item()]					)
   lowerCamelCase_						:   List[Any]		= timm_model(A__					)
   assert timm_logits.shape == outputs.logits.shape
   assert torch.allclose(A__						,						outputs.logits						,						atol=1e-3					)
   print("""Looks ok!"""					)

   if pytorch_dump_folder_path is not None:
      Path(A__					).mkdir(exist_ok=A__					)
      print(f'''Saving model {model_name} and processor to {pytorch_dump_folder_path}'''					)
      model.save_pretrained(A__					)
      processor.save_pretrained(A__					)

   if push_to_hub:
      print(f'''Pushing model {model_name} and processor to the hub'''					)
      model.push_to_hub(f'''ybelkada/{model_name}'''					)
      processor.push_to_hub(f'''ybelkada/{model_name}'''					)


if __name__ == "__main__":
      snake_case__				:	Dict					       =					argparse.ArgumentParser()
      # Required parameters
      parser.add_argument(
          '--model_name',
          default='resnetv2_50x1_bitm',
          type=str,
          help='Name of the BiT timm model 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(
          '--push_to_hub',
          action='store_true',
          help='Whether to push the model to the hub.',
      )

      snake_case__				:	int					       =					parser.parse_args()
      convert_bit_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)





