{"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 os, shutil\nimport tensorflow as tf\nimport tensorflow_datasets as tfds\nimport pandas as pd\n\n\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.models import Sequential","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:48:20.422168Z","iopub.execute_input":"2023-09-15T07:48:20.423013Z","iopub.status.idle":"2023-09-15T07:48:32.605641Z","shell.execute_reply.started":"2023-09-15T07:48:20.422981Z","shell.execute_reply":"2023-09-15T07:48:32.604603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The procedure below follows from [the tutorial](https://www.tensorflow.org/tutorials/images/classification#load_data_using_a_keras_utility)","metadata":{}},{"cell_type":"markdown","source":"# Change directory structure","metadata":{}},{"cell_type":"code","source":"labels_df = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\nunique_labels = labels_df['breed'].value_counts().index","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:48:32.607806Z","iopub.execute_input":"2023-09-15T07:48:32.608464Z","iopub.status.idle":"2023-09-15T07:48:32.667196Z","shell.execute_reply.started":"2023-09-15T07:48:32.608428Z","shell.execute_reply":"2023-09-15T07:48:32.666229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for label in unique_labels:\n    try :\n        os.makedirs('train/'+label)\n    except FileExistsError:\n        pass\n    \n    for file_name in labels_df[labels_df['breed'] == label]['id']:\n        try:\n            shutil.copyfile('/kaggle/input/dog-breed-identification/train/'+file_name+'.jpg',\n                        'train/'+label+'/'+file_name+'.jpg')\n        except shutil.SameFileError:\n            pass    \n\n\ntry:\n    shutil.copytree('/kaggle/input/dog-breed-identification/test', 'test/test') \nexcept FileExistsError:\n    pass\n\n        ","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:51:58.142042Z","iopub.execute_input":"2023-09-15T07:51:58.143003Z","iopub.status.idle":"2023-09-15T07:55:17.689598Z","shell.execute_reply.started":"2023-09-15T07:51:58.142972Z","shell.execute_reply":"2023-09-15T07:55:17.688552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load data using keras utility","metadata":{}},{"cell_type":"code","source":"#Define parameters for the loader\nbatch_size = 32\nimg_height = 180\nimg_width = 180","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:49.452181Z","iopub.execute_input":"2023-09-15T07:55:49.452609Z","iopub.status.idle":"2023-09-15T07:55:49.457372Z","shell.execute_reply.started":"2023-09-15T07:55:49.452573Z","shell.execute_reply":"2023-09-15T07:55:49.456114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = tf.keras.utils.image_dataset_from_directory(\n  'train',\n  validation_split=0.2,\n  subset=\"training\",\n  seed=123,\n  image_size=(img_height, img_width),\n  batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:49.596500Z","iopub.execute_input":"2023-09-15T07:55:49.596807Z","iopub.status.idle":"2023-09-15T07:55:55.377515Z","shell.execute_reply.started":"2023-09-15T07:55:49.596782Z","shell.execute_reply":"2023-09-15T07:55:55.376520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_ds = tf.keras.utils.image_dataset_from_directory(\n  'train',\n  validation_split=0.2,\n  subset=\"validation\",\n  seed=123,\n  image_size=(img_height, img_width),\n  batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:55.379278Z","iopub.execute_input":"2023-09-15T07:55:55.379603Z","iopub.status.idle":"2023-09-15T07:55:56.283814Z","shell.execute_reply.started":"2023-09-15T07:55:55.379570Z","shell.execute_reply":"2023-09-15T07:55:56.282808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names = train_ds.class_names\nprint(class_names[:5])","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:56.285332Z","iopub.execute_input":"2023-09-15T07:55:56.285676Z","iopub.status.idle":"2023-09-15T07:55:56.291871Z","shell.execute_reply.started":"2023-09-15T07:55:56.285642Z","shell.execute_reply":"2023-09-15T07:55:56.290868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## visualize data","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 10))\nfor images, labels in train_ds.take(1):\n  for i in range(9):\n    ax = plt.subplot(3, 3, i + 1)\n    plt.imshow(images[i].numpy().astype(\"uint8\"))\n    plt.title(class_names[labels[i]])\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:56.294867Z","iopub.execute_input":"2023-09-15T07:55:56.295299Z","iopub.status.idle":"2023-09-15T07:55:58.070257Z","shell.execute_reply.started":"2023-09-15T07:55:56.295267Z","shell.execute_reply":"2023-09-15T07:55:58.069006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Standardize data","metadata":{}},{"cell_type":"code","source":"normalization_layer = tf.keras.layers.Rescaling(1./255)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:58.071261Z","iopub.execute_input":"2023-09-15T07:55:58.071580Z","iopub.status.idle":"2023-09-15T07:55:58.080983Z","shell.execute_reply.started":"2023-09-15T07:55:58.071551Z","shell.execute_reply":"2023-09-15T07:55:58.080051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Configure the dataset for performance","metadata":{}},{"cell_type":"code","source":"AUTOTUNE = tf.data.AUTOTUNE\n\ntrain_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)\nval_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:58.082571Z","iopub.execute_input":"2023-09-15T07:55:58.083178Z","iopub.status.idle":"2023-09-15T07:55:58.102183Z","shell.execute_reply.started":"2023-09-15T07:55:58.083140Z","shell.execute_reply":"2023-09-15T07:55:58.101137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# A Basic Keras Model","metadata":{}},{"cell_type":"code","source":"num_classes = len(class_names)\n\nmodel = Sequential([\n  layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),\n  layers.Conv2D(16, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Conv2D(32, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Conv2D(64, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Flatten(),\n  layers.Dense(128, activation='relu'),\n  layers.Dense(num_classes)\n])","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:58.103717Z","iopub.execute_input":"2023-09-15T07:55:58.104551Z","iopub.status.idle":"2023-09-15T07:55:58.236506Z","shell.execute_reply.started":"2023-09-15T07:55:58.104519Z","shell.execute_reply":"2023-09-15T07:55:58.235593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(\n  optimizer='adam',\n  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n  metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:58.237868Z","iopub.execute_input":"2023-09-15T07:55:58.238509Z","iopub.status.idle":"2023-09-15T07:55:58.258252Z","shell.execute_reply.started":"2023-09-15T07:55:58.238478Z","shell.execute_reply":"2023-09-15T07:55:58.257385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 10\nhistory = model.fit(\n  train_ds,\n  validation_data=val_ds,\n  epochs=epochs,\n    verbose=2\n)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:55:58.259755Z","iopub.execute_input":"2023-09-15T07:55:58.260109Z","iopub.status.idle":"2023-09-15T07:57:09.577767Z","shell.execute_reply.started":"2023-09-15T07:55:58.260064Z","shell.execute_reply":"2023-09-15T07:57:09.576636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize Training Result","metadata":{}},{"cell_type":"code","source":"acc = 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=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Training Accuracy')\nplt.plot(epochs_range, val_acc, label='Validation Accuracy')\nplt.legend()\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()\nplt.title('Training and Validation Loss')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:57:09.582424Z","iopub.execute_input":"2023-09-15T07:57:09.582732Z","iopub.status.idle":"2023-09-15T07:57:10.084967Z","shell.execute_reply.started":"2023-09-15T07:57:09.582705Z","shell.execute_reply":"2023-09-15T07:57:10.084054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The training accuracy and validation accuracy are off by large margins.","metadata":{}},{"cell_type":"markdown","source":"# Deal with Overfitting","metadata":{}},{"cell_type":"markdown","source":"## Data Augmentation","metadata":{}},{"cell_type":"code","source":"data_augmentation = keras.Sequential(\n  [\n    layers.RandomFlip(\"horizontal\"),\n    layers.RandomRotation(0.1),\n    layers.RandomZoom(0.1),\n  ]\n)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:57:10.086396Z","iopub.execute_input":"2023-09-15T07:57:10.087438Z","iopub.status.idle":"2023-09-15T07:57:10.099684Z","shell.execute_reply.started":"2023-09-15T07:57:10.087402Z","shell.execute_reply":"2023-09-15T07:57:10.098702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10, 10))\nfor images, _ in train_ds.take(1):\n  for i in range(9):\n    augmented_images = data_augmentation(images)\n    ax = plt.subplot(3, 3, i + 1)\n    plt.imshow(augmented_images[0].numpy().astype(\"uint8\"))\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:57:10.101252Z","iopub.execute_input":"2023-09-15T07:57:10.101600Z","iopub.status.idle":"2023-09-15T07:57:11.336558Z","shell.execute_reply.started":"2023-09-15T07:57:10.101569Z","shell.execute_reply":"2023-09-15T07:57:11.335052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dropout","metadata":{}},{"cell_type":"code","source":"model = Sequential([\n  data_augmentation,\n  layers.Rescaling(1./255),\n  layers.Conv2D(16, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Conv2D(32, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Conv2D(64, 3, padding='same', activation='relu'),\n  layers.MaxPooling2D(),\n  layers.Dropout(0.5),\n  layers.Flatten(),\n  layers.Dense(128, activation='relu'),\n  layers.Dense(num_classes, name=\"outputs\")\n])","metadata":{"execution":{"iopub.status.busy":"2023-09-15T08:26:43.383540Z","iopub.execute_input":"2023-09-15T08:26:43.383908Z","iopub.status.idle":"2023-09-15T08:26:43.408416Z","shell.execute_reply.started":"2023-09-15T08:26:43.383879Z","shell.execute_reply":"2023-09-15T08:26:43.407266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Compile and Train!","metadata":{}},{"cell_type":"code","source":"model.compile(optimizer='adam',\n              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n              metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-09-15T08:26:43.982598Z","iopub.execute_input":"2023-09-15T08:26:43.983417Z","iopub.status.idle":"2023-09-15T08:26:44.000058Z","shell.execute_reply.started":"2023-09-15T08:26:43.983379Z","shell.execute_reply":"2023-09-15T08:26:43.999116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 10\nhistory = model.fit(\n  train_ds,\n  validation_data=val_ds,\n  epochs=epochs,\n    verbose=2\n)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T08:26:44.574183Z","iopub.execute_input":"2023-09-15T08:26:44.575023Z","iopub.status.idle":"2023-09-15T08:28:40.917412Z","shell.execute_reply.started":"2023-09-15T08:26:44.574984Z","shell.execute_reply":"2023-09-15T08:28:40.916332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize Training Result","metadata":{}},{"cell_type":"code","source":"acc = 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=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Training Accuracy')\nplt.plot(epochs_range, val_acc, label='Validation Accuracy')\nplt.legend()\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()\nplt.title('Training and Validation Loss')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-15T08:28:40.919392Z","iopub.execute_input":"2023-09-15T08:28:40.919841Z","iopub.status.idle":"2023-09-15T08:28:41.476447Z","shell.execute_reply.started":"2023-09-15T08:28:40.919798Z","shell.execute_reply":"2023-09-15T08:28:41.475476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict on Test Data","metadata":{}},{"cell_type":"code","source":"test_dataset = tf.keras.utils.image_dataset_from_directory(\n          \"test\",\n           shuffle=False,\n           batch_size=batch_size,\n           image_size=(img_height, img_width))\n","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:59:05.154195Z","iopub.execute_input":"2023-09-15T07:59:05.154578Z","iopub.status.idle":"2023-09-15T07:59:05.750906Z","shell.execute_reply.started":"2023-09-15T07:59:05.154548Z","shell.execute_reply":"2023-09-15T07:59:05.749925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = model.predict(test_dataset)","metadata":{"execution":{"iopub.status.busy":"2023-09-15T07:59:53.672529Z","iopub.execute_input":"2023-09-15T07:59:53.672899Z","iopub.status.idle":"2023-09-15T08:00:08.796557Z","shell.execute_reply.started":"2023-09-15T07:59:53.672869Z","shell.execute_reply":"2023-09-15T08:00:08.795637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predict = pd.DataFrame(tf.nn.softmax(predictions), columns = class_names)\n\ntest_predict.insert(0, 'id', test_dataset.file_paths)\n\n\ntest_predict['id'] = test_predict['id'].str.split(r'[\\/.]').str[2]","metadata":{"execution":{"iopub.status.busy":"2023-09-15T08:19:42.494107Z","iopub.execute_input":"2023-09-15T08:19:42.494473Z","iopub.status.idle":"2023-09-15T08:19:42.543065Z","shell.execute_reply.started":"2023-09-15T08:19:42.494444Z","shell.execute_reply":"2023-09-15T08:19:42.542122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predict.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-14T11:53:06.416125Z","iopub.status.idle":"2023-09-14T11:53:06.417142Z","shell.execute_reply.started":"2023-09-14T11:53:06.416894Z","shell.execute_reply":"2023-09-14T11:53:06.416917Z"},"trusted":true},"execution_count":null,"outputs":[]}]}