{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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\n# You can write up to 5GB 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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import keras, os, cv2, random\nfrom keras.models import Sequential # using squential for creating sequential model\n#sequential model means all the layers of the model will be arranged in sequence\nfrom keras.layers import Dense, Conv2D, MaxPool2D, Flatten\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\n#ImageDataGenerator help label the data so that it can easily import data into the model\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport numpy as np\nimport seaborn as sns\nfrom tqdm import tqdm\nfrom random import shuffle \nimport os, cv2 ,random","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nfor dirname, _, filenames in os.walk('/kaggle/working/train'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport zipfile, os\nimport matplotlib.pyplot as plt\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.applications import VGG16\nfrom keras import models\nfrom keras import layers\nfrom keras import optimizers\nfrom sklearn.model_selection import train_test_split\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as zip:\n    zip.extractall()    \n    zip.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub = pd.read_csv('/kaggle/input/dogs-vs-cats/sampleSubmission.csv')\nprint(sample_sub.head())\n\nsample_img = load_img('/kaggle/working/train/cat.6562.jpg') # cute pic :)\nplt.imshow(sample_img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames = os.listdir('/kaggle/working/train')\n\nlabels = []\nfor filename in filenames:\n    label = filename.split('.')[0] # splits on the first dot\n    if label == 'cat':\n        labels.append('0')\n    else:\n        labels.append('1')\n        \ndf = pd.DataFrame({'id': filenames, 'label':labels })\nprint(df.shape)\ndf.head()\n        ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"By using a previously trained network, we're gonna keep the convolutional base (the series of convolutions and pooling layers) of said model, run a new data through it and then train a new classifier. This is called feature extraction. It's important to note that the earlier layers will extract generic patterns, such as edges, colors, textures. Whereas the deeper layers extract more abstract patterns, such as cat ears, dog paws. Thus, if the new dataset differs frmo the original we should only use the first layers of the model."},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\n\nimport os\nprint(os.listdir(\"../input\"))\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Test_Size= 0.5\nRandom_State = 2018\nBatch_Size = 64\nNo_Epochs = 20\nNum_Classes = 2\nSample_Size  = 20000\nPATH = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/'\nTRAIN_FOLDER = './train/'\nTEST_FOLDER =  './test1'\nIMG_SIZE = 224\nRESNET_WEIGHTS_PATH = '/kaggle/input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Read The Data\n\ntrain_image_path= os.path.join(PATH, \"/kaggle/input/dogs-vs-cats/train.zip\")\ntest_image_path= os.path.join(PATH, \"/kaggle/input/dogs-vs-cats/test1.zip\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import zipfile\nwith zipfile.ZipFile(train_image_path,\"r\") as z:\n    z.extractall(\".\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with zipfile.ZipFile(test_image_path,\"r\") as z:\n    z.extractall(\".\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_image_list = os.listdir(\"./train\")[0:Sample_Size]\ntest_image_list = os.listdir(\"./test1\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We set a function for parsing the image names to extract the first 3 letters from the image names, which gives the label of the image. It will be either a cat or a dog. We are using one hot encoder, storing [1,0] for cat and [0,1] for dog.\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"def label_pet_image_one_hot_encoder(img):\n    pet = img.split('.')[-3]\n    if pet == 'cat': return [1,0]\n    elif pet == 'dog' : return [0,1]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We are defining as well a function to process the data (both train and test set)."},{"metadata":{"trusted":true},"cell_type":"code","source":"def process_data(data_image_list, DATA_FOLDER, isTrain=True):\n    data_df = []\n    for img in tqdm(data_image_list):\n        path = os.path.join(DATA_FOLDER,img)\n        if(isTrain):\n            label = label_pet_image_one_hot_encoder(img)\n        else:\n            label = img.split('.')[0]\n        img = cv2.imread(path,cv2.IMREAD_COLOR)\n        img = cv2.resize(img, (IMG_SIZE,IMG_SIZE))\n        data_df.append([np.array(img),np.array(label)])\n    shuffle(data_df)\n    return data_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Data Exploration"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_image_list_count(data_image_list):\n    labels= []\n    for img in data_image_list:\n        labels.append(img.split('.')[-3])\n    sns.countplot(labels)\n    plt.title('Cats and Dogs')\n    \nplot_image_list_count(train_image_list)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_image_list_count(os.listdir(TRAIN_FOLDER))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = process_data(train_image_list, TRAIN_FOLDER)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_images(data, isTest=False):\n    f, ax = plt.subplots(5,5, figsize=(15,15))\n    for i, data in enumerate(data[:25]):\n        img_num = data[1]\n        img_data = data[0]\n        label = np.argmax(img_num)\n        if label == 1:\n            str_label= 'Dog'\n        elif label == 0:\n            str_label = 'Cat'\n        if(isTest):\n            str_label= \"None\"\n        ax[i//5, i%5].imshow(img_data)\n        ax[i//5, i%5].axis('off')\n        ax[i//5, i%5].set_title(\"Label: {}\".format(str_label))\n    plt.show()\n\nshow_images(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test = process_data(test_image_list, TEST_FOLDER, False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_images(test, True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"raw","source":"Prepare the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"X = np.array([i[0] for i in train]).reshape(-1, IMG_SIZE, IMG_SIZE, 3)\ny = np.array([i[1] for i in train])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from IPython.display import SVG\nfrom keras.models import Model\nfrom keras.applications.vgg16 import VGG16\nfrom keras.applications.vgg16 import preprocess_input\nfrom keras.layers import Dense, Flatten, Input, Lambda\nfrom glob import glob\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_SHAPE=[224, 224]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#add preprocessing layer to the front of vgg\nvgg16 = VGG16(input_shape= IMAGE_SHAPE + [3], weights = 'imagenet', include_top= False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in vgg16.layers:\n    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Useful for getting the number of classes\nfolders = glob('./train')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Making the Flatten layer\nX = Flatten()(vgg16.output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"prediction = Dense(len(folders), activation= 'softmax')(X)\nmodel= Model(inputs= vgg16.input, outputs= prediction)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#view model structure\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#tell the model which cost and optimization method to use\nmodel.compile(\n     loss= 'categorical crossentropy',\n    optimizer = 'adam',\n    metrics=['accuracy']\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base = VGG16(weights='imagenet', include_top =False, input_shape=(200,200,3))\n\n#include_top refers to including the Dense layer on top of the network (1000 classes, in this case)\n\nmodel = models.Sequential()\nmodel .add(conv_base)\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation = 'sigmoid'))\n\n# freezing the convolutional base so that its weights aren't updated:\n#conv_base.trainable = False\n# only the weights of the Dense layers will be updated\n\n# we're gonna do some fine-tuning by training a part of the convolutional base\n# it's basically freezing all the layers except the most abstract ones\n\nconv_base.trainable = True\n\nset_trainable = False\nfor layer in conv_base.layers:\n    if layer.name == 'block5_conv1':\n        set_trainable = True\n    if set_trainable:\n        layer.trainable = True\n    else:\n        layer.trainable = False\n        \nmodel.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=1e-5), metrics=['acc'])\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#use the image data generator to import images from dataset\nfrom keras.preprocessing.image import ImageDataGenerator\n\ntrain_datagen= ImageDataGenerator(rescale = 1./255,\n                                 shear_range= 0.2,\n                                 zoom_range = 0.2,\n                                horizontal_flip= True)\ntest_datagen= ImageDataGenerator(rescale= 1./255)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_path = '/kaggle/working/train'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, validation_df = train_test_split(df, test_size=0.1)\n\ntrain_size = train_df.shape[0]\nvalidation_size = validation_df.shape[0]\nbatch_size = 20\n\ntrain_generator = train_datagen.flow_from_dataframe(train_df,\n                                                    '/kaggle/working/train/',\n                                                    x_col='id',\n                                                    y_col='label',\n                                                    class_mode='binary',\n                                                   target_size=(200,200),\n                                                   batch_size=batch_size)\n\nvalidation_generator = test_datagen.flow_from_dataframe(validation_df,\n                                                       '/kaggle/working/train/',\n                                                       x_col='id',\n                                                       y_col='label',\n                                                       class_mode='binary',\n                                                       target_size=(200,200),\n                                                       batch_size=batch_size)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_generator,\n                             steps_per_epoch=train_size//batch_size,\n                             epochs=5,\n                             validation_data=validation_generator,\n                             validation_steps=validation_size//batch_size)\n\nmodel.save('catsvsdogs_vgg16.h5')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}