{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"import os\nimport glob\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport cv2\nfrom IPython.display import display,Image\nfrom tqdm.notebook import tqdm\nimport random\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import OneHotEncoder\nimport random\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"from keras import layers\nfrom keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D\nfrom keras.models import Model, load_model\nfrom keras.initializers import glorot_uniform\nfrom keras.utils import plot_model\nfrom IPython.display import SVG\nfrom keras.utils.vis_utils import model_to_dot\nimport keras.backend as K\nimport tensorflow as tf","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# os.makedirs('images',exist_ok=True)","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_folder_input = '/kaggle/input/bengaliai-cv19/'\n# train_files = glob.glob(base_folder_input+'train_image_data_*')\n# test_files = glob.glob(base_folder_input+'test_image_data_*')\n# print(len(train_files),len(test_files))\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_folder = '/kaggle/input/bengali-character-npz-files/images/'\n# os.makedirs(base_folder,exist_ok=True)\n# def save_data(files,folder):\n#     os.makedirs(base_folder+folder,exist_ok=True)\n#     for idx in tqdm(range(len(files))):\n#         df = pd.read_parquet(files[idx], engine='pyarrow')\n#         for index in tqdm(range(len(df))):\n#             img_name = df.iloc[index]['image_id']\n#             image = list(df.loc[df.index[index]].values[1:])\n#             data = np.asarray(image)\n#             # save to npy file\n#             np.savez_compressed(base_folder+folder+'/'+img_name+'.npz', data)\n#         del df\n# #             break\n# #         break\n# #     pass\n# save_data(train_files,'train')\n# save_data(test_files,'test')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = glob.glob(base_folder+'train/*')\nprint(len(images))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = glob.glob(base_folder+'train/*')\nrandom.shuffle(images)\ntrain_files, val_files = train_test_split(images, test_size=0.33, random_state=42)\nprint(len(train_files),len(val_files),len(images))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(base_folder_input+'train.csv')\ndf_train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def image_generator(train_files,df_train,batch_size):\n    count = 0\n    x = []\n    y1 = []\n    y2 = []\n    y3 = []\n    while True:\n        idx = random.choice(range(0,len(train_files)))\n        \n        \n        img_name = train_files[idx].split(\"/\")[-1][:-4]\n        image = np.load(train_files[idx])['arr_0'].reshape(137,236)\n        temp_df = df_train[df_train['image_id']==img_name]\n        y_grapheme = np.zeros(168)\n        y_grapheme[temp_df.iloc[0]['grapheme_root']] = 1\n        y_vowel = np.zeros(11)\n        y_vowel[temp_df.iloc[0]['vowel_diacritic']] = 1\n        y_consonant = np.zeros(7)\n        y_consonant[temp_df.iloc[0]['consonant_diacritic']]=1\n        \n        \n        x.append(np.uint8(image))\n        y1.append(y_grapheme)\n        y2.append(y_vowel)\n        y3.append(y_consonant)\n        count += 1\n        \n        if count % batch_size == 0:\n            grayscale_batch = np.array(x)\n            rgb_batch = np.repeat(grayscale_batch[..., np.newaxis], 3, -1)\n            yield rgb_batch, [np.array(y1),np.array(y2),np.array(y3)]\n            x = []\n            y1 = []\n            y2 = []\n            y3 = []\n            count = 0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def identity_block(X, f, filters, stage, block):\n    # defining name basis\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n\n    # Retrieve Filters\n    F1, F2, F3 = filters\n\n    # Save the input value. We'll need this later to add back to the main path. \n    X_shortcut = X\n\n    # First component of main path\n    X = Conv2D(filters = F1, kernel_size = (1, 1), strides = (1,1), padding = 'valid', name = conv_name_base + '2a', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2a')(X)\n    X = Activation('relu')(X)\n\n    # Second component of main path\n    X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1,1), padding = 'same', name = conv_name_base + '2b', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2b')(X)\n    X = Activation('relu')(X)\n\n    # Third component of main path\n    X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1,1), padding = 'valid', name = conv_name_base + '2c', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2c')(X)\n\n    # Final step: Add shortcut value to main path, and pass it through a RELU activation\n    X = Add()([X, X_shortcut])\n    X = Activation('relu')(X)\n\n    return X","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convolutional_block(X, f, filters, stage, block, s = 2):\n    # defining name basis\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n    \n    # Retrieve Filters\n    F1, F2, F3 = filters\n    \n    # Save the input value\n    X_shortcut = X\n\n\n    ##### MAIN PATH #####\n    # First component of main path \n    X = Conv2D(F1, (1, 1), strides = (s,s), name = conv_name_base + '2a', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2a')(X)\n    X = Activation('relu')(X)\n\n    # Second component of main path\n    X = Conv2D(filters=F2, kernel_size=(f, f), strides=(1, 1), padding='same', name=conv_name_base + '2b', kernel_initializer=glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis=3, name=bn_name_base + '2b')(X)\n    X = Activation('relu')(X)\n\n    # Third component of main path\n    X = Conv2D(filters=F3, kernel_size=(1, 1), strides=(1, 1), padding='valid', name=conv_name_base + '2c', kernel_initializer=glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis=3, name=bn_name_base + '2c')(X)\n\n    \n    ##### SHORTCUT PATH ####\n    X_shortcut = Conv2D(F3, (1, 1), strides = (s,s), name = conv_name_base + '1', kernel_initializer = glorot_uniform(seed=0))(X_shortcut)\n    X_shortcut = BatchNormalization(axis = 3, name = bn_name_base + '1')(X_shortcut)\n\n    # Final step: Add shortcut value to main path, and pass it through a RELU activation\n    X = Add()([X, X_shortcut])\n    X = Activation('relu')(X)\n    \n    return X","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ResNet50(input_shape = (64, 64, 3), classes = 2):   \n    # Define the input as a tensor with shape input_shape\n    X_input = Input(input_shape)\n\n    # Zero-Padding\n    X = ZeroPadding2D((3, 3))(X_input)\n    \n    # Stage 1\n    X = Conv2D(64, (7, 7), strides = (2, 2), name = 'conv1', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = 'bn_conv1')(X)\n    X = Activation('relu')(X)\n    X = MaxPooling2D((3, 3), strides=(2, 2))(X)\n\n    # Stage 2\n    X = convolutional_block(X, f = 3, filters = [64, 64, 256], stage = 2, block='a', s = 1)\n    X = identity_block(X, 3, [64, 64, 256], stage=2, block='b')\n    X = identity_block(X, 3, [64, 64, 256], stage=2, block='c')\n\n    # Stage 3\n    X = convolutional_block(X, f = 3, filters = [128, 128, 512], stage = 3, block='a', s = 2)\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='b')\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='c')\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='d')\n\n    # Stage 4\n    X = convolutional_block(X, f = 3, filters = [256, 256, 1024], stage = 4, block='a', s = 2)\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='b')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='c')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='d')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='e')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='f')\n\n    # Stage 5\n    X = convolutional_block(X, f = 3, filters = [512, 512, 2048], stage = 5, block='a', s = 2)\n    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='b')\n    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='c')\n\n    # AVGPOOL.\n    X = AveragePooling2D((2, 2), name='avg_pool')(X)\n\n    # output layer\n    X = Flatten()(X)\n    X = Dense(classes, activation='softmax', name='fc' + str(classes), kernel_initializer = glorot_uniform(seed=0))(X)\n    \n    # Create model\n    model = Model(inputs = X_input, outputs = X, name='ResNet50')\n\n    return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size=4\nlearning_rate=3e-4\ntrain_gen = image_generator(train_files,df_train,batch_size)\nval_gen = image_generator(val_files,df_train,batch_size)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.applications import ResNet50, MobileNet, Xception, DenseNet121, InceptionV3\n# from keras.layers import GlobalAveragePooling2D\n# from keras.callbacks import Callback\nfrom keras.callbacks import Callback, ReduceLROnPlateau, EarlyStopping, ModelCheckpoint, CSVLogger\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.backend import clear_session\nfrom keras.models import Model, load_model\nfrom keras.layers import Dense, Input, Flatten,GlobalAveragePooling2D\nfrom keras.optimizers import adam","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = ResNet50(weights='imagenet', include_top=False)\nmodel_name = 'ResNet50'\n# base_model = InceptionV3(weights='imagenet', include_top=False)\n# add a global spatial average pooling layer\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\n# let's add a fully-connected layer\nx = Dense(1024, activation='relu')(x)\n# and a logistic layer -- let's say we have 200 classes\npredictions_grapheme_root = Dense(168, activation='softmax',name=\"grapheme_root\")(x)\npredictions_vowel_diacritic = Dense(11, activation='softmax',name=\"vowel_diacritic\")(x)\npredictions_consonant_diacritic = Dense(7, activation='softmax',name=\"consonant_diacritic\")(x)\n\n# this is the model we will train\nmodel = Model(inputs=base_model.input, outputs=[predictions_grapheme_root,predictions_vowel_diacritic,predictions_consonant_diacritic])\nlosses = {\"grapheme_root\": \"categorical_crossentropy\",\"vowel_diacritic\": \"categorical_crossentropy\",\"consonant_diacritic\":\"categorical_crossentropy\"}\ncust_adam = adam(lr=learning_rate)\nmodel.compile(optimizer=cust_adam,loss=losses, metrics=['accuracy'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"checkpoint_filepath = model_name+'.hdf5'\ncheckpoint = ModelCheckpoint(filepath=checkpoint_filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')\n# early_stop = EarlyStopping(monitor='acc', mode='max', verbose=1, patience=3, restore_best_weights=True)\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=2e-7, mode='min', verbose=1)\ncsv_logger = CSVLogger(filename=model_name+'_log.csv')\ncallbacks_list = [checkpoint, reduce_lr,  csv_logger]\n\n\nhistory = model.fit_generator(\n            train_gen,\n            steps_per_epoch=100,\n            epochs=2,\n            validation_data=val_gen,\n            validation_steps=80,\n            callbacks=callbacks_list\n        )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import load_model\nmodel = load_model('ResNet50.hdf5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_files = glob.glob(base_folder+'test/*')\nprint(len(test_files))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testX = []\nfor idx in range(len(test_files)):\n    img_name = test_files[idx].split(\"/\")[-1][:-4]\n    image = np.load(test_files[idx])['arr_0'].reshape(137,236)\n    testX.append(np.uint8(image))\ngrayscale_batch = np.array(testX)\nrgb_batch = np.repeat(grayscale_batch[..., np.newaxis], 3, -1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MEAN = np.mean(rgb_batch, axis=(0, 1, 2))\nSTD = np.std(rgb_batch, axis=(0, 1, 2))\n#     print(valX.shape)\nfor i in range(3):\n    rgb_batch[:, :, :, i] = (rgb_batch[:, :, :, i] - MEAN[i]) / STD[i]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = model.predict(rgb_batch)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dict_= {\"row_id\":[],\"target\":[]}\nfor idx in range(len(test_files)):\n    image_id = test_files[idx].split(\"/\")[-1][:-4]\n    for key,value in {0:\"grapheme_root\",1:\"vowel_diacritic\",2:\"consonant_diacritic\"}.items():\n        name  = image_id+'_'+value\n        val = np.argmax(predictions[key][idx])\n        dict_['row_id'].append(name)\n        dict_['target'].append(val)\nresult_df = pd.DataFrame(dict_)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df.to_csv('submission.csv',index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}