{"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":"import numpy as np\nimport pandas as pd \nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom tensorflow.keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport os\nprint(os.listdir(\"../input\"))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-04T20:40:49.396070Z","iopub.execute_input":"2021-12-04T20:40:49.396446Z","iopub.status.idle":"2021-12-04T20:40:51.284776Z","shell.execute_reply.started":"2021-12-04T20:40:49.396371Z","shell.execute_reply":"2021-12-04T20:40:51.283340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FAST_RUN = False\nIMAGE_WIDTH=128\nIMAGE_HEIGHT=128\nIMAGE_SIZE=(IMAGE_WIDTH, IMAGE_HEIGHT)\nIMAGE_CHANNELS=3","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:40:51.290594Z","iopub.execute_input":"2021-12-04T20:40:51.291466Z","iopub.status.idle":"2021-12-04T20:40:51.296034Z","shell.execute_reply.started":"2021-12-04T20:40:51.291424Z","shell.execute_reply":"2021-12-04T20:40:51.295270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Traning Data","metadata":{}},{"cell_type":"code","source":"import zipfile\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as z:\n    z.extractall(\".\")\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\",\"r\") as z:\n    z.extractall(\".\")\n\ntrain_path = \"/kaggle/working/train\"\nfilenames = os.listdir(train_path)\ncategories = []\n\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({\n    'filename': filenames,\n    'category': categories\n})","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:40:51.297238Z","iopub.execute_input":"2021-12-04T20:40:51.297672Z","iopub.status.idle":"2021-12-04T20:41:05.781602Z","shell.execute_reply.started":"2021-12-04T20:40:51.297630Z","shell.execute_reply":"2021-12-04T20:41:05.780732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:05.784114Z","iopub.execute_input":"2021-12-04T20:41:05.784314Z","iopub.status.idle":"2021-12-04T20:41:05.798670Z","shell.execute_reply.started":"2021-12-04T20:41:05.784282Z","shell.execute_reply":"2021-12-04T20:41:05.797819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['category'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:05.800515Z","iopub.execute_input":"2021-12-04T20:41:05.800761Z","iopub.status.idle":"2021-12-04T20:41:05.984345Z","shell.execute_reply.started":"2021-12-04T20:41:05.800728Z","shell.execute_reply":"2021-12-04T20:41:05.983625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# sample image","metadata":{}},{"cell_type":"code","source":"sample = random.choice(filenames)\nimage = load_img(\"./train/\"+sample)\nplt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:05.985623Z","iopub.execute_input":"2021-12-04T20:41:05.985831Z","iopub.status.idle":"2021-12-04T20:41:06.263829Z","shell.execute_reply.started":"2021-12-04T20:41:05.985803Z","shell.execute_reply":"2021-12-04T20:41:06.263118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Building\n- Input Layer: It represent input image data. It will reshape image into single diminsion array. Example your image is 64x64 = 4096, it will convert to (4096,1) array.\n- Conv Layer: This layer will extract features from image.\n- Pooling Layer: This layerreduce the spatial volume of input image after convolution.\n- Fully Connected Layer: It connect the network from a layer to another layer\n- Output Layer: It is the predicted values layer.","metadata":{}},{"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\n\nmodel = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(2, activation='softmax')) # 2 because we have cat and dog classes\n\nmodel.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:06.264865Z","iopub.execute_input":"2021-12-04T20:41:06.265114Z","iopub.status.idle":"2021-12-04T20:41:07.559508Z","shell.execute_reply.started":"2021-12-04T20:41:06.265075Z","shell.execute_reply":"2021-12-04T20:41:07.558666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Callbacks","metadata":{}},{"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ReduceLROnPlateau","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:07.561186Z","iopub.execute_input":"2021-12-04T20:41:07.561494Z","iopub.status.idle":"2021-12-04T20:41:07.566933Z","shell.execute_reply.started":"2021-12-04T20:41:07.561453Z","shell.execute_reply":"2021-12-04T20:41:07.566070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Early Stop\n\nTo prevent over fitting we will stop the learning after 10 epochs and val_loss value not decreased","metadata":{}},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=10)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:07.568352Z","iopub.execute_input":"2021-12-04T20:41:07.568918Z","iopub.status.idle":"2021-12-04T20:41:08.514517Z","shell.execute_reply.started":"2021-12-04T20:41:07.568875Z","shell.execute_reply":"2021-12-04T20:41:08.513622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Learning Rate Reduction\n\nWe will reduce the learning rate when then accuracy not increase for 2 steps","metadata":{}},{"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', \n                                            patience=2, \n                                            verbose=1, \n                                            factor=0.5, \n                                            min_lr=0.00001)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.515997Z","iopub.execute_input":"2021-12-04T20:41:08.516439Z","iopub.status.idle":"2021-12-04T20:41:08.523547Z","shell.execute_reply.started":"2021-12-04T20:41:08.516401Z","shell.execute_reply":"2021-12-04T20:41:08.522843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [earlystop, learning_rate_reduction]","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.524743Z","iopub.execute_input":"2021-12-04T20:41:08.525271Z","iopub.status.idle":"2021-12-04T20:41:08.535598Z","shell.execute_reply.started":"2021-12-04T20:41:08.525228Z","shell.execute_reply":"2021-12-04T20:41:08.534537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare data","metadata":{}},{"cell_type":"markdown","source":"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\"].replace({0: 'cat', 1: 'dog'}) ","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.536692Z","iopub.execute_input":"2021-12-04T20:41:08.537099Z","iopub.status.idle":"2021-12-04T20:41:08.547458Z","shell.execute_reply.started":"2021-12-04T20:41:08.537062Z","shell.execute_reply":"2021-12-04T20:41:08.546709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size=0.20, random_state=42)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.551504Z","iopub.execute_input":"2021-12-04T20:41:08.551920Z","iopub.status.idle":"2021-12-04T20:41:08.562593Z","shell.execute_reply.started":"2021-12-04T20:41:08.551891Z","shell.execute_reply":"2021-12-04T20:41:08.561704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['category'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.564002Z","iopub.execute_input":"2021-12-04T20:41:08.564430Z","iopub.status.idle":"2021-12-04T20:41:08.734450Z","shell.execute_reply.started":"2021-12-04T20:41:08.564393Z","shell.execute_reply":"2021-12-04T20:41:08.733696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validate_df['category'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.735597Z","iopub.execute_input":"2021-12-04T20:41:08.735869Z","iopub.status.idle":"2021-12-04T20:41:08.905252Z","shell.execute_reply.started":"2021-12-04T20:41:08.735831Z","shell.execute_reply":"2021-12-04T20:41:08.904563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]\nbatch_size=15","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.906477Z","iopub.execute_input":"2021-12-04T20:41:08.906758Z","iopub.status.idle":"2021-12-04T20:41:08.911555Z","shell.execute_reply.started":"2021-12-04T20:41:08.906721Z","shell.execute_reply":"2021-12-04T20:41:08.910886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Traning Generator","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    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\n)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    \"./train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:08.913049Z","iopub.execute_input":"2021-12-04T20:41:08.913984Z","iopub.status.idle":"2021-12-04T20:41:09.104902Z","shell.execute_reply.started":"2021-12-04T20:41:08.913945Z","shell.execute_reply":"2021-12-04T20:41:09.104074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Validation Generator","metadata":{}},{"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    \"./train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:09.106004Z","iopub.execute_input":"2021-12-04T20:41:09.106815Z","iopub.status.idle":"2021-12-04T20:41:09.162456Z","shell.execute_reply.started":"2021-12-04T20:41:09.106749Z","shell.execute_reply":"2021-12-04T20:41:09.161595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test","metadata":{}},{"cell_type":"code","source":"example_df = train_df.sample(n=1).reset_index(drop=True)\nexample_generator = train_datagen.flow_from_dataframe(\n    example_df, \n    \"./train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical'\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:09.163735Z","iopub.execute_input":"2021-12-04T20:41:09.164086Z","iopub.status.idle":"2021-12-04T20:41:09.173782Z","shell.execute_reply.started":"2021-12-04T20:41:09.164048Z","shell.execute_reply":"2021-12-04T20:41:09.172741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nfor i in range(0, 15):\n    plt.subplot(5, 3, i+1)\n    for X_batch, Y_batch in example_generator:\n        image = X_batch[0]\n        plt.imshow(image)\n        break\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:09.175007Z","iopub.execute_input":"2021-12-04T20:41:09.175317Z","iopub.status.idle":"2021-12-04T20:41:11.055327Z","shell.execute_reply.started":"2021-12-04T20:41:09.175270Z","shell.execute_reply":"2021-12-04T20:41:11.054653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Fit Model","metadata":{}},{"cell_type":"code","source":"epochs=3 if FAST_RUN else 10\nhistory = model.fit_generator(\n    train_generator, \n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=total_validate//batch_size,\n    steps_per_epoch=total_train//batch_size,\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T20:41:11.056353Z","iopub.execute_input":"2021-12-04T20:41:11.056701Z","iopub.status.idle":"2021-12-04T21:05:31.026506Z","shell.execute_reply.started":"2021-12-04T20:41:11.056669Z","shell.execute_reply":"2021-12-04T21:05:31.025676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:05:33.054855Z","iopub.execute_input":"2021-12-04T21:05:33.055327Z","iopub.status.idle":"2021-12-04T21:05:33.188616Z","shell.execute_reply.started":"2021-12-04T21:05:33.055291Z","shell.execute_reply":"2021-12-04T21:05:33.187792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Testing Data","metadata":{}},{"cell_type":"code","source":"test_filenames = os.listdir(\"./test1\")\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:08:16.444217Z","iopub.execute_input":"2021-12-04T21:08:16.444622Z","iopub.status.idle":"2021-12-04T21:08:16.465489Z","shell.execute_reply.started":"2021-12-04T21:08:16.444572Z","shell.execute_reply":"2021-12-04T21:08:16.464729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing Generator","metadata":{}},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"./test1/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=IMAGE_SIZE,\n    batch_size=batch_size,\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:09:07.545416Z","iopub.execute_input":"2021-12-04T21:09:07.545697Z","iopub.status.idle":"2021-12-04T21:09:07.664449Z","shell.execute_reply.started":"2021-12-04T21:09:07.545665Z","shell.execute_reply":"2021-12-04T21:09:07.663576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict","metadata":{}},{"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/batch_size))","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:09:34.168380Z","iopub.execute_input":"2021-12-04T21:09:34.169106Z","iopub.status.idle":"2021-12-04T21:10:03.699797Z","shell.execute_reply.started":"2021-12-04T21:09:34.169067Z","shell.execute_reply":"2021-12-04T21:10:03.698964Z"},"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":{"execution":{"iopub.status.busy":"2021-12-04T21:10:16.974363Z","iopub.execute_input":"2021-12-04T21:10:16.974630Z","iopub.status.idle":"2021-12-04T21:10:16.982000Z","shell.execute_reply.started":"2021-12-04T21:10:16.974601Z","shell.execute_reply":"2021-12-04T21:10:16.981321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We will convert the predict category back into our generator classes by using train_generator.class_indices. It is the classes that image generator map","metadata":{}},{"cell_type":"code","source":"label_map = dict((v,k) for k,v in train_generator.class_indices.items())\ntest_df['category'] = test_df['category'].replace(label_map)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:10:59.971322Z","iopub.execute_input":"2021-12-04T21:10:59.971589Z","iopub.status.idle":"2021-12-04T21:10:59.979043Z","shell.execute_reply.started":"2021-12-04T21:10:59.971556Z","shell.execute_reply":"2021-12-04T21:10:59.978242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:11:14.860218Z","iopub.execute_input":"2021-12-04T21:11:14.860674Z","iopub.status.idle":"2021-12-04T21:11:14.874854Z","shell.execute_reply.started":"2021-12-04T21:11:14.860637Z","shell.execute_reply":"2021-12-04T21:11:14.874114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:11:23.419612Z","iopub.execute_input":"2021-12-04T21:11:23.420586Z","iopub.status.idle":"2021-12-04T21:11:23.594049Z","shell.execute_reply.started":"2021-12-04T21:11:23.420531Z","shell.execute_reply":"2021-12-04T21:11:23.593343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_test = test_df.head(18)\nsample_test.head()\nplt.figure(figsize=(12, 24))\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = load_img(\"./test1/\"+filename, target_size=IMAGE_SIZE)\n    plt.subplot(6, 3, index+1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + ')' )\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:12:36.187233Z","iopub.execute_input":"2021-12-04T21:12:36.187992Z","iopub.status.idle":"2021-12-04T21:12:39.157798Z","shell.execute_reply.started":"2021-12-04T21:12:36.187950Z","shell.execute_reply":"2021-12-04T21:12:39.157045Z"},"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['label'] = submission_df['category']\nsubmission_df.drop(['filename', 'category'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-12-04T21:13:41.008150Z","iopub.execute_input":"2021-12-04T21:13:41.008420Z","iopub.status.idle":"2021-12-04T21:13:41.060739Z","shell.execute_reply.started":"2021-12-04T21:13:41.008390Z","shell.execute_reply":"2021-12-04T21:13:41.060000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}