{"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":"Thanks to: https://www.kaggle.com/drcapa/happywhale-2022-starter\n\n","metadata":{}},{"cell_type":"markdown","source":"And the preprocessor step is based on an old competition but I don't have notebook link anymore","metadata":{}},{"cell_type":"markdown","source":"# Libraries","metadata":{}},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:25.141893Z","iopub.execute_input":"2022-02-02T00:59:25.142276Z","iopub.status.idle":"2022-02-02T00:59:25.394530Z","shell.execute_reply.started":"2022-02-02T00:59:25.142149Z","shell.execute_reply":"2022-02-02T00:59:25.393657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Path","metadata":{}},{"cell_type":"code","source":"path = '/kaggle/input/happy-whale-and-dolphin/'\nos.listdir(path)","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:25.396379Z","iopub.execute_input":"2022-02-02T00:59:25.396624Z","iopub.status.idle":"2022-02-02T00:59:25.405845Z","shell.execute_reply.started":"2022-02-02T00:59:25.396591Z","shell.execute_reply":"2022-02-02T00:59:25.405000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"train_data = pd.read_csv(path+'train.csv')\nsamp_subm = pd.read_csv(path+'sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:25.407444Z","iopub.execute_input":"2022-02-02T00:59:25.407748Z","iopub.status.idle":"2022-02-02T00:59:25.560964Z","shell.execute_reply.started":"2022-02-02T00:59:25.407681Z","shell.execute_reply":"2022-02-02T00:59:25.560214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Overview","metadata":{}},{"cell_type":"code","source":"print('Number train samples:', len(train_data))\nprint('Number train images:', len(os.listdir(path+'train_images/')))\nprint('Number test images:', len(os.listdir(path+'test_images/')))","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:25.563811Z","iopub.execute_input":"2022-02-02T00:59:25.564364Z","iopub.status.idle":"2022-02-02T00:59:26.505731Z","shell.execute_reply.started":"2022-02-02T00:59:25.564320Z","shell.execute_reply":"2022-02-02T00:59:26.504966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:26.506945Z","iopub.execute_input":"2022-02-02T00:59:26.507387Z","iopub.status.idle":"2022-02-02T00:59:26.523373Z","shell.execute_reply.started":"2022-02-02T00:59:26.507350Z","shell.execute_reply":"2022-02-02T00:59:26.522697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"train_data['species'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:26.524605Z","iopub.execute_input":"2022-02-02T00:59:26.524849Z","iopub.status.idle":"2022-02-02T00:59:26.540259Z","shell.execute_reply.started":"2022-02-02T00:59:26.524818Z","shell.execute_reply":"2022-02-02T00:59:26.539291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Single Image\nWe plot the first image of of the train data.","metadata":{}},{"cell_type":"code","source":"row = 0\nfile = train_data.loc[row, 'image']\nspecies = train_data.loc[row, 'species']\n\nimg = cv2.imread(path+'train_images/'+file)\nprint('Shape:', img.shape)","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:26.541986Z","iopub.execute_input":"2022-02-02T00:59:26.542364Z","iopub.status.idle":"2022-02-02T00:59:26.577596Z","shell.execute_reply.started":"2022-02-02T00:59:26.542328Z","shell.execute_reply":"2022-02-02T00:59:26.576921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 1, figsize=(7, 7))\nax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\nax.set_xticklabels([])\nax.set_yticklabels([])\nax.set_title(species)\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-02T00:59:26.578733Z","iopub.execute_input":"2022-02-02T00:59:26.578972Z","iopub.status.idle":"2022-02-02T00:59:26.945514Z","shell.execute_reply.started":"2022-02-02T00:59:26.578940Z","shell.execute_reply":"2022-02-02T00:59:26.944669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Plot Examples\nWe plot example images of the breed top 10.","metadata":{}},{"cell_type":"code","source":"def plot_examples(category = 'bottlenose_dolphin'):\n    \"\"\" Plot 5 images of a given category \"\"\"\n    \n    fig, axs = plt.subplots(1, 5, figsize=(25, 20))\n    fig.subplots_adjust(hspace = .1, wspace=.1)\n    axs = axs.ravel()\n    temp = train_data[train_data['species']==category].copy()\n    temp.index = range(len(temp.index))\n    for i in range(5):\n        file = temp.loc[i, 'image']\n        species = temp.loc[i, 'species']\n        img = cv2.imread(path+'train_images/'+file)\n        axs[i].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n        axs[i].set_title(species)\n        axs[i].set_xticklabels([])\n        axs[i].set_yticklabels([])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:26.946720Z","iopub.execute_input":"2022-02-02T00:59:26.947581Z","iopub.status.idle":"2022-02-02T00:59:27.053447Z","shell.execute_reply.started":"2022-02-02T00:59:26.947541Z","shell.execute_reply":"2022-02-02T00:59:27.051929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_examples(category = 'bottlenose_dolphin')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-02T00:59:27.056901Z","iopub.execute_input":"2022-02-02T00:59:27.057202Z","iopub.status.idle":"2022-02-02T00:59:32.074805Z","shell.execute_reply.started":"2022-02-02T00:59:27.057137Z","shell.execute_reply":"2022-02-02T00:59:32.073846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_examples(category = 'beluga')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-02T00:59:32.076316Z","iopub.execute_input":"2022-02-02T00:59:32.076700Z","iopub.status.idle":"2022-02-02T00:59:32.787074Z","shell.execute_reply.started":"2022-02-02T00:59:32.076629Z","shell.execute_reply":"2022-02-02T00:59:32.785892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_examples(category = 'humpback_whale')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-02T00:59:32.788118Z","iopub.status.idle":"2022-02-02T00:59:32.789909Z","shell.execute_reply.started":"2022-02-02T00:59:32.789655Z","shell.execute_reply":"2022-02-02T00:59:32.789683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Image Preprocessing\nAs we can see the images have different format: landscape or portrait. For the neural network we need a standard size. So we have to prepare the data. ","metadata":{}},{"cell_type":"code","source":"\ndef crop_image_from_gray(img, tol=7):\n    \"\"\"\n    Applies masks to the orignal image and \n    returns the a preprocessed image with \n    3 channels\n    \n    :param img: A NumPy Array that will be cropped\n    :param tol: The tolerance used for masking\n    \n    :return: A NumPy array containing the cropped image\n    \"\"\"\n    # If for some reason we only have two channels\n    if img.ndim == 2:\n        mask = img > tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    # If we have a normal RGB images\n    elif img.ndim == 3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img > tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n            img = np.stack([img1,img2,img3],axis=-1)\n        return img\n    \ndef preprocess_image(image, sigmaX=10):\n    \"\"\"\n    The whole preprocessing pipeline:\n    1. Read in image\n    2. Apply masks\n    3. Resize image to desired size\n    4. Add Gaussian noise to increase Robustness\n    \n    :param img: A NumPy Array that will be cropped\n    :param sigmaX: Value used for add GaussianBlur to the image\n    \n    :return: A NumPy array containing the preprocessed image\n    \"\"\"\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (224, 224))\n    image = cv2.addWeighted (image,4, cv2.GaussianBlur(image, (0,0) ,sigmaX), -4, 128)\n    return image\n","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.791343Z","iopub.status.idle":"2022-02-02T00:59:32.791761Z","shell.execute_reply.started":"2022-02-02T00:59:32.791528Z","shell.execute_reply":"2022-02-02T00:59:32.791559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_size = 128","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.793230Z","iopub.status.idle":"2022-02-02T00:59:32.793650Z","shell.execute_reply.started":"2022-02-02T00:59:32.793412Z","shell.execute_reply":"2022-02-02T00:59:32.793435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Generator\nWe define a data generator to load the data on demand.\n\n**Coming soon**","metadata":{}},{"cell_type":"code","source":"y_train = train_data['species']\ny_train = pd.get_dummies(y_train)","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.795222Z","iopub.status.idle":"2022-02-02T00:59:32.795706Z","shell.execute_reply.started":"2022-02-02T00:59:32.795436Z","shell.execute_reply":"2022-02-02T00:59:32.795462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model\n**Coming soon**","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dropout, Dense\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport tensorflow as tf\nbase_model = EfficientNetB0(include_top=False, weights='imagenet' , input_shape=(224,224,3))\ndef add_new_last_layer(base_model, nb_classes):\n    #x = base_model.output\n    #x = GlobalAveragePooling2D()(x)\n    #x = Dense(512, activation='relu')(x)\n    #predictions = Dense(nb_classes, activation='softmax')(x)\n    #model = Model(input=base_model.input, output=predictions)\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dropout(0.5)(x)\n    x = Dense(5, activation='relu')(x)\n    final_output = Dense(nb_classes, activation='softmax', name='final_output')(x)\n    model = tf.keras.Model(inputs=base_model.input, outputs=final_output)\n    return model\nmodel = add_new_last_layer(base_model, 15587)\nmodel.save('B0')\nmodel.compile(\n        optimizer=\"adam\", loss=\"categorical_crossentropy\", metrics=[\"accuracy\"]\n    )","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.797151Z","iopub.status.idle":"2022-02-02T00:59:32.797589Z","shell.execute_reply.started":"2022-02-02T00:59:32.797357Z","shell.execute_reply":"2022-02-02T00:59:32.797381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rotation_range=360,\n                                   horizontal_flip=True,\n                                   vertical_flip=True,\n                                   validation_split=0.15,\n                                   preprocessing_function=preprocess_image, \n                                   rescale=1. / 255)\n\n\ntrain_generator = train_datagen.flow_from_dataframe(train_data, \n                                                    x_col='image', \n                                                    y_col='individual_id',\n                                                    directory = '/kaggle/input/happy-whale-and-dolphin/train_images/',\n                                                    target_size=(224, 224),\n                                                    batch_size=32,\n                                                    class_mode='categorical', \n                                                    subset='training')\nval_generator = train_datagen.flow_from_dataframe(train_data, \n                                                  x_col='image', \n                                                y_col='individual_id',\n                                                  directory = '/kaggle/input/happy-whale-and-dolphin/train_images/',\n                                                  target_size=(224, 224),\n                                                  batch_size=32,\n                                                  class_mode='categorical',\n                                                  subset='validation')","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.798793Z","iopub.status.idle":"2022-02-02T00:59:32.799510Z","shell.execute_reply.started":"2022-02-02T00:59:32.799271Z","shell.execute_reply":"2022-02-02T00:59:32.799297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist = model.fit(train_generator, steps_per_epoch=train_generator.samples // 32,\n                    epochs=1,\n                    validation_data=val_generator,\n                    validation_steps = val_generator.samples // 32)\n#training slowly, needs to improve","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.801076Z","iopub.status.idle":"2022-02-02T00:59:32.801505Z","shell.execute_reply.started":"2022-02-02T00:59:32.801279Z","shell.execute_reply":"2022-02-02T00:59:32.801302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Export","metadata":{}},{"cell_type":"code","source":"#next Step","metadata":{"execution":{"iopub.status.busy":"2022-02-02T00:59:32.802829Z","iopub.status.idle":"2022-02-02T00:59:32.803255Z","shell.execute_reply.started":"2022-02-02T00:59:32.803017Z","shell.execute_reply":"2022-02-02T00:59:32.803039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}