





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

UpperCamelCase__					    =    {
    """b0""": efficientnet.EfficientNetBa,
    """b1""": efficientnet.EfficientNetBa,
    """b2""": efficientnet.EfficientNetBa,
    """b3""": efficientnet.EfficientNetBa,
    """b4""": efficientnet.EfficientNetBa,
    """b5""": efficientnet.EfficientNetBa,
    """b6""": efficientnet.EfficientNetBa,
    """b7""": efficientnet.EfficientNetBa,
}

UpperCamelCase__					    =    {
    """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 			_a   (		SCREAMING_SNAKE_CASE_							:       Optional[Any]  ):
					__lowerCAmelCase            = EfficientNetConfig()
					__lowerCAmelCase            = CONFIG_MAP[model_name]["hidden_dim"]
					__lowerCAmelCase            = CONFIG_MAP[model_name]["width_coef"]
					__lowerCAmelCase            = CONFIG_MAP[model_name]["depth_coef"]
					__lowerCAmelCase            = CONFIG_MAP[model_name]["image_size"]
					__lowerCAmelCase            = CONFIG_MAP[model_name]["dropout_rate"]
					__lowerCAmelCase            = CONFIG_MAP[model_name]["dw_padding"]

					__lowerCAmelCase            = "huggingface/label-files"
					__lowerCAmelCase            = "imagenet-1k-id2label.json"
					__lowerCAmelCase            = 10_00
					__lowerCAmelCase            = json.load(open(hf_hub_download(SCREAMING_SNAKE_CASE_   ,   SCREAMING_SNAKE_CASE_   ,   repo_type="dataset"  )   ,   "r"  )  )
					__lowerCAmelCase            = {int(SCREAMING_SNAKE_CASE_  ): v for k, v in idalabel.items()}

					__lowerCAmelCase            = idalabel
					__lowerCAmelCase            = {v: k for k, v in idalabel.items()}
					return config







def 			_a   (		):
					__lowerCAmelCase            = "http://images.cocodataset.org/val2017/000000039769.jpg"
					__lowerCAmelCase            = Image.open(requests.get(SCREAMING_SNAKE_CASE_   ,   stream=SCREAMING_SNAKE_CASE_  ).raw  )
					return im







def 			_a   (		SCREAMING_SNAKE_CASE_							:       str  ):
					__lowerCAmelCase            = CONFIG_MAP[model_name]["image_size"]
					__lowerCAmelCase            = EfficientNetImageProcessor(
					    size={"height": size, "width": size}   ,   image_mean=[0.4_85, 0.4_56, 0.4_06]   ,   image_std=[0.47_85_39_44, 0.4_73_28_64, 0.47_43_41_63]   ,   do_center_crop=SCREAMING_SNAKE_CASE_   ,   )
					return preprocessor







def 			_a   (		SCREAMING_SNAKE_CASE_							:       Union[str, Any]  ):
					__lowerCAmelCase            = [v.split("_"  )[0].split("block"  )[1] for v in original_param_names if v.startswith("block"  )]
					__lowerCAmelCase            = sorted(set(SCREAMING_SNAKE_CASE_  )  )
					__lowerCAmelCase            = len(SCREAMING_SNAKE_CASE_  )
					__lowerCAmelCase            = {b: str(SCREAMING_SNAKE_CASE_  ) for b, i in zip(SCREAMING_SNAKE_CASE_   ,   range(SCREAMING_SNAKE_CASE_  )  )}

					__lowerCAmelCase            = []
					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            = 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            = {}
					for item in rename_keys:
										if item[0] in original_param_names:
															__lowerCAmelCase            = "efficientnet." + item[1]

					__lowerCAmelCase            = "classifier.weight"
					__lowerCAmelCase            = "classifier.bias"
					return key_mapping







def 			_a   (		SCREAMING_SNAKE_CASE_							:       List[str]   ,   SCREAMING_SNAKE_CASE_							:       int   ,   SCREAMING_SNAKE_CASE_							:       Any  ):
					for key, value in tf_params.items():
										if "normalization" in key:
															continue

										__lowerCAmelCase            = key_mapping[key]
										if "_conv" in key and "kernel" in key:
															__lowerCAmelCase            = torch.from_numpy(SCREAMING_SNAKE_CASE_  ).permute(3   ,   2   ,   0   ,   1  )
										elif "depthwise_kernel" in key:
															__lowerCAmelCase            = torch.from_numpy(SCREAMING_SNAKE_CASE_  ).permute(2   ,   3   ,   0   ,   1  )
										elif "kernel" in key:
															__lowerCAmelCase            = torch.from_numpy(np.transpose(SCREAMING_SNAKE_CASE_  )  )
										else:
															__lowerCAmelCase            = 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   (		SCREAMING_SNAKE_CASE_							:       Tuple   ,   SCREAMING_SNAKE_CASE_							:       Any   ,   SCREAMING_SNAKE_CASE_							:       Any   ,   SCREAMING_SNAKE_CASE_							:       List[Any]  ):
					__lowerCAmelCase            = 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=10_00   ,   classifier_activation="softmax"   ,   )

					__lowerCAmelCase            = original_model.trainable_variables
					__lowerCAmelCase            = original_model.non_trainable_variables
					__lowerCAmelCase            = {param.name: param.numpy() for param in tf_params}
					for param in tf_non_train_params:
										__lowerCAmelCase            = param.numpy()
					__lowerCAmelCase            = list(tf_params.keys()  )

					# Load HuggingFace model
					__lowerCAmelCase            = get_efficientnet_config(SCREAMING_SNAKE_CASE_  )
					__lowerCAmelCase            = EfficientNetForImageClassification(SCREAMING_SNAKE_CASE_  ).eval()
					__lowerCAmelCase            = hf_model.state_dict()

					# Create src-to-dst parameter name mapping dictionary
					print("Converting parameters..."  )
					__lowerCAmelCase            = rename_keys(SCREAMING_SNAKE_CASE_  )
					replace_params(SCREAMING_SNAKE_CASE_   ,   SCREAMING_SNAKE_CASE_   ,   SCREAMING_SNAKE_CASE_  )

					# Initialize preprocessor and preprocess input image
					__lowerCAmelCase            = convert_image_processor(SCREAMING_SNAKE_CASE_  )
					__lowerCAmelCase            = preprocessor(images=prepare_img()   ,   return_tensors="pt"  )

					# HF model inference
					hf_model.eval()
					with torch.no_grad():
										__lowerCAmelCase            = hf_model(**SCREAMING_SNAKE_CASE_  )
					__lowerCAmelCase            = outputs.logits.detach().numpy()

					# Original model inference
					__lowerCAmelCase            = False
					__lowerCAmelCase            = CONFIG_MAP[model_name]["image_size"]
					__lowerCAmelCase            = prepare_img().resize((image_size, image_size)   ,   resample=PIL.Image.NEAREST  )
					__lowerCAmelCase            = image.img_to_array(SCREAMING_SNAKE_CASE_  )
					__lowerCAmelCase            = np.expand_dims(SCREAMING_SNAKE_CASE_   ,   axis=0  )
					__lowerCAmelCase            = 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..."""  )
										__lowerCAmelCase            = F"""efficientnet-{model_name}"""
										preprocessor.push_to_hub(SCREAMING_SNAKE_CASE_  )
										hf_model.push_to_hub(SCREAMING_SNAKE_CASE_  )


if __name__ == "__main__":
					UpperCamelCase__					    =    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""")

					UpperCamelCase__					    =    parser.parse_args()
					convert_efficientnet_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.save_model, args.push_to_hub)










def 			_a   (		SCREAMING_SNAKE_CASE_							:       int  ):
					if divisor % 5 == 0 or divisor % 2 == 0:
										return 0
					__lowerCAmelCase            = 1
					__lowerCAmelCase            = 1
					while repunit:
										__lowerCAmelCase            = (10 * repunit + 1) % divisor
										repunit_index += 1
					return repunit_index







def 			_a   (		SCREAMING_SNAKE_CASE_							:       int = 1_00_00_00  ):
					__lowerCAmelCase            = limit - 1
					if divisor % 2 == 0:
										divisor += 1
					while least_divisible_repunit(SCREAMING_SNAKE_CASE_  ) <= limit:
										divisor += 2
					return divisor


if __name__ == "__main__":
					print(f'''{solution() = }''')




