{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nfrom tqdm.auto import tqdm\nimport time, gc\n\nimport numpy as np\nimport pandas as pd\n# pd.set_option('display.max_columns', None)\n\nfrom matplotlib import pyplot as plt\n%matplotlib inline\nimport cv2\n\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Model, Input, load_model\nfrom keras.layers import Dense, Conv2D, Flatten, Activation, Concatenate\nfrom keras.layers import MaxPool2D, AveragePooling2D, GlobalAveragePooling2D\nfrom keras.layers import Dropout, BatchNormalization\nfrom keras.optimizers import Adam\nfrom keras.callbacks import ReduceLROnPlateau, ModelCheckpoint, EarlyStopping\nfrom keras.initializers import RandomNormal\nfrom keras.applications import DenseNet121\n\nfrom sklearn.model_selection import train_test_split\n\nstart_time = time.time()\n\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"### Kaggle or Local-PC ###\nKAGGLE = True       # <==== SET ============\nif KAGGLE:\n    DIR = '../input/bengaliai-cv19'\n    DIRwork = '../input/densenet121'\nelse:               # local PC\n    DIR = './bengaliai-cv19'\n    DIRwork = './'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"### Train or Predict ###\nTRAIN = False        # <==== SET ============\n# True : Do training (GPU time limit over), model save.\n# False: Load trained model and do prediction.\n\nif TRAIN:\n    print('==TRAIN mode==\\n Training Model takes several hours and does not meet the GPU time limit for competition.')\nelse:\n    # Check file existence\n    if os.path.isfile(os.path.join(DIRwork,\"dense.h5\")):\n        print('==Not TRAIN mode (Predict only)==')\n    else:\n        print(\"==ERROR==\\n No 'Model file' and/or 'history file'.\\n Upload the files to '../input/bengaliai-cv19/mywork'.\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# read CSV files\ntrain_df = pd.read_csv(os.path.join(DIR,'train.csv'))\ntest_df = pd.read_csv(os.path.join(DIR,'test.csv'))\nclass_map_df = pd.read_csv(os.path.join(DIR,'class_map.csv'))\nsample_sub_df = pd.read_csv(os.path.join(DIR,'sample_submission.csv'))\n                            \n# read Parquet Format Image file (example)\nimg_df = pd.read_parquet(os.path.join(DIR,'train_image_data_0.parquet'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_df.shape)\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(test_df.shape)\ntest_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(class_map_df.shape)\nclass_map_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(sample_sub_df.shape)\nsample_sub_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(img_df.shape)\nimg_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# target columns\ntgt_cols = ['grapheme_root','vowel_diacritic','consonant_diacritic']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_top(tgt, n, top=True):\n    top_df = train_df.groupby([tgt]).size().reset_index(name='counts') \\\n                            ['counts'].sort_values(ascending=not top)[:n].copy()\n    top_ids = top_df.index\n    top_vals = top_df.values\n    \n    top_df = class_map_df.iloc[top_ids].copy()\n    top_df.drop(['component_type', 'label'], axis=1, inplace=True)\n    top_df['count'] = top_vals\n    return top_df\ndef disp_img(df, ids):\n    r_n = len(ids)  # character count\n    c_n = 5         # num of examples for each character\n    plt.figure()\n    fig, ax = plt.subplots(r_n, c_n, figsize=(12, 10))\n    for r, id in enumerate(ids[:r_n]):\n        sumple_ids = train_df[train_df['grapheme_root'] == id].index\n        for c, sumple_id in enumerate(sumple_ids[:c_n]):\n            flattened_image = df.iloc[sumple_id].drop('image_id').values.astype(np.uint8)\n            ax[r, c%c_n].imshow(flattened_image.reshape([137, 236]))\n            ax[r, c%c_n].set_title(str(id)+'(Train_'+str(sumple_id)+')')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"desc_df = train_df[tgt_cols].astype('str').describe()\ndesc_df\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Number of unique types\ntypes = desc_df.loc['unique',:]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"top_roots = get_top('grapheme_root', 10)\ntop_roots","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"SIZE = 64    # input image size\nN_ch = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_densenet():\n    densenet = DenseNet121(weights='imagenet', include_top=False)\n\n    input = Input(shape=(SIZE, SIZE, N_ch))\n    x = Conv2D(3, (3, 3), padding='same')(input)\n    \n    x = densenet(x)\n    \n    x = GlobalAveragePooling2D()(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.5)(x)\n    x = Dense(256, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.5)(x)\n\n    # multi output\n    grapheme_root = Dense(types['grapheme_root'],\n                          activation = 'softmax', name='root')(x)\n    vowel_diacritic = Dense(types['vowel_diacritic'],\n                            activation = 'softmax', name='vowel')(x)\n    consonant_diacritic = Dense(types['consonant_diacritic'],\n                                activation = 'softmax', name='consonant')(x)\n\n    # model\n    model = Model(input,\n                  [grapheme_root, vowel_diacritic, consonant_diacritic])\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if TRAIN:\n    # build model\n    model = build_denseNet()\n    \n    # compile\n    model.compile(Adam(lr=0.002),\n              loss={'root': 'categorical_crossentropy',\n                    'vowel': 'categorical_crossentropy',\n                    'consonant': 'categorical_crossentropy'},\n              loss_weights={'root': 0.333,        ## Set weights\n                            'vowel': 0.333,\n                            'consonant': 0.333},\n              metrics={'root': 'accuracy',\n                       'vowel': 'accuracy',\n                       'consonant': 'accuracy'}\n             )\nelse:\n    # Load pretrained-Model\n    model = load_model(os.path.join(DIRwork, 'dense.h5'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Clip horizontally\ndef clip(img):\n    cols = np.any(img < 200, axis=0)\n    xleft, xright = np.where(cols)[0][[0, -1]]\n    width = xright - xleft\n    center = int((xleft + xright) / 2)\n    \n    if width < 137:\n        img = img[:, max(0, center - 70):min(center + 70, 236)]\n    else:\n        img = img[:, max(0, xleft - 2):min(xright + 2, 236)]\n        \n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Resize image size\ndef resize(df, size=64):\n    resized = {}\n    for i in range(df.shape[0]):\n        img = clip(df.loc[df.index[i]].values.reshape(137,236))\n        image = cv2.resize(img,(size,size))\n        resized[df.index[i]] = image.reshape(-1)\n    resized_df = pd.DataFrame(resized).T\n    return resized_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if TRAIN:\n    # prepare X\n    img_df = img_df.drop(['image_id'], axis = 1)\n    X_df = (resize(img_df, SIZE) / 255.).astype('float32')\n    del img_df\n    gc.collect()\n    for i in tqdm(range(1,4)):\n        img_df = pd.read_parquet(os.path.join(\n            DIR, 'train_image_data_'+str(i)+'.parquet'))\n        img_df = img_df.drop(['image_id'], axis = 1)\n        img_df = (resize(img_df, SIZE) / 255.).astype('float32')\n        X_df = pd.concat([X_df, img_df], axis = 0)\n        del img_df\n        gc.collect()\n    \n    X_train = X_df.values.reshape(-1, SIZE, SIZE, N_ch)\n    del X_df\n    gc.collect()\nif TRAIN:\n    # prepare Y\n    train_df = train_df[tgt_cols].astype('uint8')\n    for col in tgt_cols:\n        train_df[col] = train_df[col].map('{:03}'.format)\n    Y_train = pd.get_dummies(train_df)\n\n    del train_df\n    gc.collect()\nif TRAIN:\n    # Divide the data into train and val set\n    x_train, x_test, y_train, y_test = train_test_split(X_train, Y_train,\n                                                test_size=0.1, random_state=42)\n    y_train_root = y_train.iloc[:,0:types['grapheme_root']]\n    y_train_vowel = y_train.iloc[:,types['grapheme_root']:types['grapheme_root']+types['vowel_diacritic']]\n    y_train_consonant = y_train.iloc[:,types['grapheme_root']+types['vowel_diacritic']:]\n    y_test_root = y_test.iloc[:,0:types['grapheme_root']]\n    y_test_vowel = y_test.iloc[:,types['grapheme_root']:types['grapheme_root']+types['vowel_diacritic']]\n    y_test_consonant = y_test.iloc[:,types['grapheme_root']+types['vowel_diacritic']:]\n    \n    del X_train, Y_train\n    gc.collect()    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 128\nepochs = 30          ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Callback : Learning Rate annealer\nreduceLR = ReduceLROnPlateau(monitor = 'val_root_loss',\n                             patience = 2,\n                             factor = 0.5,\n                             min_lr = 1e-5,\n                             verbose = 1)\n# Callback : Save best model\nchkPoint = ModelCheckpoint('dense.h5',\n                           monitor = 'val_root_accuracy',\n                           save_best_only = True,\n                           save_weights_only = False,\n                           mode = 'auto',\n                           period = 1,\n                           verbose = 0)\n# Callback : Early Stop\nearlyStop = EarlyStopping(monitor='val_root_accuracy',\n                          mode = 'auto',\n                          patience = 4,\n                          min_delta = 0,\n                          verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if TRAIN:\n    history = model.fit(x_train,\n                    {'root': y_train_root,\n                     'vowel': y_train_vowel,\n                     'consonant': y_train_consonant},\n                    batch_size = batch_size,\n                    epochs = epochs,\n                    shuffle = True,\n                    validation_data = (x_test,\n                                       {'root': y_test_root,\n                                        'vowel': y_test_vowel,\n                                        'consonant': y_test_consonant}),\n                    callbacks = [reduceLR, chkPoint, earlyStop],\n                    verbose = 1)\n\n    del x_train, x_test, y_train, y_test\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"row_ids = []\ntargets = []      # prediction result\nid = 0\nfor i in range(4):\n    img_df = pd.read_parquet(os.path.join(\n                            DIR, 'test_image_data_'+str(i)+'.parquet'))\n    img_df = img_df.drop('image_id', axis = 1)\n    img_df = resize(img_df, SIZE) / 255.\n    X_test = img_df.values.reshape(-1, SIZE, SIZE, N_ch)\n\n    preds = model.predict(X_test)\n    for j in range(len(X_test)):\n        for k in range(3):\n            row_ids.append('Test_'+str(id)+'_'+tgt_cols[k])\n            targets.append(np.argmax(preds[k][j]))\n        id += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submit_df = pd.DataFrame({'row_id':row_ids,'target':targets},\n                         columns = ['row_id','target'])\nsubmit_df.head(10)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submit_df.to_csv('submission.csv',index=False)","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":4}