{"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","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport random\n\n# Sklearn\nfrom sklearn.model_selection import train_test_split\n\n# keras\nfrom keras_preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Unzip the folders","metadata":{}},{"cell_type":"code","source":"import zipfile\nzip_files = ['test1', 'train']\n\nfor zip_file in zip_files:\n    with zipfile.ZipFile(\"../input/dogs-vs-cats/{}.zip\".format(zip_file), \"r\") as z:\n        z.extractall(\".\")\n        print(\"{} unzipped\".format(zip_file))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(os.listdir(\"../input/dogs-vs-cats\"))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_folder_path = \"../working/train\"\nfilenames = os.listdir(train_folder_path)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"categories = []\nfor filename in filenames:\n  category = filename.split(\".\")[0]\n  if category == 'dog':\n    categories.append(1)\n  else:\n    categories.append(0)\n\ndf = pd.DataFrame({'filename': filenames, \n                   'category' : categories})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['category'].value_counts()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['category'].value_counts().plot(kind = 'bar')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## See sample image","metadata":{}},{"cell_type":"code","source":"train_folder_path + \"/\" +sample","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample= random.choice(filenames)\nimage = load_img(train_folder_path + \"/\" +sample)\nplt.imshow(image)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Build Model Framework ","metadata":{}},{"cell_type":"code","source":"img_wd, img_ht = 128, 128","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import layers from keras\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Sequential()\n\n# layer 1 (Convo)\nmodel.add(Conv2D(32,(3,3),activation='relu',\n                 input_shape=(img_wd,img_ht,3)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size = (2,2)))\nmodel.add(Dropout(0.25))\n\n# layer 2 ( Convo)\nmodel.add(Conv2D(64, (3,3), activation = 'relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size = (2, 2)))\nmodel.add(Dropout(0.25))\n\n# layer 3 (Convo)\nmodel.add(Conv2D(128, (3,3), activation = 'relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size = (2, 2)))\nmodel.add(Dropout(0.25))\n\n# layer 4 Dense \nmodel.add(Flatten()) # input layer\nmodel.add(Dense(512, activation = 'relu')) # hidden layer\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.25))\n\nmodel.add(Dense(2, activation = 'softmax')) # output layer\n\n# model compile\nmodel.compile(loss = 'categorical_crossentropy', \n              optimizer = 'rmsprop', metrics = ['accuracy'])\nmodel.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Callbacks","metadata":{}},{"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ReduceLROnPlateau","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=15)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Learning Rate Reduction**    \nWe will reduce the learning rate when then accuracy not increase for 2 steps","metadata":{}},{"cell_type":"code","source":"lr_reduction = ReduceLROnPlateau(monitor = 'val_acc', patience = 2, verbose = 1, \n                                factor = 0.5, min_lr = 0.00001)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [earlystop, lr_reduction]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Preparation","metadata":{}},{"cell_type":"markdown","source":"Because we will use image genaretor with class_mode=\"categorical\". We need to convert column category into string. Then imagenerator will convert it one-hot encoding which is good for our classification.\n\nSo we will convert 1 to dog and 0 to cat","metadata":{}},{"cell_type":"code","source":"df['category'] = df['category'].map({0: 'cat', 1: 'dog'})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size= 0.2, random_state=42)\ntrain_df = train_df.reset_index(drop = True)\nvalidate_df = validate_df.reset_index(drop = True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['category'].value_counts().plot(kind = 'bar')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validate_df['category'].value_counts().plot(kind = 'bar')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_size = train_df.shape[0]\nval_size = validate_df.shape[0]\nbatch_size = 200","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Image Generator for data augmentation","metadata":{}},{"cell_type":"markdown","source":"## Train data generator","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rotation_range= 15, \n                                  rescale= 1/255,\n                                  shear_range= 0.1,\n                                  zoom_range=0.2,\n                                  horizontal_flip=True,\n                                  width_shift_range = 0.1,\n                                  height_shift_range=0.1)\ntrain_generator = train_datagen.flow_from_dataframe(train_df, \n                                                   \"../working/train/\",\n                                                   x_col = 'filename', \n                                                   y_col = 'category', \n                                                   target_size = (img_wd,img_ht),\n                                                   class_mode = 'categorical')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Validation Data Generator","metadata":{}},{"cell_type":"code","source":"valid_datagen = ImageDataGenerator(rescale = 1/255)\n\nvalid_generator = valid_datagen.flow_from_dataframe(validate_df, \n                                                   \"../working/train/\",\n                                                   x_col = 'filename', \n                                                   y_col = 'category', \n                                                   target_size = (img_wd,img_ht),\n                                                   class_mode = 'categorical', \n                                                   batch_size=batch_size)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## let's see the working of generator","metadata":{}},{"cell_type":"code","source":"example_df = train_df.sample(n = 1).reset_index(drop=True)\nexample_gen = train_datagen.flow_from_dataframe(example_df, \n                                                   \"../working/train/\",\n                                                   x_col = 'filename', \n                                                   y_col = 'category', \n                                                   target_size = (img_wd,img_ht),\n                                                   class_mode = 'categorical')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (12, 12))\nfor i in range(0, 20):\n    plt.subplot(5, 4, i+1)\n    for x_batch, y_batch in example_gen:\n        img = x_batch[0]\n        plt.imshow(img)\n        break\nplt.tight_layout()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Fitting","metadata":{}},{"cell_type":"code","source":"Fast_run = False\nepochs = 3 if Fast_run else 50\nhistroy = model.fit(train_generator, \n                             epochs = epochs,\n                             validation_data=valid_generator,\n                             validation_steps=val_size//batch_size, \n                             steps_per_epoch=train_size//batch_size,\n                             callbacks = callbacks)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Save Model","metadata":{}},{"cell_type":"code","source":"model.save('model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize Training","metadata":{}},{"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(2, 1, figsize =(12,12))\n\nax1.plot(histroy.history['loss'], color = 'b', label = 'Training loss')\nax1.plot(histroy.history['val_loss'], color = 'r', label = 'validation loss')\nax1.set_xticks(np.arange(1, epochs, 1))\nax1.set_yticks(np.arange(0,1,0.1))\n\nax2.plot(histroy.history['accuracy'], color = 'b', label = 'Training acc')\nax2.plot(histroy.history['val_accuracy'],color = 'r', label = 'validation acc')\nax2.set_xticks(np.arange(1,epochs, 1))\n\nlegend = plt.legend(loc = 'best', shadow = True)\nplt.tight_layout()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preparing Test Data","metadata":{}},{"cell_type":"code","source":"test_folder_path = \"../working/test1\"\ntest_filenames = os.listdir(test_folder_path)\n\ntest_df = pd.DataFrame({'filename': test_filenames})\ntest_size = test_df.shape[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating Test Generators","metadata":{}},{"cell_type":"code","source":"test_datagen = ImageDataGenerator(rescale = 1/255)\ntest_generator = test_datagen.flow_from_dataframe(test_df,\n                                                 \"../working/test1/\",\n                                                 x_col = 'filename',\n                                                 y_col = None,\n                                                 class_mode = None,\n                                                 target_size = (img_wd, img_ht),\n                                                 batch_size = batch_size,\n                                                 shuffle = False\n                                                 )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict","metadata":{}},{"cell_type":"code","source":"predict = model.predict(test_generator, steps = np.ceil(test_size/batch_size))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"For categoral classication the prediction will come with probability of each category. So we will pick the category that have the highest probability with numpy average max","metadata":{}},{"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis = -1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_map = dict((v,k) for k,v in train_generator.class_indices.items())\n\ntest_df['category'] = test_df['category'].map(label_map)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = test_df['category'].map({'cat':0, 'dog':1})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'].value_counts()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## See predicted results with images","metadata":{}},{"cell_type":"code","source":"sample_test = test_df.head(15)\nsample_test.head()\nplt.figure(figsize = (12,24))\n\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = load_img(\"../working/test1/\" + filename, \n                   target_size = (img_wd, img_ht))\n    plt.subplot(5,3, index +1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + \")\")\n    \nplt.tight_layout()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"submission_df = test_df.copy()\nsubmission_df['id'] = submission_df['filename'].str.split(\".\").str[0]\nsubmission_df.rename(columns= {'category': 'label'}, inplace = True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.drop('filename', axis = 1, inplace = True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv('submission.csv', index = False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}