





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()
SCREAMING_SNAKE_CASE__       :			List[str]			      =						logging.get_logger(__name__)

SCREAMING_SNAKE_CASE__       :			Optional[int]			      =						{
    """b0""": efficientnet.EfficientNetBa,
    """b1""": efficientnet.EfficientNetBa,
    """b2""": efficientnet.EfficientNetBa,
    """b3""": efficientnet.EfficientNetBa,
    """b4""": efficientnet.EfficientNetBa,
    """b5""": efficientnet.EfficientNetBa,
    """b6""": efficientnet.EfficientNetBa,
    """b7""": efficientnet.EfficientNetBa,
}

SCREAMING_SNAKE_CASE__       :			Union[str, Any]			      =						{
    """b0""": {
        """hidden_dim""": 1_2_8_0,
        """width_coef""": 1.0,
        """depth_coef""": 1.0,
        """image_size""": 2_2_4,
        """dropout_rate""": 0.2,
        """dw_padding""": [],
    },
    """b1""": {
        """hidden_dim""": 1_2_8_0,
        """width_coef""": 1.0,
        """depth_coef""": 1.1,
        """image_size""": 2_4_0,
        """dropout_rate""": 0.2,
        """dw_padding""": [1_6],
    },
    """b2""": {
        """hidden_dim""": 1_4_0_8,
        """width_coef""": 1.1,
        """depth_coef""": 1.2,
        """image_size""": 2_6_0,
        """dropout_rate""": 0.3,
        """dw_padding""": [5, 8, 1_6],
    },
    """b3""": {
        """hidden_dim""": 1_5_3_6,
        """width_coef""": 1.2,
        """depth_coef""": 1.4,
        """image_size""": 3_0_0,
        """dropout_rate""": 0.3,
        """dw_padding""": [5, 1_8],
    },
    """b4""": {
        """hidden_dim""": 1_7_9_2,
        """width_coef""": 1.4,
        """depth_coef""": 1.8,
        """image_size""": 3_8_0,
        """dropout_rate""": 0.4,
        """dw_padding""": [6],
    },
    """b5""": {
        """hidden_dim""": 2_0_4_8,
        """width_coef""": 1.6,
        """depth_coef""": 2.2,
        """image_size""": 4_5_6,
        """dropout_rate""": 0.4,
        """dw_padding""": [1_3, 2_7],
    },
    """b6""": {
        """hidden_dim""": 2_3_0_4,
        """width_coef""": 1.8,
        """depth_coef""": 2.6,
        """image_size""": 5_2_8,
        """dropout_rate""": 0.5,
        """dw_padding""": [3_1],
    },
    """b7""": {
        """hidden_dim""": 2_5_6_0,
        """width_coef""": 2.0,
        """depth_coef""": 3.1,
        """image_size""": 6_0_0,
        """dropout_rate""": 0.5,
        """dw_padding""": [1_8],
    },
}






def       _A  (      lowerCamelCase   ):
   a__	:						Optional[Any]      		=  EfficientNetConfig()
   a__	:						List[str]      		=  CONFIG_MAP[model_name]["hidden_dim"]
   a__	:						Optional[Any]      		=  CONFIG_MAP[model_name]["width_coef"]
   a__	:						List[str]      		=  CONFIG_MAP[model_name]["depth_coef"]
   a__	:						Optional[int]      		=  CONFIG_MAP[model_name]["image_size"]
   a__	:						int      		=  CONFIG_MAP[model_name]["dropout_rate"]
   a__	:						List[str]      		=  CONFIG_MAP[model_name]["dw_padding"]

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

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






def       _A  (      ):
   a__	:						str      		=  "http://images.cocodataset.org/val2017/000000039769.jpg"
   a__	:						int      		=  Image.open(requests.get(_SCREAMING_SNAKE_CASE							, stream=_SCREAMING_SNAKE_CASE   ).raw   )
   return im






def       _A  (      lowerCamelCase   ):
   a__	:						List[str]      		=  CONFIG_MAP[model_name]["image_size"]
   a__	:						Dict      		=  EfficientNetImageProcessor(
       size={"height": size, "width": size}							, image_mean=[0.485, 0.456, 0.406]							, image_std=[0.47853944, 0.4732864, 0.47434163]							, do_center_crop=_SCREAMING_SNAKE_CASE							, )
   return preprocessor






def       _A  (      lowerCamelCase   ):
   a__	:						List[str]      		=  [v.split("_"   )[0].split("block"   )[1] for v in original_param_names if v.startswith("block"   )]
   a__	:						str      		=  sorted(set(_SCREAMING_SNAKE_CASE   )   )
   a__	:						str      		=  len(_SCREAMING_SNAKE_CASE   )
   a__	:						Dict      		=  {b: str(_SCREAMING_SNAKE_CASE   ) for b, i in zip(_SCREAMING_SNAKE_CASE							, range(_SCREAMING_SNAKE_CASE   )   )}

   a__	:						Optional[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:
      a__	:						Optional[int]      		=  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")   )

   a__	:						Optional[int]      		=  {}
   for item in rename_keys:
      if item[0] in original_param_names:
         a__	:						str      		=  "efficientnet." + item[1]

   a__	:						List[str]      		=  "classifier.weight"
   a__	:						Union[str, Any]      		=  "classifier.bias"
   return key_mapping






def       _A  (      lowerCamelCase							, lowerCamelCase							, lowerCamelCase   ):
   for key, value in tf_params.items():
      if "normalization" in key:
         continue

      a__	:						List[Any]      		=  key_mapping[key]
      if "_conv" in key and "kernel" in key:
         a__	:						Optional[Any]      		=  torch.from_numpy(_SCREAMING_SNAKE_CASE   ).permute(3							, 2							, 0							, 1   )
      elif "depthwise_kernel" in key:
         a__	:						Any      		=  torch.from_numpy(_SCREAMING_SNAKE_CASE   ).permute(2							, 3							, 0							, 1   )
      elif "kernel" in key:
         a__	:						Dict      		=  torch.from_numpy(np.transpose(_SCREAMING_SNAKE_CASE   )   )
      else:
         a__	:						Tuple      		=  torch.from_numpy(_SCREAMING_SNAKE_CASE   )

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






@torch.no_grad()
def       _A  (      lowerCamelCase							, lowerCamelCase							, lowerCamelCase							, lowerCamelCase   ):
   a__	:						Dict      		=  model_classes[model_name](
       include_top=_SCREAMING_SNAKE_CASE							, weights="imagenet"							, input_tensor=_SCREAMING_SNAKE_CASE							, input_shape=_SCREAMING_SNAKE_CASE							, pooling=_SCREAMING_SNAKE_CASE							, classes=1000							, classifier_activation="softmax"							, )

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

   # Load HuggingFace model
   a__	:						Optional[Any]      		=  get_efficientnet_config(_SCREAMING_SNAKE_CASE   )
   a__	:						List[str]      		=  EfficientNetForImageClassification(_SCREAMING_SNAKE_CASE   ).eval()
   a__	:						Any      		=  hf_model.state_dict()

   # Create src-to-dst parameter name mapping dictionary
   print("Converting parameters..."   )
   a__	:						Any      		=  rename_keys(_SCREAMING_SNAKE_CASE   )
   replace_params(_SCREAMING_SNAKE_CASE							, _SCREAMING_SNAKE_CASE							, _SCREAMING_SNAKE_CASE   )

   # Initialize preprocessor and preprocess input image
   a__	:						Optional[Any]      		=  convert_image_processor(_SCREAMING_SNAKE_CASE   )
   a__	:						Dict      		=  preprocessor(images=prepare_img()							, return_tensors="pt"   )

   # HF model inference
   hf_model.eval()
   with torch.no_grad():
      a__	:						Tuple      		=  hf_model(**_SCREAMING_SNAKE_CASE   )
   a__	:						Any      		=  outputs.logits.detach().numpy()

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

   # Check whether original and HF model outputs match  -> np.allclose
   assert np.allclose(_SCREAMING_SNAKE_CASE							, _SCREAMING_SNAKE_CASE							, 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(_SCREAMING_SNAKE_CASE   ):
         os.mkdir(_SCREAMING_SNAKE_CASE   )
      # Save converted model and image processor
      hf_model.save_pretrained(_SCREAMING_SNAKE_CASE   )
      preprocessor.save_pretrained(_SCREAMING_SNAKE_CASE   )

   if push_to_hub:
      # Push model and image processor to hub
      print(F"""Pushing converted {model_name} to the hub..."""   )
      a__	:						List[Any]      		=  F"""efficientnet-{model_name}"""
      preprocessor.push_to_hub(_SCREAMING_SNAKE_CASE   )
      hf_model.push_to_hub(_SCREAMING_SNAKE_CASE   )


if __name__ == "__main__":
  SCREAMING_SNAKE_CASE__       :			List[Any]			      =						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""")

  SCREAMING_SNAKE_CASE__       :			List[Any]			      =						parser.parse_args()
  convert_efficientnet_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.save_model, args.push_to_hub)









# Lint as: python3
import itertools
import os
import re


SCREAMING_SNAKE_CASE__       :			Tuple			      =						re.compile(R"""([A-Z]+)([A-Z][a-z])""")
SCREAMING_SNAKE_CASE__       :			List[str]			      =						re.compile(R"""([a-z\d])([A-Z])""")

SCREAMING_SNAKE_CASE__       :			Tuple			      =						re.compile(R"""(?<!_)_(?!_)""")
SCREAMING_SNAKE_CASE__       :			Dict			      =						re.compile(R"""(_{2,})""")

SCREAMING_SNAKE_CASE__       :			List[Any]			      =						R"""^\w+(\.\w+)*$"""

SCREAMING_SNAKE_CASE__       :			Union[str, Any]			      =						R"""<>:/\|?*"""






def       _A  (      lowerCamelCase   ):
   a__	:						List[str]      		=  _uppercase_uppercase_re.sub(r"\1_\2"							, lowerCamelCase   )
   a__	:						Dict      		=  _lowercase_uppercase_re.sub(r"\1_\2"							, lowerCamelCase   )
   return name.lower()






def       _A  (      lowerCamelCase   ):
   a__	:						Tuple      		=  _single_underscore_re.split(lowerCamelCase   )
   a__	:						Any      		=  [_multiple_underscores_re.split(lowerCamelCase   ) for n in name]
   return "".join(n.capitalize() for n in itertools.chain.from_iterable(lowerCamelCase   ) if n != ""   )






def       _A  (      lowerCamelCase   ):
   if os.path.basename(lowerCamelCase   ) != name:
      raise ValueError(F"""Should be a dataset name, not a path: {name}"""   )
   return camelcase_to_snakecase(lowerCamelCase   )






def       _A  (      lowerCamelCase							, lowerCamelCase   ):
   if os.path.basename(lowerCamelCase   ) != name:
      raise ValueError(F"""Should be a dataset name, not a path: {name}"""   )
   if not re.match(_split_re							, lowerCamelCase   ):
      raise ValueError(F"""Split name should match '{_split_re}'' but got '{split}'."""   )
   return F"""{filename_prefix_for_name(lowerCamelCase   )}-{split}"""






def       _A  (      lowerCamelCase							, lowerCamelCase							, lowerCamelCase							, lowerCamelCase=None   ):
   a__	:						Union[str, Any]      		=  filename_prefix_for_split(lowerCamelCase							, lowerCamelCase   )
   if filetype_suffix:
      prefix += F""".{filetype_suffix}"""
   a__	:						Any      		=  os.path.join(lowerCamelCase							, lowerCamelCase   )
   return F"""{filepath}*"""






def       _A  (      lowerCamelCase							, lowerCamelCase							, lowerCamelCase							, lowerCamelCase=None							, lowerCamelCase=None   ):
   a__	:						List[str]      		=  filename_prefix_for_split(lowerCamelCase							, lowerCamelCase   )
   a__	:						Tuple      		=  os.path.join(lowerCamelCase							, lowerCamelCase   )

   if shard_lengths:
      a__	:						List[str]      		=  len(lowerCamelCase   )
      a__	:						str      		=  [F"""{prefix}-{shard_id:05d}-of-{num_shards:05d}""" for shard_id in range(lowerCamelCase   )]
      if filetype_suffix:
         a__	:						Optional[Any]      		=  [filename + F""".{filetype_suffix}""" for filename in filenames]
      return filenames
   else:
      a__	:						Optional[int]      		=  prefix
      if filetype_suffix:
         filename += F""".{filetype_suffix}"""
      return [filename]

