{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport os\nimport time, gc\nimport numpy as np\nimport pandas as pd\n\nimport tensorflow as tf\nimport keras\nfrom keras import backend as K\nfrom keras.models import Model, Input\nfrom keras.layers import Dense, Lambda\nfrom math import ceil\n\n# Install EfficientNet\n!pip install '../input/kerasefficientnetb3/efficientnet-1.0.0-py3-none-any.whl'\nimport efficientnet.keras as efn","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Constants\nHEIGHT = 137\nWIDTH = 236\nFACTOR = 0.70\nHEIGHT_NEW = int(HEIGHT * FACTOR)\nWIDTH_NEW = int(WIDTH * FACTOR)\nCHANNELS = 3\nBATCH_SIZE = 16\n\n# Dir\nDIR = '../input/bengaliai-cv19'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Image Preprocessing","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Image Size Summary\nprint(HEIGHT_NEW)\nprint(WIDTH_NEW)\n\n# Image Prep\ndef resize_image(img, WIDTH_NEW, HEIGHT_NEW):\n    # Invert\n    img = 255 - img\n\n    # Normalize\n    img = (img * (255.0 / img.max())).astype(np.uint8)\n\n    # Reshape\n    img = img.reshape(HEIGHT, WIDTH)\n    image_resized = cv2.resize(img, (WIDTH_NEW, HEIGHT_NEW), interpolation = cv2.INTER_AREA)\n\n    return image_resized.reshape(-1)   ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Generalized mean pool - GeM\ngm_exp = tf.Variable(3.0, dtype = tf.float32)\ndef generalized_mean_pool_2d(X):\n    pool = (tf.reduce_mean(tf.abs(X**(gm_exp)), \n                        axis = [1, 2], \n                        keepdims = False) + 1.e-7)**(1./gm_exp)\n    return pool","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create Model\ndef create_model(input_shape):\n    # Input Layer\n    input = Input(shape = input_shape)\n    \n    # Create and Compile Model and show Summary\n    x_model = efn.EfficientNetB3(weights = None, include_top = False, input_tensor = input, pooling = None, classes = None)\n    \n    # UnFreeze all layers\n    for layer in x_model.layers:\n        layer.trainable = True\n    \n    # GeM\n    lambda_layer = Lambda(generalized_mean_pool_2d)\n    lambda_layer.trainable_weights.extend([gm_exp])\n    x = lambda_layer(x_model.output)\n    \n    # multi output\n    grapheme_root = Dense(168, activation = 'softmax', name = 'root')(x)\n    vowel_diacritic = Dense(11, activation = 'softmax', name = 'vowel')(x)\n    consonant_diacritic = Dense(7, activation = 'softmax', name = 'consonant')(x)\n\n    # model\n    model = Model(inputs = x_model.input, outputs = [grapheme_root, vowel_diacritic, consonant_diacritic])\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create Model\nmodel1 = create_model(input_shape = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))\nmodel2 = create_model(input_shape = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))\nmodel3 = create_model(input_shape = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))\nmodel4 = create_model(input_shape = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))\nmodel5 = create_model(input_shape = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load Model Weights\nmodel1.load_weights('../input/kerasefficientnetb3/Train1_model_59.h5') \nmodel2.load_weights('../input/kerasefficientnetb3/Train1_model_64.h5') \nmodel3.load_weights('../input/kerasefficientnetb3/Train1_model_68.h5') \nmodel4.load_weights('../input/kerasefficientnetb3/Train1_model_57.h5') \nmodel5.load_weights('../input/kerasefficientnetb3/Train1_model_70.h5') ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Generator","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class TestDataGenerator(keras.utils.Sequence):\n    def __init__(self, X, batch_size = 16, img_size = (512, 512, 3), *args, **kwargs):\n        self.X = X\n        self.indices = np.arange(len(self.X))\n        self.batch_size = batch_size\n        self.img_size = img_size\n                    \n    def __len__(self):\n        return int(ceil(len(self.X) / self.batch_size))\n\n    def __getitem__(self, index):\n        indices = self.indices[index*self.batch_size:(index+1)*self.batch_size]\n        X = self.__data_generation(indices)\n        return X\n    \n    def __data_generation(self, indices):\n        X = np.empty((self.batch_size, *self.img_size))\n        \n        for i, index in enumerate(indices):\n            image = self.X[index]\n            image = np.stack((image,)*CHANNELS, axis=-1)\n            image = image.reshape(-1, HEIGHT_NEW, WIDTH_NEW, CHANNELS)\n            \n            X[i,] = image\n        \n        return X","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Predict and Submission","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create Submission File\ntgt_cols = ['grapheme_root','vowel_diacritic','consonant_diacritic']\n\n# Create Predictions\nrow_ids, targets = [], []\n\n# Loop through Test Parquet files (X)\nfor i in range(0, 4):\n    # Test Files Placeholder\n    test_files = []\n\n    # Read Parquet file\n    df = pd.read_parquet(os.path.join(DIR, 'test_image_data_'+str(i)+'.parquet'))\n    # Get Image Id values\n    image_ids = df['image_id'].values \n    # Drop Image_id column\n    df = df.drop(['image_id'], axis = 1)\n\n    # Loop over rows in Dataframe and generate images \n    X = []\n    for image_id, index in zip(image_ids, range(df.shape[0])):\n        test_files.append(image_id)\n        X.append(resize_image(df.loc[df.index[index]].values, WIDTH_NEW, HEIGHT_NEW))\n\n    # Data_Generator\n    data_generator_test = TestDataGenerator(X, batch_size = BATCH_SIZE, img_size = (HEIGHT_NEW, WIDTH_NEW, CHANNELS))\n        \n    # Predict with all 3 models\n    preds1 = model1.predict_generator(data_generator_test, verbose = 1)\n    preds2 = model2.predict_generator(data_generator_test, verbose = 1)\n    preds3 = model3.predict_generator(data_generator_test, verbose = 1)\n    preds4 = model4.predict_generator(data_generator_test, verbose = 1)\n    preds5 = model5.predict_generator(data_generator_test, verbose = 1)\n    \n    # Loop over Preds    \n    for i, image_id in zip(range(len(test_files)), test_files):\n        \n        for subi, col in zip(range(len(preds1)), tgt_cols):\n            sub_preds1 = preds1[subi]\n            sub_preds2 = preds2[subi]\n            sub_preds3 = preds3[subi]\n            sub_preds4 = preds4[subi]\n            sub_preds5 = preds5[subi]\n\n            # Set Prediction with average of 5 predictions\n            row_ids.append(str(image_id)+'_'+col)\n            sub_pred_value = np.argmax((sub_preds1[i] + sub_preds2[i] + sub_preds3[i] + sub_preds4[i] + sub_preds5[i]) / 5)\n            targets.append(sub_pred_value)\n    \n    # Cleanup\n    del df\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create and Save Submission File\nsubmit_df = pd.DataFrame({'row_id':row_ids,'target':targets}, columns = ['row_id','target'])\nsubmit_df.to_csv('submission.csv', index = False)\nprint(submit_df.head(40))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I hope you like it and if you find this kernel helpfull..then please don't forget to upvote it.****","execution_count":null}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}