{"cells":[{"metadata":{"_uuid":"bddfec74c23aeaa2c3f1c2f63d79ee8fd11b33fa"},"cell_type":"markdown","source":"<h2><center> Quick, Draw! Doodle Recognition Challenge & CNNs</center> </h2>\n\n### Let's see how CNNS the already proven model to image classification peforms in this challenge.\n\nThis is just a demonstration that's why im not using all the categories from the train set."},{"metadata":{"_uuid":"fbbd08adf945810e393b1ee5589a71d6a9603527"},"cell_type":"markdown","source":"### Dependencies"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"import os\nimport ast\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.utils import shuffle\nfrom keras import optimizers\nfrom keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D, Activation, BatchNormalization\nfrom keras.models import Sequential\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1bf5617c8fc0b429af469516bff3f781fbf810bf"},"cell_type":"markdown","source":"### Auxiliar functions"},{"metadata":{"trusted":true,"_uuid":"0ffc0761a2238abf1dfc627bada004f1d8f70b7c","_kg_hide-input":true},"cell_type":"code","source":"def drawing_to_np(drawing, shape=(28, 28)):\n    # evaluates the drawing array\n    drawing = eval(drawing)\n    fig, ax = plt.subplots()\n    for x,y in drawing:\n        ax.plot(x, y, marker='.')\n        ax.axis('off')        \n    fig.canvas.draw()\n    # Close figure so it won't get displayed while transforming the set\n    plt.close(fig)\n    # Convert images to numpy array\n    np_drawing = np.array(fig.canvas.renderer._renderer)\n    # Take only one channel\n    np_drawing =np_drawing[:, :, 1]    \n    # Normalize data\n    np_drawing = np_drawing / 255.\n    return cv2.resize(np_drawing, shape) # Resize array\n\n\ndef plot_metrics_primary(acc, val_acc, loss, val_loss):\n    fig, (ax1, ax2) = plt.subplots(1, 2, sharex='col', figsize=(20,7))\n\n    ax1.plot(acc, label='Train Accuracy')\n    ax1.plot(val_acc, label='Validation accuracy')\n    ax1.legend(loc='best')\n    ax1.set_title('Accuracy')\n\n    ax2.plot(loss, label='Train loss')\n    ax2.plot(val_loss, label='Validation loss')\n    ax2.legend(loc='best')\n    ax2.set_title('Loss')\n\n    plt.xlabel('Epochs')\n    \n    \ndef plot_confusion_matrix(cnf_matrix, labels): \n    cnf_matrix_norm = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]\n    df_cm = pd.DataFrame(cnf_matrix_norm, index=labels, columns=labels)\n    plt.figure(figsize=(20,7))\n    sns.heatmap(df_cm, annot=True, fmt='.2f', cmap=\"Blues\")\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a375679d24161a4ca475c12d764441a92fb5db10"},"cell_type":"markdown","source":"### Load data"},{"metadata":{"trusted":true,"_uuid":"1e0d021c412b05153cb5196b91eda69ba723c3d1"},"cell_type":"code","source":"TRAIN_PATH = '../input/train_simplified/'\nTEST_PATH = '../input/test_simplified.csv'\nSUBMISSION_NAME = 'submission.csv'\n\ntrain = pd.DataFrame()\nfor file in os.listdir(TRAIN_PATH)[:5]:\n    train = train.append(pd.read_csv(TRAIN_PATH + file, usecols=[1, 5], nrows=2000))\n# Shuffle data\ntrain = shuffle(train, random_state=123)\ntest = pd.read_csv(TEST_PATH, usecols=[0, 2], nrows=100)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d099e2ef4514ecf42fc32ba3988cef35796cf39e"},"cell_type":"markdown","source":"### Parameters"},{"metadata":{"trusted":true,"_uuid":"f85138e26d4c31c71800eb7490e5d6b8f80d988b"},"cell_type":"code","source":"# Model parameters\nBATCH_SIZE = 64\nEPOCHS = 60\nLEARNING_RATE = 0.001\nN_CLASSES = train['word'].nunique()\nHEIGHT = 28\nWIDTH = 28\nCHANNEL = 1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2f1203ec86e6cfd7b5a5dda96a1806a113f4a72e"},"cell_type":"markdown","source":"### Let's take a look at the raw data"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"2a89405a1e8c3fc6d2da20be92a09481fb12f14a"},"cell_type":"code","source":"print('Train set shape: ', train.shape)\nprint('Train set features: %s' % train.columns.values)\nprint('Train number of label categories: %s' % N_CLASSES)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b4481756873c4c2c9219f00226fad5b51314557c"},"cell_type":"markdown","source":"### Pre process"},{"metadata":{"trusted":true,"_uuid":"32354478386c3936bca205a017d94117bf21d707","_kg_hide-output":true},"cell_type":"code","source":"#Fixing labels.\ntrain['word'] = train['word'].replace(' ', '_', regex=True)\n# Get labels and one-hot encode them.\nclasses_names = train['word'].unique()\nlabels = pd.get_dummies(train['word']).values\ntrain.drop(['word'], axis=1, inplace=True)\n# Transform drawing into numpy arrays\ntrain['drawing_np'] = train['drawing'].apply(drawing_to_np)\n# Reshape arrays\ntrain_drawings = np.asarray([x.reshape(HEIGHT, WIDTH, CHANNEL) for x in train['drawing_np'].values])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a33a9c48680b575c0d55a58eb8cf2c401227634d","_kg_hide-input":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b59cf34b2b3caf122bf544e00df79bbe8d17b5f1"},"cell_type":"markdown","source":"### Split data in train and validation (90% ~ 10%)"},{"metadata":{"trusted":true,"_uuid":"6dc86fbe18e8cffbbc07a7334b44163f7152fd19"},"cell_type":"code","source":"x_train, x_val, y_train, y_val = train_test_split(train_drawings, labels, test_size=0.1, random_state=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"849ec3f88cbe0a1b5db7c0c284a1f729b0370ffd"},"cell_type":"markdown","source":"### Model"},{"metadata":{"trusted":true,"_uuid":"8443527fcc4c0663920d87207bffb4560b0243b8"},"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(32, kernel_size=(5,5),padding='Same', activation='relu', input_shape=(HEIGHT, WIDTH, CHANNEL)))\nmodel.add(Conv2D(32, kernel_size=(5,5),padding='Same', activation='relu'))\nmodel.add(MaxPool2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, kernel_size=(3,3),padding='Same', activation='relu'))\nmodel.add(Conv2D(64, kernel_size=(3,3),padding='Same', activation='relu'))\nmodel.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\n\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dropout(0.5))\n\nmodel.add(Dense(N_CLASSES, activation = \"softmax\"))\n\noptimizer = optimizers.adam(lr=LEARNING_RATE)\nmodel.compile(optimizer=optimizer , loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"14c2382a1443d8ad7585d9ee48b5fc57e710da0a","_kg_hide-input":true},"cell_type":"code","source":"print('Dataset size: %s' % train.shape[0])\nprint('Epochs: %s' % EPOCHS)\nprint('Learning rate: %s' % LEARNING_RATE)\nprint('Batch size: %s' % BATCH_SIZE)\nprint('Input dimension: (%s, %s, %s)' % (HEIGHT, WIDTH, CHANNEL))\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"70a5d92e5a7beb5a2dcb63114c4ceb18bd023dae","_kg_hide-output":true},"cell_type":"code","source":"history = model.fit(x_train, y_train, batch_size=BATCH_SIZE, epochs=EPOCHS, validation_data=(x_val, y_val))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c9eb42eb2195c16b28916d8bf2a1f9a9d182a5f0"},"cell_type":"markdown","source":"Let's take a look at our model loss and accuracy training and validation graph."},{"metadata":{"trusted":true,"_uuid":"d029f102a1839c521cb897c499ba348ee64867ef","_kg_hide-output":false,"_kg_hide-input":true},"cell_type":"code","source":"plot_metrics_primary(history.history['acc'], history.history['val_acc'], history.history['loss'], history.history['val_loss'])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9179b2bb235c169fa2d6a8bec52a55cbd9988e11"},"cell_type":"markdown","source":"A good way to evaluate a classification model is to take a look at the model confusion matrix, this way we can have a better insight on what our model is getting right and what not."},{"metadata":{"trusted":true,"_uuid":"4794a29cf065c219b9811407c7ca6d2a52959d18","_kg_hide-input":true},"cell_type":"code","source":"cnf_matrix = confusion_matrix(np.argmax(y_val, axis=1), model.predict_classes(x_val))\nplot_confusion_matrix(cnf_matrix, classes_names)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"23678316ac9ff6cf5f0ef6eb8a53a80ab3d522cf"},"cell_type":"markdown","source":"Finally let's predict the test data and output our predictions."},{"metadata":{"_uuid":"82ddcd2903e53f322ed219493c9a0fb42b6d935c"},"cell_type":"markdown","source":"### Process test"},{"metadata":{"trusted":true,"_uuid":"6da72903616ec04c9295619547dc5932a9b99265","_kg_hide-output":false},"cell_type":"code","source":"# Transform drawing into numpy arrays.\ntest['drawing_np'] = test['drawing'].apply(drawing_to_np)\n# Reshape arrays.\ntest_drawings = np.asarray([x.reshape(HEIGHT, WIDTH, CHANNEL) for x in test['drawing_np'].values])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0331a8c9470c1d4839d51471fd612ce42a86643c"},"cell_type":"code","source":"predictions = model.predict(test_drawings)\ntop_3_predictions = np.asarray([np.argpartition(pred, -3)[-3:] for pred in predictions])\ntop_3_predictions = ['%s %s %s' % (classes_names[pred[0]], classes_names[pred[1]], classes_names[pred[2]]) for pred in top_3_predictions]\ntest['word'] = top_3_predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ad2d257cb229ac7a7480c3e45fafefbd0774413a"},"cell_type":"code","source":"submission = test[['key_id', 'word']]\nsubmission.to_csv(SUBMISSION_NAME, index=False)\nsubmission.head(10)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}