{"cells":[{"metadata":{"_uuid":"2407da09107a3b7f3e9bcb63b0e671ea85593c2d"},"cell_type":"markdown","source":"# Whale Identification using CNN"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport gc\n\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mplimg\nfrom matplotlib.pyplot import imshow\nimport seaborn as sns\n\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.preprocessing import OneHotEncoder\nimport random\nfrom IPython.display import Image\n\nfrom keras import layers\nfrom keras.preprocessing import image\nfrom keras.applications.imagenet_utils import preprocess_input\nfrom keras.layers import Input, Dense, Activation, BatchNormalization, Flatten, Conv2D\nfrom keras.layers import AveragePooling2D, MaxPooling2D, Dropout\nfrom keras.models import Model\n\nimport keras.backend as K\nfrom keras.models import Sequential\n\n%matplotlib inline\nimport warnings\nwarnings.simplefilter(\"ignore\", category=DeprecationWarning)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b04d3433b8d5dbd316ba563649aefeb7eeef4379"},"cell_type":"code","source":"os.listdir(\"../input\")","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# load image data\ndf = pd.read_csv('../input/train.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"059d928adfaed6a0eefeb0f1608ea616aefd6f7a"},"cell_type":"code","source":"df.tail()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b57f56b99ceb88f6d34c1fdfef3d331f1039d895"},"cell_type":"markdown","source":"Now let's open one of the images in the training set to see how they look like."},{"metadata":{"trusted":true,"_uuid":"2bf5dac212f783c00b578f3e87797465bcf3b469"},"cell_type":"code","source":"#show sample image\nImage(filename=\"../input/train/\"+random.choice(df['Image'])) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"25c4470c56b11a2fa2dc9b6ad44feabb2297e4ae"},"cell_type":"code","source":"# lets find total number of different whales present\nprint(f'Training examples: {len(df)}')\nprint(\"Unique whales: \",df['Id'].nunique()) # it includes new_whale as a separate type.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a49e6ecfb3cf5e958cab833ecc8e6f656385220d"},"cell_type":"code","source":"training_pts_per_class = df.groupby('Id').size()\ntraining_pts_per_class","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"683391c9d4024c83e8a51c1ec4822a8d0b9d2f3d"},"cell_type":"code","source":"print(\"Min example a class can have: \",training_pts_per_class.min())\nprint(\"0.99 quantile: \",training_pts_per_class.quantile(0.99))\nprint(\"Max example a class can have: \\n\",training_pts_per_class.nlargest(5))    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d32cbf59c72eda3d727a6256a40ce3cb1651bde8"},"cell_type":"code","source":"data = training_pts_per_class.copy()\ndata.loc[data > data.quantile(0.99)] = '22+'\nplt.figure(figsize=(15,10))\nsns.countplot(data.astype('str'))\nplt.title(\"#classes with different number of images\",fontsize=15)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"94fd580fe0c2151a44735c802be5b86b79d588e7"},"cell_type":"code","source":"# new_whales is addes as a new class.\n# above graph shows that there are more than 2000 classes with just one training example.\n# and around 1300 classes with 2 training examples.\n# it also shows that around 50 classes have more than 22 training examples.\n\ndata","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b7e53ebeb7f02aa4945693beb3ac33c8fc4c7f88"},"cell_type":"markdown","source":"The next set of code is meant to prepare the images to be used for the training. It changes their shape and converts it into an array."},{"metadata":{},"cell_type":"markdown","source":"# ** MY FILTER **"},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport glob\nimport numpy as np\nimport os, sys, time\nimport numpy as numpy\n\n\ndef filterForTails (img):\n    draw = False\n    waitValue = 10\n\n    imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    blur = cv2.GaussianBlur(imgray, (7, 7), 0)\n    ret,thresh = cv2.threshold(blur,127,255,0)\n\n    blur2 = cv2.GaussianBlur(thresh, (7, 7), 0)\n    thresh2 = cv2.threshold(blur2, 250, 250, cv2.THRESH_BINARY)[1]\n    #blur3 = cv2.GaussianBlur(thresh2, (7, 7), 0)\n\n    contours2, hierarchy = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n\n    for c in contours2:\n\n        approx = cv2.approxPolyDP(c, 0.01 * cv2.arcLength(c, True), True)\n\n        x, y, w, h = cv2.boundingRect(c)\n        roi = img[y:h+y, x:w+x]\n        imgray2 = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)\n\n        if (len(approx) != 1):\n            draw = True\n\n    if (draw):\n        img = cv2.drawContours(img, contours2, -3, (255, 255, 255), -8)\n\n        draw = False\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"59a52ac7632498fba5a9204372a49773d7a59f58"},"cell_type":"code","source":"def prepare_images(data, m, dataset, filterOn):\n    print(\"Preparing images\")\n    X_train = np.zeros((m, 100, 100, 3))\n    count = 0\n    \n    for fig in data['Image']:\n       #load images into images of size 100x100x3\n        img = cv2.imread(\"../input/\"+dataset+\"/\"+fig)\n        if(filterOn):\n            img = filterForTails(img)\n        img = cv2.resize(img, (100, 100))\n        \n        x = image.img_to_array(img)\n        x = preprocess_input(x)\n        \n        X_train[count] = x\n        if (count%500 == 0):\n            print(\"Processing image: \", count+1, \", \", fig)\n        count += 1\n    \n    return X_train","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b6c0d88c07ca490f2821dc4ddc3c22f4d6882621"},"cell_type":"markdown","source":"Preparing the labels, by converting them into one-hot vectors."},{"metadata":{"trusted":true,"_uuid":"bc5f8ade69f1647502bc274c7de4a3fae857bf22"},"cell_type":"code","source":"def prepare_labels(y):\n    values = np.array(y)\n    label_encoder = LabelEncoder()\n    integer_encoded = label_encoder.fit_transform(values)\n    # print(integer_encoded)\n\n    onehot_encoder = OneHotEncoder(sparse=False)\n    integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)\n    onehot_encoded = onehot_encoder.fit_transform(integer_encoded)\n    # print(onehot_encoded)\n\n    y = onehot_encoded\n    # print(y.shape)\n    return y, label_encoder","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c7b9352f994330a7fc286c6d0dc928bb5b1b2dbc"},"cell_type":"code","source":"filterOn = True\n\nstart = time.time()\nX = prepare_images(df, df.shape[0], \"train\", filterOn)\nX /= 255\nend = time.time()\nelapsed = end - start\nprint(\"Elapsed time: \", elapsed)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"24af0d15c2cee44e8732b57a818f9c9e10f9ccfe"},"cell_type":"code","source":"y, label_encoder = prepare_labels(df['Id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.2, random_state=2)\nX = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7e07953e0ce1ce0e60ac541334edb4afb45baa0d"},"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(32, (7, 7), strides = (1, 1), name = 'conv0', input_shape = (100, 100, 3)))\n\nmodel.add(BatchNormalization(axis = 3, name = 'bn0'))\nmodel.add(Activation('relu'))\n\nmodel.add(MaxPooling2D((2, 2), name='max_pool'))\nmodel.add(Conv2D(64, (3, 3), strides = (1,1), name=\"conv1\"))\nmodel.add(Activation('relu'))\nmodel.add(AveragePooling2D((3, 3), name='avg_pool'))\n\nmodel.add(Flatten())\nmodel.add(Dense(500, activation=\"relu\", name='rl'))\nmodel.add(Dropout(0.8))\nmodel.add(Dense(y.shape[1], activation='softmax', name='sm'))\n\nmodel.compile(loss='categorical_crossentropy', optimizer=\"adam\", metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"858e1d9aad086036e7f600e42649e6d7dbb84a1e"},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e01a20d0c4ffd755353277610ce7404a9584d8e1"},"cell_type":"code","source":"start = time.time()\n\nhistory = model.fit(X_train, Y_train, epochs=10, batch_size=4, verbose=1)\ngc.collect()\n\nend = time.time()\nelapsed = end - start\nprint(\"Elapsed time: \", elapsed)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"18fd69468d3084a3d9ef7d4e7dd753f72f39e04e"},"cell_type":"code","source":"# Plot the loss curve for training\nplt.plot(history.history['loss'], color='r', label=\"Train Loss\")\nplt.title(\"Train Loss\")\nplt.xlabel(\"Number of Epochs\")\nplt.ylabel(\"Loss\")\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Plot the accuracy curve for training\nplt.plot(history.history['accuracy'], color='g', label=\"Train Accuracy\")\nplt.title(\"Train Accuracy\")\nplt.xlabel(\"Number of Epochs\")\nplt.ylabel(\"Accuracy\")\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2d538aad036783064096e9cc054ea9030a798dce"},"cell_type":"code","source":"test = os.listdir(\"../input/test/\")\nprint(len(test))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b07a5f5eb265335b60abfa639a6b6d72d5a64429"},"cell_type":"code","source":"col = ['Image']\ntest_df = pd.DataFrame(test, columns=col)\ntest_df['Id'] = ''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3ded6bfed97808e98ef1540643304f22fbaf009e"},"cell_type":"code","source":"X_test = prepare_images(test_df, test_df.shape[0], \"test\")\nX_test /= 255","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"55cf2fa33be3d1463f2adb57999f1feb2cceba8e"},"cell_type":"code","source":"predictions = model.predict(np.array(X_test), verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"00262ebd8f66be387c7d9cb49ff3454b1c4e09c3"},"cell_type":"code","source":"for i, pred in enumerate(predictions):\n    test_df.loc[i, 'Id'] = ' '.join(label_encoder.inverse_transform(pred.argsort()[-5:][::-1]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ff0fae854b11325c3a4cacb999ae2e17277cd01b"},"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","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}