{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is the updates version of the https://www.kaggle.com/ipythonx/keras-grapheme-gridmask-augmix-in-efficientnet. Other kernels from where I took code from is this https://www.kaggle.com/code1110/mixup-cutmix-in-keras. \n\nPlease upvote the kernel if you like it. "},{"metadata":{"trusted":true},"cell_type":"code","source":"import os \n\nos.listdir('../input')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/efficientnetgithub/efficientnet-1.0.0/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.__version__","execution_count":null,"outputs":[]},{"metadata":{"colab":{},"colab_type":"code","id":"6auBKrAZ0V5w","trusted":true},"cell_type":"code","source":"# general packages\nimport os\nimport cv2\nimport gc\nimport math\nimport random\nimport warnings\nimport time\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom glob import glob\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n# from tqdm.notebook import tqdm\nfrom tqdm import tqdm\n\n#sklearns \nfrom sklearn.metrics import cohen_kappa_score, accuracy_score, recall_score\nfrom sklearn.model_selection import train_test_split \n\nfrom tensorflow.keras.optimizers import Adam, Nadam, SGD\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Model, load_model, Sequential\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout, Conv2D, GlobalMaxPooling2D, concatenate\nfrom tensorflow.keras.layers import (MaxPooling2D, Input, Average, Activation, MaxPool2D,\n                          Flatten, LeakyReLU, BatchNormalization)\nfrom tensorflow.keras import models\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.preprocessing.image import load_img\nfrom tensorflow.keras.preprocessing.image import img_to_array\n\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras import utils as np_utils\nfrom tensorflow.keras.callbacks import (Callback, ModelCheckpoint,\n                                        LearningRateScheduler,EarlyStopping, \n                                        ReduceLROnPlateau,CSVLogger)\n# from keras_tqdm import TQDMNotebookCallback\n\nwarnings.simplefilter('ignore')\nsns.set_style('whitegrid')","execution_count":null,"outputs":[]},{"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":195},"colab_type":"code","executionInfo":{"elapsed":415299,"status":"ok","timestamp":1581827966888,"user":{"displayName":"Urvish Patel","photoUrl":"","userId":"01983570727953039713"},"user_tz":-330},"id":"Pr2N4SKU01VA","outputId":"e0234170-1351-4309-8b35-e7599a1415e7","trusted":true},"cell_type":"code","source":"# declare some parameter\nSEED = int(time.time())\nepoch = 3\nbatch_size = 32 \ndim = (125, 125)\nSIZE = 125\nstats = (0.0692, 0.2051)\nHEIGHT = 137 \nWIDTH = 236\n\ndef seed_all(SEED):\n    random.seed(SEED)\n    np.random.seed(SEED)\n    \n# seed all\nseed_all(SEED)\n\n# load files\nim_path = '../input/grapheme-imgs-128x128/'\ntrain = pd.read_csv('../input/bengaliai-cv19/train.csv')\ntest = pd.read_csv('../input/bengaliai-cv19/test.csv')\ntrain['filename'] = train.image_id.apply(lambda filename: im_path + filename + '.png')\n\n# top 5 samples\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"colab_type":"text","id":"wtJaeOBwKYsi"},"cell_type":"markdown","source":"# Data Augmentation  \nWe will be using following two augmentation method. The program will choose randomly one of them while training. \n\n- [GridMask](https://arxiv.org/abs/2001.04086): It utilizes information removal to achieve state-of-the-art results in a variety of computer vision tasks. It is based on the deletion of regions of the input image.\n- [AugMix](https://arxiv.org/abs/1912.02781): A data processing technique that is simple to implement, adds limited computational overhead, and helps models withstand unforeseen corruptions. \n\n### GridMask From [Qishen Ha](https://www.kaggle.com/haqishen/gridmask) "},{"metadata":{"colab":{},"colab_type":"code","id":"f0A3Ixks5eaY","trusted":true},"cell_type":"code","source":"## Grid Mask\n# code takesn from https://www.kaggle.com/haqishen/gridmask\n\nimport albumentations\nfrom albumentations.core.transforms_interface import DualTransform, ImageOnlyTransform\nfrom albumentations.augmentations import functional as F\n\nclass GridMask(DualTransform):\n    \"\"\"GridMask augmentation for image classification and object detection.\n\n    Args:\n        num_grid (int): number of grid in a row or column.\n        fill_value (int, float, lisf of int, list of float): value for dropped pixels.\n        rotate ((int, int) or int): range from which a random angle is picked. If rotate is a single int\n            an angle is picked from (-rotate, rotate). Default: (-90, 90)\n        mode (int):\n            0 - cropout a quarter of the square of each grid (left top)\n            1 - reserve a quarter of the square of each grid (left top)\n            2 - cropout 2 quarter of the square of each grid (left top & right bottom)\n\n    Targets:\n        image, mask\n\n    Image types:\n        uint8, float32\n\n    Reference:\n    |  https://arxiv.org/abs/2001.04086\n    |  https://github.com/akuxcw/GridMask\n    \"\"\"\n\n    def __init__(self, num_grid=3, fill_value=0, rotate=0, mode=0, always_apply=False, p=0.5):\n        super(GridMask, self).__init__(always_apply, p)\n        if isinstance(num_grid, int):\n            num_grid = (num_grid, num_grid)\n        if isinstance(rotate, int):\n            rotate = (-rotate, rotate)\n        self.num_grid = num_grid\n        self.fill_value = fill_value\n        self.rotate = rotate\n        self.mode = mode\n        self.masks = None\n        self.rand_h_max = []\n        self.rand_w_max = []\n\n    def init_masks(self, height, width):\n        if self.masks is None:\n            self.masks = []\n            n_masks = self.num_grid[1] - self.num_grid[0] + 1\n            for n, n_g in enumerate(range(self.num_grid[0], self.num_grid[1] + 1, 1)):\n                grid_h = height / n_g\n                grid_w = width / n_g\n                this_mask = np.ones((int((n_g + 1) * grid_h), int((n_g + 1) * grid_w))).astype(np.uint8)\n                for i in range(n_g + 1):\n                    for j in range(n_g + 1):\n                        this_mask[\n                             int(i * grid_h) : int(i * grid_h + grid_h / 2),\n                             int(j * grid_w) : int(j * grid_w + grid_w / 2)\n                        ] = self.fill_value\n                        if self.mode == 2:\n                            this_mask[\n                                 int(i * grid_h + grid_h / 2) : int(i * grid_h + grid_h),\n                                 int(j * grid_w + grid_w / 2) : int(j * grid_w + grid_w)\n                            ] = self.fill_value\n                \n                if self.mode == 1:\n                    this_mask = 1 - this_mask\n\n                self.masks.append(this_mask)\n                self.rand_h_max.append(grid_h)\n                self.rand_w_max.append(grid_w)\n\n    def apply(self, image, mask, rand_h, rand_w, angle, **params):\n        h, w = image.shape[:2]\n        mask = F.rotate(mask, angle) if self.rotate[1] > 0 else mask\n        mask = mask[:,:,np.newaxis] if image.ndim == 3 else mask\n        image *= mask[rand_h:rand_h+h, rand_w:rand_w+w].astype(image.dtype)\n        return image\n\n    def get_params_dependent_on_targets(self, params):\n        img = params['image']\n        height, width = img.shape[:2]\n        self.init_masks(height, width)\n\n        mid = np.random.randint(len(self.masks))\n        mask = self.masks[mid]\n        rand_h = np.random.randint(self.rand_h_max[mid])\n        rand_w = np.random.randint(self.rand_w_max[mid])\n        angle = np.random.randint(self.rotate[0], self.rotate[1]) if self.rotate[1] > 0 else 0\n\n        return {'mask': mask, 'rand_h': rand_h, 'rand_w': rand_w, 'angle': angle}\n\n    @property\n    def targets_as_params(self):\n        return ['image']\n\n    def get_transform_init_args_names(self):\n        return ('num_grid', 'fill_value', 'rotate', 'mode')","execution_count":null,"outputs":[]},{"metadata":{"colab_type":"text","id":"ybIAIoSUKYsl"},"cell_type":"markdown","source":"### AugMix From [Bibek](https://www.kaggle.com/bibek777/augmentation-augmix)"},{"metadata":{"colab":{},"colab_type":"code","id":"9GfIC3jGKwlA","trusted":true},"cell_type":"code","source":"# augmix : https://github.com/google-research/augmix\n\nfrom PIL import Image\nfrom PIL import ImageOps\nimport numpy as np\n\ndef int_parameter(level, maxval):\n    \"\"\"Helper function to scale `val` between 0 and maxval .\n    Args:\n    level: Level of the operation that will be between [0, `PARAMETER_MAX`].\n    maxval: Maximum value that the operation can have. This will be scaled to\n      level/PARAMETER_MAX.\n    Returns:\n    An int that results from scaling `maxval` according to `level`.\n    \"\"\"\n    return int(level * maxval / 10)\n\n\ndef float_parameter(level, maxval):\n    \"\"\"Helper function to scale `val` between 0 and maxval.\n    Args:\n    level: Level of the operation that will be between [0, `PARAMETER_MAX`].\n    maxval: Maximum value that the operation can have. This will be scaled to\n      level/PARAMETER_MAX.\n    Returns:\n    A float that results from scaling `maxval` according to `level`.\n    \"\"\"\n    return float(level) * maxval / 10.\n\ndef sample_level(n):\n    return np.random.uniform(low=0.1, high=n)\n\ndef autocontrast(pil_img, _):\n    return ImageOps.autocontrast(pil_img)\n\ndef equalize(pil_img, _):\n    return ImageOps.equalize(pil_img)\n\ndef posterize(pil_img, level):\n    level = int_parameter(sample_level(level), 4)\n    return ImageOps.posterize(pil_img, 4 - level)\n\ndef rotate(pil_img, level):\n    degrees = int_parameter(sample_level(level), 30)\n    if np.random.uniform() > 0.5:\n        degrees = -degrees\n    return pil_img.rotate(degrees, resample=Image.BILINEAR)\n\ndef solarize(pil_img, level):\n    level = int_parameter(sample_level(level), 256)\n    return ImageOps.solarize(pil_img, 256 - level)\n\ndef shear_x(pil_img, level):\n    level = float_parameter(sample_level(level), 0.3)\n    if np.random.uniform() > 0.5:\n        level = -level\n    return pil_img.transform((SIZE, SIZE),\n                           Image.AFFINE, (1, level, 0, 0, 1, 0),\n                           resample=Image.BILINEAR)\n\ndef shear_y(pil_img, level):\n    level = float_parameter(sample_level(level), 0.3)\n    if np.random.uniform() > 0.5:\n        level = -level\n    return pil_img.transform((SIZE, SIZE),\n                           Image.AFFINE, (1, 0, 0, level, 1, 0),\n                           resample=Image.BILINEAR)\n\ndef translate_x(pil_img, level):\n    level = int_parameter(sample_level(level), SIZE / 3)\n    if np.random.random() > 0.5:\n        level = -level\n    return pil_img.transform((SIZE, SIZE),\n                           Image.AFFINE, (1, 0, level, 0, 1, 0),\n                           resample=Image.BILINEAR)\n\n\ndef translate_y(pil_img, level):\n    level = int_parameter(sample_level(level), SIZE / 3)\n    if np.random.random() > 0.5:\n        level = -level\n    return pil_img.transform((SIZE, SIZE),\n                           Image.AFFINE, (1, 0, 0, 0, 1, level),\n                           resample=Image.BILINEAR)\n\naugmentations = [\n    autocontrast, equalize, posterize, rotate, solarize, shear_x, shear_y,\n    translate_x, translate_y\n]\n\n# taken from https://www.kaggle.com/iafoss/image-preprocessing-128x128\nMEAN = [ 0.06922848809290576,  0.06922848809290576,  0.06922848809290576]\nSTD = [ 0.20515700083327537,  0.20515700083327537,  0.20515700083327537]\n\ndef normalize(image):\n    \"\"\"Normalize input image channel-wise to zero mean and unit variance.\"\"\"\n    image = image.transpose(2, 0, 1)  # Switch to channel-first\n    mean, std = np.array(MEAN), np.array(STD)\n    image = (image - mean[:, None, None]) / std[:, None, None]\n    return image.transpose(1, 2, 0)\n\n\ndef apply_op(image, op, severity):\n    image = np.clip(image * 255., 0, 255).astype(np.uint8)\n    pil_img = Image.fromarray(image)  # Convert to PIL.Image\n    pil_img = op(pil_img, severity)\n    return np.asarray(pil_img) / 255.\n\n\ndef augment_and_mix(image, severity=1, width=3, depth=1, alpha=1.):\n    \"\"\"Perform AugMix augmentations and compute mixture.\n    Args:\n    image: Raw input image as float32 np.ndarray of shape (h, w, c)\n    severity: Severity of underlying augmentation operators (between 1 to 10).\n    width: Width of augmentation chain\n    depth: Depth of augmentation chain. -1 enables stochastic depth uniformly\n      from [1, 3]\n    alpha: Probability coefficient for Beta and Dirichlet distributions.\n    Returns:\n    mixed: Augmented and mixed image.\n  \"\"\"\n    ws = np.float32(\n      np.random.dirichlet([alpha] * width))\n    m = np.float32(np.random.beta(alpha, alpha))\n\n    mix = np.zeros_like(image)\n    for i in range(width):\n        image_aug = image.copy()\n        depth = depth if depth > 0 else np.random.randint(1, 4)\n        \n        for _ in range(depth):\n            op = np.random.choice(augmentations)\n            image_aug = apply_op(image_aug, op, severity)\n        mix = np.add(mix, ws[i] * normalize(image_aug), out=mix, \n                     casting=\"unsafe\")\n\n    mixed = (1 - m) * normalize(image) + m * mix\n    return mixed","execution_count":null,"outputs":[]},{"metadata":{"colab_type":"text","id":"BSKufUUYKYso"},"cell_type":"markdown","source":"# Grapheme Data Generator"},{"metadata":{"colab":{},"colab_type":"code","id":"_HE2FmYFK1uU","trusted":true},"cell_type":"code","source":"# helper for mixup\ndef get_rand_bbox(width, height, l):\n    r_x = np.random.randint(width)\n    r_y = np.random.randint(height)\n    r_l = np.sqrt(1 - l)\n    r_w = np.int(width * r_l)\n    r_h = np.int(height * r_l)\n    return r_x, r_y, r_l, r_w, r_h\n\nclass GraphemeGenerator(Sequence):\n    def __init__(self, data, batch_size, dim, shuffle=True, transform=None, mix_up_alpha = 0.0, cutmix_alpha = 0.0):\n        self._data = data\n        self._label_1 = pd.get_dummies(self._data['grapheme_root'], \n                                       columns = ['grapheme_root'])\n        self._label_2 = pd.get_dummies(self._data['vowel_diacritic'], \n                                       columns = ['vowel_diacritic'])\n        self._label_3 = pd.get_dummies(self._data['consonant_diacritic'], \n                                       columns = ['consonant_diacritic'])\n        self._list_idx = data.index.values\n        self._batch_size = batch_size\n        self._dim = dim\n        self._shuffle = shuffle\n        self.transform = transform\n        self.on_epoch_end()\n        \n        # Mix-up\n        assert mix_up_alpha >= 0.0\n        self.mix_up_alpha = mix_up_alpha\n        \n        # Cutmix\n        assert cutmix_alpha >= 0.0\n        self.cutmix_alpha = cutmix_alpha\n        \n    def __len__(self):\n        return int(np.floor(len(self._data)/self._batch_size))\n    \n    def __getitem__(self, index):\n        batch_idx = self._indices[index * self._batch_size:(index+1) * self._batch_size]\n        next_batch_idx = self._indices[(index + 1) * self._batch_size:(index+2) * self._batch_size if index>(len(self._data)-2) \n                                      else (index) * self._batch_size:(index+1) * self._batch_size]\n        \n        _idx = [self._list_idx[k] for k in batch_idx]\n        _next_idx = [self._list_idx[k] for k in next_batch_idx]\n        \n        X1, y1 = self.__get_data__(_idx)\n        X2, y2 = self.__get_data__(_next_idx)\n        \n        if self.transform is not None:\n            randInt = np.random.rand()\n            if randInt <= 0.5:\n                return self.mix_up(np.array(X1), y1, np.array(X2), y2)\n            else:\n                return self.cutmix(np.array(X1), y1, np.array(X2), y2)\n        else:\n            return X1, y1\n        \n    def on_epoch_end(self):\n        self._indices = np.arange(len(self._list_idx))\n        if self._shuffle:\n            np.random.shuffle(self._indices)\n    \n    def __get_data__(self, _idx):\n        Data     = np.empty((self._batch_size, *self._dim, 1))\n        Target_1 = np.empty((self._batch_size, 168), dtype = int)\n        Target_2 = np.empty((self._batch_size, 11 ), dtype = int)\n        Target_3 = np.empty((self._batch_size,  7 ), dtype = int)\n        \n        for i, k in enumerate(_idx):\n            # load the image file using cv2\n            image = cv2.imread(im_path + self._data['image_id'][k] + '.png')\n            image = (cv2.resize(image,  self._dim) / 255.0 - stats[0])/stats[1] \n            \n            if self.transform is not None:\n                randint = np.random.rand()\n                if randint <= 0.4:\n                    #pass\n                    # albumentation : grid mask\n                    res = self.transform(image=image)\n                    image = res['image']\n                elif randint > 0.4 and randint <=0.7:\n                    #pass\n                    # augmix augmentation\n                    image = augment_and_mix(image)\n                else:\n                    pass\n            \n            # gray scaling \n            gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114]) \n            image = gray(image)  \n            \n            # expand the axises \n            image = image[:, :, np.newaxis]\n            Data[i,:, :, :] =  image\n        \n            Target_1[i,:] = self._label_1.loc[k, :].values\n            Target_2[i,:] = self._label_2.loc[k, :].values\n            Target_3[i,:] = self._label_3.loc[k, :].values\n\n        return Data, [Target_1, Target_2, Target_3]\n    \n    def mix_up(self, X1, y1, X2, y2):\n        assert X1.shape[0] == X2.shape[0]\n        batch_size = X1.shape[0]\n        l = np.random.beta(self.mix_up_alpha, self.mix_up_alpha, batch_size)\n        X_l = l.reshape(batch_size, 1, 1, 1)\n        y_l = l.reshape(batch_size, 1)\n        X = X1 * X_l + X2 * (1-X_l)\n        return X, y1\n    \n    def cutmix(self, X1, y1, X2, y2):\n        assert X1.shape[0] == X2.shape[0]\n        lam = np.random.beta(self.cutmix_alpha, self.cutmix_alpha)\n        width = X1.shape[1]\n        height = X1.shape[0]\n        r_x, r_y, r_l, r_w, r_h = get_rand_bbox(width, height, lam)\n        bx1 = np.clip(r_x - r_w // 2, 0, width)\n        by1 = np.clip(r_y - r_h // 2, 0, height)\n        bx2 = np.clip(r_x + r_w // 2, 0, width)\n        by2 = np.clip(r_y + r_h // 2, 0, height)\n        X1[:, bx1:bx2, by1:by2, :] = X2[:, bx1:bx2, by1:by2, :]\n        X = X1\n        return X, y1","execution_count":null,"outputs":[]},{"metadata":{"colab_type":"text","id":"zRMlgUI1KYsr"},"cell_type":"markdown","source":"\n# Modeling"},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"import efficientnet.tfkeras as enf\n\n# enf.__dict__\nwg = '../input/efficientnet-tfkeras-weights-b0/efficientnet-b0_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\nefnet = enf.EfficientNetB0(weights=wg,\n                           include_top = False,\n                           input_shape=(125, 125, 3))","execution_count":null,"outputs":[]},{"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":454},"colab_type":"code","executionInfo":{"elapsed":1403,"status":"ok","timestamp":1581828094779,"user":{"displayName":"Urvish Patel","photoUrl":"","userId":"01983570727953039713"},"user_tz":-330},"id":"gQwscMZUQHuG","outputId":"1cc6a3d7-174b-4e74-93b8-d9c26a34c1c3","trusted":true},"cell_type":"code","source":"def create_model(input_dim, output_dim, base_model):\n    \n    input_tensor = Input(input_dim)\n    \n    x = Conv2D(3, (3, 3), padding='same',  kernel_initializer='he_uniform', \n               bias_initializer='zeros')(input_tensor)\n    curr_output = base_model(x)\n    curr_output = GlobalAveragePooling2D()(curr_output)\n    curr_output = Dropout(0.3)(curr_output)\n    curr_output = Dense(512, activation='elu')(curr_output)\n    curr_output = Dropout(0.5)(curr_output)\n        \n    oputput1 = Dense(168,  activation='softmax', name='gra') (curr_output)\n    oputput2 = Dense(11,  activation='softmax', name='vow') (curr_output)\n    oputput3 = Dense(7,  activation='softmax', name='cons') (curr_output)\n    output_tensor = [oputput1, oputput2, oputput3]\n\n    model = Model(input_tensor, output_tensor)\n    \n    return model\n\n# building the complete model\nmodel = create_model(input_dim=(125,125,1), output_dim=(168,11,7), base_model = efnet)\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"colab":{},"colab_type":"code","id":"wuQwPnGRN4c7","trusted":true},"cell_type":"code","source":"# compiling    \nmodel.compile(\n    \n    optimizer = Adam(learning_rate=0.0001), \n    \n    loss = {'gra' : 'categorical_crossentropy', \n            'vow' : 'categorical_crossentropy', \n            'cons': 'categorical_crossentropy'},\n    \n    loss_weights = {'gra' : 0.5,\n                    'vow' : 0.25,\n                    'cons': 0.25},\n    \n    metrics={'gra' : ['accuracy'], \n             'vow' : ['accuracy'], \n             'cons': ['accuracy']}\n)","execution_count":null,"outputs":[]},{"metadata":{"colab":{},"colab_type":"code","id":"3jZUqpeeQQ-J","trusted":true},"cell_type":"code","source":"# grid mask augmentation\ntransforms_train = albumentations.Compose([\n    GridMask(num_grid=3, rotate=15, p=1),\n])\n\n# for way one - data generator\ntrain_labels, val_labels = train_test_split(train, test_size = 0.20, \n                                            random_state = SEED)\n\n# training generator\ntrain_generator = GraphemeGenerator(train_labels, batch_size, dim, \n                                shuffle = True, transform=transforms_train, mix_up_alpha = 0.4, cutmix_alpha = 0.4)\n\n# validation generator: no shuffle , not augmentation\nval_generator = GraphemeGenerator(val_labels, batch_size, dim, \n                              shuffle = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def macro_recall(y_true, y_pred):\n    return recall_score(y_true, y_pred, average='macro')\n\nclass CustomCallback(tf.keras.callbacks.Callback):\n    def __init__(self, val_data, batch_size = 32):\n        super().__init__()\n        self.valid_data = val_data\n        self.batch_size = batch_size\n    \n    def on_epoch_begin(self,epoch, logs={}):\n        self.recall_scores = []\n        \n    def on_epoch_end(self, epoch, logs={}):\n        batches = len(self.valid_data)\n        total = batches * self.batch_size\n        self.val_recalls = {0: [], 1:[], 2:[]}\n        \n        for batch in range(batches):\n            xVal, yVal = self.valid_data.__getitem__(batch)\n            val_preds = self.model.predict(xVal)\n            \n            for i in range(3):\n                preds = np.argmax(val_preds[i], axis=1)\n                true = np.argmax(yVal[i], axis=1)\n                self.val_recalls[i].append(macro_recall(true, preds))\n        \n        for i in range(3):\n            self.recall_scores.append(np.average(self.val_recalls[i]))\n            \n        print(\"validation recall score: \", np.average(self.recall_scores, weights=[2, 1, 1]))\n        \n        return ","execution_count":null,"outputs":[]},{"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":222},"colab_type":"code","executionInfo":{"elapsed":11752462,"status":"ok","timestamp":1581800480407,"user":{"displayName":"Urvish Patel","photoUrl":"","userId":"01983570727953039713"},"user_tz":-330},"id":"Bm2ps__hhWuj","outputId":"e5c6b86d-8ed2-45f1-f198-268a8a4f6789","scrolled":true,"trusted":true},"cell_type":"code","source":"from tensorflow.keras.callbacks import (ModelCheckpoint, LearningRateScheduler,\n                             EarlyStopping, ReduceLROnPlateau, TensorBoard, CSVLogger)\n\n# some call back function; feel free to add more for experiment\ndef Call_Back():\n    learning_rate_reduction_root = ReduceLROnPlateau(monitor='gra_accuracy', \n                                            patience=3, \n                                            verbose=1,\n                                            factor=0.5, \n                                            min_lr=0.000001)\n    learning_rate_reduction_vowel = ReduceLROnPlateau(monitor='vow_accuracy', \n                                            patience=3, \n                                            verbose=1,\n                                            factor=0.5, \n                                            min_lr=0.000001)\n    learning_rate_reduction_consonant = ReduceLROnPlateau(monitor='cons_accuracy', \n                                            patience=3, \n                                            verbose=1,\n                                            factor=0.5, \n                                            min_lr=0.000001)\n    #lr_scheduler = LearningRateScheduler(schedule=lambda epoch: 0.001 * (0.9 ** epoch))\n    csv_logger = CSVLogger('E0Grapheme-B0-1-epochs.csv')\n    \n    custom_callback = CustomCallback(val_generator)\n    \n    return [csv_logger,custom_callback, \n            learning_rate_reduction_root, learning_rate_reduction_vowel, learning_rate_reduction_consonant]","execution_count":null,"outputs":[]},{"metadata":{"scrolled":false,"trusted":true},"cell_type":"code","source":"# epoch size \nepochs = 1 # increase the number, ex.: 100/200\ntraining = True # setting it true for training the model\n\n# calling all callbacks \ncallbacks = Call_Back()\n\nif training:\n    # acatual training (fitting)\n    train_history = model.fit(\n        train_generator,\n        steps_per_epoch=int(len(train_labels)/batch_size), \n        validation_data=val_generator,\n        validation_steps = int(len(val_labels)/batch_size),\n        epochs=epochs,\n        callbacks=callbacks, \n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"accelerator":"GPU","colab":{"authorship_tag":"ABX9TyN2gMGkIhGH+zKaw1ixF0gi","collapsed_sections":[],"name":"EfficientNet tf hub.ipynb","provenance":[]},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.3"}},"nbformat":4,"nbformat_minor":1}