{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\nimport tensorflow as tf\nimport tensorflow_addons as tfa\nfrom kaggle_datasets import KaggleDatasets","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"try: # detect TPUs\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver() # TPU detection\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\n    CASSAVA_GCS_PATH = KaggleDatasets().get_gcs_path(\"cassava-leaf-disease-classification\")\n    MERGED_DATASET_PATH = KaggleDatasets().get_gcs_path(\"20192020-merged-tfrecords-512x512\")\nexcept ValueError: # no TPU found, detect GPUs\n    strategy = tf.distribute.MirroredStrategy()\n    CASSAVA_GCS_PATH = \"../input/cassava-leaf-disease-classification\"\n    MERGED_DATASET_PATH = \"../input/20192020-merged-tfrecords-512x512\"\n\nprint(\"Number of accelerators: \", strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_tfrecords_dir = MERGED_DATASET_PATH + \"/*.tfrec\"\ntfrec_filenames = tf.io.gfile.glob(train_tfrecords_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"feature_description = {\n    'image': tf.io.FixedLenFeature([], tf.string),\n    'image_name': tf.io.FixedLenFeature([], tf.string),\n    'target': tf.io.FixedLenFeature([], tf.int64, default_value=0), # using default value for test dataset\n}\n\ndef _parse_tfrec(example_proto):\n    features = tf.io.parse_single_example(example_proto, feature_description)\n    \n    image = features['image']\n    label = features['target']\n    image_name = features['image_name']\n    \n    return image, label, image_name\n\ndef _parse_image(image, label, image_name, training=False):\n    image = tf.io.decode_image(image)\n    image = tf.reshape(image, (512, 512, 3))\n    if training:\n        image = tfa.image.gaussian_filter2d(image)\n    image = tf.cast(image, tf.float32)\n    image = tf.keras.applications.inception_v3.preprocess_input(image)\n    \n    return image, tf.one_hot(label, depth=5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_image_name_labels(image, label, image_name):\n    return image_name, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_dataset = tf.data.TFRecordDataset(tfrec_filenames).map(_parse_tfrec, num_parallel_calls=tf.data.experimental.AUTOTUNE)\nall_dataset = all_dataset.map(get_image_name_labels, num_parallel_calls=tf.data.experimental.AUTOTUNE)\nall_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.DataFrame(\n    [(image_name.numpy(),label.numpy()) for image_name, label in all_dataset],\n    columns=[\"image_id\", \"label\"]\n)\n\ndf2 = pd.read_csv(CASSAVA_GCS_PATH + \"/train.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.shape, df2.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.setdiff1d(df2.image_id.map(lambda x: bytes(x.strip(\".jpg\"), \"utf-8\")).values, df.image_id.values).shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_cat_3 = df[df['label']==3]\ndf_cat_3 = df_cat_3.sample(n=3500, random_state=0)\ndf_cat_3.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = df[df['label']!=3]\ndf.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = df.append(df_cat_3, ignore_index=True)\ndf.label.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"kf = StratifiedKFold(n_splits=5, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for train_idx, val_idx in kf.split(df.image_id, df.label):\n    train_image_ids = np.array(df.iloc[train_idx]['image_id'])\n    val_image_ids = np.array(df.iloc[val_idx]['image_id'])\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_image_ids.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"val_image_ids.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.layers.experimental import preprocessing\n\ndata_augmentation = tf.keras.Sequential([\n    preprocessing.RandomFlip(\"horizontal_and_vertical\"),\n    preprocessing.RandomRotation(0.4),\n    preprocessing.RandomContrast(0.3),\n    preprocessing.RandomTranslation(0.2, 0.2)\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BATCH_SIZE = 32 * strategy.num_replicas_in_sync\nBATCH_SIZE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dataset = tf.data.TFRecordDataset(tfrec_filenames).map(_parse_tfrec, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\ntrain_dataset = train_dataset.filter(lambda image, label, image_id: tf.reduce_any(tf.equal(image_id, train_image_ids)))\n\ntrain_dataset = train_dataset.map(_parse_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\ntrain_dataset = train_dataset.shuffle(1000).batch(BATCH_SIZE)\n# train_dataset = train_dataset.map(lambda images, labels: (tfa.image.gaussian_filter2d(images), labels),  num_parallel_calls=tf.data.experimental.AUTOTUNE)\ntrain_dataset = train_dataset.map(lambda images, labels: (data_augmentation(images, training=True), labels),  num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\ntrain_dataset = train_dataset.prefetch(tf.data.experimental.AUTOTUNE)\n\ntrain_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"valid_dataset = tf.data.TFRecordDataset(tfrec_filenames).map(_parse_tfrec, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\nvalid_dataset = valid_dataset.filter(lambda image, label, image_id: tf.reduce_any(tf.equal(image_id, val_image_ids)))\n\nvalid_dataset = valid_dataset.map(_parse_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\nvalid_dataset = valid_dataset.batch(BATCH_SIZE).prefetch(tf.data.experimental.AUTOTUNE)\n\nvalid_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for images, labels in train_dataset:\n    plt.figure(figsize=(10,10))\n    for i in range(1,13):\n        plt.subplot(3,4,i)\n        plt.imshow(images[i])\n        plt.axis(\"off\")\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with strategy.scope():\n    base_model = tf.keras.applications.InceptionV3(\n        include_top=False,\n        input_shape=(512,512,3),\n        weights=\"imagenet\"\n    )\n\n    base_model.trainable = True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with strategy.scope():\n    inputs = tf.keras.layers.Input([512, 512, 3], dtype=tf.float32)\n    x = base_model(inputs)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    x = tf.keras.layers.Dropout(0.2)(x)\n    x = tf.keras.layers.Dense(1024, activation='relu')(x)\n    x = tf.keras.layers.Dropout(0.2)(x)\n    x = tf.keras.layers.Dense(512, activation='relu')(x)\n    x = tf.keras.layers.Dropout(0.2)(x)\n    outputs = tf.keras.layers.Dense(5, \"softmax\")(x)\n    \n    model = tf.keras.Model(inputs, outputs)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with strategy.scope():\n    model.compile(\n        optimizer=\"adam\",\n        loss=\"categorical_crossentropy\",\n        metrics=['accuracy']\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"early_stopping = tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS = 100","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(train_dataset, validation_data=valid_dataset, epochs=EPOCHS, callbacks=[early_stopping])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history=model.history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(history.epoch, history.history['loss'], label=\"Training Loss\")\nplt.plot(history.epoch, history.history['val_loss'], label=\"Validation Loss\")\nplt.title(\"Loss Graph\")\nplt.ylim((0, 2))\nplt.legend()\nplt.show()\n\nplt.plot(history.epoch, history.history['accuracy'], label=\"Training Accuracy\")\nplt.plot(history.epoch, history.history['val_accuracy'], label=\"Validation Accuracy\")\nplt.title(\"Accuracy Graph\")\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.evaluate(valid_dataset)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds = []\nactuals = []\nfor images, labels in valid_dataset:\n    actuals.extend(np.argmax(labels.numpy(), axis=1))\n\npreds.extend(np.argmax(model.predict(valid_dataset), axis=1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import seaborn as sns\nfrom sklearn.metrics import confusion_matrix","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.heatmap(confusion_matrix(actuals, preds), annot=True, fmt=\"d\", cmap='Blues')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.keras.models.save_model(\n    model,\n    \"./model.h5\",\n    overwrite=True,\n    save_format='h5'\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_dataset = tf.data.TFRecordDataset(tfrec_filenames).map(_parse_tfrec, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\nall_dataset = all_dataset.map(_parse_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)\n\nall_dataset = all_dataset.batch(BATCH_SIZE).prefetch(tf.data.experimental.AUTOTUNE)\n\nall_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.evaluate(all_dataset)","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}