{"cells":[{"metadata":{"_uuid":"15caa51a139cdd9e7ecb0d140274f9e7e0a5b0c0"},"cell_type":"markdown","source":"# Cat vs Dog Redux Competition\n\nThe competition is to build a model which can predict if the picture contains a cat or a dog.\n\nWe've 25000 images, 12500 images of each category.\nDog is labeled 1 and cat 0.\n\nThe test set contains 12500 random images."},{"metadata":{"trusted":true,"_uuid":"017dcb7f7ef0d792ca922e4445e7a21511e51371"},"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport os, cv2\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom tensorflow.keras.utils import to_categorical, Sequence\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import Conv2D, MaxPool2D, Dropout, Flatten, Dense\nfrom tensorflow.keras.optimizers import SGD, Adam\nfrom tensorflow.keras import regularizers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tqdm import tqdm      # a nice pretty percentage bar for tasks.\nfrom random import shuffle","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"05966eb422efdafcfd2a97aa8d7826f593854238"},"cell_type":"markdown","source":"Im going to load the images as graysacle images with resolution of 128x128"},{"metadata":{"trusted":true,"_uuid":"8c818f989cf856b0e22079a66355fb3691091483"},"cell_type":"code","source":"TRAIN_DIR = '../input/train/'\nTEST_DIR = '../input/test/'\n\nROWS = 128\nCOLS = 128\nCHANNELS = 1\nRETRAIN = True\n\ndata_dict = {}\n\ndog_train_list = [TRAIN_DIR+name for i,name in \\\n                  enumerate(os.listdir(TRAIN_DIR))\n                  if 'dog' in name]\n\ncat_train_list = [TRAIN_DIR+name for i,name in \\\n                  enumerate(os.listdir(TRAIN_DIR))\n                  if 'cat' in name]\n\nTRAIN_COUNT = len(dog_train_list) + len(cat_train_list)\n\n\ndata_dict['train_data_files'] = dog_train_list + cat_train_list\ndata_dict['train_labels'] = [1]*int(TRAIN_COUNT/2) + [0]*int(TRAIN_COUNT/2)\n\n# Loading the test set\ntest_image_list = [TEST_DIR+i for i in os.listdir(TEST_DIR)]\n\n\nprint('Total Training Images: {}'.format(len(data_dict['train_data_files'])))\nprint('Total Test Images: {}'.format(len(test_image_list)))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7adfada8c9357655a216d265e216c159e611e271"},"cell_type":"code","source":"def load_image(file_path):\n    img = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE)\n    return cv2.resize(img, (ROWS,COLS))\n    \n\ndef load_image_list(file_list):\n    count = len(file_list)\n    data = np.ndarray((count, ROWS, COLS, CHANNELS),\\\n                      dtype=np.uint8)\n    for i, image_name in tqdm(enumerate(file_list)):\n        data[i] = np.expand_dims(load_image(image_name), axis=2)\n    return data\n\ndata_dict['train_data'] = load_image_list(\\\n                            data_dict['train_data_files'])\n\ntest_set = load_image_list(test_image_list)\nprint('data_dict shape: {}'.format(data_dict['train_data'].shape))\nprint('test_set shape: {}'.format(test_set.shape))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"273403e5ad33e1bf95e863c400b1ca3ce22e23c5"},"cell_type":"markdown","source":"# Data Augmentation\n* We will featurewise centerlize and std normalize the training and validation data, but we will fit the generator only on the training data.\n* We will use augmentation only on the training data."},{"metadata":{"trusted":true,"_uuid":"a010f13185a2ec0191f01a4290df1728b2155548"},"cell_type":"code","source":"datagen_train = ImageDataGenerator(\n    featurewise_center=True,\n    featurewise_std_normalization=True,\n    rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    horizontal_flip=True,\n     zoom_range = 0.1,\n    )\n\ndatagen_val = ImageDataGenerator(\n    featurewise_center=True,\n    featurewise_std_normalization=True,\n    )","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c7e30fb17983244031f698251024336a750d009b"},"cell_type":"markdown","source":"# Some Images Before Augmentation\nA human can distinct which picture has a cat and which has a dog, so a ML model can achive high accuracy on this data set."},{"metadata":{"trusted":true,"_uuid":"0a9149f57a3b7ee288a95cdbcf6424b4822f6463"},"cell_type":"code","source":"f, axarr = plt.subplots(2,2)\n\naxarr[0,0].imshow(np.squeeze(data_dict['train_data'][0], axis=2), cmap='gray')\n\naxarr[1,0].imshow(np.squeeze(data_dict['train_data'][int(TRAIN_COUNT/2)-1], axis=2), cmap='gray')\n\naxarr[0,1].imshow(np.squeeze(data_dict['train_data'][int(TRAIN_COUNT/2) + 2], axis=2), cmap='gray')\n\naxarr[1,1].imshow(np.squeeze(data_dict['train_data'][TRAIN_COUNT -1], axis=2), cmap='gray')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"768692ec8f926155cee68013373c22e2de1b3657"},"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(filters=4, kernel_size=(4,4),\\\n                 padding='Same', activation='relu',\\\n                 input_shape=(ROWS,COLS,CHANNELS)))\nmodel.add(Conv2D(filters=8, kernel_size=(4,4),\\\n                 padding='Same', activation='relu'))\nmodel.add(MaxPool2D(pool_size=(4,4)))\n# model.add(Dropout(0.5))\n\nmodel.add(Conv2D(filters=16, kernel_size=(8,8),\\\n                 padding='Same', activation='relu'))\nmodel.add(Conv2D(filters=32, kernel_size=(8,8),\\\n                 padding='Same', activation='relu'))\nmodel.add(MaxPool2D(pool_size=(4,4)))\n# model.add(Dropout(0.5))\n\nmodel.add(Flatten())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(8**2, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1, activation='sigmoid'))\n\noptimizer = SGD(lr=0.03)\nmodel.compile(optimizer=optimizer,\n              loss=\"binary_crossentropy\",\n              metrics=[\"accuracy\"])\n\nprint(model.summary())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":false,"_uuid":"05d2e9eea788538354c2d6abfbc085c84ea75e1c"},"cell_type":"code","source":"model.compile(optimizer=optimizer,\n              loss='binary_crossentropy',\n              metrics=['accuracy'])\n\n# Saving the initial weights, in order to initiate the model in each fold.\nmodel.save_weights('initial.h5')\n\nfilepath='cat_dog_v4a1'\n\nearly_stop = EarlyStopping(monitor='val_loss',\n                              patience=5,\n                              verbose=0, \n                              mode='min')\n\ncheckpoint = ModelCheckpoint(filepath,\n                             monitor='val_loss',\n                             verbose=1,\n                             save_best_only=False,\n                             mode='min')\n\nepochs = 60\n\nkfold = StratifiedKFold(n_splits = 4, shuffle=True)\nhistory_list = []\nfor i, (train, test) in enumerate(kfold.split(data_dict['train_data'], data_dict['train_labels'])):\n    model.load_weights('initial.h5')\n    # Training \n    datagen_train.fit(data_dict['train_data'][train], augment=True)\n    datagen_val.fit(data_dict['train_data'][train], augment=False)\n    \n    history = model.fit_generator(generator=datagen_train.flow(\n                      data_dict['train_data'][train],np.asarray(data_dict['train_labels'])[train]),\n                  epochs=epochs,\n                  verbose=1,\n                  validation_data=datagen_val.flow(data_dict['train_data'][test]\\\n                                                   ,np.asarray(data_dict['train_labels'])[test]),\n                  callbacks=[checkpoint,early_stop])\n    \n    history_list.append(history)\n    \n    # Evaluate the test set with the current fold model\n    filename = 'sub_file' + str(i) +'.csv'\n    with open(filename,'w') as f:\n        f.write('id,label\\n')\n        print('Evaluate the test set #{}..'.format(i))\n        prediction = model.predict_generator(datagen_val.flow(test_set), steps=391)\n        print('Writing the prediction in the submition file..')\n        for i, image_file in tqdm(enumerate(prediction)):\n            f.write('{},{}\\n'.format(i+1, prediction[i][0]))\n                           \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4c7995a7e0025152373bf3e479f950ea191da0ff"},"cell_type":"code","source":"print(len(history_list))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c3352f63e2dfb66fb575f7f45f604cea004957c8"},"cell_type":"code","source":"train_loss = np.array([history.history['loss'] for history in history_list])\ntrain_loss_mean = np.mean(train_loss,axis=0)\n\nval_loss = np.array([history.history['val_loss'] for history in history_list])\nval_loss_mean = np.mean(val_loss,axis=0)\n\ntrain_acc = np.array([history.history['acc'] for history in history_list])\ntrain_acc_mean = np.mean(train_acc,axis=0)\n\nval_acc = np.array([history.history['val_acc'] for history in history_list])\nval_acc_mean = np.mean(val_acc,axis=0)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a754c9de22ffda63268c2b8c11bfcf97145ae8df"},"cell_type":"code","source":"fig, ax = plt.subplots(2,2)\nfor i, history in enumerate(history_list):\n    ax[i%2, int(i/2)].plot(history.history['loss'], color='b', label=\"Training Loss\")\n    ax[i%2, int(i/2)].plot(history.history['val_loss'], color='r', label='Validation Loss')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c9b4a0801d908620cf6dab99b2013504e53cd350"},"cell_type":"code","source":"fig, ax = plt.subplots(2,1)\n# Loss Plot\n# for history in history_list\nax[0].plot(train_loss_mean, color='b', label=\"Training Loss\")\nax[0].plot(val_loss_mean, color='r', label='Validation Loss')\n\nlegend = ax[0].legend(loc='best', shadow=True)\n\n# Accuracy Plot\nax[1].plot(train_acc_mean, color='b', label='Training Accuracy')\nax[1].plot(val_acc_mean, color='r', label='Validation Accuracy')\nlegend = ax[1].legend(loc='best', shadow=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e3fadb76d714388ecb2a944bc312731ceec537a6"},"cell_type":"code","source":"# test_image_list = [TEST_DIR+i for i in os.listdir(TEST_DIR)]\n\n# datagen_test = ImageDataGenerator(\n#     featurewise_center=True,\n#     featurewise_std_normalization=True)\n\n# test_set = load_image_list(test_image_list)\n# datagen_test.fit(test_set)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"82c63fa13b16de60fee181a9142383759ffd460e"},"cell_type":"code","source":"# with open('submission_file2.csv','w') as f:\n#     f.write('id,label\\n')\n# with open('submission_file2.csv','a') as f:\n# #     test_set = load_image_list(test_image_list)\n#     print('Evaluate the test set..')\n#     prediction = model.predict_generator(datagen_test.flow(test_set), steps=391)\n#     print('Writing the prediction in the submition file..')\n#     for i, image_file in tqdm(enumerate(prediction)):\n#         f.write('{},{}\\n'.format(i+1, prediction[i][0]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"808a1588cac479aa825ebd19134a8f45e82c51db"},"cell_type":"code","source":"","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}