{"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":"**Things I did differently**\n\n**in 1 sentence : Fine Tuning while keeping layers trainable**\n\n* Plus some aggressive data augmentation using Imaug Library, increasing the number of training images by 30 %\n* I Used Resnet50, you may use any other, but remember it is by keeping layers trainable, as the dataset is huge it will do a great job\n* CutMix Augmentation Technique : This can be implemented with imaug library, difficult with Image Generator","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\n# 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\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ReduceLROnPlateau, EarlyStopping\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Dense, Flatten\nfrom tensorflow.keras.models import Model\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport imgaug.augmenters as iaa\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":{"execution":{"iopub.status.busy":"2023-04-07T12:31:19.635819Z","iopub.execute_input":"2023-04-07T12:31:19.636209Z","iopub.status.idle":"2023-04-07T12:31:19.655157Z","shell.execute_reply.started":"2023-04-07T12:31:19.636176Z","shell.execute_reply":"2023-04-07T12:31:19.653991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip /kaggle/input/dogs-vs-cats/test1.zip","metadata":{"execution":{"iopub.status.busy":"2023-04-07T12:31:19.657687Z","iopub.execute_input":"2023-04-07T12:31:19.658705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip /kaggle/input/dogs-vs-cats/train.zip ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\ncd train\nls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\nmkdir train/0\nmkdir train/1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\nmv /kaggle/working/train/cat* /kaggle/working/train/0 && mv /kaggle/working/train/dog* /kaggle/working/train/1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\ncd train \nls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !ls train/0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !ls tester/0\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash \nmkdir tester\nmkdir -p tester/0 tester/1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\n# move 10% of \"cat\" images to tester/0\nmv $(ls /kaggle/working/train/0/cat* | shuf -n $(($(ls /kaggle/working/train/0/cat* | wc -l)*10/100))) /kaggle/working/tester/0/\n\n# move 10% of \"dog\" images to tester/1\nmv $(ls /kaggle/working/train/1/dog* | shuf -n $(($(ls /kaggle/working/train/1/dog* | wc -l)*10/100))) /kaggle/working/tester/1/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls /kaggle/working/train/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import cv2\n# seq = iaa.Sequential([\n#     iaa.Sometimes(0.5, iaa.GaussianBlur(sigma=(0, 0.5))),\n#     iaa.ContrastNormalization((0.75, 1.5)),\n#     iaa.Multiply((0.8, 1.2)),\n#     iaa.Affine(rotate=(-10, 10)),\n#     iaa.Flipud(0.5),\n#     iaa.Cutout(nb_iterations=1, size=0.2, squared=False),\n#     iaa.MultiplyElementwise((0.5, 1.5)),\n#     iaa.CoarseDropout((0.03, 0.15), size_percent=(0.02, 0.05), per_channel=0.5),\n# #     iaa.Sometimes(0.5, iaa.Mixup(0.5)),\n#     iaa.Sometimes(0.5, iaa.Cutout(nb_iterations=1, size=0.2, squared=False))\n# ])\n\n# # Define the folder containing the images\n# folder_path = \"/kaggle/working/train/0\"\n\n# # Loop through each image in the folder and apply the augmentations\n# for filename in os.listdir(folder_path):\n#     if filename.endswith('.jpg') or filename.endswith('.png'):\n#         image = cv2.imread(os.path.join(folder_path, filename))\n#         images_aug = [seq(image=image) for _ in range(30)] # apply 30 augmentations to each image\n#         for i, img in enumerate(images_aug):\n#             new_filename = f\"{os.path.splitext(filename)[0]}_{i}.jpg\"\n#             cv2.imwrite(os.path.join(folder_path, new_filename), img)\n            \n            \n            \n# folder_path = \"/kaggle/working/train/1\"\n\n# # Loop through each image in the folder and apply the augmentations\n# for filename in os.listdir(folder_path):\n#     if filename.endswith('.jpg') or filename.endswith('.png'):\n#         image = cv2.imread(os.path.join(folder_path, filename))\n#         images_aug = [seq(image=image) for _ in range(30)] # apply 30 augmentations to each image\n#         for i, img in enumerate(images_aug):\n#             new_filename = f\"{os.path.splitext(filename)[0]}_{i}.jpg\"\n#             cv2.imwrite(os.path.join(folder_path, new_filename), img)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !ls /kaggle/working/train/0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Increase images by 30 %\nimport os\nimport cv2\nimport imgaug.augmenters as iaa\nimport numpy as np\n\n# def mixup(images, labels, alpha=1.0):\n#     # Shuffle the images and labels\n#     indices = np.arange(len(images))\n#     np.random.shuffle(indices)\n#     shuffled_images = images[indices]\n#     shuffled_labels = labels[indices]\n\n#     # Compute the mixup coefficients\n#     lam = np.random.beta(alpha, alpha, len(images))\n\n#     # Mix the images and labels\n#     mixed_images = lam.reshape(-1, 1, 1, 1) * images + (1 - lam).reshape(-1, 1, 1, 1) * shuffled_images\n#     mixed_labels = lam.reshape(-1, 1) * labels + (1 - lam).reshape(-1, 1) * shuffled_labels\n\n#     return mixed_images, mixed_labels\n\n\n# Define the augmentations to be applied\nseq = iaa.Sequential([\n    iaa.Sometimes(0.5, iaa.GaussianBlur(sigma=(0, 0.5))),\n    iaa.ContrastNormalization((0.75, 1.5)),\n    iaa.Multiply((0.8, 1.2)),\n    iaa.Affine(rotate=(-10, 10)),\n    iaa.Flipud(0.5),\n    iaa.Cutout(nb_iterations=1, size=0.2, squared=False),\n    iaa.MultiplyElementwise((0.5, 1.5)),\n    iaa.CoarseDropout((0.03, 0.15), size_percent=(0.02, 0.05), per_channel=0.5),\n#     iaa.Sometimes(0.5, iaa.Mixup(0.5)),\n    iaa.Sometimes(0.5, iaa.Cutout(nb_iterations=1, size=0.2, squared=False))\n])\n\n# Define the folder containing the images\nfolder_path = \"/kaggle/working/train/0\"\n\nimage_filenames = [filename for filename in os.listdir(folder_path) if filename.endswith('.jpg') or filename.endswith('.png')]\n\n# Calculate the number of images to augment\nnum_images_to_augment = int(len(image_filenames) * 0.3)\n\n# Randomly select the images to augment\nimages_to_augment = np.random.choice(image_filenames, size=num_images_to_augment, replace=False)\n\n# Loop through the selected images and apply the augmentations\nfor filename in images_to_augment:\n    image = cv2.imread(os.path.join(folder_path, filename))\n    images_aug = [seq(image=image) for _ in range(3)] # apply augmentations to generate 3 additional images\n    for i, img in enumerate(images_aug):\n        new_filename = f\"{os.path.splitext(filename)[0]}_{i}.jpg\"\n        cv2.imwrite(os.path.join(folder_path, new_filename), img)\n\n            \n\nfolder_path = \"/kaggle/working/train/1\"\n\nimage_filenames = [filename for filename in os.listdir(folder_path) if filename.endswith('.jpg') or filename.endswith('.png')]\n\n# Calculate the number of images to augment\nnum_images_to_augment = int(len(image_filenames) * 0.3)\n\n# Randomly select the images to augment\nimages_to_augment = np.random.choice(image_filenames, size=num_images_to_augment, replace=False)\n\n# Loop through the selected images and apply the augmentations\nfor filename in images_to_augment:\n    image = cv2.imread(os.path.join(folder_path, filename))\n    images_aug = [seq(image=image) for _ in range(3)] # apply augmentations to generate 3 additional images\n    for i, img in enumerate(images_aug):\n        new_filename = f\"{os.path.splitext(filename)[0]}_{i}.jpg\"\n        cv2.imwrite(os.path.join(folder_path, new_filename), img)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_shape=(80, 80, 3) ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define data augmentation parameters\ndatagen = ImageDataGenerator(\n    rotation_range=20, # randomly rotate images by up to 20 degrees\n    width_shift_range=0.1, # randomly shift images horizontally by up to 10%\n    height_shift_range=0.1, # randomly shift images vertically by up to 10%\n    shear_range=0.2, # apply random shear transformations\n    zoom_range=0.2, # randomly zoom into images by up to 20%\n    horizontal_flip=True, # randomly flip images horizontally\n    fill_mode='nearest', # fill any empty pixels with the nearest value\n    rescale=1./255,\n    validation_split=0.2\n)\n\n# define the image data generator\ntrain_generator = datagen.flow_from_directory(\n    '/kaggle/working/train/', # path to training directory\n    target_size=(input_shape[0], input_shape[1]), # resize images to (224, 224)\n    batch_size=32, # number of images in each batch\n    class_mode='binary',\n    subset='training'\n)\n\nval_generator = datagen.flow_from_directory(\n    '/kaggle/working/train/', # path to training directory\n    target_size=(input_shape[0], input_shape[1]), # resize images to (224, 224)\n    batch_size=32, # number of images in each batch\n    class_mode='binary',\n    subset='validation'\n)\n\n\n# define data augmentation parameters\ntest_datagen = ImageDataGenerator(\n   rescale=1./255\n)\n\ntest1_generator = test_datagen.flow_from_directory(\n    '/kaggle/working/tester/', # path to training directory\n    target_size=(input_shape[0], input_shape[1]), # resize images to (224, 224)\n    batch_size=32, # number of images in each batch\n    class_mode='binary' # type of classification problem (binary, categorical, etc.)\n)\n\n# test2_generator = test_datagen.flow_from_directory(\n#     '/kaggle/working/test1/', # path to training directory\n#     target_size=(224, 224), # resize images to (224, 224)\n#     batch_size=32, # number of images in each batch\n#     class_mode='binary' # type of classification problem (binary, categorical, etc.)\n# )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"jupyter":{"source_hidden":true}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lrs = []\ndef lrfn(epoch):\n    LR_START = 0.00001\n    LR_MAX = 0.00005\n    LR_MIN = 0.00001\n    LR_RAMPUP_EPOCHS = 5\n    LR_SUSTAIN_EPOCHS = 0\n    LR_EXP_DECAY = .8\n    \n    if epoch < LR_RAMPUP_EPOCHS:\n        lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START\n    elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:\n        lr = LR_MAX\n    else:\n        lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY**(epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS) + LR_MIN\n\n    lrs.append(lr)\n    return lr\n\nlr_schedule = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=1)\ncallback = [lr_schedule]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Load the ResNet50 model\nresnet50 = tf.keras.applications.ResNet50(\n    include_top=False, # do not include the fully connected layer at the top of the network\n    weights='imagenet', # load the pre-trained weights on ImageNet dataset\n    input_shape=input_shape # set the input shape of the model\n)\n\n# Freeze the weights of the pre-trained layers\nfor layer in resnet50.layers:\n    layer.trainable = True\n\n# Add a custom output layer to the ResNet50 model\nx = resnet50.output\nx = tf.keras.layers.GlobalAveragePooling2D()(x)\nx = Flatten()(x)\nx = tf.keras.layers.Dropout(0.5)(x)\nx = Dense(128, activation='relu')(x)\nx = Dense(1, activation='sigmoid')(x)\n\n# Define the new model with ResNet50 as base and the custom output layer\nmodel = Model(inputs=resnet50.input, outputs=x)\n\n# Compile the model with binary cross-entropy loss and Adam optimizer\nmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(tf.test.gpu_device_name())\ndevice = tf.test.gpu_device_name()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the model on your training data using the fit function\nwith tf.device(device):\n    history = model.fit(train_generator,validation_data=val_generator,\n    callbacks=callback, epochs=80) ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(np.array(lrs))\nplt.show() ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(test1_generator)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot the accuracy curves\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('Model accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# plot the loss curves\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import os\n# import pandas as pd\n# from tensorflow.keras.preprocessing import image\n\n# # set the path to the directory containing the test images\n# test_path = '/kaggle/working/test1/'\n\n# # create a list to store the predictions\n# predictions = []\n\n# # loop through each image file in the directory\n# for filename in os.listdir(test_path):\n#     # load the image and resize it to the same size as the training images\n#     img = image.load_img(os.path.join(test_path, filename), target_size=(80, 80))\n#     # convert the image to a numpy array\n#     x = image.img_to_array(img)\n#     # scale the pixel values to be between 0 and 1\n#     x = x / 255.0\n#     # add a batch dimension to the array\n#     x = np.expand_dims(x, axis=0)\n#     # make a prediction on the image\n#     pred = model.predict(x,verbose=False)\n#     # append the prediction to the list of predictions\n#     predictions.append(int(np.round(pred)))\n\n# # create a dataframe with the image filenames and predictions\n# df = pd.DataFrame({'id': os.listdir(test_path), 'label': predictions})\n# # save the dataframe as a csv file\n# df.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Tasks\n\n* create submision file in the easist way possible ","metadata":{}},{"cell_type":"code","source":"test_filenames = os.listdir(\"/kaggle/working/test1\")\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"/kaggle/working/test1/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=(80,80),\n    batch_size=32,\n    shuffle=False\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/32))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis=-1)","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())\ntest_df['category'] = test_df['category'].replace(label_map)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}