{"cells":[{"metadata":{"_uuid":"69d2efeec40b970538a50997a6ae667fb52145b8"},"cell_type":"markdown","source":"# Image classification with Keras with simple MLP model"},{"metadata":{"_uuid":"1edb476cc9fdc8079734156e8c8a3a1f6d18cfbb"},"cell_type":"markdown","source":"![](http://)## Install dependencies"},{"metadata":{"_uuid":"d9a854a3cd7e221db870f61d95b8372b5e642f69","trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport os\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport string\nfrom PIL import Image\nfrom PIL import ImageFont\nfrom PIL import ImageDraw\nfrom scipy.ndimage.filters import gaussian_filter\nfrom scipy import ndimage\n\nfrom keras import regularizers, optimizers\nfrom keras.utils.np_utils import to_categorical  # convert to one-hot-encoding\nfrom keras.models import Sequential\nfrom keras.layers import (\n    Dense,\n    Dropout,\n    Flatten,\n    ZeroPadding2D,\n    Conv2D,\n    AveragePooling1D,\n    MaxPool2D,\n    BatchNormalization,\n    Activation,\n)\nfrom keras.optimizers import Adam\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import LearningRateScheduler\nfrom keras.preprocessing.image import (\n    random_rotation,\n    random_shift,\n    random_shear,\n    random_zoom,\n    random_channel_shift,\n    img_to_array,\n    ImageDataGenerator,\n)\nfrom keras import backend as K\nfrom keras.datasets import fashion_mnist\nfrom keras_tqdm import TQDMCallback, TQDMNotebookCallback\nimport itertools\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.model_selection import train_test_split\nfrom collections import Counter\nfrom sklearn.utils import class_weight","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"78bf344f5f3dcd1ff3962520998d7aacf21e98ef","trusted":true},"cell_type":"code","source":"# Set consistent random seed\nrandom_seed = 2018\nnp.random.seed(random_seed)  \ntf.set_random_seed(random_seed)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2d1d46e6569522b8ecd1b07a7b94a6b1ab9c4d9e"},"cell_type":"markdown","source":""},{"metadata":{"_uuid":"dae00b73201663ee1d221e084857d364f9070948"},"cell_type":"markdown","source":"## Dataset\nWhales dataset"},{"metadata":{"_uuid":"153d1c97dabbba900aca6b5ba2610023e6c9ba54"},"cell_type":"markdown","source":"### Show the content of the current and parent folder"},{"metadata":{"_uuid":"b5a53e5267fe99d98ce6227f54c9952280f67a6e","trusted":true},"cell_type":"code","source":"print(os.listdir(\"..\"))\nprint(os.listdir(\".\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fe89170d5cfe11ff0e517ac2be24c8a93679b3ee"},"cell_type":"markdown","source":"### Show the content of the input folder"},{"metadata":{"_uuid":"f5d2eadabe3dcff48419b129b0731cd6ac5238ba","trusted":true},"cell_type":"code","source":"print(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2c3c0355171cc1c56578f56b884fb98607691550"},"cell_type":"markdown","source":"### Importing, normalizing, visualizing"},{"metadata":{"_uuid":"1dfb8fd00f700d01d58c2daefbbe66999079cec3"},"cell_type":"markdown","source":"Let's upload whales dataset."},{"metadata":{"_uuid":"a3511c220c54d001ade23212c8500c1da4587651","trusted":true},"cell_type":"code","source":"# flow_from_dataframe\ntraindf=pd.read_csv(\"../input/train.csv\",dtype=str)\n# Remove new whales from input\ntraindf = traindf[traindf.Id != \"new_whale\"]\n# Remove single whales values\n# traindf = traindf.groupby('Id').filter(lambda x: len(x) > 1)\n# Plot Id frequencies\ntraindf['Id'].value_counts()[1:16].plot(kind='bar')\n\ntestdf=pd.read_csv(\"../input/sample_submission.csv\",dtype=str)\n\ndatagen=ImageDataGenerator(rescale=1./255.,validation_split=0.25)\n\"\"\"\ndatagen = ImageDataGenerator(\n        rotation_range=20,\n        width_shift_range=0.1,\n        height_shift_range=0.1,\n        shear_range=0.5,\n        zoom_range=(0.9, 1.1),\n        horizontal_flip=False,\n        vertical_flip=False,\n        fill_mode='constant',\n        cval=0,\n        rescale=1./255.,\n        validation_split=0.25    \n)\n\"\"\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"719fb63b764a0a9922c03f4113944d9654ea6776"},"cell_type":"markdown","source":"Print obtained dataframes for checking"},{"metadata":{"_uuid":"12537f7667d69638cb0ff5bac022b4c810abb59c","trusted":true},"cell_type":"code","source":"traindf.shape\n# Calculate number of unique classes (whales)\nnumber_of_classes = traindf['Id'].nunique()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c51bbc67a4d2b97b4cca0f1ad1d0516f22c51b3a","trusted":true},"cell_type":"code","source":"testdf.head(1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"17b1aabe891e79ea851b4953857d2e213d189523","trusted":true},"cell_type":"code","source":"# Pass the dataframes to 2 different flow_from_dataframe functions\ntrain_generator = datagen.flow_from_dataframe(\n    dataframe=traindf,\n    directory=\"../input/train/\",\n    x_col=\"Image\",\n    y_col=\"Id\",\n    subset=\"training\",\n    batch_size=32,\n    seed=42,\n    shuffle=True,\n    class_mode=\"categorical\",\n    target_size=(80, 80),\n)\n\nvalid_generator = datagen.flow_from_dataframe(\n    dataframe=traindf,\n    directory=\"../input/train/\",\n    x_col=\"Image\",\n    y_col=\"Id\",\n    subset=\"validation\",\n    batch_size=32,\n    seed=42,\n    shuffle=True,\n    class_mode=\"categorical\",\n    target_size=(80, 80),\n)\n\ntest_datagen = ImageDataGenerator(rescale=1.0 / 255.0)\n\ntest_generator = test_datagen.flow_from_dataframe(\n    dataframe=testdf,\n    directory=\"../input/test/\",\n    x_col=\"Image\",\n    y_col=None,\n    batch_size=32,\n    seed=42,\n    shuffle=False,\n    class_mode=None,\n    target_size=(80, 80),\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8c5edbb0be6a2744be4b83100117fc529c811966","trusted":true},"cell_type":"code","source":"# Model @frommedium\n# https://medium.com/@vijayabhaskar96/tutorial-on-keras-flow-from-dataframe-1fd4493d237c\nmodel = Sequential()\nmodel.add(Flatten(input_shape=(80, 80, 3), name=\"Input_layer\"))\n\"\"\"\n# maybe good 0.030\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(1024, activation='relu'))\nmodel.add(Dense(1024, activation='relu'))\n\"\"\"\n\"\"\"\n# maybe good 0.031\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\n\"\"\"\n\"\"\"\n# maybe good 0.036 after 1st epoch\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\n\"\"\"\n# maybe good 0.039 after 1st epoch\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\n\"\"\"\n# maybe good 0.033 after 1st epoch\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(1024, activation='relu'))\n\"\"\"\n\"\"\"\n# maybe good 0.031 after 1st epoch\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dense(512, activation='relu'))\nmodel.add(Dense(1024, activation='relu'))\n\"\"\"\nmodel.add(Dense(number_of_classes, activation=\"softmax\"))\nmodel.compile(\n    optimizers.rmsprop(lr=0.0001, decay=1e-6),\n    loss=\"categorical_crossentropy\",\n    metrics=[\"accuracy\"],\n)\n\n\nprint(\"The model was compiled\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a327641474e8e4f16db9425e2480df704c1b1670","trusted":true},"cell_type":"code","source":"# Fit the model @frommedium\n# https://medium.com/@vijayabhaskar96/tutorial-on-keras-flow-from-dataframe-1fd4493d237c\nSTEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID=valid_generator.n//valid_generator.batch_size\nSTEP_SIZE_TEST=test_generator.n//test_generator.batch_size\n# Class weights balancing\nhistory = model.fit_generator(\n    generator=train_generator,\n    steps_per_epoch=STEP_SIZE_TRAIN,\n    validation_data=valid_generator,\n    validation_steps=STEP_SIZE_VALID,\n    class_weight=\"auto\",\n    epochs=37,\n)\n\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"76c432630680af5db7238f8fdbfc6bc79aa53ab9","trusted":true},"cell_type":"code","source":"# history plots\nplt.plot(history.history['acc'])\nplt.title('Model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('Epoch')\nplt.show()\n\n# 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":{"_uuid":"c9293c3f6eeed1df370336320229ff3aa5a0e6c2","trusted":true},"cell_type":"code","source":"# Evaluate model\nmodel.evaluate_generator(generator=valid_generator, steps=1)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"_uuid":"f1b92e7a9e0bc0f6130a092023943447137db546","trusted":true},"cell_type":"code","source":"# Predict the output\ntest_generator.reset()\npred = model.predict_generator(test_generator, steps=STEP_SIZE_TEST + 1, verbose=1)\n\npredicted_class_indices = np.argmax(pred, axis=1)\n\nlabels = train_generator.class_indices\nlabels = dict((v, k) for k, v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]\n\nfilenames = test_generator.filenames\n\nprint(\"Filenames were prepared\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8769dc3c129d44a3e1afe5f2c6d51714cf7f4bde","trusted":true},"cell_type":"code","source":"# Multiple classes output\n# https://www.kaggle.com/hexadd5/simple-resnet50-with-keras\nkth = 5\nclasses = np.array([c for c, v in train_generator.class_indices.items()])\n\nif True:\n    classify_index = np.argpartition(-pred, kth)[:, :kth]\n    classify_value = pred[np.arange(pred.shape[0])[:, None], classify_index]\n    best_5_pred = np.zeros((len(classify_index), 5))\n    best_5_class = np.zeros((len(classify_index), 5), dtype=\"int32\")\n    for i, p in enumerate(classify_value):\n        sort_index = np.argsort(p)[::-1]\n        best_5_pred[i] = p[sort_index]\n        best_5_class[i] = classify_index[i][sort_index]\n\n    # create output\n    submit = pd.DataFrame(columns=[\"Image\", \"Id\"])\n    for i, p in enumerate(best_5_pred):\n        submit_classes = []\n        if p[0] < 0.55:\n            submit_classes.append(\"new_whale\")\n            submit_classes.extend(classes[best_5_class[i]][0:4])\n        elif p[1] < 0.4:\n            submit_classes.extend(classes[best_5_class[i]][0:1])\n            submit_classes.append(\"new_whale\")\n            submit_classes.extend(classes[best_5_class[i]][1:4])\n        elif p[2] < 0.1:\n            submit_classes.extend(classes[best_5_class[i]][0:2])\n            submit_classes.append(\"new_whale\")\n            submit_classes.extend(classes[best_5_class[i]][2:4])\n        elif p[3] < 0.05:\n            submit_classes.extend(classes[best_5_class[i]][0:3])\n            submit_classes.append(\"new_whale\")\n            submit_classes.extend(classes[best_5_class[i]][3:4])\n        else:\n            submit_classes.extend(classes[best_5_class[i]])\n        classes_text = \" \".join(submit_classes)\n        submit = submit.append(\n            pd.Series(\n                np.array([test_generator.filenames[i], classes_text]),\n                index=submit.columns,\n            ),\n            ignore_index=True,\n        )\n        # print(submit)\n    submit.to_csv(\"submit.csv\", index=False)\n    print(\"Submission results were written\")\n","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}