{"cells":[{"metadata":{},"cell_type":"markdown","source":"https://www.kaggle.com/abebe9849/bengali-ai-simple-densenet-in-keras　を参考にmodelをefficientnetb0に"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nload_dir = '../input/grapheme-imgs-128x128/'\n\ntrain = pd.read_csv('/kaggle/input/bengaliai-cv19/train.csv')\ntrain['filename'] = train.image_id.apply(lambda filename: load_dir + filename + '.png')\n\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nimport os, time, random, glob, pickle, warnings, math\n\nfrom keras import backend as K\nimport tensorflow as tf\nfrom keras.backend.tensorflow_backend import set_session\nfrom keras.models import Model\nfrom keras.applications.vgg16 import VGG16\nfrom keras.applications.resnet50 import  ResNet50\nfrom keras.applications.densenet import  DenseNet121\nfrom keras.layers import GlobalMaxPooling2D,Conv2D, Dense,BatchNormalization,Flatten,Input, Multiply ,Dropout,GlobalAveragePooling2D\nfrom keras.utils import Sequence\nfrom keras.optimizers import Adam\nfrom keras import optimizers\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ModelCheckpoint\nimport cv2\nwarnings.filterwarnings('ignore') # warningを非表示にする\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # kerasのwarningを非表示にする","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from __future__ import print_function\nfrom __future__ import absolute_import\n\nimport warnings\n\nfrom keras.layers import Input\nfrom keras import layers\nfrom keras.layers import Dense\nfrom keras.layers import Activation\nfrom keras.layers import Flatten\nfrom keras.layers import Conv2D\nfrom keras.layers import MaxPooling2D\nfrom keras.layers import AveragePooling2D\nfrom keras.layers import GlobalAveragePooling2D\nfrom keras.layers import GlobalMaxPooling2D\nfrom keras.layers import BatchNormalization\nfrom keras.layers import Reshape\nfrom keras.layers import Multiply\nfrom keras.models import Model\nfrom keras import backend as K\nfrom keras.engine.topology import get_source_inputs\nfrom keras.utils import layer_utils\nfrom keras.utils.data_utils import get_file\n#from keras.applications.imagenet_utils import _obtain_input_shape\n\n\ndef preprocess_input(x):\n    # 'RGB'->'BGR'\n    x = x[..., ::-1]\n    \n    # Zero-center by mean pixel\n    x[..., 0] -= 103.939\n    x[..., 1] -= 116.779\n    x[..., 2] -= 123.68\n\n    # Scale\n    x *= 0.017\n    return x\n  \ndef identity_block(input_tensor, kernel_size, filters, stage, block):\n    filters1, filters2, filters3 = filters\n    if K.image_data_format() == 'channels_last':\n        bn_axis = 3\n    else:\n        bn_axis = 1\n    bn_eps = 0.0001\n        \n    block_name = str(stage) + \"_\" + str(block)\n    conv_name_base = \"conv\" + block_name\n    relu_name_base = \"relu\" + block_name\n\n    x = Conv2D(filters1, (1, 1), use_bias=False, name=conv_name_base + '_x1')(input_tensor)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x1_bn')(x)\n    x = Activation('relu', name=relu_name_base + '_x1')(x)\n\n    x = Conv2D(filters2, kernel_size, padding='same', use_bias=False, name=conv_name_base + '_x2')(x)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x2_bn')(x)\n    x = Activation('relu', name=relu_name_base + '_x2')(x)\n\n    x = Conv2D(filters3, (1, 1), use_bias=False, name=conv_name_base + '_x3')(x)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x3_bn')(x)\n\n    se = GlobalAveragePooling2D(name='pool' + block_name + '_gap')(x)\n    se = Dense(filters3 // 16, activation='relu', name = 'fc' + block_name + '_sqz')(se)\n    se = Dense(filters3, activation='sigmoid', name = 'fc' + block_name + '_exc')(se)\n    se = Reshape([1, 1, filters3])(se)\n    x = Multiply(name='scale' + block_name)([x, se])\n\n    x = layers.add([x, input_tensor], name='block_' + block_name)\n    x = Activation('relu', name=relu_name_base)(x)\n    return x\n\n\ndef conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):\n    filters1, filters2, filters3 = filters\n    if K.image_data_format() == 'channels_last':\n        bn_axis = 3\n    else:\n        bn_axis = 1\n    bn_eps = 0.0001\n    \n    block_name = str(stage) + \"_\" + str(block)\n    conv_name_base = \"conv\" + block_name\n    relu_name_base = \"relu\" + block_name\n\n    x = Conv2D(filters1, (1, 1), use_bias=False, name=conv_name_base + '_x1')(input_tensor)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x1_bn')(x)\n    x = Activation('relu', name=relu_name_base + '_x1')(x)\n\n    x = Conv2D(filters2, kernel_size, strides=strides, padding='same', use_bias=False, name=conv_name_base + '_x2')(x)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x2_bn')(x)\n    x = Activation('relu', name=relu_name_base + '_x2')(x)\n\n    x = Conv2D(filters3, (1, 1), use_bias=False, name=conv_name_base + '_x3')(x)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_x3_bn')(x)\n    \n    se = GlobalAveragePooling2D(name='pool' + block_name + '_gap')(x)\n    se = Dense(filters3 // 16, activation='relu', name = 'fc' + block_name + '_sqz')(se)\n    se = Dense(filters3, activation='sigmoid', name = 'fc' + block_name + '_exc')(se)\n    se = Reshape([1, 1, filters3])(se)\n    x = Multiply(name='scale' + block_name)([x, se])\n    \n    shortcut = Conv2D(filters3, (1, 1), strides=strides, use_bias=False, name=conv_name_base + '_prj')(input_tensor)\n    shortcut = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name=conv_name_base + '_prj_bn')(shortcut)\n\n    x = layers.add([x, shortcut], name='block_' + block_name)\n    x = Activation('relu', name=relu_name_base)(x)\n    return x\n\n\ndef SEResNet50(include_top=True, weights='imagenet',\n               input_tensor=None, input_shape=(125,125,3),\n               pooling=None,\n               classes=1000):\n\n    # Determine proper input shape\n    input_shape=(125,125,3)\n\n    if input_tensor is None:\n        img_input = Input(shape=input_shape)\n    else:\n        if not K.is_keras_tensor(input_tensor):\n            img_input = Input(tensor=input_tensor, shape=input_shape)\n        else:\n            img_input = input_tensor\n    if K.image_data_format() == 'channels_last':\n        bn_axis = 3\n    else:\n        bn_axis = 1\n    bn_eps = 0.0001\n\n    x = Conv2D(64, (7, 7), strides=(2, 2), padding='same', use_bias=False, name='conv1')(img_input)\n    x = BatchNormalization(axis=bn_axis, epsilon=bn_eps, name='conv1_bn')(x)\n    x = Activation('relu', name='relu1')(x)\n    x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(x)\n\n    x = conv_block(x, 3, [64, 64, 256], stage=2, block=1, strides=(1, 1))\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block=2)\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block=3)\n\n    x = conv_block(x, 3, [128, 128, 512], stage=3, block=1)\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block=2)\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block=3)\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block=4)\n\n    x = conv_block(x, 3, [256, 256, 1024], stage=4, block=1)\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block=2)\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block=3)\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block=4)\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block=5)\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block=6)\n\n    x = conv_block(x, 3, [512, 512, 2048], stage=5, block=1)\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block=2)\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block=3)\n\n\n    # Ensure that the model takes into account\n    # any potential predecessors of `input_tensor`.\n    if input_tensor is not None:\n        inputs = get_source_inputs(input_tensor)\n    else:\n        inputs = img_input\n    # Create model.\n    model = Model(inputs, x, name='se-resnet50')\n    return model  \n  \n  \nse_resnet50 = SEResNet50(weights=None, input_shape=(125, 125, 3),include_top=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/efficientnet-keras-source-code/repository/qubvel-efficientnet-c993591\nimport efficientnet.keras as efn \nfrom keras.applications.resnet50 import ResNet50\n# we will be using EfficientNetB0\nwg0 = '../input/efficientnet-keras-weights-b0b5/efficientnet-b0_imagenet_1000_notop.h5'\nwg1 = '../input/efficientnet-keras-weights-b0b5/efficientnet-b1_imagenet_1000_notop.h5'\nwg2 = '../input/efficientnet-keras-weights-b0b5/efficientnet-b2_imagenet_1000_notop.h5'\nwg3 = '../input/efficientnet-keras-weights-b0b5/efficientnet-b3_imagenet_1000_notop.h5'\n#wg_res=\"../input/resnet-50\"\nefnet_b0 = efn.EfficientNetB0(weights=wg0, include_top = False, input_shape=(125, 125, 3))\nefnet_b1 = efn.EfficientNetB1(weights=wg1, include_top = False, input_shape=(125, 125, 3))\nefnet_b2 = efn.EfficientNetB2(weights=wg2, include_top = False, input_shape=(125, 125, 3))\nefnet_b3 = efn.EfficientNetB3(weights=wg3, include_top = False, input_shape=(125, 125, 3))\n\nprint(tf.keras.__version__)\nprint(tf.__version__)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# code: https://github.com/titu1994/keras-adabound   \nclass AdaBound(optimizers.Optimizer):\n    \"\"\"AdaBound optimizer.\n    Default parameters follow those provided in the original paper.\n    # Arguments\n        lr: float >= 0. Learning rate.\n        final_lr: float >= 0. Final learning rate.\n        beta_1: float, 0 < beta < 1. Generally close to 1.\n        beta_2: float, 0 < beta < 1. Generally close to 1.\n        gamma: float >= 0. Convergence speed of the bound function.\n        epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`.\n        decay: float >= 0. Learning rate decay over each update.\n        weight_decay: Weight decay weight.\n        amsbound: boolean. Whether to apply the AMSBound variant of this\n            algorithm.\n    # References\n        - [Adaptive Gradient Methods with Dynamic Bound of Learning Rate]\n          (https://openreview.net/forum?id=Bkg3g2R9FX)\n        - [Adam - A Method for Stochastic Optimization]\n          (https://arxiv.org/abs/1412.6980v8)\n        - [On the Convergence of Adam and Beyond]\n          (https://openreview.net/forum?id=ryQu7f-RZ)\n    \"\"\"\n\n    def __init__(self, learning_rate=0.001, final_lr=0.1, beta_1=0.9, beta_2=0.999, gamma=1e-3,\n                 epsilon=None, decay=0., amsbound=False, weight_decay=0.0, **kwargs):\n        super(AdaBound, self).__init__(**kwargs)\n\n        if not 0. <= gamma <= 1.:\n            raise ValueError(\"Invalid `gamma` parameter. Must lie in [0, 1] range.\")\n\n        with K.name_scope(self.__class__.__name__):\n            self.iterations = K.variable(0, dtype='int64', name='iterations')\n            self.learning_rate = K.variable(learning_rate, name='learning_rate')\n            self.beta_1 = K.variable(beta_1, name='beta_1')\n            self.beta_2 = K.variable(beta_2, name='beta_2')\n            self.decay = K.variable(decay, name='decay')\n\n        self.final_lr = final_lr\n        self.gamma = gamma\n\n        if epsilon is None:\n            epsilon = K.epsilon()\n        self.epsilon = epsilon\n        self.initial_decay = decay\n        self.amsbound = amsbound\n\n        self.weight_decay = float(weight_decay)\n        self.base_lr = float(learning_rate)\n\n    def get_updates(self, loss, params):\n        grads = self.get_gradients(loss, params)\n        self.updates = [K.update_add(self.iterations, 1)]\n\n        learning_rate = self.learning_rate\n        if self.initial_decay > 0:\n            learning_rate = learning_rate * (1. / (1. + self.decay * K.cast(self.iterations,\n                                                      K.dtype(self.decay))))\n\n        t = K.cast(self.iterations, K.floatx()) + 1\n\n        # Applies bounds on actual learning rate\n        step_size = learning_rate * (K.sqrt(1. - K.pow(self.beta_2, t)) /\n                          (1. - K.pow(self.beta_1, t)))\n\n        final_lr = self.final_lr * learning_rate / self.base_lr\n        lower_bound = final_lr * (1. - 1. / (self.gamma * t + 1.))\n        upper_bound = final_lr * (1. + 1. / (self.gamma * t))\n\n        ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]\n        vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]\n        if self.amsbound:\n            vhats = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]\n        else:\n            vhats = [K.zeros(1) for _ in params]\n        self.weights = [self.iterations] + ms + vs + vhats\n\n        for p, g, m, v, vhat in zip(params, grads, ms, vs, vhats):\n            # apply weight decay\n            if self.weight_decay != 0.:\n                g += self.weight_decay * K.stop_gradient(p)\n\n            m_t = (self.beta_1 * m) + (1. - self.beta_1) * g\n            v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g)\n\n            if self.amsbound:\n                vhat_t = K.maximum(vhat, v_t)\n                denom = (K.sqrt(vhat_t) + self.epsilon)\n                self.updates.append(K.update(vhat, vhat_t))\n            else:\n                denom = (K.sqrt(v_t) + self.epsilon)\n\n            # Compute the bounds\n            step_size_p = step_size * K.ones_like(denom)\n            step_size_p_bound = step_size_p / denom\n            bounded_lr_t = m_t * K.minimum(K.maximum(step_size_p_bound,\n                                                     lower_bound), upper_bound)\n\n            p_t = p - bounded_lr_t\n\n            self.updates.append(K.update(m, m_t))\n            self.updates.append(K.update(v, v_t))\n            new_p = p_t\n\n            # Apply constraints.\n            if getattr(p, 'constraint', None) is not None:\n                new_p = p.constraint(new_p)\n\n            self.updates.append(K.update(p, new_p))\n        return self.updates\n\n    def get_config(self):\n        config = {'learning_rate': float(K.get_value(self.learning_rate)),\n                  'final_lr': float(self.final_lr),\n                  'beta_1': float(K.get_value(self.beta_1)),\n                  'beta_2': float(K.get_value(self.beta_2)),\n                  'gamma': float(self.gamma),\n                  'decay': float(K.get_value(self.decay)),\n                  'epsilon': self.epsilon,\n                  'weight_decay': self.weight_decay,\n                  'amsbound': self.amsbound}\n        base_config = super(AdaBound, self).get_config()\n        return dict(list(base_config.items()) + list(config.items()))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def get_model(base_model):   \n    input_=Input((125,125,1))\n    x = Conv2D(3, (3, 3), padding='same')(input_)\n    base_model=base_model(x)\n    x = BatchNormalization()(base_model)\n    x = Dropout(0.5)(x)\n    x=Flatten()(x)\n    x = Dense(256, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.5)(x)\n    out_grapheme = Dense(168, activation='softmax', name='grapheme')(x)\n    out_vowel = Dense(11, activation='softmax', name='vowel')(x)\n    out_consonant = Dense(7, activation='softmax', name='consonant')(x)\n    \n    return Model(inputs=input_, outputs=[out_grapheme, out_vowel, out_consonant])\nmodel_se_resnet=get_model(se_resnet50)\nmodel_se_resnet.summary()\nmodel_se_resnet.compile(AdaBound(), metrics=['accuracy'], loss='sparse_categorical_crossentropy')\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_pad_width(im, new_shape, is_rgb=True):\n    pad_diff = new_shape - im.shape[0], new_shape - im.shape[1]\n    t, b = math.floor(pad_diff[0]/2), math.ceil(pad_diff[0]/2)\n    l, r = math.floor(pad_diff[1]/2), math.ceil(pad_diff[1]/2)\n    if is_rgb:\n        pad_width = ((t,b), (l,r), (0, 0))\n    else:\n        pad_width = ((t,b), (l,r))\n    return pad_width","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(cv2.__version__)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{"trusted":true},"cell_type":"code","source":"def crop_object(file, thresh=220, maxval=255, square=True):\n    \"\"\"\n    Source: https://stackoverflow.com/questions/49577973/how-to-crop-the-biggest-object-in-image-with-python-opencv\n    \"\"\"\n    img=cv2.imread(file)\n    gray = cv2.imread(file,cv2.IMREAD_GRAYSCALE) # convert to grayscale\n    # threshold to get just the signature (INVERTED)\n    retval, thresh_gray = cv2.threshold(gray, thresh=thresh, maxval=maxval, type=cv2.THRESH_BINARY_INV)\n\n    contours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)\n\n    # Find object with the biggest bounding box\n    mx = (0,0,0,0)      # biggest bounding box so far\n    mx_area = 0\n    for cont in contours:\n        x,y,w,h = cv2.boundingRect(cont)\n        area = w*h\n        if area > mx_area:\n            mx = x,y,w,h\n            mx_area = area\n    x,y,w,h = mx\n    \n    crop = img[y:y+h, x:x+w]\n    \n    if square:\n        pad_width = get_pad_width(crop, max(crop.shape))\n        crop = np.pad(crop, pad_width=pad_width, mode='constant', constant_values=255)\n    \n    return crop","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def data_generator(filenames, y, batch_size=64, shape=(125, 125, 1), random_state=2019):\n    y = y.copy()\n    np.random.seed(random_state)\n    indices = np.arange(len(filenames))\n    \n    while True:\n        np.random.shuffle(indices)\n        \n        for i in range(0, len(indices), batch_size):\n            batch_idx = indices[i:i+batch_size]\n            size = len(batch_idx)\n            \n            batch_files = filenames[batch_idx]\n            X_batch = np.zeros((size, *shape))\n            y_batch = y[batch_idx]\n            \n            for i, file in enumerate(batch_files):\n                img = crop_object(file, thresh=220)\n                img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n                img = cv2.resize(img, shape[:2])\n                X_batch[i, :, :, 0] = img / 255.\n            \n            yield X_batch, [y_batch[:, i] for i in range(y_batch.shape[1])]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tra_files=train.filename.values[:100]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#test\nthresh=220\nmaxval=255\nfile=tra_files[0]\nimg=cv2.imread(file)\nprint(img.shape)\ngray = cv2.imread(file,cv2.IMREAD_GRAYSCALE) # convert to grayscale\n    # threshold to get just the signature (INVERTED) \nretval, thresh_gray = cv2.threshold(gray, thresh=thresh, maxval=maxval, type=cv2.THRESH_BINARY_INV)\n\ncontours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)\n\n    # Find object with the biggest bounding box\nmx = (0,0,0,0)      # biggest bounding box so far\nmx_area = 0\nfor cont in contours:\n    x,y,w,h = cv2.boundingRect(cont)\n    area = w*h\n    if area > mx_area:\n        mx = x,y,w,h\n        mx_area = area\nx,y,w,h = mx\ncrop = img[y:y+h, x:x+w]\nshape=(125, 125, 1)\nimg = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)\nimg = cv2.resize(img, shape[:2])\nprint(img.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nimport cv2\ntrain_files, valid_files, y_train, y_valid = train_test_split(\n    train.filename.values, \n    train[['grapheme_root','vowel_diacritic', 'consonant_diacritic']].values, \n    test_size=0.25, \n    random_state=2019\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 128\n\ntrain_gen = data_generator(train_files, y_train)\nvalid_gen = data_generator(valid_files, y_valid)\n\ntrain_steps = round(len(train_files) / batch_size) + 1\nvalid_steps = round(len(valid_files) / batch_size) + 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"callbacks = [tf.keras.callbacks.ModelCheckpoint('model.h5', save_best_only=True)]\n\ntrain_history = model_se_resnet.fit_generator(\n    train_gen,\n    steps_per_epoch=train_steps,\n    epochs=1,\n    validation_data=valid_gen,\n    validation_steps=valid_steps,\n    #callbacks=callbacks\n).history","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"予測：領域検出してresizeしたものを学習済みモデルに入れる。"},{"metadata":{"trusted":true},"cell_type":"code","source":"SEED = 2020\nbatch_size = 12 \ndim = (125, 125)\nSIZE = 125\nstats = (0.0692, 0.2051)\nHEIGHT = 137 \nWIDTH = 236\nfrom tqdm import tqdm\ndef bbox(img):\n    rows = np.any(img, axis=1)\n    cols = np.any(img, axis=0)\n    rmin, rmax = np.where(rows)[0][[0, -1]]\n    cmin, cmax = np.where(cols)[0][[0, -1]]\n    return rmin, rmax, cmin, cmax\n\ndef crop_resize(img0, size=125, pad=16):\n    #crop a box around pixels large than the threshold \n    #some images contain line at the sides\n    ymin,ymax,xmin,xmax = bbox(img0[5:-5,5:-5] > 80)\n    #cropping may cut too much, so we need to add it back\n    xmin = xmin - 13 if (xmin > 13) else 0\n    ymin = ymin - 10 if (ymin > 10) else 0\n    xmax = xmax + 13 if (xmax < WIDTH - 13) else WIDTH\n    ymax = ymax + 10 if (ymax < HEIGHT - 10) else HEIGHT\n    img = img0[ymin:ymax,xmin:xmax]\n    #remove lo intensity pixels as noise\n    img[img < 28] = 0\n    lx, ly = xmax-xmin,ymax-ymin\n    l = max(lx,ly) + pad\n    #make sure that the aspect ratio is kept in rescaling\n    img = np.pad(img, [((l-ly)//2,), ((l-lx)//2,)], mode='constant')\n    \n    return cv2.resize(img,(size,size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import gc\ndef test_batch_generator(df, batch_size):\n    num_imgs = len(df)\n\n    for batch_start in range(0, num_imgs, batch_size):\n        curr_batch_size = min(num_imgs, batch_start + batch_size) - batch_start\n        idx = np.arange(batch_start, batch_start + curr_batch_size)\n\n        names_batch = df.iloc[idx, 0].values\n        imgs_batch = 255 - df.iloc[idx, 1:].values.reshape(-1, HEIGHT, WIDTH).astype(np.uint8)\n        X_batch = np.zeros((curr_batch_size, SIZE, SIZE, 1))\n        \n        for j in range(curr_batch_size):\n            img = (imgs_batch[j,]*(255.0/imgs_batch[j,].max())).astype(np.uint8)\n            img = crop_resize(img, size=SIZE)\n            img = img[:, :, np.newaxis]\n            X_batch[j,] = img\n\n        yield X_batch, names_batch\nTEST = [\n    \"../input/bengaliai-cv19/test_image_data_0.parquet\",\n    \"../input/bengaliai-cv19/test_image_data_1.parquet\",\n    \"../input/bengaliai-cv19/test_image_data_2.parquet\",\n    \"../input/bengaliai-cv19/test_image_data_3.parquet\",\n]\n\n# placeholders \nrow_id = []\ntarget = []\n\n# iterative over the test sets\nfor fname in tqdm(TEST):\n    test_ = pd.read_parquet(fname)\n    test_gen = test_batch_generator(test_, batch_size=batch_size)\n\n    for batch_x, batch_name in test_gen:\n        batch_predict = model_se_resnet.predict(batch_x)\n        for idx, name in enumerate(batch_name):\n            row_id += [\n                f\"{name}_consonant_diacritic\",\n                f\"{name}_grapheme_root\",\n                f\"{name}_vowel_diacritic\",\n            ]\n            target += [\n                np.argmax(batch_predict[2], axis=1)[idx],\n                np.argmax(batch_predict[0], axis=1)[idx],\n                np.argmax(batch_predict[1], axis=1)[idx],\n            ]\n\n    del test_\n    gc.collect()\n    \n    \ndf_sample = pd.DataFrame(\n    {\n        'row_id': row_id,\n        'target':target\n    },\n    columns = ['row_id','target'] \n)\n\ndf_sample.to_csv('submission.csv',index=False)\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":1}