{"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 os\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nimport tensorflow.keras as keras\nfrom tensorflow.keras.models import Model, Sequential\nfrom tensorflow.keras.layers import *\nfrom keras.initializers import glorot_uniform\nfrom tensorflow.keras.utils import image_dataset_from_directory","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-26T04:33:31.991865Z","iopub.execute_input":"2022-07-26T04:33:31.992765Z","iopub.status.idle":"2022-07-26T04:33:42.193294Z","shell.execute_reply.started":"2022-07-26T04:33:31.992679Z","shell.execute_reply":"2022-07-26T04:33:42.192547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"execution":{"iopub.status.busy":"2022-07-21T06:11:39.787499Z","iopub.status.idle":"2022-07-21T06:11:39.787921Z","shell.execute_reply.started":"2022-07-21T06:11:39.787710Z","shell.execute_reply":"2022-07-21T06:11:39.787729Z"}}},{"cell_type":"markdown","source":"## Steps needs to be performed\n\n1. Perform EDA on actual images and train.csv (Using this file which can used for inserting meta information while training)\n2. Do data augmentation to increase size of training records\n3. Create custom CNN model\n4. Perform transfer learning using VGG16 and ResNet52\n5. Perform transfer learning using EfficientNet\n6. Perform transfer learning using VisionTransformer","metadata":{}},{"cell_type":"code","source":"global_path = \"/kaggle/input/paddy-disease-classification/\"\ntrain_path = os.path.join(global_path, \"train_images\")\ntest_path = os.path.join(global_path, \"test_images\")\n\nprint(f\"Global path is {global_path}\")\nprint(f\"Train images path is {train_path}\")\nprint(f\"Test images path is {test_path}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:33:42.194806Z","iopub.execute_input":"2022-07-26T04:33:42.195541Z","iopub.status.idle":"2022-07-26T04:33:42.203736Z","shell.execute_reply.started":"2022-07-26T04:33:42.195511Z","shell.execute_reply":"2022-07-26T04:33:42.202114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 1. Perform EDA on actual images","metadata":{}},{"cell_type":"code","source":"# Generate dataframe from train_images folder\ndf_trn = pd.DataFrame()\n\nfor folder in os.listdir(train_path):\n    for img in os.listdir(os.path.join(train_path, folder)):\n        df_trn = df_trn.append({\"image_id\": img, \"category\": folder, \"image_path\": os.path.join(train_path, folder, img)}, ignore_index=True)\n\ndf_trn.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:33:42.204836Z","iopub.execute_input":"2022-07-26T04:33:42.205302Z","iopub.status.idle":"2022-07-26T04:34:00.691424Z","shell.execute_reply.started":"2022-07-26T04:33:42.205276Z","shell.execute_reply":"2022-07-26T04:34:00.690215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Total number of images from actual train folder are {len(df_trn)}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:00.693814Z","iopub.execute_input":"2022-07-26T04:34:00.694697Z","iopub.status.idle":"2022-07-26T04:34:00.698429Z","shell.execute_reply.started":"2022-07-26T04:34:00.694672Z","shell.execute_reply":"2022-07-26T04:34:00.697835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read train.csv file\ndf_trn_csv = pd.read_csv(os.path.join(global_path, \"train.csv\"))\ndf_trn_csv.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:00.699210Z","iopub.execute_input":"2022-07-26T04:34:00.699513Z","iopub.status.idle":"2022-07-26T04:34:00.732706Z","shell.execute_reply.started":"2022-07-26T04:34:00.699479Z","shell.execute_reply":"2022-07-26T04:34:00.731571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Total number of images from csv file are {len(df_trn_csv)}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:00.733926Z","iopub.execute_input":"2022-07-26T04:34:00.734150Z","iopub.status.idle":"2022-07-26T04:34:00.740097Z","shell.execute_reply.started":"2022-07-26T04:34:00.734129Z","shell.execute_reply":"2022-07-26T04:34:00.738932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let join both dataframe and see can we use extra metadata available in the model\ndf_trn_joined = df_trn.set_index(\"image_id\").join(df_trn_csv.set_index(\"image_id\"), on=\"image_id\", how=\"inner\") # we have to pass set_index to both dataframe as these are columns which we need to join\ndf_trn_joined.reset_index(inplace=True)\ndf_trn_joined.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:00.741631Z","iopub.execute_input":"2022-07-26T04:34:00.741966Z","iopub.status.idle":"2022-07-26T04:34:00.783216Z","shell.execute_reply.started":"2022-07-26T04:34:00.741929Z","shell.execute_reply":"2022-07-26T04:34:00.781991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display number of images per category\ndf_trn_joined[\"category\"].value_counts().plot(kind=\"bar\", figsize=(50, 10), fontsize=15)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:00.784475Z","iopub.execute_input":"2022-07-26T04:34:00.784783Z","iopub.status.idle":"2022-07-26T04:34:01.141427Z","shell.execute_reply.started":"2022-07-26T04:34:00.784756Z","shell.execute_reply":"2022-07-26T04:34:01.140509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display percentage of images per category\n(df_trn_joined[\"category\"].value_counts(normalize=True) * 100).plot(kind='bar', figsize=(50, 10), fontsize=15)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:01.142456Z","iopub.execute_input":"2022-07-26T04:34:01.142727Z","iopub.status.idle":"2022-07-26T04:34:01.452401Z","shell.execute_reply.started":"2022-07-26T04:34:01.142700Z","shell.execute_reply":"2022-07-26T04:34:01.451362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**In categories like bacterial_panicle_blight, bacterial_leaf_streak, bacterial_leaf_blight downy_mildew percentage is low compare to other category. We might have to use techniques like oversampling to improve those categories images quantity**","metadata":{}},{"cell_type":"code","source":"# Read image using opencv then convert into RGB format for display purpose\ndef read_img(img):\n    return cv2.cvtColor(cv2.imread(img, cv2.IMREAD_COLOR), cv2.COLOR_BGR2RGB)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:01.455390Z","iopub.execute_input":"2022-07-26T04:34:01.456070Z","iopub.status.idle":"2022-07-26T04:34:01.461143Z","shell.execute_reply.started":"2022-07-26T04:34:01.456046Z","shell.execute_reply":"2022-07-26T04:34:01.459881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display images of each category to get idea of the difference in between them\nfig, axs = plt.subplots(10, 5, figsize=(25, 80)) # figsize=(width, height)\n\nfor cat_idx, category in enumerate(df_trn_joined[\"category\"].unique()):\n    for img_idx, (img, cat) in enumerate(df_trn_joined[[\"image_path\", \"category\"]][df_trn_joined[\"category\"]==category].sample(n=5).values):\n        axs[cat_idx, img_idx].set_title(cat)\n        axs[cat_idx, img_idx].imshow(read_img(img))","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:01.464671Z","iopub.execute_input":"2022-07-26T04:34:01.464995Z","iopub.status.idle":"2022-07-26T04:34:12.010878Z","shell.execute_reply.started":"2022-07-26T04:34:01.464967Z","shell.execute_reply":"2022-07-26T04:34:12.008347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Do data augmentation to increase size of training records (SKIPPED TEMPORARY ONLY DATA LOADING USING image_dataset_from_directory)","metadata":{}},{"cell_type":"code","source":"image_width = 224\nimage_height = 224\nimage_channel = 3\nbatch_size = 128","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:12.012147Z","iopub.execute_input":"2022-07-26T04:34:12.012501Z","iopub.status.idle":"2022-07-26T04:34:12.023258Z","shell.execute_reply.started":"2022-07-26T04:34:12.012471Z","shell.execute_reply":"2022-07-26T04:34:12.017742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trn_ds = tf.keras.utils.image_dataset_from_directory(train_path, validation_split=0.2, subset=\"training\", seed=0, \n                                                       image_size=(image_width, image_height), batch_size=batch_size)\n\nval_ds = tf.keras.utils.image_dataset_from_directory(train_path, validation_split=0.2, subset=\"validation\", seed=0, \n                                                     image_size=(image_width, image_height), batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:12.025278Z","iopub.execute_input":"2022-07-26T04:34:12.025636Z","iopub.status.idle":"2022-07-26T04:34:15.220283Z","shell.execute_reply.started":"2022-07-26T04:34:12.025606Z","shell.execute_reply":"2022-07-26T04:34:15.218586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = tf.keras.utils.image_dataset_from_directory(test_path, image_size=(image_width, image_height), batch_size=batch_size, labels=None, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:15.221971Z","iopub.execute_input":"2022-07-26T04:34:15.222496Z","iopub.status.idle":"2022-07-26T04:34:16.625457Z","shell.execute_reply.started":"2022-07-26T04:34:15.222464Z","shell.execute_reply":"2022-07-26T04:34:16.624374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Classes involve in this training data :\\n{trn_ds.class_names}\\n\\n\")\nprint(f\"Classes involve in this validation data :\\n{val_ds.class_names}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:16.627215Z","iopub.execute_input":"2022-07-26T04:34:16.627803Z","iopub.status.idle":"2022-07-26T04:34:16.633053Z","shell.execute_reply.started":"2022-07-26T04:34:16.627770Z","shell.execute_reply":"2022-07-26T04:34:16.632166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Demo purpose to showcase how batch looks and once images passed through it\nfor image_batch, labels_batch in trn_ds:\n    print(f\"Single batch image shape : {image_batch.shape}\")\n    print(f\"Single batch label shape : {labels_batch.shape}\")\n    break","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:16.634523Z","iopub.execute_input":"2022-07-26T04:34:16.635131Z","iopub.status.idle":"2022-07-26T04:34:21.781377Z","shell.execute_reply.started":"2022-07-26T04:34:16.635097Z","shell.execute_reply":"2022-07-26T04:34:21.780170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Create custom CNN model","metadata":{}},{"cell_type":"code","source":"verbose = 1\nepochs = 5\nnumber_classes = len(trn_ds.class_names)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:21.782761Z","iopub.execute_input":"2022-07-26T04:34:21.783744Z","iopub.status.idle":"2022-07-26T04:34:21.788765Z","shell.execute_reply.started":"2022-07-26T04:34:21.783710Z","shell.execute_reply":"2022-07-26T04:34:21.787332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = keras.models.Sequential()\nmodel.add(keras.layers.Rescaling(1./255, input_shape=(image_width, image_height, image_channel)))\nmodel.add(keras.layers.Conv2D(3, 3, padding=\"same\", activation='relu'))\nmodel.add(keras.layers.MaxPooling2D(2, 2))\nmodel.add(keras.layers.Conv2D(3, 3, padding=\"same\", activation='relu'))\nmodel.add(keras.layers.MaxPooling2D(2, 2))\nmodel.add(keras.layers.Conv2D(3, 3, padding=\"same\", activation='relu'))\nmodel.add(keras.layers.MaxPooling2D(2, 2))\nmodel.add(keras.layers.Conv2D(3, 3, padding=\"same\", activation='relu'))\nmodel.add(keras.layers.MaxPooling2D(2, 2))\n\nmodel.add(keras.layers.Flatten())\nmodel.add(keras.layers.Dense(100, activation=\"relu\"))\nmodel.add(keras.layers.Dropout(0.5))\nmodel.add(keras.layers.Dense(number_classes))\n\nmodel.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True), \n              optimizer=keras.optimizers.Adam(learning_rate=0.00001), metrics=[\"accuracy\"])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:21.790193Z","iopub.execute_input":"2022-07-26T04:34:21.790504Z","iopub.status.idle":"2022-07-26T04:34:21.949482Z","shell.execute_reply.started":"2022-07-26T04:34:21.790476Z","shell.execute_reply":"2022-07-26T04:34:21.948199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"history = model.fit(trn_ds, validation_data=val_ds, epochs=epochs, verbose=verbose)","metadata":{}},{"cell_type":"raw","source":"# Accuracy over the period of each epoch\nacc = history.history[\"accuracy\"]\nval_acc = history.history[\"val_accuracy\"]\n\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\n\nepochs_range = range(epochs)\n\nplt.figure(figsize=(25, 5))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label=\"Training Accuracy\")\nplt.plot(epochs_range, val_acc, label=\"Validation Accuracy\")\nplt.legend(loc=\"lower right\")\nplt.title(\"Training and Validation Accuracy\")\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label=\"Training Loss\")\nplt.plot(epochs_range, val_loss, label=\"Validation Loss\")\nplt.legend(loc=\"upper right\")\nplt.title(\"Training and Validation Loss\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:21.950945Z","iopub.execute_input":"2022-07-26T04:34:21.951273Z","iopub.status.idle":"2022-07-26T04:34:22.237225Z","shell.execute_reply.started":"2022-07-26T04:34:21.951243Z","shell.execute_reply":"2022-07-26T04:34:22.234738Z"}}},{"cell_type":"raw","source":"df_pred = pd.DataFrame([[pred_image.split(\"/\")[-1], trn_ds.class_names[pred_label]] for pred_image, pred_label in \n               zip(test_ds.file_paths, np.argmax(model.predict(test_ds), axis=1))], columns=[\"image_id\", \"label\"])\n\ndf_pred.head()","metadata":{}},{"cell_type":"raw","source":"df_pred.to_csv(\"custom_cnn_submissions.csv\", index=False)","metadata":{}},{"cell_type":"markdown","source":"## 4. Perform transfer learning using VGG16 and ResNet52","metadata":{}},{"cell_type":"markdown","source":"### 4a. VGG16 Model","metadata":{}},{"cell_type":"code","source":"!wget https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels.h5","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:35:44.175421Z","iopub.execute_input":"2022-07-26T04:35:44.175788Z","iopub.status.idle":"2022-07-26T04:36:21.842066Z","shell.execute_reply.started":"2022-07-26T04:35:44.175760Z","shell.execute_reply":"2022-07-26T04:36:21.841006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"verbose = 1\nnumber_classes = len(trn_ds.class_names)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:21.843847Z","iopub.execute_input":"2022-07-26T04:36:21.844104Z","iopub.status.idle":"2022-07-26T04:36:21.850131Z","shell.execute_reply.started":"2022-07-26T04:36:21.844081Z","shell.execute_reply":"2022-07-26T04:36:21.849030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vgg_mean = np.array([123.68, 116.779, 103.939], dtype=np.float32).reshape((1,1,3))\ndef vgg_preprocess(x):\n    \"\"\"\n        Subtracts the mean RGB value, and transposes RGB to BGR.\n        The mean RGB was computed on the image set used to train the VGG model.\n        Args: \n            x: Image array (height x width x channels)\n        Returns:\n            Image array (height x width x transposed_channels)\n    \"\"\"\n    x = x - vgg_mean\n    return x[:, ::-1] # reverse axis rgb->bgr","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:21.852149Z","iopub.execute_input":"2022-07-26T04:36:21.852474Z","iopub.status.idle":"2022-07-26T04:36:21.862958Z","shell.execute_reply.started":"2022-07-26T04:36:21.852436Z","shell.execute_reply":"2022-07-26T04:36:21.861515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# VGG16 model architecture with pretrained imagenet 1000 categories\nvgg16_model = keras.models.Sequential()\nvgg16_model.add(keras.layers.Lambda(vgg_preprocess, input_shape=(224, 224, 3), output_shape=(224, 224, 3)))\nvgg16_model.add(keras.layers.Conv2D(64, (3, 3), activation=\"relu\", padding=\"same\", name=\"block1_conv1\"))\nvgg16_model.add(keras.layers.Conv2D(64, (3, 3), activation=\"relu\", padding=\"same\", name=\"block1_conv2\"))\nvgg16_model.add(keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name=\"block1_pool\"))\n\nvgg16_model.add(keras.layers.Conv2D(128, (3, 3), activation=\"relu\", padding=\"same\", name=\"block2_conv1\"))\nvgg16_model.add(keras.layers.Conv2D(128, (3, 3), activation=\"relu\", padding=\"same\", name=\"block2_conv2\"))\nvgg16_model.add(keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name=\"block2_pool\"))\n\nvgg16_model.add(keras.layers.Conv2D(256, (3, 3), activation=\"relu\", padding=\"same\", name=\"block3_conv1\"))\nvgg16_model.add(keras.layers.Conv2D(256, (3, 3), activation=\"relu\", padding=\"same\", name=\"block3_conv2\"))\nvgg16_model.add(keras.layers.Conv2D(256, (3, 3), activation=\"relu\", padding=\"same\", name=\"block3_conv3\"))\nvgg16_model.add(keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name=\"block3_pool\"))\n\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block4_conv1\"))\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block4_conv2\"))\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block4_conv3\"))\nvgg16_model.add(keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name=\"block4_pool\"))\n\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block5_conv1\"))\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block5_conv2\"))\nvgg16_model.add(keras.layers.Conv2D(512, (3, 3), activation=\"relu\", padding=\"same\", name=\"block5_conv3\"))\nvgg16_model.add(keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name=\"block5_pool\"))\n\nvgg16_model.add(keras.layers.Flatten(name=\"flatten\"))\nvgg16_model.add(keras.layers.Dense(4096, activation=\"relu\", name=\"fc1\"))\nvgg16_model.add(keras.layers.Dense(4096, activation=\"relu\", name=\"fc2\"))\n\nvgg16_model.add(keras.layers.Dense(1000, activation=\"softmax\", name=\"predictions\"))\nvgg16_model.load_weights(\"/kaggle/working/vgg16_weights_tf_dim_ordering_tf_kernels.h5\")\nvgg16_model.compile(loss=keras.losses.CategoricalCrossentropy(), optimizer=keras.optimizers.Adam(learning_rate=0.0001), metrics=[\"Accuracy\"])\nvgg16_model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:21.865859Z","iopub.execute_input":"2022-07-26T04:36:21.866292Z","iopub.status.idle":"2022-07-26T04:36:22.981570Z","shell.execute_reply.started":"2022-07-26T04:36:21.866255Z","shell.execute_reply":"2022-07-26T04:36:22.980187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**As we can see all the parameters of vgg network is trainable. Let's freeze all layers so when we perform transfer learning not all layers will be trained**","metadata":{}},{"cell_type":"code","source":"# Setting trainable parameter to false that will freeze all layers parameter\nfor layer in vgg16_model.layers:\n    layer.trainable = False\nvgg16_model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:22.982974Z","iopub.execute_input":"2022-07-26T04:36:22.983234Z","iopub.status.idle":"2022-07-26T04:36:22.991522Z","shell.execute_reply.started":"2022-07-26T04:36:22.983210Z","shell.execute_reply":"2022-07-26T04:36:22.990397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Now after freezing we have to remove last classification layer and add new classification layer with required classes**","metadata":{}},{"cell_type":"code","source":"vgg16_model.pop()\nvgg16_model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:22.993000Z","iopub.execute_input":"2022-07-26T04:36:22.993637Z","iopub.status.idle":"2022-07-26T04:36:23.008962Z","shell.execute_reply.started":"2022-07-26T04:36:22.993607Z","shell.execute_reply":"2022-07-26T04:36:23.007455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vgg16_model.add(keras.layers.Dense(10, activation=\"softmax\", name=\"predictions\"))\nvgg16_model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0001), loss=keras.losses.SparseCategoricalCrossentropy(), metrics=[\"Accuracy\"])\nvgg16_model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:23.010357Z","iopub.execute_input":"2022-07-26T04:36:23.011649Z","iopub.status.idle":"2022-07-26T04:36:23.035224Z","shell.execute_reply.started":"2022-07-26T04:36:23.011600Z","shell.execute_reply":"2022-07-26T04:36:23.033482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"epochs = 100\nvgg16_history = vgg16_model.fit(trn_ds, validation_data=val_ds, epochs=epochs, verbose=verbose)","metadata":{}},{"cell_type":"raw","source":"# Accuracy over the period of each epoch\nacc = vgg16_history.history[\"Accuracy\"]\nval_acc = vgg16_history.history[\"val_Accuracy\"]\n\nloss = vgg16_history.history[\"loss\"]\nval_loss = vgg16_history.history[\"val_loss\"]\n\nepochs_range = range(epochs)\n\nplt.figure(figsize=(25, 5))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label=\"Training Accuracy\")\nplt.plot(epochs_range, val_acc, label=\"Validation Accuracy\")\nplt.legend(loc=\"lower right\")\nplt.title(\"Training and Validation Accuracy\")\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label=\"Training Loss\")\nplt.plot(epochs_range, val_loss, label=\"Validation Loss\")\nplt.legend(loc=\"upper right\")\nplt.title(\"Training and Validation Loss\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:34:22.252519Z","iopub.status.idle":"2022-07-26T04:34:22.252983Z","shell.execute_reply.started":"2022-07-26T04:34:22.252738Z","shell.execute_reply":"2022-07-26T04:34:22.252760Z"}}},{"cell_type":"raw","source":"df_pred = pd.DataFrame([[pred_image.split(\"/\")[-1], trn_ds.class_names[pred_label]] for pred_image, pred_label in \n               zip(test_ds.file_paths, np.argmax(vgg16_model.predict(test_ds), axis=1))], columns=[\"image_id\", \"label\"])\n\ndf_pred.head()","metadata":{}},{"cell_type":"raw","source":"df_pred.to_csv(\"vgg16_submissions.csv\", index=False)","metadata":{}},{"cell_type":"markdown","source":"### 4b. ResNet50 Model","metadata":{}},{"cell_type":"code","source":"!wget https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:23.036460Z","iopub.execute_input":"2022-07-26T04:36:23.037597Z","iopub.status.idle":"2022-07-26T04:36:46.297620Z","shell.execute_reply.started":"2022-07-26T04:36:23.037567Z","shell.execute_reply":"2022-07-26T04:36:46.296094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def identity_block(X, f, filters, stage, block):\n    \"\"\"\n    Implementation of the identity block as defined in Figure 3\n    \n    Arguments:\n    X -- input tensor of shape (m, n_H_prev, n_W_prev, n_C_prev)\n    f -- integer, specifying the shape of the middle CONV's window for the main path\n    filters -- python list of integers, defining the number of filters in the CONV layers of the main path\n    stage -- integer, used to name the layers, depending on their position in the network\n    block -- string/character, used to name the layers, depending on their position in the network\n    \n    Returns:\n    X -- output of the identity block, tensor of shape (n_H, n_W, n_C)\n    \"\"\"\n    \n    # defining name basis\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n    \n    # Retrieve Filters\n    F1, F2, F3 = filters\n    \n    # Save the input value. You'll need this later to add back to the main path. \n    X_shortcut = X\n    \n    # First component of main path\n    X = Conv2D(filters = F1, kernel_size = (1, 1), strides = (1,1), padding = 'valid', name = conv_name_base + '2a', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2a')(X)\n    X = Activation('relu')(X)\n\n    \n    # Second component of main path (≈3 lines)\n    X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1,1), padding = 'same', name = conv_name_base + '2b', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2b')(X)\n    X = Activation('relu')(X)\n\n    # Third component of main path (≈2 lines)\n    X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1,1), padding = 'valid', name = conv_name_base + '2c', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2c')(X)\n\n    # Final step: Add shortcut value to main path, and pass it through a RELU activation (≈2 lines)\n    X = Add()([X, X_shortcut])\n    X = Activation('relu')(X)\n    \n    \n    return X","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:46.300202Z","iopub.execute_input":"2022-07-26T04:36:46.300591Z","iopub.status.idle":"2022-07-26T04:36:46.313306Z","shell.execute_reply.started":"2022-07-26T04:36:46.300564Z","shell.execute_reply":"2022-07-26T04:36:46.312389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convolutional_block(X, f, filters, stage, block, s = 2):\n    \"\"\"\n    Implementation of the convolutional block as defined in Figure 4\n    \n    Arguments:\n    X -- input tensor of shape (m, n_H_prev, n_W_prev, n_C_prev)\n    f -- integer, specifying the shape of the middle CONV's window for the main path\n    filters -- python list of integers, defining the number of filters in the CONV layers of the main path\n    stage -- integer, used to name the layers, depending on their position in the network\n    block -- string/character, used to name the layers, depending on their position in the network\n    s -- Integer, specifying the stride to be used\n    \n    Returns:\n    X -- output of the convolutional block, tensor of shape (n_H, n_W, n_C)\n    \"\"\"\n    \n    # defining name basis\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n    \n    # Retrieve Filters\n    F1, F2, F3 = filters\n    \n    # Save the input value\n    X_shortcut = X\n\n\n    ##### MAIN PATH #####\n    # First component of main path \n    X = Conv2D(F1, (1, 1), strides = (s,s), name = conv_name_base + '2a', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2a')(X)\n    X = Activation('relu')(X)\n\n    # Second component of main path (≈3 lines)\n    X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1,1), padding = 'same', name = conv_name_base + '2b', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2b')(X)\n    X = Activation('relu')(X)\n\n\n    # Third component of main path (≈2 lines)\n    X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1,1), padding = 'valid', name = conv_name_base + '2c', kernel_initializer = glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis = 3, name = bn_name_base + '2c')(X)\n\n\n    ##### SHORTCUT PATH #### (≈2 lines)\n    X_shortcut = Conv2D(filters = F3, kernel_size = (1, 1), strides = (s,s), padding = 'valid', name = conv_name_base + '1',\n                        kernel_initializer = glorot_uniform(seed=0))(X_shortcut)\n    X_shortcut = BatchNormalization(axis = 3, name = bn_name_base + '1')(X_shortcut)\n\n    # Final step: Add shortcut value to main path, and pass it through a RELU activation (≈2 lines)\n    X = Add()([X, X_shortcut])\n    X = Activation('relu')(X)\n    \n    \n    return X","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:46.316893Z","iopub.execute_input":"2022-07-26T04:36:46.317188Z","iopub.status.idle":"2022-07-26T04:36:46.333903Z","shell.execute_reply.started":"2022-07-26T04:36:46.317165Z","shell.execute_reply":"2022-07-26T04:36:46.332687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ResNet50(input_shape=(224, 224, 3), classes=1000):\n    \"\"\"\n    Implementation of the popular ResNet50 the following architecture:\n    CONV2D -> BATCHNORM -> RELU -> MAXPOOL -> CONVBLOCK -> IDBLOCK*2 -> CONVBLOCK -> IDBLOCK*3\n    -> CONVBLOCK -> IDBLOCK*5 -> CONVBLOCK -> IDBLOCK*2 -> AVGPOOL -> TOPLAYER\n\n    Arguments:\n    input_shape -- shape of the images of the dataset\n    classes -- integer, number of classes\n\n    Returns:\n    model -- a Model() instance in Keras\n    \"\"\"\n\n    # Define the input as a tensor with shape input_shape\n    X_input = Input(input_shape)\n\n    # Zero-Padding\n    X = ZeroPadding2D((3, 3))(X_input)\n\n    # Stage 1\n    X = Conv2D(64, (7, 7), strides=(2, 2), name='conv1', kernel_initializer=glorot_uniform(seed=0))(X)\n    X = BatchNormalization(axis=3, name='bn_conv1')(X)\n    X = Activation('relu')(X)\n    X = MaxPooling2D((3, 3), strides=(2, 2))(X)\n\n    # Stage 2\n    X = convolutional_block(X, f=3, filters=[64, 64, 256], stage=2, block='a', s=1)\n    X = identity_block(X, 3, [64, 64, 256], stage=2, block='b')\n    X = identity_block(X, 3, [64, 64, 256], stage=2, block='c')\n\n    ### START CODE HERE ###\n\n    # Stage 3 (≈4 lines)\n    X = convolutional_block(X, f = 3, filters = [128, 128, 512], stage = 3, block='a', s = 2)\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='b')\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='c')\n    X = identity_block(X, 3, [128, 128, 512], stage=3, block='d')\n\n    # Stage 4 (≈6 lines)\n    X = convolutional_block(X, f = 3, filters = [256, 256, 1024], stage = 4, block='a', s = 2)\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='b')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='c')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='d')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='e')\n    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='f')\n\n    # Stage 5 (≈3 lines)\n    X = convolutional_block(X, f = 3, filters = [512, 512, 2048], stage = 5, block='a', s = 2)\n    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='b')\n    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='c')\n\n    # AVGPOOL (≈1 line). Use \"X = AveragePooling2D(...)(X)\"\n    X = AveragePooling2D((2,2), name=\"avg_pool\")(X)\n\n    ### END CODE HERE ###\n\n    # output layer\n    X = Flatten()(X)\n    X = Dense(classes, activation='softmax', name='fc' + str(classes), kernel_initializer = glorot_uniform(seed=0))(X)\n    \n    \n    # Create model\n    model = Model(inputs = X_input, outputs = X, name='ResNet50')\n    model.load_weights(\"/kaggle/working/resnet50_weights_tf_dim_ordering_tf_kernels.h5\")\n    model.compile(loss=\"categorical_crossentrophy\", optimizer=keras.optimizers.Adam(learning_rate=0.0001), metrics=[\"Accuracy\"])\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:46.334966Z","iopub.execute_input":"2022-07-26T04:36:46.335242Z","iopub.status.idle":"2022-07-26T04:36:46.354185Z","shell.execute_reply.started":"2022-07-26T04:36:46.335218Z","shell.execute_reply":"2022-07-26T04:36:46.352815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"resnet50_model = ResNet50()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:36:46.355745Z","iopub.execute_input":"2022-07-26T04:36:46.356224Z","iopub.status.idle":"2022-07-26T04:36:47.970617Z","shell.execute_reply.started":"2022-07-26T04:36:46.356168Z","shell.execute_reply":"2022-07-26T04:36:47.968910Z"}}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def identity_block(input_tensor, kernel_size, filters, stage, block):\n    '''The identity_block is the block that has no conv layer at shortcut\n    # Arguments\n        input_tensor: input tensor\n        kernel_size: defualt 3, the kernel size of middle conv layer at main path\n        filters: list of integers, the nb_filters of 3 conv layer at main path\n        stage: integer, current stage label, used for generating layer names\n        block: 'a','b'..., current block label, used for generating layer names\n    '''\n    nb_filter1, nb_filter2, nb_filter3 = filters\n    bn_axis = 3\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n\n    x = Convolution2D(nb_filter1, (1, 1), name=conv_name_base + '2a')(input_tensor)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)\n    x = Activation('relu')(x)\n\n    x = Convolution2D(nb_filter2, (kernel_size, kernel_size), padding='same', name=conv_name_base + '2b')(x)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)\n    x = Activation('relu')(x)\n\n    x = Convolution2D(nb_filter3, (1, 1), name=conv_name_base + '2c')(x)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)\n\n    x = Add()([x, input_tensor])\n    x = Activation('relu')(x)\n    return x","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:38:17.310943Z","iopub.execute_input":"2022-07-26T04:38:17.311292Z","iopub.status.idle":"2022-07-26T04:38:17.321139Z","shell.execute_reply.started":"2022-07-26T04:38:17.311265Z","shell.execute_reply":"2022-07-26T04:38:17.320060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):\n    '''conv_block is the block that has a conv layer at shortcut\n    # Arguments\n        input_tensor: input tensor\n        kernel_size: defualt 3, the kernel size of middle conv layer at main path\n        filters: list of integers, the nb_filters of 3 conv layer at main path\n        stage: integer, current stage label, used for generating layer names\n        block: 'a','b'..., current block label, used for generating layer names\n    Note that from stage 3, the first conv layer at main path is with subsample=(2,2)\n    And the shortcut should have subsample=(2,2) as well\n    '''\n    nb_filter1, nb_filter2, nb_filter3 = filters\n    bn_axis = 3\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n\n    x = Convolution2D(nb_filter1, (1, 1), strides=strides, name=conv_name_base + '2a')(input_tensor)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)\n    x = Activation('relu')(x)\n\n    x = Convolution2D(nb_filter2, (kernel_size, kernel_size), padding='same', name=conv_name_base + '2b')(x)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)\n    x = Activation('relu')(x)\n\n    x = Convolution2D(nb_filter3, (1, 1), name=conv_name_base + '2c')(x)\n    x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)\n\n    shortcut = Convolution2D(nb_filter3, (1, 1), strides=strides, name=conv_name_base + '1')(input_tensor)\n    shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)\n\n    x = Add()([x, shortcut])\n    x = Activation('relu')(x)\n    return x","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:38:18.365885Z","iopub.execute_input":"2022-07-26T04:38:18.366580Z","iopub.status.idle":"2022-07-26T04:38:18.376633Z","shell.execute_reply.started":"2022-07-26T04:38:18.366539Z","shell.execute_reply":"2022-07-26T04:38:18.375566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ResNet50():\n    '''Instantiate the ResNet50 architecture,\n    optionally loading weights pre-trained\n    on ImageNet. Note that when using TensorFlow,\n    for best performance you should set\n    `image_dim_ordering=\"tf\"` in your Keras config\n    at ~/.keras/keras.json.\n    The model and the weights are compatible with both\n    TensorFlow and Theano. The dimension ordering\n    convention used by the model is the one\n    specified in your Keras config file.\n    # Arguments\n        include_top: whether to include the 3 fully-connected\n            layers at the top of the network.\n        weights: one of `None` (random initialization)\n            or \"imagenet\" (pre-training on ImageNet).\n        input_tensor: optional Keras tensor (i.e. xput of `layers.Input()`)\n            to use as image input for the model.\n    # Returns\n        A Keras model instance.\n    '''\n    img_input = Input(shape=(224, 224, 3))\n    bn_axis = 3\n\n    x = ZeroPadding2D((3, 3))(img_input)\n    x = Convolution2D(64, (7, 7), strides=(2, 2), name='conv1')(x)\n    x = BatchNormalization(axis=bn_axis, name='bn_conv1')(x)\n    x = Activation('relu')(x)\n    x = MaxPooling2D((3, 3), strides=(2, 2))(x)\n\n    x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')\n\n    x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')\n    x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')\n\n    x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')\n    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')\n\n    x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')\n\n    x = AveragePooling2D((7, 7), name='avg_pool')(x)\n\n    x = Flatten()(x)\n    x = Dense(1000, activation='softmax', name='fc1000')(x)\n\n    model = Model(img_input, x)\n    model.load_weights(\"/kaggle/working/resnet50_weights_tf_dim_ordering_tf_kernels.h5\")\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:38:18.453385Z","iopub.execute_input":"2022-07-26T04:38:18.453948Z","iopub.status.idle":"2022-07-26T04:38:18.469967Z","shell.execute_reply.started":"2022-07-26T04:38:18.453913Z","shell.execute_reply":"2022-07-26T04:38:18.469171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resnet50_model = ResNet50()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T04:38:19.247626Z","iopub.execute_input":"2022-07-26T04:38:19.248223Z","iopub.status.idle":"2022-07-26T04:38:21.196992Z","shell.execute_reply.started":"2022-07-26T04:38:19.248186Z","shell.execute_reply":"2022-07-26T04:38:21.195745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}