{"cells":[{"metadata":{},"cell_type":"markdown","source":"> Import the packages needed","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nfrom tensorflow.python.client import device_lib\nimport numpy as np\nimport shutil\nimport matplotlib.pyplot as plt\nfrom matplotlib.pyplot import imshow\n\n!ls ../input/","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> Unzip the dataset provided by kaggle","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!unzip ../input/dogs-vs-cats-redux-kernels-edition/train.zip\n!unzip ../input/dogs-vs-cats-redux-kernels-edition/test.zip\n!ls ../working","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!mkdir all_images","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# All the images used to train and test are copied to a new directory named all_images","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport shutil\n\ntrain_dir = '../working/train'\ndest_dir = '../working/all_images'\n\ncounter = 0\n\n\nfor subdir, dirs, files in os.walk(train_dir):\n    \n    for file in files:\n        full_path = os.path.join(subdir, file)\n        shutil.copy(full_path, dest_dir)\n        counter = counter + 1\n        \nprint(counter)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Now we create two files\n### One to create the arrays representing the images\n### One to the labels","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"subdirs, dirs, files = os.walk('../working/all_images').__next__()\nm = len(files)\n\n\nfilenames = []\nlabels = np.zeros((m, 1))\n\n\nimages_dir = '../working/all_images'\nfilenames_counter = 0\n\n\nfor subdir, dirs, files in os.walk(train_dir):\n    \n    for file in files:\n        filenames.append(file)\n                                    \n        if 'cat' in file: labels[filenames_counter, 0]  = 1;\n        else : labels[filenames_counter, 0] = 0;\n    \n        filenames_counter = filenames_counter + 1\n    \n    \nprint(len(filenames))\nprint(labels.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":" ## Now we shuffle the data","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.utils import shuffle\n\nfilenames_shuffled, y_labels_shuffled = shuffle(filenames, labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"## Splitting data using sklearn","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n# Used this line as our filename array is not a numpy array.\nfilenames_shuffled_numpy = np.array(filenames_shuffled)\n\nX_train_filenames, X_val_filenames, y_train, y_val = train_test_split(\n    filenames_shuffled_numpy, y_labels_shuffled, test_size=0.2, random_state=1)\n\nX_val_filenames, X_test_filenames, y_val, y_test = train_test_split(\n    X_val_filenames, y_val, test_size=0.5, random_state=1)\n\nprint(X_train_filenames.shape)\nprint(y_train.shape)          \n\nprint(X_val_filenames.shape)  \nprint(y_val.shape)            \n\nprint(X_val_filenames.shape)  \nprint(y_val.shape)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Note: As our dataset is too large to fit in memory, we have to load the dataset from the hard disk in batches to our memory.**\n\n# Custom Generator to load batches to memmory","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import keras\nfrom PIL import Image\n\n#this function receive keras.utils.Sequence to be compatible with the keras models in runtime\nclass My_Custom_Generator(keras.utils.Sequence) :\n  \n  def __init__(self, image_filenames, labels, batch_size) :\n    self.image_filenames = image_filenames\n    self.labels = labels\n    self.batch_size = batch_size\n    \n  def __len__(self) :\n    return (np.ceil(len(self.image_filenames) / float(self.batch_size))).astype(np.int)\n  \n  \n  def __getitem__(self, idx) :\n    batch_x = self.image_filenames[idx * self.batch_size : (idx+1) * self.batch_size]\n    batch_y = self.labels[idx * self.batch_size : (idx+1) * self.batch_size]\n    \n    return np.array([\n            np.array(Image.open('../working/all_images/' + str(file_name)).resize((120,120)))\n               for file_name in batch_x])/255.0, np.array(batch_y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 128\n\nmy_training_batch_generator = My_Custom_Generator(X_train_filenames, y_train, batch_size)\nmy_validation_batch_generator = My_Custom_Generator(X_val_filenames, y_val, batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"l = my_training_batch_generator.__getitem__(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(l[0].shape)\n#if its a gray scale image, add this shit -> cmap = plt.get_cmap('gray')\nplt.imshow(l[0][11])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from keras.losses import binary_crossentropy\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras.losses import binary_crossentropy\nfrom keras.layers import * \nfrom keras.models import Model, Sequential\nfrom keras.preprocessing import image\nfrom keras.utils import layer_utils\nfrom keras.utils.data_utils import get_file\nfrom keras.utils import plot_model\n\nimport keras.backend as K\nK.set_image_data_format('channels_last')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_model():\n    model = Sequential()\n\n    model.add(ZeroPadding2D((3, 3),input_shape=(120,120,3)))\n\n    model.add(Conv2D(filters = 64, kernel_size = (5,5), activation ='relu'))\n    model.add(BatchNormalization(axis=3))\n    model.add(Conv2D(filters = 64, kernel_size = (5,5), activation ='relu'))\n    model.add(MaxPooling2D(pool_size=(2,2)))\n    model.add(BatchNormalization(axis=3))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(filters = 128, kernel_size = (5,5), activation ='relu'))\n    model.add(BatchNormalization(axis=3))\n    model.add(Conv2D(filters = 128, kernel_size = (5,5), activation ='relu'))\n    model.add(MaxPooling2D(pool_size=(2,2)))\n    model.add(BatchNormalization(axis=3))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(filters = 256, kernel_size = (5,5), activation ='relu'))\n    model.add(BatchNormalization(axis=3))\n    model.add(Conv2D(filters = 256, kernel_size = (5,5), activation ='relu'))\n    model.add(MaxPooling2D(pool_size=(2,2)))\n    model.add(BatchNormalization(axis=3))\n    model.add(Dropout(0.5))\n\n\n    model.add(Conv2D(filters = 512, kernel_size = (3,3), activation ='relu'))\n    model.add(BatchNormalization(axis=3))\n    model.add(Conv2D(filters = 512, kernel_size = (3,3), activation ='relu'))\n    model.add(MaxPooling2D(pool_size=(2,2)))\n    model.add(BatchNormalization(axis=3))\n    model.add(Dropout(0.5))\n\n    model.add(Flatten())\n\n    model.add(Dense(256, activation = \"relu\")) #Fully connected layer\n    model.add(BatchNormalization())\n    model.add(Dropout(0.5))\n\n\n    model.add(Dense(60, activation = \"relu\")) #Fully connected layer\n    model.add(BatchNormalization())\n    model.add(Dropout(0.6))\n    \n    model.add(Dense(1, activation='sigmoid', name='fc'))\n\n    return model\n\n#build the model\nmodel = build_model()\n\n#adam as optimizer and binary cross entropy as metric\nmodel.compile(optimizer = 'adam', loss = binary_crossentropy , metrics = ['accuracy'])\n\nmodel.summary()\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras.losses import binary_crossentropy\n\ncallbacks = [\n        ModelCheckpoint(filepath=\"best_weights.hdf5\", \n                               monitor = 'val_accuracy',\n                               mode = 'max',\n                               verbose=1,\n                               period = 2,\n                               save_best_only=True),\n        EarlyStopping(monitor='val_accuracy',\n                      mode = 'max',\n                      patience = 5)\n]\n\nhistory = model.fit(my_training_batch_generator,\n                   #steps_per_epoch = int(20000 // batch_size),\n                   epochs = 10,\n                   verbose = 2,\n                   validation_data = my_validation_batch_generator,\n                   #validation_steps = int(5000 // batch_size),\n                   callbacks= callbacks,\n                   shuffle = True\n                   )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Now we create a function that plots the accuracys and losses of the model output ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_history(history):\n    print(history.history.keys())\n    \n    #Regarding to the accuracy and val_accuracy of the model\n    plt.plot(history.history[\"accuracy\"])\n    plt.plot(history.history[\"val_accuracy\"])\n    plt.title(\"Accuracy of the model\")\n    plt.ylabel(\"Accuracy\")\n    plt.xlabel(\"Epoch\")\n    plt.show()\n    \n    #Regarding to the losses of the model\n    plt.plot(history.history[\"loss\"])\n    plt.plot(history.history[\"val_loss\"])\n    plt.title(\"Loss of the model\")\n    plt.ylabel(\"Loss\")\n    plt.xlabel(\"Epoch\")\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(history.history.keys())\nshow_history(history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.evaluate(X_test_filenames,y_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"**Saving**\n\nIm saving the model here.\nThis is a model that ilustrate a simple model, Adam as optimizer and binary classification as losso function\n\nTrain accuracy -> 98%\n\nTest accuracy -> 90%\n\nThe model seems to overfitt, try refularization or a more sophesticated model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#model.summary()\nplot_model(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# serialize model to JSON\nmodel_json = model.to_json()\nwith open(\"model.json\", \"w\") as json_file:\n    json_file.write(model_json)\n# serialize weights to HDF5\nmodel.save_weights(\"model.h5\")\nprint(\"Saved model to disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import model_from_json\n\njson_file = open('model.json', 'r')\nloaded_model_json = json_file.read()\njson_file.close()\nloaded_model = model_from_json(loaded_model_json)\n# load weights into new model\nloaded_model.load_weights(\"model.h5\")\nprint(\"Loaded model from disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaded_model.compile(optimizer = 'adam', loss = binary_crossentropy , metrics = ['accuracy'])\nloaded_model.evaluate(y_test_set,y_result_set)","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}