{"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 in \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 \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import cv2   #use it in reading and resizing our Images.\nimport numpy as np  #process large, multi-dimensional arrays and matrices super easy and fast.\nimport pandas as pd #manipulating numerical tables and time series.\nimport matplotlib.pyplot as plt #plotting lines, bar-chart, graphs, histograms\n%matplotlib inline \n#makes our plots appear in the notebook\n\nimport os #accessing your computer and file system.\nimport random # create random numbers, split or shuffle our data set.\nimport gc # garbage collector is an important tool for manually cleaning and deleting unnecessary variables.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create a file path for both test and train sets\ntrain_dir = '../input/train'\ntest_dir = '../input/test'\n\n#create two variables train_dogs and train_cats\n#write a list comprehension: os.listdir() to get all the images in the train data\n#and retrieve all images with dog/cat in their name\ntrain_dogs = ['../input/train/{}'.format(i) for i in os.listdir(train_dir) if 'dog' in i]\ntrain_cats = ['../input/train/{}'.format(i) for i in os.listdir(train_dir) if 'cat' in i]\n\n#get our test images\ntest_imgs = ['../input/test/{}'.format(i) for i in os.listdir(test_dir) ]\n\n# with little computational power, we’re going to extract only 2000 images for both classes\ntrain_imgs = train_dogs[:2000] + train_cats[:2000]\nrandom.shuffle(train_imgs) #randomly shuffle the train_imgs\n\n# delete two columns to save memories\ndel train_dogs\ndel train_cats\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Import an image plotting module from matplotlib\nimport matplotlib.image as mpimg\n#Run a for loop to plot the first three images in train_imgs\nfor ima in train_imgs[0:3]:\n    img = mpimg.imread(ima)\n    imgplot = plt.imshow(img)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#resize the images using the cv2 module\n#declare the new dimensions we want to use: 150 by 150 for height and width and 3 channels\n\nnrows = 150\nncolumns = 150\nchannels = 3 #change to 1 if you want to use grayscale image\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_and_process_image(list_of_images):\n    \"\"\"\n    Returns two arrays:\n        X is an array of resized images\n        y is an array of labels\n    \"\"\"\n    X = [] #images\n    y = [] #labels\n    \n    for image in list_of_images: #read images one after the other and resize them with the cv2 commands.\n        X.append(cv2.resize(cv2.imread(image, cv2.IMREAD_COLOR), (nrows, ncolumns), interpolation = cv2.INTER_CUBIC)) #read the image\n        #get the labels\n        if 'dog' in image:\n            y.append(1)\n        elif 'cat' in image:\n            y.append(0)\n        \n    return X, y\n            ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X, y = read_and_process_image(train_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#We can’t plot the images in X with the mpimg module of matplotlib.image above \n#because these are now arrays of pixels not raw jpg files\n#So we should use the imshow() command.\n\n\nplt.figure(figsize = (20, 10))\ncolumns = 5 \nfor i in range(columns):\n    plt.subplot(5/ columns + 1, columns, i + 1)\n    plt.imshow(X[i])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import seaborn as sns\n\n#we delete the train_imgs, since it has already been converted to an array and saved in X.\ndel train_imgs\ngc.collect()\n\n#X and y are currently of type list (list of python array)\n#convert list to numpy array so we can feed it into our model\nX = np.array(X)\ny = np.array(y)\n\n#Lets plot the to be sure we just have two classes\n#Plot a colorful diagram to confirm the number of classes\nsns.countplot(y)\nplt.title('Labels for Cats and Dogs')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#check the shape of data \nprint(\"Shape of the image is:\", X.shape)\nprint(\"Shape of the label is:\", y.shape)\n\n#keras model takes as input an array of (height, width,channels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#split data into test and train set\nfrom sklearn.model_selection import train_test_split\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size = 0.20, random_state = 2)\n\nprint(\"Shape of train images is\", X_train.shape)\nprint(\"Shape of validation images is\", X_val.shape)\nprint(\"Shape of train label is\", y_train.shape)\nprint(\"Shape of validation label is\", y_val.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del X\ndel y\ngc.collect()\n\n#get the length of the train and validation data\nntrain = len(X_train)\nnval = len(X_val)\n\n# use batch size of 32\nbatch_size = 32\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#use a Convolutional Neural Network (convnet) to train our model.\n#In creating our model we’re going to use KERAS.\n\n#Keras is an open source neural network library written in Python. \n#It is capable of running on top of TensorFlow","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import layers\nfrom keras import models #Sequential model will be used\nfrom keras import optimizers #contains different types of back propagation algorithm for training our model\nfrom keras.preprocessing.image import ImageDataGenerator #(ImageDataGenerator) used when working with a small data set\nfrom keras.preprocessing.image import img_to_array, load_img\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create our Network architecture follow VGGnet structure\n#32 > 64 > 128 > 512 > 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#create a sequential model so that \n#tells keras to stack all layers sequentially\nmodel = models.Sequential() \n\n# Conv2D (filter size,  kernel_size,  activation function, input shape)\n# filter size: the size of the output dimension\n# kernel_size: the height and width of the 2D convolution window.\n# input shape : the dimensions we resized our images (We do not pass 4000 since it's  the batch dimension.)\nmodel.add(layers.Conv2D(32, (3,3), activation = 'relu', input_shape =(150, 150, 3)))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(64, (3,3), activation = 'relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3,3), activation = 'relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3,3), activation = 'relu'))\n\n#add a MaxPool2D layer \n#to reduce the spatial size of the incoming features\n#thereby helping to reduce overfitting.\nmodel.add(layers.MaxPooling2D((2, 2)))\n\n#How A conv2D layers extract and learn spatial features:\n#(1) it has been flattened\n#(2) then passed to a dense layer \nmodel.add(layers.Flatten())\n\n# add a Dropout layer: randomly drop half of the layers. (with value = 0.5)\n# therefore, the network learns to be independent and not reliable on a single layer.\nmodel.add(layers.Dropout(0.5)) \n\nmodel.add(layers.Dense(512, activation ='relu'))\nmodel.add(layers.Dense(1, activation ='sigmoid')) # sigmoid function in the end because we have just two classes\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss ='binary_crossentropy', optimizer = optimizers.RMSprop(lr = 1e-4), metrics = ['acc'])\n# specify a loss function: optimizer will minimize the cost; and since it is two class problem, we use binary crossentropy loss \n# use one of the optimizers called rmsprop: calculate the difference between a world class model and a naive one\n# specify which metric we want to use: to know if our model is doing well, and since it is a classification problem\n# , the accuracy metric (acc) is a good choice. ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#perform some Normalization. \n#i.e scale our image pixel values to have a unit standard deviation and a mean of 0.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#ImageDataGenerator() automatically turn image files into preprocessed tensors \n#that can be fed directly into models during trainng.\n# is able to:\n#  Decode the JPEG to RGB grids\n#  Convert these into floating-point tensors\n#  rescale pixel values (between 0 and 255) to the [0, 1] interval \n#  easily augment images:  important feature for small training set\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# augmentation configuration: prevent overfitting since we have small training set\ntrain_datagen = ImageDataGenerator(rescale = 1./255, # scale the image between 0 and 1\n                                  rotation_range = 0.2,\n                                  width_shift_range = 0.2,\n                                  height_shift_range = 0.2,\n                                  shear_range = 0.2,\n                                  zoom_range = 0.2,\n                                  horizontal_flip = True,)\n\nval_datagen = ImageDataGenerator(rescale = 1./255) # do not augment val_dat, only need rescale ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create two generators for both training and validation\ntrain_generator = train_datagen.flow(X_train, y_train, batch_size = batch_size)\nval_generator = val_datagen.flow(X_val, y_val, batch_size = batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#\nhistory = model.fit_generator(train_generator, \n                             steps_per_epoch = ntrain // batch_size,\n                             epochs = 64, \n                             validation_data = val_generator,\n                             validation_steps = nval // batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save_weights('model_wieghts.h5')\nmodel.save('model_keras.h5')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}