{"cells":[{"metadata":{},"cell_type":"markdown","source":"Python notebook using data from https://www.kaggle.com/c/dogs-vs-cats/data"},{"metadata":{},"cell_type":"markdown","source":"This Kernel for someone want to deep dive into image classification. I use CNN for classification model. "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Import The Libraries\n\nimport numpy as np\nimport pandas as pd \nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!unzip /kaggle/input/dogs-vs-cats/train.zip -d train\n!unzip /kaggle/input/dogs-vs-cats/test1.zip -d test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Prepare Traning Data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames = os.listdir('train/train')\ncategories = []\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})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.category.value_counts().plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# See Sample\nsample = random.choice(filenames)\nimage = load_img('train/train/'+sample)\nplt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build The CNN "},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\n\ncnn = Sequential()\n\ncnn.add(Conv2D(32, (3, 3), activation = 'relu', input_shape = (128, 128, 3)))\ncnn.add(BatchNormalization())\ncnn.add(MaxPooling2D(pool_size= (2, 2)))\ncnn.add(Dropout(0.25))\n\ncnn.add(Conv2D(64, (3, 3), activation = 'relu'))\ncnn.add(BatchNormalization())\ncnn.add(MaxPooling2D(pool_size= (2, 2)))\ncnn.add(Dropout(0.25))\n\ncnn.add(Conv2D(128, (3, 3), activation = 'relu'))\ncnn.add(BatchNormalization())\ncnn.add(MaxPooling2D(pool_size= (2, 2)))\ncnn.add(Dropout(0.25))\n\ncnn.add(Flatten())\ncnn.add(Dense(512, activation = 'relu'))\ncnn.add(BatchNormalization())\ncnn.add(Dropout(0.5))\ncnn.add(Dense(2, activation = 'softmax'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cnn.compile(optimizer = 'rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cnn.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Callbacks "},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ReduceLROnPlateau","execution_count":null,"outputs":[]},{"metadata":{},"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":{"trusted":true},"cell_type":"code","source":"earlystop = EarlyStopping(patience=10)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Learning Rate Reduction\n\nWe will reduce the learning rate when the accuracy not increase for 2 steps "},{"metadata":{"trusted":true},"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)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"callbacks = [earlystop, learning_rate_reduction]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Prepare Data\nBecause 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":{"trusted":true},"cell_type":"code","source":"df.category = df.category.replace({0 : 'cat', 1 : 'dog'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, test_df = train_test_split(df, test_size = 0.20, random_state= 42)\ntrain_df = train_df.reset_index(drop = True)\ntest_df = test_df.reset_index(drop = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.category.value_counts().plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.category.value_counts().plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_test = test_df.shape[0]\nbatch_size=15","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Traning Generator "},{"metadata":{"trusted":true},"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    \"dataset/train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=(128, 128),\n    class_mode='categorical',\n    batch_size=batch_size\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Testing Generator "},{"metadata":{"trusted":true},"cell_type":"code","source":"test_datagen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_datagen.flow_from_dataframe(\n    test_df, \n    \"dataset/train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=(128, 128),\n    class_mode='categorical',\n    batch_size=batch_size\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## See how our generator work"},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_df = train_df.sample(n= 1).reset_index(drop = True)\nsample_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    \"train/train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=(128, 128),\n    class_mode='categorical',\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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 sample_generator:\n        image = X_batch[0]\n        plt.imshow(image)\n        break\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Fit Model"},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"FAST_RUN = False\nepochs=3 if FAST_RUN else 11\nhistory = cnn.fit_generator(\n    train_generator, \n    epochs=epochs,\n    validation_data=test_generator,\n    validation_steps=total_test//batch_size,\n    steps_per_epoch=total_train//batch_size,\n    callbacks=callbacks\n    \n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install PyYAML","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_yaml = cnn.to_yaml()\nwith open(\"model.yaml\", \"w\") as yaml_file:\n    yaml_file.write(model_yaml)\n# serialize weights to HDF5\ncnn.save_weights(\"model.h5\")\nprint(\"Saved model to disk\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare Testing Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_filenames = os.listdir(\"dataset/test/\")\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create Testing Generator "},{"metadata":{"trusted":true},"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"dataset/test/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=(128, 128),\n    batch_size=batch_size,\n    shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Predict "},{"metadata":{"trusted":true},"cell_type":"code","source":"predict = cnn.predict_generator(test_generator, steps=np.ceil(nb_samples/batch_size))","execution_count":null,"outputs":[]},{"metadata":{},"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":{"trusted":true},"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis=-1)","execution_count":null,"outputs":[]},{"metadata":{},"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 while converting data into computer vision "},{"metadata":{"trusted":true},"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)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## See predicted result with images "},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_test = test_df.head(36)\nsample_test.head()\nplt.figure(figsize=(12, 20))\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = load_img(\"dataset/test/\"+filename, target_size=(128, 128))\n    plt.subplot(9, 4, index+1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + ')' )\nplt.tight_layout()\n\nplt.show()","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}