{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Import of all the libraries we'll use\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sn\nimport os\nfrom IPython.display import display, Image\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\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\n# Libraries useful for our neural network model\n        \nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array\nfrom keras.models import Model\nimport keras\nimport tensorflow as tf\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D, GlobalMaxPooling2D\nfrom sklearn.model_selection import train_test_split\nfrom keras.layers import Dropout, Flatten, Dense\nfrom keras.models import Sequential\nfrom keras.callbacks import ModelCheckpoint\nfrom tqdm import tqdm\nfrom keras.utils import to_categorical\nfrom sklearn.metrics import confusion_matrix","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-24T10:17:36.80554Z","iopub.execute_input":"2021-09-24T10:17:36.806387Z","iopub.status.idle":"2021-09-24T10:17:42.307527Z","shell.execute_reply.started":"2021-09-24T10:17:36.806299Z","shell.execute_reply":"2021-09-24T10:17:42.306354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_num_files(path):\n    '''\n    Function which counts the number of files in a folder.\n    '''\n    if not os.path.exists(path):\n        return 0\n    return sum([len(files) for r, d, files in os.walk(path)])","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:17:42.308986Z","iopub.execute_input":"2021-09-24T10:17:42.309336Z","iopub.status.idle":"2021-09-24T10:17:42.31728Z","shell.execute_reply.started":"2021-09-24T10:17:42.309302Z","shell.execute_reply":"2021-09-24T10:17:42.316193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Paths\ntrain_dir = '/kaggle/input/dog-breed-identification/train'\ntest_dir = '/kaggle/input/dog-breed-identification/test'\n# Count/Print train and test samples.\ndata_size = get_num_files(train_dir)\ntest_size = get_num_files(test_dir)\nprint('Data samples size: ', data_size)\nprint('Test samples size: ', test_size)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:17:42.319654Z","iopub.execute_input":"2021-09-24T10:17:42.320084Z","iopub.status.idle":"2021-09-24T10:18:06.454294Z","shell.execute_reply.started":"2021-09-24T10:17:42.320049Z","shell.execute_reply":"2021-09-24T10:18:06.453327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read CSV of our data\n\nsample_df = pd.read_csv(\"../input/dog-breed-identification/sample_submission.csv\")\nlabels = pd.read_csv(\"../input/dog-breed-identification/labels.csv\")\nlabels.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:18:06.455923Z","iopub.execute_input":"2021-09-24T10:18:06.456471Z","iopub.status.idle":"2021-09-24T10:18:06.972573Z","shell.execute_reply.started":"2021-09-24T10:18:06.45643Z","shell.execute_reply":"2021-09-24T10:18:06.971529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create list of alphabetically sorted labels.\ndog_breeds = sorted(list(set(labels['breed'])))\nn_classes = len(dog_breeds)\nprint(n_classes)\ndog_breeds[:119]","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:23:18.649599Z","iopub.execute_input":"2021-09-24T10:23:18.649927Z","iopub.status.idle":"2021-09-24T10:23:18.659356Z","shell.execute_reply.started":"2021-09-24T10:23:18.649896Z","shell.execute_reply":"2021-09-24T10:23:18.65854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Map each label string to an integer label.\n\nclass_to_num = dict(zip(dog_breeds, range(n_classes)))","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:18:06.986444Z","iopub.execute_input":"2021-09-24T10:18:06.986943Z","iopub.status.idle":"2021-09-24T10:18:06.996539Z","shell.execute_reply.started":"2021-09-24T10:18:06.986904Z","shell.execute_reply":"2021-09-24T10:18:06.995595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def images_to_array(data_dir, labels_dataframe, img_size = (224,224,3)):\n    '''\n    1- Read image samples from certain directory.\n    2- Resize it, then stack them into one big numpy array.\n    3- Read sample's label form the labels dataframe.\n    4- One hot encode labels array.\n    5- Shuffle Data and label arrays.\n    '''\n    images_names = labels_dataframe['id']\n    images_labels = labels_dataframe['breed']\n    data_size = len(images_names)\n    # initailize output arrays.\n    X = np.zeros([data_size, img_size[0], img_size[1], img_size[2]], dtype=np.uint8)\n    y = np.zeros([data_size,1], dtype=np.uint8)\n    # read data and lables.\n    for i in tqdm(range(data_size)):\n        image_name = images_names[i]\n        img_dir = os.path.join(data_dir, image_name+'.jpg')\n        img_pixels = load_img(img_dir, target_size=img_size)\n        X[i] = img_pixels\n        \n        image_breed = images_labels[i]\n        y[i] = class_to_num[image_breed]\n    \n    # One hot encoder\n    y = to_categorical(y)\n    # shuffle    \n    ind = np.random.permutation(data_size)\n    X = X[ind]\n    y = y[ind]\n    print('Output Data Size: ', X.shape)\n    print('Output Label Size: ', y.shape)\n    return X, y","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:18:06.997848Z","iopub.execute_input":"2021-09-24T10:18:06.998257Z","iopub.status.idle":"2021-09-24T10:18:07.008219Z","shell.execute_reply.started":"2021-09-24T10:18:06.99822Z","shell.execute_reply":"2021-09-24T10:18:07.007084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Calling of the function to get the arrays of our images\nX, y = images_to_array(train_dir, labels)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:18:07.011821Z","iopub.execute_input":"2021-09-24T10:18:07.012215Z","iopub.status.idle":"2021-09-24T10:19:24.804633Z","shell.execute_reply.started":"2021-09-24T10:18:07.012179Z","shell.execute_reply":"2021-09-24T10:19:24.803759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_validation, y_train, y_validation = train_test_split(X, y, test_size=0.3, random_state=6)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:19:24.806436Z","iopub.execute_input":"2021-09-24T10:19:24.806708Z","iopub.status.idle":"2021-09-24T10:19:25.260519Z","shell.execute_reply.started":"2021-09-24T10:19:24.806681Z","shell.execute_reply":"2021-09-24T10:19:25.259639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Building of the hand-built model\n\nmodel = Sequential()\nmodel.add(Conv2D(filters=16, kernel_size=2, padding='same',activation='relu',input_shape=(224,224,3)))\nmodel.add(MaxPooling2D(pool_size=(2, 2), strides=None, padding=\"same\"\n))\nmodel.add(Dropout(0.3))\nmodel.add(Conv2D(filters=32, kernel_size=2, padding='same',activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2), strides=None, padding=\"same\"\n))\nmodel.add(Dropout(0.3))\nmodel.add(Conv2D(filters=64, kernel_size=2, padding='same',activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2), strides=None, padding=\"same\"\n))\nmodel.add(Dropout(0.3))\nmodel.add(GlobalAveragePooling2D())\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(120, activation='softmax'))\n\nmodel.summary() # Display of all the layers of our pre-trained model\n\nmodel.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:19:25.261758Z","iopub.execute_input":"2021-09-24T10:19:25.262179Z","iopub.status.idle":"2021-09-24T10:19:27.436071Z","shell.execute_reply.started":"2021-09-24T10:19:25.262135Z","shell.execute_reply":"2021-09-24T10:19:27.435215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define an early stopping to stop after a number of epochs which the validation loss doesn't decrease anymore\nearly_stopping = keras.callbacks.EarlyStopping(\n    patience=4,\n    min_delta=0.001,\n    restore_best_weights=True,\n)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:19:27.437342Z","iopub.execute_input":"2021-09-24T10:19:27.437687Z","iopub.status.idle":"2021-09-24T10:19:27.444315Z","shell.execute_reply.started":"2021-09-24T10:19:27.437649Z","shell.execute_reply":"2021-09-24T10:19:27.443564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 5\ncheckpointer = ModelCheckpoint(filepath='saved_models/weights.best.from_scratch.hdf5', \n                               verbose=1, save_best_only=True)\n\n# Train simple DNN on extracted features.\nmodel.fit(X, y, epochs=epochs, batch_size=20, validation_data = (X_validation, y_validation), callbacks=[checkpointer, early_stopping], verbose=1)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:20:05.817742Z","iopub.execute_input":"2021-09-24T10:20:05.818201Z","iopub.status.idle":"2021-09-24T10:21:24.67413Z","shell.execute_reply.started":"2021-09-24T10:20:05.818138Z","shell.execute_reply":"2021-09-24T10:21:24.673378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Deletion of X to free some memory\n\ndel X","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:23:30.17095Z","iopub.execute_input":"2021-09-24T10:23:30.171324Z","iopub.status.idle":"2021-09-24T10:23:30.175113Z","shell.execute_reply.started":"2021-09-24T10:23:30.171292Z","shell.execute_reply":"2021-09-24T10:23:30.17411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del X_train","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:23:31.869658Z","iopub.execute_input":"2021-09-24T10:23:31.870033Z","iopub.status.idle":"2021-09-24T10:23:31.87715Z","shell.execute_reply.started":"2021-09-24T10:23:31.869983Z","shell.execute_reply":"2021-09-24T10:23:31.875925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def images_to_array2(data_dir, labels_dataframe, img_size = (224,224,3)):\n    '''\n    Do same as images_to_array but omit some unnecessary steps for test data.\n    '''\n    images_names = labels_dataframe['id']\n    data_size = len(images_names)\n    X = np.zeros([data_size, img_size[0], img_size[1], 3], dtype=np.uint8)\n    \n    for i in tqdm(range(data_size)):\n        image_name = images_names[i]\n        img_dir = os.path.join(data_dir, image_name+'.jpg')\n        img_pixels = tf.keras.preprocessing.image.load_img(img_dir, target_size=img_size)\n        X[i] = img_pixels\n        \n    print('Output Data Size: ', X.shape)\n    return X\n\ntest_data = images_to_array2(test_dir, sample_df)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:23:33.644081Z","iopub.execute_input":"2021-09-24T10:23:33.644416Z","iopub.status.idle":"2021-09-24T10:24:58.618705Z","shell.execute_reply.started":"2021-09-24T10:23:33.644386Z","shell.execute_reply":"2021-09-24T10:24:58.616722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = model.predict(test_data)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:25:41.417763Z","iopub.execute_input":"2021-09-24T10:25:41.418098Z","iopub.status.idle":"2021-09-24T10:25:50.717365Z","shell.execute_reply.started":"2021-09-24T10:25:41.418066Z","shell.execute_reply":"2021-09-24T10:25:50.716513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del test_data","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:25:53.625547Z","iopub.execute_input":"2021-09-24T10:25:53.625863Z","iopub.status.idle":"2021-09-24T10:25:53.651496Z","shell.execute_reply.started":"2021-09-24T10:25:53.625834Z","shell.execute_reply":"2021-09-24T10:25:53.649644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(y_pred[0])\nprint(f\"Max value (probability of prediction): {np.max(y_pred[0])}\") # the max probability value","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:25:55.595596Z","iopub.execute_input":"2021-09-24T10:25:55.595922Z","iopub.status.idle":"2021-09-24T10:25:55.605789Z","shell.execute_reply.started":"2021-09-24T10:25:55.59588Z","shell.execute_reply":"2021-09-24T10:25:55.604657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_key(my_dict, val):\n    \"\"\" Function which returns the key of a dictionary according to its value \"\"\"\n    for key, value in my_dict.items():\n         if val == value:\n             return key\n    return \"key doesn't exist\"","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:00.193409Z","iopub.execute_input":"2021-09-24T10:26:00.19374Z","iopub.status.idle":"2021-09-24T10:26:00.198396Z","shell.execute_reply.started":"2021-09-24T10:26:00.19371Z","shell.execute_reply":"2021-09-24T10:26:00.197304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predicted by the model\nprint(f\"Sum: {np.sum(y_pred[0])}\") # because we used softmax activation in our model, this will be close to 1\nprint(f\"Max index: {np.argmax(y_pred[0])}\") # the index of where the max value in predictions[0] occurs\nprint(f\"Predicted label: {get_key(class_to_num, np.argmax(y_pred[0]))}\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:03.064647Z","iopub.execute_input":"2021-09-24T10:26:03.06498Z","iopub.status.idle":"2021-09-24T10:26:03.071309Z","shell.execute_reply.started":"2021-09-24T10:26:03.064948Z","shell.execute_reply":"2021-09-24T10:26:03.070466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create pandas DataFrame with empty columns\npreds_df = pd.DataFrame(columns=[\"id\"] + list(dog_breeds))\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:14.809853Z","iopub.execute_input":"2021-09-24T10:26:14.810207Z","iopub.status.idle":"2021-09-24T10:26:14.834487Z","shell.execute_reply.started":"2021-09-24T10:26:14.810177Z","shell.execute_reply":"2021-09-24T10:26:14.833474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Inclusion of our images in the dataframe\n\ntest_path = \"../input/dog-breed-identification/test/\"\npreds_df[\"id\"] = [os.path.splitext(path)[0] for path in os.listdir(test_path)]\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:17.049461Z","iopub.execute_input":"2021-09-24T10:26:17.049783Z","iopub.status.idle":"2021-09-24T10:26:17.352707Z","shell.execute_reply.started":"2021-09-24T10:26:17.049753Z","shell.execute_reply":"2021-09-24T10:26:17.351341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df.loc[:,list(dog_breeds)]= y_pred\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:19.737746Z","iopub.execute_input":"2021-09-24T10:26:19.7381Z","iopub.status.idle":"2021-09-24T10:26:19.836101Z","shell.execute_reply.started":"2021-09-24T10:26:19.738068Z","shell.execute_reply":"2021-09-24T10:26:19.835148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_size = (224,224,3)\n\ndef loading_image(path):\n    \"\"\" Function which loads an image and makes a prediction on its breed \"\"\"\n    Image(path)\n    img_g = load_img('../input/testing-images/index.jpeg',target_size = img_size)\n    img_g = tf.keras.preprocessing.image.img_to_array(img_g)\n    img_g = np.expand_dims(img_g, axis=0)\n    predg = model.predict(img_g)\n    return predg","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:27:59.139057Z","iopub.execute_input":"2021-09-24T10:27:59.139384Z","iopub.status.idle":"2021-09-24T10:27:59.144339Z","shell.execute_reply.started":"2021-09-24T10:27:59.139356Z","shell.execute_reply":"2021-09-24T10:27:59.143373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"prediction = loading_image(\"../input/testing-images/index.jpeg\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:28:23.648736Z","iopub.execute_input":"2021-09-24T10:28:23.649137Z","iopub.status.idle":"2021-09-24T10:28:23.693476Z","shell.execute_reply.started":"2021-09-24T10:28:23.649105Z","shell.execute_reply":"2021-09-24T10:28:23.692585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Displaying of the prediction\n\nprint(f\"Predicted label: {get_key(class_to_num, np.argmax(prediction[0]))}\")\nprint(f\"Probability of prediction: {round(np.max(prediction[0]) * 100, 3)} %\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:28:29.857962Z","iopub.execute_input":"2021-09-24T10:28:29.858418Z","iopub.status.idle":"2021-09-24T10:28:29.866344Z","shell.execute_reply.started":"2021-09-24T10:28:29.858372Z","shell.execute_reply":"2021-09-24T10:28:29.863256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_confusion_matrix(data_pred_cls,data_predicted_cls):\n    # This is called from print_test_accuracy() below.\n\n\n    # cls_pred is an array of the predicted class-number for\n    # all images in the test-set.\n  \n    # Get the confusion matrix using sklearn.\n    df_cm = confusion_matrix(y_true=data_pred_cls,\n                          y_pred=data_predicted_cls, normalize = 'true')\n\n\n    # Print the confusion matrix as text.\n    print(df_cm)\n    breeds_dataframe = pd.DataFrame(df_cm, columns=dog_breeds)\n    \n    # Plot the confusion matrix as an image.\n    plt.figure(figsize = (40,35))\n    \n    # plt.matshow(cm)\n\n\n    # Make various adjustments to the plot.\n#     plt.colorbar()\n#     tick_marks = np.arange(n_classes)\n#     plt.xticks(tick_marks, dog_breeds, rotation=90)\n#     plt.yticks(tick_marks, dog_breeds)\n#     plt.xlabel('Predicted')\n#     plt.ylabel('True')\n\n\n    # Ensure the plot is shown correctly with multiple plots\n    # in a single Notebook cell.\n    sn.heatmap(breeds_dataframe, annot=False, xticklabels=breeds_dataframe.columns, yticklabels=breeds_dataframe.columns)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:31.457575Z","iopub.execute_input":"2021-09-24T10:26:31.457915Z","iopub.status.idle":"2021-09-24T10:26:31.46372Z","shell.execute_reply.started":"2021-09-24T10:26:31.457877Z","shell.execute_reply":"2021-09-24T10:26:31.462806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_validation_toPred_cls = np.argmax(y_validation, axis=1)\ny_pred_valid = model.predict(X_validation)\ndf_validation_predicted_cls = np.argmax(y_pred_valid, axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:33.752739Z","iopub.execute_input":"2021-09-24T10:26:33.753094Z","iopub.status.idle":"2021-09-24T10:26:36.573147Z","shell.execute_reply.started":"2021-09-24T10:26:33.753061Z","shell.execute_reply":"2021-09-24T10:26:36.572308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_confusion_matrix(df_validation_toPred_cls,df_validation_predicted_cls)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T10:26:39.371165Z","iopub.execute_input":"2021-09-24T10:26:39.371617Z","iopub.status.idle":"2021-09-24T10:26:43.999557Z","shell.execute_reply.started":"2021-09-24T10:26:39.371575Z","shell.execute_reply":"2021-09-24T10:26:43.998688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}