{"cells":[{"metadata":{"_uuid":"da035fe58e548e8b1b7e8e89725b9e6bc745aa7b"},"cell_type":"markdown","source":"# Humpback Whale Identification with MobileNet\n* This kernel is based on \n<br>@Ankit : https://www.kaggle.com/satian/keras-mobilenet-starter, which is a combination of \n<br>@peter : https://www.kaggle.com/pestipeti/keras-cnn-starter and \n<br>@beluga: https://www.kaggle.com/gaborfodor/greyscale-mobilenet-lb-0-892 from google doodle quickdraw competition"},{"metadata":{"_uuid":"0d9c73ad23e6c2eae3028255ee00c3254fe66401","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport os\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mplimg\nfrom matplotlib.pyplot import imshow\n\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.preprocessing import OneHotEncoder\n\nfrom keras import layers\nfrom keras.preprocessing import image\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\nfrom keras.metrics import categorical_accuracy, top_k_categorical_accuracy, categorical_crossentropy\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom keras.optimizers import Adam\nfrom keras.applications import MobileNet\nfrom keras.applications.mobilenet import preprocess_input\n\nimport warnings\nwarnings.simplefilter(\"ignore\", category=DeprecationWarning)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2cea35de3530cc898be5b85063b84e875401d092","trusted":true},"cell_type":"code","source":"os.listdir(\"../input/\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"46a8839e13a14eb8d16ea6823de9927ea63d5001","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(\"../input/train.csv\")\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f46b24dbba74f22833cac6140e60348b15a8e047","trusted":true},"cell_type":"code","source":"def prepareImages(data, m, dataset):\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 = image.load_img(\"../input/\"+dataset+\"/\"+fig, target_size=(100, 100, 3))\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":"6587a101b58af064af0f9c60a1070c6c8f52d45f","trusted":true},"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":{"_uuid":"4afe4128a0cd6859848c8a80686208082d647c39","trusted":true},"cell_type":"code","source":"X = prepareImages(train_df, train_df.shape[0], \"train\")\nX /= 255","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"675924f8863aef27cf90dc668e0a68cd609dfc1c","trusted":true},"cell_type":"code","source":"y, label_encoder = prepare_labels(train_df['Id'])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"14d243b19023e830b636bea16679e13bc40deae6","trusted":true},"cell_type":"code","source":"y.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2f50a1a33fb9036bc4268572d179ebdacc914284","trusted":true},"cell_type":"code","source":"def top_5_accuracy(y_true, y_pred):\n    return top_k_categorical_accuracy(y_true, y_pred, k=5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"50ccd4c97a3c980e8d1f665188c02d869fc70c39","trusted":true,"scrolled":true},"cell_type":"code","source":"model = MobileNet(input_shape=(100, 100, 3), alpha=1., weights=None, classes=5005)\nmodel.compile(optimizer=Adam(lr=0.002), loss='categorical_crossentropy',\n              metrics=[categorical_crossentropy, categorical_accuracy, top_5_accuracy])\nprint(model.summary())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"169f45e150c3a584e0f655a8eda523e0675da63a","trusted":true},"cell_type":"code","source":"# Ankit's kernel ran for 100 epochs\nhistory = model.fit(X, y, epochs=50, batch_size=100, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7bca48a1d0963cbf70685b75431435cef9499895","trusted":true},"cell_type":"code","source":"plt.plot(history.history['categorical_accuracy'])\nplt.title('Model categorical accuracy')\nplt.ylabel('categorical accuracy')\nplt.xlabel('Epoch')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"debe961c93b72bef151d9aad3ca2cb500ee00aaa","trusted":true},"cell_type":"code","source":"test = os.listdir(\"../input/test/\")\nprint(len(test))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"72ed8198f519f7b1ae3efbc688933c78d8cdd0e4","trusted":true},"cell_type":"code","source":"col = ['Image']\ntest_df = pd.DataFrame(test, columns=col)\ntest_df['Id'] = ''","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"52262195fc0b8755cff78bf8c98e6116d50f79af","trusted":true},"cell_type":"code","source":"X = prepareImages(test_df, test_df.shape[0], \"test\")\nX /= 255","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"88c8d8ff98fbdb1df4218abb6bd51889e855a6fb","trusted":true},"cell_type":"code","source":"predictions = model.predict(np.array(X), verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0571f54c4487b65f804ce7adb7ad5d94992075ed"},"cell_type":"code","source":"len(predictions)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66f0bdde31b8c7847916268aa82d9a1bdc9c0658","trusted":true},"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":{"_uuid":"09d7c1eb9b554e4e580b0c3c7eb609c15636892d","trusted":true},"cell_type":"code","source":"test_df.head(10)\ntest_df.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cddee631d70901ef595e76cc2f3dbbd3bae75017"},"cell_type":"markdown","source":"Here's a look at the success of a few variations of this kernel on the public test data.\n\n@Ankit's kernel yields a score of:<br>\n* 0.313 unaltered<br>\n* 0.301 with fitting divided into two 50-epoch calls<br>\n* 0.321 with only 50 epochs total<br>\n\nThe differences between the first two versions can be attributed to [this issue](https://github.com/rstudio/keras/issues/415) with multiple fit calls.<br><br>\nWith fewer epochs leading to a higher score, it seems that overfitting hurt the performance with 100 epochs. However, with only a minor portion of the test data used to obtain these scores, the 3rd option could turn out to be less robust overall.  "}],"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}