{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from matplotlib import pyplot as plt\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport PIL.Image as Image, PIL.ImageDraw as ImageDraw, PIL.ImageFont as ImageFont\nimport random \nimport os\nimport cv2\nimport gc\nfrom tqdm.auto import tqdm\n\n\nimport numpy as np\nimport keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Activation\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.optimizers import SGD\nfrom tensorflow.keras.layers import BatchNormalization\nfrom tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.models import clone_model\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.utils import plot_model\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport numpy as np\nimport datetime as dt\nnow = dt.datetime.now\n\n\nfor 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":"num_classes = {\n    'grapheme_root': 168,\n    'vowel_diacritic': 11,\n    'consonant_diacritic': 7\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def resize(df, size=64, need_progress_bar=True):\n    resized = {}\n    for i in range(df.shape[0]):\n        image = cv2.resize(df.loc[df.index[i]].values.reshape(137,236),(size,size))\n        resized[df.index[i]] = image.reshape(-1)\n    resized = pd.DataFrame(resized).T\n    return resized","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_data = pd.read_csv('/kaggle/input/bengaliai-cv19/train.csv')\n\ntrain_data =  pd.merge(pd.read_parquet(f'/kaggle/input/bengaliai-cv19/train_image_data_0.parquet'), train_data, on='image_id').drop(['image_id'], axis=1)\n\ntrain_labels = train_data[['grapheme_root', 'vowel_diacritic', 'consonant_diacritic','grapheme']]\n\ntrain_data = train_data.drop(['grapheme_root', 'vowel_diacritic', 'consonant_diacritic','grapheme'], axis=1)\n\ntrain_data = resize(train_data)/255\n\ntrain_data = train_data.values.reshape(-1, 64, 64, 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_model(model, train_data, train_labels, target, batch_size, epochs):\n    labels = train_labels[target]\n    labels = pd.get_dummies(labels).values\n    x_train, x_test, y_train, y_test = train_test_split(train_data, labels, test_size=0.1, random_state=123)\n    y_train = tf.cast(y_train, tf.int32)\n    y_test = tf.cast(y_test, tf.int32)\n    print('x_train shape:', x_train.shape)\n    print(x_train.shape[0], 'train samples')\n    print(x_test.shape[0], 'test samples')\n\n    model.compile(optimizer=\"adam\", loss=['categorical_crossentropy'], metrics=['accuracy'])\n\n    datagen = ImageDataGenerator()\n    checkpoint_cb = ModelCheckpoint(\"{}.h5\".format(target), save_best_only=True)\n    early_stopping_cb = EarlyStopping(patience=3, restore_best_weights=True)\n    t = now()\n    history = model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size), \n                                               epochs = epochs, validation_data = (x_test, y_test), callbacks=[checkpoint_cb, early_stopping_cb])\n    \n    model = keras.models.load_model(\"{}.h5\".format(target))\n    print('Training time: %s' % (now() - t))\n    score = model.evaluate(x_test, y_test, verbose=0)\n    print('Test score:', score[0])\n    print('Test accuracy:', score[1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"feature_layers = [\n    Conv2D(32, 5, activation=\"relu\", padding=\"same\", input_shape=[64, 64, 1]),\n    layers.BatchNormalization(momentum=0.15),\n    MaxPooling2D(2),\n    Conv2D(64, 3, activation=\"relu\", padding=\"same\"),\n    Conv2D(64, 3, activation=\"relu\", padding=\"same\"),\n    MaxPooling2D(2),\n    Conv2D(128, 3, activation=\"relu\", padding=\"same\"),\n    Conv2D(128, 3, activation=\"relu\", padding=\"same\"),\n    MaxPooling2D(2),\n    Conv2D(256, 3, activation=\"relu\", padding=\"same\"),\n    Conv2D(256, 3, activation=\"relu\", padding=\"same\"),\n    MaxPooling2D(2),\n    Flatten(),\n]\n\nclassification_layers = [\n    Dense(1024),\n    Activation('relu'),\n    Dropout(0.5),\n    Dense(1024),\n    Activation('relu'),\n    Dropout(0.5),\n    Dense(num_classes['grapheme_root']),\n    Activation('softmax')\n]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_grapheme_root = Sequential(feature_layers + classification_layers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 32\nepochs = 10","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_model(model_grapheme_root, train_data, train_labels, 'grapheme_root', batch_size, epochs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classification_layers = [\n    Dense(1024),\n    Activation('relu'),\n    Dropout(0.5),\n    Dense(512),\n    Activation('relu'),\n    Dropout(0.5),\n    Dense(num_classes['vowel_diacritic']),\n    Activation('softmax')\n]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# freeze feature layers and rebuild model\nfor l in feature_layers:\n    l.trainable = False\n\nmodel_vowel_diacritic = Sequential(feature_layers + classification_layers)\n\n# transfer: train dense layers for new classification task\ntrain_model(model_vowel_diacritic, train_data, train_labels, 'vowel_diacritic', batch_size, epochs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_dict = {\n    'grapheme_root': Sequential(),\n    'vowel_diacritic': Sequential(),\n    'consonant_diacritic': Sequential()\n}\n\nfor model_type, model in model_dict.items():\n    model.add(Conv2D(32, 5, activation=\"relu\", padding=\"same\", input_shape=[64, 64, 1]))\n    model.add(layers.BatchNormalization(momentum=0.15))\n    model.add(MaxPooling2D(2))\n    model.add(Conv2D(64, 3, activation=\"relu\", padding=\"same\"))\n    model.add(Conv2D(64, 3, activation=\"relu\", padding=\"same\"))\n    model.add(MaxPooling2D(2))\n    model.add(Conv2D(128, 3, activation=\"relu\", padding=\"same\"))\n    model.add(Conv2D(128, 3, activation=\"relu\", padding=\"same\"))\n    model.add(MaxPooling2D(2))\n    model.add(Conv2D(256, 3, activation=\"relu\", padding=\"same\"))\n    model.add(Conv2D(256, 3, activation=\"relu\", padding=\"same\"))\n    model.add(MaxPooling2D(2))\n    model.add(Flatten())\n    model.add(Dense(1024, activation=\"relu\"))\n    model.add(Dropout(0.5))\n    model.add(Dense(512, activation=\"relu\"))\n    model.add(Dropout(0.5))\n    if model_type == 'grapheme_root':\n        model.add(layers.Dense(168, activation='softmax', name='root_out'))\n    elif model_type == 'vowel_diacritic':\n        model.add(layers.Dense(11, activation='softmax', name='vowel_out'))\n    elif model_type == 'consonant_diacritic':\n        model.add(layers.Dense(7, activation='softmax', name='consonant_out'))\n\n    model.compile(optimizer=\"adam\", loss=['categorical_crossentropy'], metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# del Y_train\n# del x_train\n# del x_test\n# del y_train\n# del y_test\n# gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"keras.backend.clear_session()\nnp.random.seed(42)\ntf.random.set_seed(42)\nmodel_types = ['grapheme_root', 'vowel_diacritic', 'consonant_diacritic']\nfor target in model_types:\n    Y_train = train_labels[target]\n    Y_train = pd.get_dummies(Y_train).values\n    x_train, x_test, y_train, y_test = train_test_split(train_data, Y_train, test_size=0.1, random_state=123)\n    y_train = tf.cast(y_train, tf.int32)\n    y_test = tf.cast(y_test, tf.int32)\n#     datagen = ImageDataGenerator(rotation_range=5)\n    datagen = ImageDataGenerator()\n    checkpoint_cb = ModelCheckpoint(\"{}.h5\".format(target), save_best_only=True)\n    early_stopping_cb = EarlyStopping(patience=3, restore_best_weights=True)\n    history = model_dict[target].fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size), \n                                               epochs = epochs, validation_data = (x_test, y_test), callbacks=[checkpoint_cb, early_stopping_cb])\n    history_list.append(history)\n    model_dict[target] = keras.models.load_model(\"{}.h5\".format(target))\n    \n    del Y_train\n    del x_train\n    del x_test\n    del y_train\n    del y_test\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure()\nfor i in range(3):\n    plt.plot(np.arange(0, len(history_list[i].history['accuracy'])), history_list[i].history['accuracy'], label='train_accuracy')\n    plt.plot(np.arange(0, len(history_list[i].history['accuracy'])), history_list[i].history['val_accuracy'], label='val_accuracy')\n    plt.title(model_types[i])\n    plt.xlabel('Epoch #')\n    plt.ylabel('Accuracy')\n    plt.legend(loc='lower right')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds_dict = {\n    'grapheme_root': [],\n    'vowel_diacritic': [],\n    'consonant_diacritic': []\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"target=[] # model predictions placeholder\nrow_id=[] # row_id place holder\nfor i in range(4):\n    print(\"Parquet: {}\".format(i))\n    df_test_img = pd.read_parquet('/kaggle/input/bengaliai-cv19/test_image_data_{}.parquet'.format(i)) \n    df_test_img.set_index('image_id', inplace=True)\n\n    X_test = resize(df_test_img, need_progress_bar=False)/255\n    X_test = X_test.values.reshape(-1, 64, 64, 1)\n\n    for i, p in preds_dict.items():\n        model = keras.models.load_model(\"{}.h5\".format(i))\n        preds = model.predict(X_test)\n        preds_dict[i] = np.argmax(preds, axis=1)\n\n    for k,id in enumerate(df_test_img.index.values):  \n        for i,comp in enumerate(model_types):\n            id_sample=id+'_'+comp\n            row_id.append(id_sample)\n            target.append(preds_dict[comp][k])\n            \n    del df_test_img\n    del X_test\n    gc.collect()\n\ndf_sample = pd.DataFrame(\n    {\n        'row_id': row_id,\n        'target':target\n    },\n    columns = ['row_id','target'] \n)\ndf_sample.to_csv('submission.csv',index=False)\ndf_sample.head()","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}