{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Image Classification with CNN - Tutorial\n\n> Image classification is the primary domain, in which deep neural networks play the most important role of medical image analysis. The image classification accepts the given input images and produces output classification.In image classification, CNNs are the recent state-of-the-art methods. The CNNs learned about natural images, showing strong performance and encountering the accuracy of human expert systems.\n\n\n> The Convolution layer is always the first. Тhe image (matrix with pixel values) is entered into it. Imagine that the reading of the input matrix begins at the top left of image. Next the software selects a smaller matrix there, which is called a filter. Then the filter produces convolution, i.e. moves along the input image. The filter’s task is to multiply its values by the original pixel values. All these multiplications are summed up. One number is obtained in the end. \n\n> The nonlinear layer is added after each convolution operation. It has an activation function, which brings nonlinear property.\n\n> The pooling layer follows the nonlinear layer. It works with width and height of the image and performs a downsampling operation on them. As a result the image volume is reduced.\n\n> After completion of series of convolutional, nonlinear and pooling layers, it is necessary to attach a fully connected layer. This layer takes the output information from convolutional networks.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# *Please upvote the kernel if you find it insightful*","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# Import Libraries","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\n\nimport tensorflow as tf\nfrom tensorflow.python import keras\nfrom tensorflow.python.keras.models import Sequential\nfrom tensorflow.python.keras.layers import Dense, Flatten, Conv2D, Dropout, MaxPooling2D\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n%matplotlib inline ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Importing the dataset","execution_count":null},{"metadata":{"id":"E8IQ_Vgub6pU","outputId":"ba927e6d-d566-4580-d311-e13599a6a31f","trusted":true,"_uuid":"5c72ced17af30d76432a1648a47dd47d8261b8b8"},"cell_type":"code","source":"data_train = pd.read_csv('../input/fashionmnist/fashion-mnist_train.csv')\ndata_test = pd.read_csv('../input/fashionmnist/fashion-mnist_test.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e2913e422697fe46a435b399e889a861fe1cfbeb"},"cell_type":"code","source":"x_train = np.array(data_train.iloc[:, 1:])\ny_train = np.array(data_train.iloc[:, 0])\n\nx_test = np.array(data_test.iloc[:, 1:])\ny_test = np.array(data_test.iloc[:, 0])\n\nprint(\"x_train shape:\", x_train.shape, \"y_train shape:\", y_train.shape)","execution_count":null,"outputs":[]},{"metadata":{"id":"tuUcMrLocNKY","outputId":"1a5598b8-7476-4af7-8ce5-d5126ef639f3","trusted":true,"_uuid":"119bc0c7a229658321e631d4551364bfee47db33"},"cell_type":"code","source":"print(\"x_train shape:\", x_train.shape, \"y_train shape:\", y_train.shape)\n\nx_train = x_train.reshape(x_train.shape[0], 28, 28)\nx_test = x_test.reshape(x_test.shape[0], 28, 28)\n\n# Print the number of training and test datasets\nprint(x_train.shape[0], 'train set')\nprint(x_test.shape[0], 'test set')\n\n# Define the text labels\nfashion_mnist_labels = [\"T-shirt/top\",  # index 0\n                        \"Trouser\",      # index 1\n                        \"Pullover\",     # index 2 \n                        \"Dress\",        # index 3 \n                        \"Coat\",         # index 4\n                        \"Sandal\",       # index 5\n                        \"Shirt\",        # index 6 \n                        \"Sneaker\",      # index 7 \n                        \"Bag\",          # index 8 \n                        \"Ankle boot\"]   # index 9","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Class Distribution for Trainset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create a dictionary for each type of label \nlabels = {0 : \"T-shirt/top\", 1: \"Trouser\", 2: \"Pullover\", 3: \"Dress\", 4: \"Coat\",\n          5: \"Sandal\", 6: \"Shirt\", 7: \"Sneaker\", 8: \"Bag\", 9: \"Ankle Boot\"}\n\ndef get_classes_distribution(data):\n    # Get the count for each label\n    label_counts = data[\"label\"].value_counts()\n\n    # Get total number of samples\n    total_samples = len(data)\n\n\n    # Count the number of items in each class\n    for i in range(len(label_counts)):\n        label = labels[label_counts.index[i]]\n        count = label_counts.values[i]\n        percent = (count / total_samples) * 100\n        print(\"{:<20s}:   {} or {}%\".format(label, count, percent))\n\nget_classes_distribution(data_train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_label_per_class(data):\n    f, ax = plt.subplots(1,1, figsize=(12,4))\n    g = sns.countplot(data.label, order = data[\"label\"].value_counts().index)\n    g.set_title(\"Number of labels for each class\")\n\n    for p, label in zip(g.patches, data[\"label\"].value_counts().index):\n        g.annotate(labels[label], (p.get_x(), p.get_height()+0.1))\n    plt.show()  \n    \nplot_label_per_class(data_train)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Class Distribution for Testset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"get_classes_distribution(data_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_label_per_class(data_test)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Preprocessing","execution_count":null},{"metadata":{"id":"4AKEmwXCcz0W","trusted":true,"_uuid":"d8e8ae9aa04d15990113bd25f717710038f51d58"},"cell_type":"code","source":"x_train = x_train.astype('float32') / 255\nx_test = x_test.astype('float32') / 255","execution_count":null,"outputs":[]},{"metadata":{"id":"iO3mc8Z7dLHZ","outputId":"b0a6fe6b-a226-4780-f29a-135093842fa2","trusted":true,"_uuid":"82b8b349217705e3e41fc3f979b32a6c8e303cd9"},"cell_type":"code","source":"# Further break training data into train / validation sets\n(x_train, x_valid) = x_train[5000:], x_train[:5000] \n(y_train, y_valid) = y_train[5000:], y_train[:5000]\n\n# Reshape input data\nx_train = x_train.reshape(x_train.shape[0], 28,28, 1)\nx_valid = x_valid.reshape(x_valid.shape[0], 28,28, 1)\nx_test = x_test.reshape(x_test.shape[0], 28,28, 1)\n\n# One-hot encode the labels\ny_train = tf.keras.utils.to_categorical(y_train, 10)\ny_valid = tf.keras.utils.to_categorical(y_valid, 10)\ny_test = tf.keras.utils.to_categorical(y_test, 10)\n\n# Print training set shape\nprint(\"x_train shape:\", x_train.shape, \"y_train shape:\", y_train.shape)\n\n# Print the number of training, validation, and test datasets\nprint(x_train.shape[0], 'train set')\nprint(x_valid.shape[0], 'validation set')\nprint(x_test.shape[0], 'test set')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Class imbalance for Trainset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_count_per_class(yd):\n    ydf = pd.DataFrame(yd)\n    f, ax = plt.subplots(1,1, figsize=(12,4))\n    g = sns.countplot(ydf[0], order = np.arange(0,10))\n    g.set_title(\"Number of items for each class\")\n    g.set_xlabel(\"Category\")\n    \n    for p, label in zip(g.patches, np.arange(0,10)):\n        g.annotate(labels[label], (p.get_x(), p.get_height()+0.1))\n        \n    plt.show()  \n\ndef get_count_per_class(yd):\n    ydf = pd.DataFrame(yd)\n    # Get the count for each label\n    label_counts = ydf[0].value_counts()\n\n    # Get total number of samples\n    total_samples = len(yd)\n\n\n    # Count the number of items in each class\n    for i in range(len(label_counts)):\n        label = labels[label_counts.index[i]]\n        count = label_counts.values[i]\n        percent = (count / total_samples) * 100\n        print(\"{:<20s}:   {} or {}%\".format(label, count, percent))\n    \nplot_count_per_class(np.argmax(y_train,axis=1))\nget_count_per_class(np.argmax(y_train,axis=1))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Class imbalance for Validationset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_count_per_class(np.argmax(y_valid,axis=1))\nget_count_per_class(np.argmax(y_valid,axis=1))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model definition and Training","execution_count":null},{"metadata":{"id":"RVk2c_S5dsaH","outputId":"082a7229-e396-4f1d-f7e7-1efa61f771be","trusted":true,"_uuid":"d1b6b2bbef9c364d733d43b3e4fe8e55173ebef0"},"cell_type":"code","source":"model = tf.keras.Sequential()\n\n# Must define the input shape in the first layer of the neural network\nmodel.add(tf.keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu', input_shape=(28,28,1))) \nmodel.add(tf.keras.layers.MaxPooling2D(pool_size=2))\nmodel.add(tf.keras.layers.Dropout(0.2))\n\nmodel.add(tf.keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu'))\nmodel.add(tf.keras.layers.MaxPooling2D(pool_size=2))\nmodel.add(tf.keras.layers.Dropout(0.2))\n\nmodel.add(tf.keras.layers.Flatten())\nmodel.add(tf.keras.layers.Dense(256, activation='relu'))\nmodel.add(tf.keras.layers.Dropout(0.5))\nmodel.add(tf.keras.layers.Dense(10, activation='softmax'))\n\n# Take a look at the model summary\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"id":"iLwc8LCXd_DS","trusted":true,"_uuid":"3910aeaf6a2a4256c0e52310054eb551ec525201"},"cell_type":"code","source":"model.compile(loss='categorical_crossentropy',\n             optimizer='adam',\n             metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"id":"6T_Gaz29eFFG","outputId":"4b1064ac-6339-4f37-8a94-3808a4997835","trusted":true,"_uuid":"cce2983b37fd4b506f1ec9d53653306f640fe7b8"},"cell_type":"code","source":"history = model.fit(x_train,y_train, batch_size=100, epochs=30, validation_data=(x_valid, y_valid))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Evaluation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"acc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nplt.figure(figsize=(8, 8))\nplt.subplot(2, 1, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.ylabel('Accuracy')\nplt.ylim([-1,1])\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(2, 1, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.ylabel('Cross Entropy')\nplt.ylim([-1,1.0])\nplt.title('Training and Validation Loss')\nplt.xlabel('epoch')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"id":"cBha2BdzeOWq","outputId":"ff22eab6-2706-4035-9ad7-332a5b5820b5","trusted":true,"_uuid":"cca16512f0889552a60c15ee4eeb2c1d7f666fe6"},"cell_type":"code","source":"# Evaluate the model on test set\nscore = model.evaluate(x_test, y_test, verbose=0)\n\n# Print test accuracy\nprint('\\n', 'Test accuracy:', score[1])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prediction","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"y_hat = model.predict(x_test)\npredicted_classes = model.predict_classes(x_test)\ny_true = data_test.iloc[:, 0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Classification Report","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"target_names = [\"Class {} ({}) :\".format(i,labels[i]) for i in range(10)]\nprint(classification_report(y_true, predicted_classes, target_names=target_names))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Predicted labels Visualization","execution_count":null},{"metadata":{"id":"9xj89DgukQry","outputId":"5a468ba6-f3d8-470e-9d4f-3b93aeca16aa","trusted":true,"_uuid":"219bdd618fc1eaed5cf8a0de0a409a59abcdd026"},"cell_type":"code","source":"figure = plt.figure(figsize=(20, 8))\nfor i, index in enumerate(np.random.choice(x_test.shape[0], size=15, replace=False)):\n    ax = figure.add_subplot(3, 5, i + 1, xticks=[], yticks=[])\n    # Display each image\n    ax.imshow(np.squeeze(x_test[index]))\n    predict_index = np.argmax(y_hat[index])\n    true_index = np.argmax(y_test[index])\n    # Set the title for each image\n    ax.set_title(\"{} ({})\".format(fashion_mnist_labels[predict_index], \n                                  fashion_mnist_labels[true_index]),\n                                  color=(\"green\" if predict_index == true_index else \"red\"))","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}