{"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":"markdown","source":"## This notebook is inspired from Ruchi Bhatia's Notebook [Link](https://www.kaggle.com/ruchi798/and-identification-eda-augmentation/notebook) and Andrada Olteanu's notebook [Link](https://www.kaggle.com/andradaolteanu/whales-dolphins-effnet-embedding-cos-distance#7.-Cosine-Distance)","metadata":{"execution":{"iopub.status.busy":"2022-02-12T10:35:26.573946Z","iopub.execute_input":"2022-02-12T10:35:26.574284Z","iopub.status.idle":"2022-02-12T10:35:28.376621Z","shell.execute_reply.started":"2022-02-12T10:35:26.57426Z","shell.execute_reply":"2022-02-12T10:35:28.376116Z"}}},{"cell_type":"markdown","source":"# Import libraries","metadata":{}},{"cell_type":"code","source":"!pip install imagesize","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:19.278019Z","iopub.execute_input":"2022-02-17T14:53:19.278387Z","iopub.status.idle":"2022-02-17T14:53:31.208746Z","shell.execute_reply.started":"2022-02-17T14:53:19.278282Z","shell.execute_reply":"2022-02-17T14:53:31.207623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\nimport os\nimport cv2\n\nfrom termcolor import colored\nimport imagesize\n\nfrom tqdm import tqdm\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:31.211283Z","iopub.execute_input":"2022-02-17T14:53:31.211565Z","iopub.status.idle":"2022-02-17T14:53:32.940912Z","shell.execute_reply.started":"2022-02-17T14:53:31.211537Z","shell.execute_reply":"2022-02-17T14:53:32.94012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = pd.read_csv(\"../input/happy-whale-and-dolphin/train.csv\")\ntrain_data.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:32.942378Z","iopub.execute_input":"2022-02-17T14:53:32.942793Z","iopub.status.idle":"2022-02-17T14:53:33.06984Z","shell.execute_reply.started":"2022-02-17T14:53:32.942742Z","shell.execute_reply":"2022-02-17T14:53:33.069095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Figure out unique data and fix repeating names","metadata":{}},{"cell_type":"code","source":"print(\"Number of unique species :\", train_data[\"species\"].nunique())\nprint(\"Unique Species names :\", list(train_data[\"species\"].unique()))","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:33.102648Z","iopub.execute_input":"2022-02-17T14:53:33.103358Z","iopub.status.idle":"2022-02-17T14:53:33.132613Z","shell.execute_reply.started":"2022-02-17T14:53:33.10332Z","shell.execute_reply":"2022-02-17T14:53:33.131946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### 1. Bottlenose_dolphin has been mispelled as bottlenose_dolpin\n#### 2. Killer_whale has been mispelled as kiler_whale\n\n#### Fixing...\n\n#### pilot_whale and globis are both short_finned_pilot_whale and thus the three can be merged - From [discussions](https://www.kaggle.com/c/happy-whale-and-dolphin/discussion/305468)","metadata":{}},{"cell_type":"code","source":"train_data[\"species\"] = train_data[\"species\"].str.replace('bottlenose_dolpin', 'bottlenose_dolphin')\ntrain_data[\"species\"] = train_data[\"species\"].str.replace('kiler_whale', 'killer_whale')\ntrain_data[\"species\"] = train_data[\"species\"].str.replace('pilot_whale', 'short_finned_pilot_whale')\ntrain_data[\"species\"] = train_data[\"species\"].str.replace('globis', 'short_finned_pilot_whale')\n\ntrain_data[\"species\"] = train_data[\"species\"].str.replace('short_finned_short_finned_pilot_whale', 'short_finned_pilot_whale')\ntrain_data[\"species\"] = train_data[\"species\"].str.replace('long_finned_short_finned_pilot_whale', 'long_finned_pilot_whale')\n\n\nprint(colored(\"Duplicates fixed...\", 'red'))\n\nprint(colored(\"Number of unique species : {0}\".format(train_data[\"species\"].nunique()), \"green\"))\nprint(\"Unique Species names :\", list(train_data[\"species\"].unique()))","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:33.134008Z","iopub.execute_input":"2022-02-17T14:53:33.134486Z","iopub.status.idle":"2022-02-17T14:53:33.413135Z","shell.execute_reply.started":"2022-02-17T14:53:33.134452Z","shell.execute_reply":"2022-02-17T14:53:33.412088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train and Test data","metadata":{}},{"cell_type":"code","source":"test_img_dir = '../input/happy-whale-and-dolphin/test_images'\ntrain_img_dir = '../input/happy-whale-and-dolphin/train_images'\n\ndef getCompleteImagePath(path):\n    image_names = []\n    for dirname, _, filenames in os.walk(path):\n        for imageName in filenames:\n            complete_path = os.path.join(dirname, imageName)\n            image_names.append(complete_path)\n    return image_names, len(image_names)\n\ntrain_img_path, num_train_images = getCompleteImagePath(train_img_dir)\ntest_img_path, num_test_images = getCompleteImagePath(test_img_dir)\n\nprint(colored(\"Number of train images : {0}\".format(num_train_images), 'blue'))\nprint(colored(\"Number of test images : {0}\".format(num_test_images), 'green'))","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:33.414654Z","iopub.execute_input":"2022-02-17T14:53:33.414908Z","iopub.status.idle":"2022-02-17T14:53:55.30079Z","shell.execute_reply.started":"2022-02-17T14:53:33.414873Z","shell.execute_reply":"2022-02-17T14:53:55.299594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def addCompleteImagePath(train_data, train_img_dir):\n    train_data[\"complete_img_path\"] = \"empty\"\n    for index, row in train_data.iterrows():\n        row[\"complete_img_path\"] = os.path.join(train_img_dir, row[\"image\"])\n    return train_data\n    \ntrain_data = addCompleteImagePath(train_data, train_img_dir)\ntrain_data.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:55.301986Z","iopub.execute_input":"2022-02-17T14:53:55.302204Z","iopub.status.idle":"2022-02-17T14:53:58.627364Z","shell.execute_reply.started":"2022-02-17T14:53:55.302178Z","shell.execute_reply":"2022-02-17T14:53:58.62636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def displayImages(image_path, rows, cols, title, figsize=(20, 8)):\n    figure, ax = plt.subplots(nrows=rows, ncols=cols, figsize=figsize)\n    plt.suptitle(title, fontsize=18)\n    for index, pathImage in enumerate(image_path):\n        img = cv2.cvtColor(cv2.imread(pathImage), cv2.COLOR_BGR2RGB)\n        try:\n            ax.ravel()[index].imshow(img)\n            ax.ravel()[index].set_axis_off()\n        except:\n            continue;\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:58.628643Z","iopub.execute_input":"2022-02-17T14:53:58.628909Z","iopub.status.idle":"2022-02-17T14:53:58.637219Z","shell.execute_reply.started":"2022-02-17T14:53:58.628879Z","shell.execute_reply":"2022-02-17T14:53:58.636161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"displayImages(train_img_path[:30], 6, 5, \"Train images(30)\")","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:53:58.638551Z","iopub.execute_input":"2022-02-17T14:53:58.638856Z","iopub.status.idle":"2022-02-17T14:54:12.995232Z","shell.execute_reply.started":"2022-02-17T14:53:58.638799Z","shell.execute_reply":"2022-02-17T14:54:12.993937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"displayImages(test_img_path[:30], 6, 5, \"Test images(30)\")","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:12.996621Z","iopub.execute_input":"2022-02-17T14:54:12.997065Z","iopub.status.idle":"2022-02-17T14:54:26.029705Z","shell.execute_reply.started":"2022-02-17T14:54:12.997032Z","shell.execute_reply":"2022-02-17T14:54:26.028713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Whales : Dolphins as Super Class","metadata":{}},{"cell_type":"markdown","source":"#### Let's split the classes to Super_class to understand distribution of whales and dolphins","metadata":{}},{"cell_type":"code","source":"train_data[\"super_class\"] = train_data.species.map(lambda x : 'dolphin' if 'dolphin' in x else 'whale')","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:26.030982Z","iopub.execute_input":"2022-02-17T14:54:26.031221Z","iopub.status.idle":"2022-02-17T14:54:26.054184Z","shell.execute_reply.started":"2022-02-17T14:54:26.031192Z","shell.execute_reply":"2022-02-17T14:54:26.053297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(16, 8))\nfig.suptitle(\"Distribution of Whales and Dolphins\", size=22)\nexplode = (0.05, 0.05)\nlabels = list(train_data.super_class.value_counts().index)\nsizes = train_data.super_class.value_counts().values\nax.pie(sizes, explode=explode, startangle=45, labels=labels, autopct=\"%1.0f%%\", pctdistance=0.8, colors=['#03fcdf', '#03a5fc'])\nax.add_artist(plt.Circle((0,0), 0.6, fc=\"white\"))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:26.057611Z","iopub.execute_input":"2022-02-17T14:54:26.057935Z","iopub.status.idle":"2022-02-17T14:54:26.232542Z","shell.execute_reply.started":"2022-02-17T14:54:26.057889Z","shell.execute_reply":"2022-02-17T14:54:26.231315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* #### The data is imbalanced from super_class perspective itself. We see Whale:Dolphin :: 67:33. \n* #### We may need to focus on Dolphins more while preprcessing/data augmentations to bring the ratio to atleast 55:45.\n* #### This is just a general idea. Best ratio would be 50:50 anyday. To be realistic, I think, 55:45 should be a good ratio if achieveable. Again, this ratio needs to be tested at model performance level.","metadata":{}},{"cell_type":"markdown","source":"# Distribution within Whales and Dolphins","metadata":{}},{"cell_type":"code","source":"whales = train_data[train_data[\"super_class\"]==\"whale\"]\ndolphins = train_data[train_data[\"super_class\"]!=\"whale\"]\n\nfig, ax = plt.subplots(nrows = 1,ncols = 2, figsize=(16, 8))\n\nsns.countplot(y=\"species\", data=whales, order=whales.iloc[0:][\"species\"].value_counts().index, ax=ax[0], color=\"#03fcdf\")\nax[0].set_title(\"Distribution of Whales\")\nax[0].set_ylabel(None)\n\nsns.countplot(y=\"species\", data=dolphins, order=dolphins.iloc[0:][\"species\"].value_counts().index, ax=ax[1], color=\"#03a5fc\")\nax[1].set_title(\"Distribution of Dolphins\")\nax[1].set_ylabel(None)\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:26.234659Z","iopub.execute_input":"2022-02-17T14:54:26.235369Z","iopub.status.idle":"2022-02-17T14:54:26.907583Z","shell.execute_reply.started":"2022-02-17T14:54:26.235297Z","shell.execute_reply":"2022-02-17T14:54:26.906007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Whales :-**\n\n* #### Mind = Blown xD. We have appx 7k Beluga and nearly 10~100 Pygmy killer whale. (As per the results of few searches, Pygmy killer whale is itself a very species of whale xD. So having less data is understood). \n\n* #### Balancing such data would be very challeneging. If it was real life scenario where you would very rarely see this whale, we would have omitted this class. This means adding data from other sources would be challeneging too (most probably)\n\n* #### Even for Brydes whale, we lack information.\n\n* #### So for last 8 whale species, we have less than 1k images.\n\n### **Dolphins :-**\n\n* #### 10k+ images for bottlenose dolphin, and nearly nil for frasiers dolphin. \n\n* #### Frasiers dolphin are mostly found in deep waters = hard to spot on surface, hence less images?\n\n* #### For last 7 dolphin classes we have very less images.\n\n### In this scenario, data augmentation might help, but till what extent? Can't increase 500 images to 5k using just augmentations xD. Augmentations should be very well experimented. Might do wonders!","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nplt.yticks(fontsize=12)\nplt.xticks(fontsize=12)\nsns.countplot(y=\"species\", data=train_data, order=train_data.iloc[0:][\"species\"].value_counts().index, palette=\"hls\", linewidth=4)\nplt.title(\"Entire Train set Distribution\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:26.909269Z","iopub.execute_input":"2022-02-17T14:54:26.909696Z","iopub.status.idle":"2022-02-17T14:54:27.353165Z","shell.execute_reply.started":"2022-02-17T14:54:26.90965Z","shell.execute_reply":"2022-02-17T14:54:27.35204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Working with individual ids","metadata":{}},{"cell_type":"code","source":"all_indv = train_data[\"individual_id\"].value_counts().reset_index()\nindividuals = train_data[\"individual_id\"].value_counts().reset_index().head(1000)\n\nprint(colored(\"Total Unique IDs : {0}\".format(all_indv.shape[0]),\"blue\"))\nprint(colored(\"ID : {1} occurs {0} times (Max)\".format(all_indv.max()[\"individual_id\"], all_indv.max()[\"index\"]),\"green\"))\nprint(colored(\"ID : {1} occurs {0} times (Min)\".format(all_indv.min()[\"individual_id\"], all_indv.min()[\"index\"]),\"yellow\"))","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:27.354507Z","iopub.execute_input":"2022-02-17T14:54:27.35476Z","iopub.status.idle":"2022-02-17T14:54:27.41037Z","shell.execute_reply.started":"2022-02-17T14:54:27.354731Z","shell.execute_reply":"2022-02-17T14:54:27.4093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_indv","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:27.412239Z","iopub.execute_input":"2022-02-17T14:54:27.412585Z","iopub.status.idle":"2022-02-17T14:54:27.426762Z","shell.execute_reply.started":"2022-02-17T14:54:27.41254Z","shell.execute_reply":"2022-02-17T14:54:27.425867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nsns.barplot(data=all_indv.head(50), x=\"individual_id\", y=\"index\", palette=\"flare\")\nplt.title(\"Top 50 individual IDs\")\nplt.ylabel(\"Individual\")\nplt.xlabel(\"Frequncy\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:27.429001Z","iopub.execute_input":"2022-02-17T14:54:27.429333Z","iopub.status.idle":"2022-02-17T14:54:28.572461Z","shell.execute_reply.started":"2022-02-17T14:54:27.429288Z","shell.execute_reply":"2022-02-17T14:54:28.571401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize each species","metadata":{}},{"cell_type":"code","source":"def display_individual_species(species_name):\n    \n    if species_name not in train_data[\"species\"].unique():\n        print(colored(\"Invalid species name...\", red))\n        return\n    \n    possible_num_images = train_data[train_data[\"species\"]==species_name].shape[0]\n    \n    if possible_num_images > 10:\n        possible_num_images = 10\n    \n    indv_species = train_data[train_data[\"species\"]==species_name].head(possible_num_images)\n    \n    if possible_num_images == 10:\n        displayImages(indv_species[\"complete_img_path\"].tolist(), 2, 5, species_name, figsize=(10, 5))\n    else:\n        displayImages(indv_species[\"complete_img_path\"].tolist(), 1, 5, species_name, figsize=(10, 5))","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:28.573776Z","iopub.execute_input":"2022-02-17T14:54:28.574148Z","iopub.status.idle":"2022-02-17T14:54:28.58201Z","shell.execute_reply.started":"2022-02-17T14:54:28.574116Z","shell.execute_reply":"2022-02-17T14:54:28.58098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_species = train_data[\"species\"].unique().tolist()\nfor species in unique_species:\n    display_individual_species(species)","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:54:28.583231Z","iopub.execute_input":"2022-02-17T14:54:28.583549Z","iopub.status.idle":"2022-02-17T14:56:13.225588Z","shell.execute_reply.started":"2022-02-17T14:54:28.583512Z","shell.execute_reply":"2022-02-17T14:56:13.224995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Take a look at the image sizes","metadata":{}},{"cell_type":"code","source":"width_list, height_list = [], []\n\nfor fish_path in tqdm(train_data[\"complete_img_path\"]):\n    width, height = imagesize.get(fish_path)\n    width_list.append(width)\n    height_list.append(height)","metadata":{"execution":{"iopub.status.busy":"2022-02-17T14:56:13.226573Z","iopub.execute_input":"2022-02-17T14:56:13.227338Z","iopub.status.idle":"2022-02-17T15:03:50.964749Z","shell.execute_reply.started":"2022-02-17T14:56:13.227295Z","shell.execute_reply":"2022-02-17T15:03:50.963871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data[\"width\"] = width_list\ntrain_data[\"height\"] = height_list\ntrain_data[\"dimension\"] = train_data[\"width\"] * train_data[\"height\"]","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:50.966378Z","iopub.execute_input":"2022-02-17T15:03:50.966891Z","iopub.status.idle":"2022-02-17T15:03:51.020792Z","shell.execute_reply.started":"2022-02-17T15:03:50.966828Z","shell.execute_reply":"2022-02-17T15:03:51.01988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"min_size = train_data[train_data[\"dimension\"]==train_data[\"dimension\"].min()]\nmax_size = train_data[train_data[\"dimension\"]==train_data[\"dimension\"].max()]","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:51.022342Z","iopub.execute_input":"2022-02-17T15:03:51.022641Z","iopub.status.idle":"2022-02-17T15:03:51.037878Z","shell.execute_reply.started":"2022-02-17T15:03:51.0226Z","shell.execute_reply":"2022-02-17T15:03:51.036747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image with lowest dimension","metadata":{}},{"cell_type":"code","source":"min_size","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:51.039533Z","iopub.execute_input":"2022-02-17T15:03:51.03989Z","iopub.status.idle":"2022-02-17T15:03:51.055297Z","shell.execute_reply.started":"2022-02-17T15:03:51.039792Z","shell.execute_reply":"2022-02-17T15:03:51.054227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image with highest resolution","metadata":{}},{"cell_type":"code","source":"max_size","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:51.057046Z","iopub.execute_input":"2022-02-17T15:03:51.057437Z","iopub.status.idle":"2022-02-17T15:03:51.075916Z","shell.execute_reply.started":"2022-02-17T15:03:51.057391Z","shell.execute_reply":"2022-02-17T15:03:51.074918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data[\"dimension\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:51.077641Z","iopub.execute_input":"2022-02-17T15:03:51.078256Z","iopub.status.idle":"2022-02-17T15:03:51.091021Z","shell.execute_reply.started":"2022-02-17T15:03:51.078215Z","shell.execute_reply":"2022-02-17T15:03:51.090011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Out of 51k images, we have 24,233 unique image dimensions","metadata":{}},{"cell_type":"code","source":"temp_data = train_data[[\"species\", \"dimension\", \"super_class\"]]","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:03:51.094363Z","iopub.execute_input":"2022-02-17T15:03:51.094973Z","iopub.status.idle":"2022-02-17T15:03:51.104818Z","shell.execute_reply.started":"2022-02-17T15:03:51.09494Z","shell.execute_reply":"2022-02-17T15:03:51.103916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(16, 16))\nsns.violinplot(data=temp_data, x=\"species\", y=\"dimension\", hue=\"super_class\", palette=\"magma\")\nplt.xlabel(\"Species\")\nplt.ylabel(\"Dimension\")\nplt.xticks(rotation=90)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-17T15:14:08.882863Z","iopub.execute_input":"2022-02-17T15:14:08.883417Z","iopub.status.idle":"2022-02-17T15:14:10.005281Z","shell.execute_reply.started":"2022-02-17T15:14:08.883371Z","shell.execute_reply":"2022-02-17T15:14:10.003948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"By this graph we can see that \"frasiers_dolphin\" species has very small resolution images. ","metadata":{}},{"cell_type":"markdown","source":"# Work under process...","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}