{"cells":[{"metadata":{},"cell_type":"markdown","source":"### Setup & Imports"},{"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\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path = '../input/Kannada-MNIST/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom PIL import Image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.utils import to_categorical\n\nfrom keras.models import Sequential\nfrom keras.layers import Dense\nfrom keras.layers import Dropout, Flatten\nfrom keras.layers import Conv2D, MaxPooling2D\n\nfrom keras.callbacks import EarlyStopping","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Data loading & inspection"},{"metadata":{},"cell_type":"markdown","source":"##### helper functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\nhelper function to show a number of randomly selected images \nbelonging either to a specified label or selected across all labels\n\"\"\"\n\ndef show_random_images(images, num=10, label=None):\n\n    # generating images' subsample if label specified\n    if label is not None:\n        images = images[images.label == label]\n    \n    fig, axs = plt.subplots(num, figsize=(1.25, num * 2.5))\n    \n    for i in range(num):\n    \n        rnd = np.random.randint(len(images))\n    \n        # getting image data and splitting between label and pixels' vector\n        img_data = np.array(images.iloc[rnd], dtype='uint8')    \n        img_label = img_data[0]\n        img_pixels = img_data[1:]\n        \n        # reshaping image to 2D array\n        img_shape = (int(np.sqrt(img_pixels.shape[0])), int(np.sqrt(img_pixels.shape[0])))\n        img_array = img_pixels.reshape(img_shape)\n        \n        title = 'Image {} / labelled {}'.format(rnd, img_label)\n        \n        axs[i].imshow(img_array, alpha=0.66, cmap='gray')\n        axs[i].set_title(title)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### \"train.csv\""},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_data = pd.read_csv(path + 'train.csv')\ntrain_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# checking labels distribution\n\ntrain_data.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_random_images(train_data, num=5, label=5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### \"Dig-MNIST.csv\""},{"metadata":{"trusted":true},"cell_type":"code","source":"dig_data = pd.read_csv(path + 'Dig-MNIST.csv')\ndig_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# checking labels distribution\n\ndig_data.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_random_images(dig_data, num=5, label=5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Data preparation"},{"metadata":{},"cell_type":"markdown","source":"##### Helper functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"# helper function to show randomly selected image from 2D images array\n\ndef show_random_image(imgset):\n    \n    rnd = np.random.randint(imgset.shape[0])\n    imgarray = imgset[rnd,:,:,0]\n    plt.figure(figsize=(1.5, 1.5))\n    plt.imshow(imgarray, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Preparing \"train\" images"},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing train image labels using 'one-hot' encoding\n\ntrain_labels = to_categorical(train_data.label)\ntrain_labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_labels.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing train images array ('flat' image vectors)\n\ntrain_images = np.array(train_data.drop(columns='label'))\ntrain_images.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing 2D train images array (reshaping original 'flat' image vectors array)\n\nn_images = train_images.shape[0]\ndim = int(np.sqrt(train_images.shape[1]))\n\ntrain_images_2D = train_images.reshape(n_images, dim, dim, 1)\ntrain_images_2D.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_random_image(train_images_2D)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# normalizing \"train\" images\n\ntrain_images_2D = train_images_2D.astype('float')\ntrain_images_2D /= 255","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Preparing \"Dig-MNIST\" images"},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing dig-mnist image labels using 'one-hot' encoding\n\ndig_labels = to_categorical(dig_data.label)\ndig_labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dig_labels.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing train images array ('flat' image vectors)\n\ndig_images = np.array(dig_data.drop(columns='label'))\ndig_images.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing 2D dig-mnist images array (reshaping original 'flat' image vectors array)\n\nn_images = dig_images.shape[0]\ndim = int(np.sqrt(dig_images.shape[1]))\n\ndig_images_2D = dig_images.reshape(n_images, dim, dim, 1)\ndig_images_2D.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_random_image(dig_images_2D)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# normalizing \"Dig-MNIST\" images\n\ndig_images_2D = dig_images_2D.astype('float')\ndig_images_2D /= 255","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Modelling"},{"metadata":{},"cell_type":"markdown","source":"#### Loading test images and sample submission"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data = pd.read_csv(path + 'test.csv', index_col='id')\ntest_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.read_csv(path + 'sample_submission.csv', index_col='id')\nsubmission","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Preparing test images"},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing test images array ('flat' image vectors)\n\ntest_images = np.array(test_data)\ntest_images.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing 2D test images array (reshaping original 'flat' image vectors array)\n\nn_images = test_images.shape[0]\ndim = int(np.sqrt(train_images.shape[1]))\n\ntest_images_2D = test_images.reshape(n_images, dim, dim, 1)\ntest_images_2D.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# normalizing \"test\" images\n\ntest_images_2D = test_images_2D.astype('float')\ntest_images_2D /= 255","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Setting (hyper)parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting input dimensionality - 2D image arrays\ninput_shape = (dim, dim, 1)\nnum_classes = 10","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting optimization parameters\noptimizer = 'rmsprop'\nloss = 'categorical_crossentropy'\nmetrics = ['accuracy']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting training parameters\nepochs = 100\nbatch_size = 1024\n\nearly_stop = EarlyStopping(monitor='val_loss', \n                           min_delta=0, \n                           patience=3, \n                           verbose=True, \n                           mode='auto', \n                           baseline=None, \n                           restore_best_weights=False)\n\ncallbacks = [early_stop]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(32, kernel_size=(3, 3),\n                 activation='relu',\n                 input_shape=input_shape))\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\n\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dropout(0.5))\n\nmodel.add(Dense(num_classes, activation='softmax'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer=optimizer, loss=loss, metrics=metrics)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.fit(train_images_2D, train_labels, \n          batch_size=batch_size, epochs=epochs, \n          verbose=True, \n          callbacks=callbacks, \n          validation_split=0.1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Model evaluation"},{"metadata":{"trusted":true},"cell_type":"code","source":"# showing history of 'accuracy'\n\nplt.figure()\nplt.plot(model.history.history['accuracy'], label='TRAIN ACC')\nplt.plot(model.history.history['val_accuracy'], label='VAL ACC')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# showing history of 'loss'\n\nplt.figure()\nplt.plot(model.history.history['loss'], label='TRAIN LOSS')\nplt.plot(model.history.history['val_loss'], label='VAL LOSS')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# making predictions for \"train\" data (in-sample check)\n\npred_train = model.predict_classes(train_images_2D)\npred_train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hits = (pred_train == train_data.label)\nprint('Hits: {}, i.e. {:.2f}%'.format(hits.sum(), hits.sum() / pred_train.shape[0] * 100))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"miss = (pred_train != train_data.label)\nprint('Misses: {}, i.e. {:.2f}%'.format(miss.sum(), miss.sum() / pred_train.shape[0] * 100))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# evaluating model on \"train\" data\n\neval_metrics = model.evaluate(x=train_images_2D, y=train_labels, \n                              batch_size=batch_size, verbose=True, callbacks=callbacks)\npd.DataFrame(eval_metrics, index=model.metrics_names, columns=['metric'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# evaluating model on \"Dig-MNIST\" data\n\neval_metrics = model.evaluate(x=dig_images_2D, y=dig_labels, \n                              batch_size=batch_size, verbose=True, callbacks=callbacks)\npd.DataFrame(eval_metrics, index=model.metrics_names, columns=['metric'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Making predictions"},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting the optimal number of epochs\nepochs = 8\n\n# re-training the model on full train dataset\nmodel.fit(train_images_2D, train_labels, \n          batch_size=batch_size, epochs=epochs, \n          verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# making predictions on \"test\" data\n\npred_test = model.predict_classes(test_images_2D)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.label = pred_test\nsubmission.to_csv('submission.csv')","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}