{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook is a simple walkthrough a binary classification.  I'll try to make the model better in a next notebook."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport tensorflow as tf\nimport os\nimport zipfile\nimport random\nimport shutil\nfrom tensorflow.keras.optimizers import RMSprop\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom shutil import copyfile\nfrom os import getcwd\n\n\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","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" We extract the train images"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"\nprint(os.listdir(\"../input\"))\n\npath_cats_and_dogs = \"../input/dogs-vs-cats/train.zip\"\n#shutil.rmtree('/tmp')\n\nlocal_zip = path_cats_and_dogs\nzip_ref = zipfile.ZipFile(local_zip, 'r')\nzip_ref.extractall('.')\nzip_ref.close()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" We extract the test images"},{"metadata":{"trusted":true},"cell_type":"code","source":"path_cats_and_dogs = \"../input/dogs-vs-cats/test1.zip\"\n#shutil.rmtree('/tmp')\n\nlocal_zip = path_cats_and_dogs\nzip_ref = zipfile.ZipFile(local_zip, 'r')\nzip_ref.extractall('.')\nzip_ref.close()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We'll next create a cats and dogs directories for the train data and the validation data. Here down I created this:\ntrain->dogs - cats\nval -> dogs - cats\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"try:\n    main_dir = \"/kaggle/working/\"\n    train_dir = \"train\"\n    val_dir = \"val\"\n\n    train_dir = os.path.join(main_dir,train_dir)\n    # Directory with our training cat/dog pictures\n    train_cats_dir = os.path.join(train_dir, 'cats')\n    train_dogs_dir = os.path.join(train_dir, 'dogs')\n    os.mkdir(train_cats_dir)\n    os.mkdir(train_dogs_dir)\n    # Directory with our validation cat/dog pictures\n    val_dir = os.path.join(main_dir,\"val\")\n    os.mkdir(val_dir)\n    val_cats_dir = os.path.join(val_dir, 'cats')\n    val_dogs_dir = os.path.join(val_dir, 'dogs')\n    os.mkdir(val_cats_dir)\n    os.mkdir(val_dogs_dir)\n\nexcept OSError:\n    pass","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The training images has the classification in their name. Dogs images names is built like this: dog.number.jpg and cat's : cat.number.jpg \nSo to classify the files we will create two lists one for dogs files and another for cats files. thanks to the shutil library we will move the files to the according directories in train."},{"metadata":{"trusted":true},"cell_type":"code","source":"##let's put the cats images in the cats directory and the dogs in the dogs directory\n# for the train directory we parse the jpg name if the name start with cat we put it in the cats dir\nmain_dir = \"/kaggle/working/\"\ntrain_dir = \"train\"\ntrain_path = os.path.join(main_dir,train_dir)\n\nprefixed_dogs = [filename for filename in os.listdir(train_path) if filename.startswith(\"dog.\")]\nprint(len(prefixed_dogs))\nprefixed_cats = [filename for filename in os.listdir(train_path) if filename.startswith(\"cat.\")]\nprint(len(prefixed_cats))\n\ndef move_files(src_file):\n    \n    for filename in prefixed_dogs:\n        shutil.move(src_file+filename, src_file+'dogs/'+filename)\n        \n    for filename in prefixed_cats:\n        shutil.move(src_file+filename, src_file+'cats/'+filename)\n    \n\nmove_files(\"/kaggle/working/train/\")\n\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(os.listdir('/kaggle/working/train/dogs')))\nprint(len(os.listdir('/kaggle/working/train/cats')))\nprint(len(os.listdir('/kaggle/working/train')))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So now we've got a directory train with two subdirectory cats and dogs and a validation directory that is, at this point, empty. Let's split our training data.\nTo do that I created the split function. \n"},{"metadata":{"trusted":true},"cell_type":"code","source":"def split_data(SOURCE, VALID, SPLIT_SIZE):\n# This funtion takes as argument:\n###SOURCE : the directory's path of images that will be splitted\n###VALID : the directory's path of the validation receiving the dogs or the cats images\n###SPLIT_SIZE: the size of the split. 0.9 means 90% of cats images will remain in train/cats and 10% will be moved to the validation directory's cats \n###and the same will be done to the dogs images\n    SRC_files = [f for f in os.listdir(SOURCE) if os.path.isfile(os.path.join(SOURCE, f))]\n    SRC_Size = len(SRC_files)\n    #print(SRC_Size)\n    if SRC_Size != 0:\n        # we shuffle the images before the split\n        shuffled_files = random.sample(SRC_files, len(SRC_files))\n        #print(\"shuffled\")\n        TRN_size = int(SRC_Size * SPLIT_SIZE)\n        VAL_SIZE = int(SRC_Size - TRN_size)\n        print(TRN_size)\n        train_set = shuffled_files[0:TRN_size]\n        val_set = shuffled_files[-VAL_SIZE:SRC_Size]\n        for filename in val_set:\n            if os.path.getsize(SOURCE+filename)!=0:\n                shutil.move(SOURCE+filename, VALID+filename)\n            else:\n                print(filename + ' is zero length. So ignoring!')\n                pass\n\n\n                    \nCAT_SOURCE_DIR = \"/kaggle/working/train/cats/\"\nTESTING_CATS_DIR = \"/kaggle/working/val/cats/\"\n\nDOG_SOURCE_DIR = \"/kaggle/working/train/dogs/\"\nTESTING_DOGS_DIR = \"/kaggle/working/val/dogs/\"\n\nsplit_size = .9\nsplit_data(CAT_SOURCE_DIR, TESTING_CATS_DIR, split_size)\nsplit_data(DOG_SOURCE_DIR, TESTING_DOGS_DIR, split_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(os.listdir('/kaggle/working/train/dogs')))\nprint(len(os.listdir('/kaggle/working/train/cats')))\nprint(len(os.listdir('/kaggle/working/train')))\nprint(len(os.listdir('/kaggle/working/val/dogs')))\nprint(len(os.listdir('/kaggle/working/val/cats')))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So now let's build our model. It will be a simple one with three layers of conv2d and Maxpooling. We will finish by a Dense layer with sigmoid activation to have the probabilities."},{"metadata":{"trusted":true},"cell_type":"code","source":"# DEFINE A KERAS MODEL TO CLASSIFY CATS V DOGS\n# USE AT LEAST 3 CONVOLUTION LAYERS\nIMAGE_WIDTH=150\nIMAGE_HEIGHT=150\nIMAGE_SIZE=(IMAGE_WIDTH, IMAGE_HEIGHT)\n\nmodel = tf.keras.models.Sequential([\n# YOUR CODE HERE\n    tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, 3)),\n    tf.keras.layers.MaxPooling2D(2,2),\n    tf.keras.layers.Conv2D(32, (3,3), activation='relu'),\n    tf.keras.layers.MaxPooling2D(2,2), \n    tf.keras.layers.Conv2D(64, (3,3), activation='relu'), \n    tf.keras.layers.MaxPooling2D(2,2),\n    tf.keras.layers.Flatten(),\n    tf.keras.layers.Dense(512, activation='relu'), \n    tf.keras.layers.Dense(1, activation='sigmoid')  \n])\n\nmodel.compile(optimizer=RMSprop(lr=0.001), loss='binary_crossentropy', metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We will use the ImageDataGenerator to handle the images but without any augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAINING_DIR = '/kaggle/working/train'\ntrain_datagen = ImageDataGenerator(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.2,\n#       horizontal_flip=True,\n#       fill_mode='nearest')#YOUR CODE HERE\n\n# NOTE: YOU MUST USE A BATCH SIZE OF 10 (batch_size=10) FOR THE \n# TRAIN GENERATOR.\ntrain_generator = train_datagen.flow_from_directory(TRAINING_DIR,\n                                                    batch_size=10,\n                                                    class_mode='binary',\n                                                    target_size=(150, 150))\n\nVALIDATION_DIR = '/kaggle/working/val'#YOUR CODE HERE\nvalidation_datagen = ImageDataGenerator( rescale = 1.0/255. )#YOUR CODE HERE\n\n# NOTE: YOU MUST USE A BACTH SIZE OF 10 (batch_size=10) FOR THE \n# VALIDATION GENERATOR.\nvalidation_generator = validation_datagen.flow_from_directory(VALIDATION_DIR,\n                                                         batch_size=10,\n                                                         class_mode  = 'binary',\n                                                         target_size = (150, 150))\n\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_generator,\n                              epochs=2,\n                              verbose=1,\n                              validation_data=validation_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save_weights(\"model.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\n\nimport matplotlib.image  as mpimg\nimport matplotlib.pyplot as plt\n\n#-----------------------------------------------------------\n# Retrieve a list of list results on training and test data\n# sets for each training epoch\n#-----------------------------------------------------------\nacc=history.history['acc']\nval_acc=history.history['val_acc']\nloss=history.history['loss']\nval_loss=history.history['val_loss']\n\nepochs=range(len(acc)) # Get number of epochs\n\n#------------------------------------------------\n# Plot training and validation accuracy per epoch\n#------------------------------------------------\nplt.plot(epochs, acc, 'r', \"Training Accuracy\")\nplt.plot(epochs, val_acc, 'b', \"Validation Accuracy\")\nplt.title('Training and validation accuracy')\nplt.figure()\n\n#------------------------------------------------\n# Plot training and validation loss per epoch\n#------------------------------------------------\nplt.plot(epochs, loss, 'r', \"Training Loss\")\nplt.plot(epochs, val_loss, 'b', \"Validation Loss\")\n\n\nplt.title('Training and validation loss')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now let's put the test images into the datagenertor so we could predict."},{"metadata":{"trusted":true},"cell_type":"code","source":"test = os.listdir('/kaggle/working/test1')\nprint(type(test))\n\n# preprocessing test\nTEST_DIR  = '/kaggle/working/test1'\ntest_df = pd.DataFrame({'filename': test})\n\nnb_samples = test_df.shape[0]\n\ntest_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    TEST_DIR, \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=(150,150),\n    batch_size = 10\n)\n\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predict = model.predict_generator(test_generator)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's see what our predictions look like"},{"metadata":{"trusted":true},"cell_type":"code","source":"predict[2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df['prediction'] = predict","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntest_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"you can change the test image path to check if the prediction is correct"},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator, load_img\nimport matplotlib.pyplot as plt\nimg = load_img('/kaggle/working/test1/10392.jpg', target_size=(150,150))\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df = test_df.copy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df['id'] = submission_df['filename'].str.split('.').str[0]\nsubmission_df[\"label\"] =  np.where(submission_df['prediction'] >0.7, 1, 0)\nsubmission_df.drop(['filename','prediction'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)\nsubmission_df\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df.to_csv('submission.csv', index=False)","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}