{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-10-04T14:04:05.003888Z","iopub.execute_input":"2021-10-04T14:04:05.004202Z","iopub.status.idle":"2021-10-04T14:04:05.102678Z","shell.execute_reply.started":"2021-10-04T14:04:05.004123Z","shell.execute_reply":"2021-10-04T14:04:05.101748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nimport random\nimport shutil\nimport tensorflow as tf\nfrom tensorflow.keras.optimizers import RMSprop\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications.vgg16 import VGG16, preprocess_input\n\nfrom shutil import copyfile\nfrom os import getcwd","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:05.104502Z","iopub.execute_input":"2021-10-04T14:04:05.104789Z","iopub.status.idle":"2021-10-04T14:04:09.333203Z","shell.execute_reply.started":"2021-10-04T14:04:05.104754Z","shell.execute_reply":"2021-10-04T14:04:09.332486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This code block unzips the full Cats-v-Dogs dataset \npath_cats_and_dogs = \"/kaggle/input/dogs-vs-cats/train.zip\"\n\nlocal_zip = path_cats_and_dogs\nzip_ref = zipfile.ZipFile(local_zip, 'r')\nzip_ref.extractall()\nzip_ref.close()","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:09.334349Z","iopub.execute_input":"2021-10-04T14:04:09.335274Z","iopub.status.idle":"2021-10-04T14:04:22.014707Z","shell.execute_reply.started":"2021-10-04T14:04:09.335243Z","shell.execute_reply":"2021-10-04T14:04:22.013838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path_cats_and_dogs = \"/kaggle/input/dogs-vs-cats/test1.zip\"\n\nlocal_zip = path_cats_and_dogs\nzip_ref = zipfile.ZipFile(local_zip, 'r')\nzip_ref.extractall()\nzip_ref.close()","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:22.016723Z","iopub.execute_input":"2021-10-04T14:04:22.01694Z","iopub.status.idle":"2021-10-04T14:04:27.362081Z","shell.execute_reply.started":"2021-10-04T14:04:22.016917Z","shell.execute_reply":"2021-10-04T14:04:27.361354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filenames = os.listdir(\"/kaggle/working/train\")","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:27.363164Z","iopub.execute_input":"2021-10-04T14:04:27.363434Z","iopub.status.idle":"2021-10-04T14:04:27.381937Z","shell.execute_reply.started":"2021-10-04T14:04:27.363374Z","shell.execute_reply":"2021-10-04T14:04:27.381299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(filenames)","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:27.383032Z","iopub.execute_input":"2021-10-04T14:04:27.383348Z","iopub.status.idle":"2021-10-04T14:04:27.390729Z","shell.execute_reply.started":"2021-10-04T14:04:27.383313Z","shell.execute_reply":"2021-10-04T14:04:27.389952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Make a proper directory structure for splitting training and validation images. \nThis will also help in using Keras Image generators for augmentation and preprocessing tasks**","metadata":{}},{"cell_type":"code","source":"base_dir = '/kaggle/working/'\nsource_dir = '/kaggle/working/train/'\n\n\n\ncat_dir = os.path.join(base_dir, 'cat')\nos.mkdir(cat_dir)\ndog_dir = os.path.join(base_dir, 'dog')\nos.mkdir(dog_dir)\n\ntrain_dir = os.path.join(base_dir, 'train1')\nvalidation_dir = os.path.join(base_dir, 'validation1')\nos.mkdir(train_dir)\nos.mkdir(validation_dir)\n\n# Directory with our training cat/dog pictures\ntrain_cats_dir = os.path.join(train_dir, 'cats')\ntrain_dogs_dir = os.path.join(train_dir, 'dogs')\nos.mkdir(train_cats_dir)\nos.mkdir(train_dogs_dir)\n\n\n# Directory with our validation cat/dog pictures\nvalidation_cats_dir = os.path.join(validation_dir, 'cats')\nvalidation_dogs_dir = os.path.join(validation_dir, 'dogs')\nos.mkdir(validation_cats_dir)\nos.mkdir(validation_dogs_dir)\n\n","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:27.392104Z","iopub.execute_input":"2021-10-04T14:04:27.392572Z","iopub.status.idle":"2021-10-04T14:04:27.402243Z","shell.execute_reply.started":"2021-10-04T14:04:27.392541Z","shell.execute_reply":"2021-10-04T14:04:27.401611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Move all the files from source to their respective training and validation folder**","metadata":{}},{"cell_type":"code","source":"for c in filenames:\n    category = c.split('.')[0]\n    if category == \"cat\":\n        temp_source = source_dir +'/'+ c\n        temp_dest   = cat_dir +'/'+ c\n        copyfile(temp_source,temp_dest)\n    else:\n        temp_source = source_dir +'/' + c\n        temp_dest   = dog_dir +'/'+ c\n        copyfile(temp_source,temp_dest)\n\ndef split_data(SOURCE, TRAINING, VALIDATION, SPLIT_SIZE):\n    f = os.listdir(SOURCE)\n    train_size   =  int(SPLIT_SIZE * len(f))\n    test_size    =  int(len(f) - train_size)\n    final_files  =  random.sample(f,len(f))\n    train_files  =  final_files[0:train_size] \n    test_files   =  final_files[-test_size:]\n    \n    for i in train_files:\n        temp_source = SOURCE +'/'+ i\n        temp_dest   = TRAINING +'/'+ i\n        copyfile(temp_source,temp_dest)\n        \n    for j in test_files:\n        temp_source = SOURCE + '/'+ j\n        temp_dest   = VALIDATION +'/'+ j\n        copyfile(temp_source,temp_dest)\n        \n\nsplit_size = .9\nsplit_data(cat_dir, train_cats_dir, validation_cats_dir, split_size)\nsplit_data(dog_dir, train_dogs_dir, validation_dogs_dir, split_size)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:27.403507Z","iopub.execute_input":"2021-10-04T14:04:27.403827Z","iopub.status.idle":"2021-10-04T14:04:33.1781Z","shell.execute_reply.started":"2021-10-04T14:04:27.403796Z","shell.execute_reply":"2021-10-04T14:04:33.17693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"***Check the number of files in each directory***","metadata":{}},{"cell_type":"code","source":"test_dir ='/kaggle/working/test1'\nprint(\"Total images in cat directory\" , len(os.listdir(cat_dir)))\nprint(\"Total images in dog directory\" , len(os.listdir(dog_dir)))\nprint(\"Total images in train/cat directory\" , len(os.listdir(train_cats_dir)))\nprint(\"Total images in train/dog directory\" , len(os.listdir(train_dogs_dir)))\nprint(\"Total images in validation/cat directory\" , len(os.listdir(validation_cats_dir)))\nprint(\"Total images in validation/dog directory\" , len(os.listdir(validation_dogs_dir)))\nprint(\"Total images in test directory\" , len(os.listdir(test_dir)))\n","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:33.181378Z","iopub.execute_input":"2021-10-04T14:04:33.182446Z","iopub.status.idle":"2021-10-04T14:04:33.264823Z","shell.execute_reply.started":"2021-10-04T14:04:33.182377Z","shell.execute_reply":"2021-10-04T14:04:33.26412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"***Check the names of files in destination folders randomly *******","metadata":{}},{"cell_type":"code","source":"train_cat_fnames = os.listdir( train_cats_dir )\ntrain_dog_fnames = os.listdir( train_dogs_dir )\ntest_names = os.listdir(test_dir)\n\nprint(train_cat_fnames[:10])\nprint(train_dog_fnames[:10])","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:33.267596Z","iopub.execute_input":"2021-10-04T14:04:33.267985Z","iopub.status.idle":"2021-10-04T14:04:33.307913Z","shell.execute_reply.started":"2021-10-04T14:04:33.267953Z","shell.execute_reply":"2021-10-04T14:04:33.305938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Setup some code to view the pictures using matplotlib**","metadata":{}},{"cell_type":"code","source":"%matplotlib inline\n\nimport matplotlib.image as mpimg\nimport matplotlib.pyplot as plt\n\n# Parameters for our graph; we'll output images in a 4x4 configuration\nnrows = 4\nncols = 4\n\npic_index = 0 # Index for iterating over imag","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:33.318511Z","iopub.execute_input":"2021-10-04T14:04:33.323958Z","iopub.status.idle":"2021-10-04T14:04:33.345491Z","shell.execute_reply.started":"2021-10-04T14:04:33.32362Z","shell.execute_reply":"2021-10-04T14:04:33.340638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set up matplotlib fig, and size it to fit 4x4 pics\nfig = plt.gcf()\nfig.set_size_inches(ncols*4, nrows*4)\n\npic_index+=8\n\nnext_cat_pix = [os.path.join(train_cats_dir, fname) \n                for fname in train_cat_fnames[ pic_index-8:pic_index] \n              ]\n\nnext_test_pix = [os.path.join(test_dir, fname) \n                for fname in test_names[ pic_index-8:pic_index]\n               ]\n\nfor i, img_path in enumerate(next_cat_pix+next_test_pix):\n  # Set up subplot; subplot indices start at 1\n  sp = plt.subplot(nrows, ncols, i + 1)\n  sp.axis('Off') # Don't show axes (or gridlines)\n\n  img = mpimg.imread(img_path)\n  plt.imshow(img)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:33.346846Z","iopub.execute_input":"2021-10-04T14:04:33.347089Z","iopub.status.idle":"2021-10-04T14:04:35.136145Z","shell.execute_reply.started":"2021-10-04T14:04:33.347059Z","shell.execute_reply":"2021-10-04T14:04:35.135439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Modelling Starts**\n\nSimple VGG3 baseline models give about 75-80% accuracy. After some iterations I have done VGG5 model with dropouts. ","metadata":{}},{"cell_type":"code","source":"model = tf.keras.models.Sequential([\n    # Note the input shape is the desired size of the image 150x150 with 3 bytes color\n    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)),\n    tf.keras.layers.MaxPooling2D(2,2),\n    tf.keras.layers.BatchNormalization(),\n    \n    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),\n    tf.keras.layers.MaxPooling2D(2,2), \n    tf.keras.layers.BatchNormalization(),\n\n    tf.keras.layers.Conv2D(128, (3,3), activation='relu'), \n    tf.keras.layers.MaxPooling2D(2,2),\n    tf.keras.layers.BatchNormalization(),\n    \n    tf.keras.layers.Conv2D(128, (3,3), activation='relu'), \n    tf.keras.layers.MaxPooling2D(2,2),\n    tf.keras.layers.BatchNormalization(),\n          \n    # Flatten the results to feed into a DNN\n    tf.keras.layers.Flatten(), \n    # 512 neuron hidden layer\n    tf.keras.layers.Dense(512, activation='relu'),\n    tf.keras.layers.Dropout(0.3),\n    \n    # Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('cats') and 1 for the other ('dogs')\n    tf.keras.layers.Dense(1, activation='sigmoid')  \n])","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:35.137224Z","iopub.execute_input":"2021-10-04T14:04:35.137481Z","iopub.status.idle":"2021-10-04T14:04:37.555465Z","shell.execute_reply.started":"2021-10-04T14:04:35.137451Z","shell.execute_reply":"2021-10-04T14:04:37.554649Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.optimizers import RMSprop\n\nmodel.compile(optimizer=RMSprop(learning_rate=0.0001),\n              loss='binary_crossentropy',\n              metrics = ['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:37.556645Z","iopub.execute_input":"2021-10-04T14:04:37.556963Z","iopub.status.idle":"2021-10-04T14:04:37.574931Z","shell.execute_reply.started":"2021-10-04T14:04:37.556923Z","shell.execute_reply":"2021-10-04T14:04:37.574101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n      rescale=1./255,\n      rotation_range=40,\n      width_shift_range=0.2,\n      height_shift_range=0.2,\n      shear_range=0.2,\n      zoom_range=0.1,\n      horizontal_flip=True,\n      fill_mode='nearest')\n\ntrain_generator = train_datagen.flow_from_directory(\n        train_dir,  # This is the source directory for training images\n        target_size=(150, 150),  # All images will be resized to 150x150\n        batch_size=30,\n        # Since we use binary_crossentropy loss, we need binary labels\n        class_mode='binary')\n\n\nvalidation_datagen = ImageDataGenerator(rescale=1/255)\n\n\nvalidation_generator = validation_datagen.flow_from_directory(\n       validation_dir,  \n        target_size=(150, 150),  # All images will be resized to 150x150\n        batch_size=30,\n        # Since we use binary_crossentropy loss, we need binary labels\n        class_mode='binary')","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:37.575958Z","iopub.execute_input":"2021-10-04T14:04:37.576208Z","iopub.status.idle":"2021-10-04T14:04:39.689279Z","shell.execute_reply.started":"2021-10-04T14:04:37.576176Z","shell.execute_reply":"2021-10-04T14:04:39.688512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit_generator(train_generator,\n                              epochs=30,\n                              verbose=1,\n                              validation_data=validation_generator)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-04T14:04:39.690593Z","iopub.execute_input":"2021-10-04T14:04:39.691078Z","iopub.status.idle":"2021-10-04T15:24:42.315905Z","shell.execute_reply.started":"2021-10-04T14:04:39.69104Z","shell.execute_reply":"2021-10-04T15:24:42.315138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_acc_loss():\n    \n#-----------------------------------------------------------\n# Retrieve a list of list results on training and test data\n# sets for each training epoch\n#-----------------------------------------------------------\n    acc      = history.history[     'accuracy' ]\n    val_acc  = history.history[ 'val_accuracy' ]\n    loss     = history.history[    'loss' ]\n    val_loss = history.history['val_loss' ]\n\n    epochs   = range(len(acc)) # Get number of epochs\n\n#------------------------------------------------\n# Plot training and validation accuracy per epoch\n#------------------------------------------------\n    plt.plot  ( epochs,     acc )\n    plt.plot  ( epochs, val_acc )\n    plt.title ('Training and validation accuracy')\n    plt.figure()\n\n#------------------------------------------------\n# Plot training and validation loss per epoch\n#------------------------------------------------\n    plt.plot  ( epochs,     loss )\n    plt.plot  ( epochs, val_loss )\n    plt.title ('Training and validation loss'   )","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:24:42.31896Z","iopub.execute_input":"2021-10-04T15:24:42.31917Z","iopub.status.idle":"2021-10-04T15:24:42.327439Z","shell.execute_reply.started":"2021-10-04T15:24:42.319143Z","shell.execute_reply":"2021-10-04T15:24:42.326779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_acc_loss()","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:24:42.330054Z","iopub.execute_input":"2021-10-04T15:24:42.330776Z","iopub.status.idle":"2021-10-04T15:24:42.720163Z","shell.execute_reply.started":"2021-10-04T15:24:42.33068Z","shell.execute_reply":"2021-10-04T15:24:42.71952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_files = os.listdir(\"/kaggle/working/test1\")\ntest_df = pd.DataFrame({'filename' : test_files})    \nsamples = test_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:24:42.72148Z","iopub.execute_input":"2021-10-04T15:24:42.721735Z","iopub.status.idle":"2021-10-04T15:24:42.739182Z","shell.execute_reply.started":"2021-10-04T15:24:42.721702Z","shell.execute_reply":"2021-10-04T15:24:42.738573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = ImageDataGenerator(rescale=1./255)\ntest_generator = test_data.flow_from_dataframe(\n    test_df, \n    \"./test1/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=[150,150],\n    batch_size=30,\n    shuffle=False)\n\n\n","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:24:42.740358Z","iopub.execute_input":"2021-10-04T15:24:42.740697Z","iopub.status.idle":"2021-10-04T15:24:42.848537Z","shell.execute_reply.started":"2021-10-04T15:24:42.740657Z","shell.execute_reply":"2021-10-04T15:24:42.847893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(samples/30))","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:24:42.849586Z","iopub.execute_input":"2021-10-04T15:24:42.849821Z","iopub.status.idle":"2021-10-04T15:25:12.764479Z","shell.execute_reply.started":"2021-10-04T15:24:42.849788Z","shell.execute_reply":"2021-10-04T15:25:12.763718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis=-1)\ntest_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:25:12.76807Z","iopub.execute_input":"2021-10-04T15:25:12.768468Z","iopub.status.idle":"2021-10-04T15:25:12.776325Z","shell.execute_reply.started":"2021-10-04T15:25:12.768441Z","shell.execute_reply":"2021-10-04T15:25:12.77564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = test_df.copy()\nsubmission_df['id'] = submission_df['filename'].str.split('.').str[0]\nsubmission_df['label'] = submission_df['category']\nsubmission_df.drop(['filename', 'category'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-10-04T15:25:12.779271Z","iopub.execute_input":"2021-10-04T15:25:12.779528Z","iopub.status.idle":"2021-10-04T15:25:13.048802Z","shell.execute_reply.started":"2021-10-04T15:25:12.779504Z","shell.execute_reply":"2021-10-04T15:25:13.0481Z"},"trusted":true},"execution_count":null,"outputs":[]}]}