{"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":"# 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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix, classification_report\nimport tensorflow as tf\nimport tensorflow_datasets as tfds\nimport seaborn as sns\nimport json\nfrom scipy import stats\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\n# for 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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-25T08:50:48.650992Z","iopub.execute_input":"2021-05-25T08:50:48.651805Z","iopub.status.idle":"2021-05-25T08:50:54.653000Z","shell.execute_reply.started":"2021-05-25T08:50:48.651691Z","shell.execute_reply":"2021-05-25T08:50:54.652025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## check how data is distributed and create tf.Data","metadata":{}},{"cell_type":"code","source":"train_csv = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\nprint(\"Number of train images: {}\".format(len(train_csv)))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.654906Z","iopub.execute_input":"2021-05-25T08:50:54.655274Z","iopub.status.idle":"2021-05-25T08:50:54.688963Z","shell.execute_reply.started":"2021-05-25T08:50:54.655235Z","shell.execute_reply":"2021-05-25T08:50:54.688330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.691634Z","iopub.execute_input":"2021-05-25T08:50:54.691879Z","iopub.status.idle":"2021-05-25T08:50:54.709976Z","shell.execute_reply.started":"2021-05-25T08:50:54.691856Z","shell.execute_reply":"2021-05-25T08:50:54.709045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('/kaggle/input/cassava-leaf-disease-classification/label_num_to_disease_map.json', 'r') as fp:\n    class_map = json.load(fp)\nclass_map","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.711796Z","iopub.execute_input":"2021-05-25T08:50:54.712135Z","iopub.status.idle":"2021-05-25T08:50:54.722252Z","shell.execute_reply.started":"2021-05-25T08:50:54.712102Z","shell.execute_reply":"2021-05-25T08:50:54.721296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ax=train_csv.pivot_table(columns='label',aggfunc='size').plot(kind='barh')\nax.set_yticklabels(class_map.values()) \nax.set_xlabel('count')","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.725641Z","iopub.execute_input":"2021-05-25T08:50:54.725888Z","iopub.status.idle":"2021-05-25T08:50:54.892390Z","shell.execute_reply.started":"2021-05-25T08:50:54.725864Z","shell.execute_reply":"2021-05-25T08:50:54.891693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"apparently the class is not balanced, we will need to address that problem during training.\n\nIt is also helpful to understand what we are trying to solve, read here for more info about the diseases:\nhttps://www.kaggle.com/c/cassava-leaf-disease-classification/discussion/198143","metadata":{}},{"cell_type":"markdown","source":"#### Create tf.dataset","metadata":{}},{"cell_type":"code","source":"@tf.function\ndef process_data(path, label):\n    path = '/kaggle/input/cassava-leaf-disease-classification/train_images/' + path\n    img = tf.io.read_file(path)\n    img = tf.image.decode_jpeg(img, channels=3) \n    return img, tf.one_hot(label, 5) ","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.895625Z","iopub.execute_input":"2021-05-25T08:50:54.895880Z","iopub.status.idle":"2021-05-25T08:50:54.900804Z","shell.execute_reply.started":"2021-05-25T08:50:54.895854Z","shell.execute_reply":"2021-05-25T08:50:54.899815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train, val=train_test_split(train_csv, test_size=0.1, random_state=42,stratify=train_csv['label'])","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.902281Z","iopub.execute_input":"2021-05-25T08:50:54.902783Z","iopub.status.idle":"2021-05-25T08:50:54.928629Z","shell.execute_reply.started":"2021-05-25T08:50:54.902743Z","shell.execute_reply":"2021-05-25T08:50:54.927920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"oversampled_df = []\ntarget_count = int(train.pivot_table(columns='label',aggfunc='size').values[3]*0.5)\nfor i in range(len(class_map)):\n    class_i = train[train.label==i]\n    oversampled_df.append(class_i.sample(target_count, replace=True))\n","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.930144Z","iopub.execute_input":"2021-05-25T08:50:54.930525Z","iopub.status.idle":"2021-05-25T08:50:54.966091Z","shell.execute_reply.started":"2021-05-25T08:50:54.930489Z","shell.execute_reply":"2021-05-25T08:50:54.965190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resampled_train = pd.concat(oversampled_df, axis=0)\nresampled_train.pivot_table(columns='label',aggfunc='size')","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.967312Z","iopub.execute_input":"2021-05-25T08:50:54.967687Z","iopub.status.idle":"2021-05-25T08:50:54.981930Z","shell.execute_reply.started":"2021-05-25T08:50:54.967651Z","shell.execute_reply":"2021-05-25T08:50:54.981085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resampled_train = resampled_train.sample(frac=1).reset_index(drop=True)\nresampled_train.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.984539Z","iopub.execute_input":"2021-05-25T08:50:54.984778Z","iopub.status.idle":"2021-05-25T08:50:54.997998Z","shell.execute_reply.started":"2021-05-25T08:50:54.984755Z","shell.execute_reply":"2021-05-25T08:50:54.997199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 8","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:54.999357Z","iopub.execute_input":"2021-05-25T08:50:54.999708Z","iopub.status.idle":"2021-05-25T08:50:55.003581Z","shell.execute_reply.started":"2021-05-25T08:50:54.999675Z","shell.execute_reply":"2021-05-25T08:50:55.002558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = tf.data.Dataset.from_tensor_slices((train.image_id.values, train.label.values))\\\n                .map(process_data, num_parallel_calls = tf.data.experimental.AUTOTUNE)\\\n                .shuffle(buffer_size = 2000)\\\n                .batch(batch_size)\\\n                .prefetch(tf.data.experimental.AUTOTUNE) \n\nval_ds = tf.data.Dataset.from_tensor_slices((val.image_id.values, val.label.values))\\\n                .map(process_data, num_parallel_calls = tf.data.experimental.AUTOTUNE)\\\n                .batch(batch_size)\\\n                .prefetch(tf.data.experimental.AUTOTUNE) ","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:55.005239Z","iopub.execute_input":"2021-05-25T08:50:55.005910Z","iopub.status.idle":"2021-05-25T08:50:57.265965Z","shell.execute_reply.started":"2021-05-25T08:50:55.005870Z","shell.execute_reply":"2021-05-25T08:50:57.265246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation = tf.keras.Sequential(\n    [\n        tf.keras.layers.experimental.preprocessing.RandomCrop(height=512, width=512),\n        tf.keras.layers.experimental.preprocessing.RandomFlip(\"horizontal_and_vertical\"),\n        tf.keras.layers.experimental.preprocessing.RandomRotation(0.25),\n        tf.keras.layers.experimental.preprocessing.RandomZoom((-0.2, 0)),\n        tf.keras.layers.experimental.preprocessing.RandomContrast((0,0.2))\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:57.267187Z","iopub.execute_input":"2021-05-25T08:50:57.267526Z","iopub.status.idle":"2021-05-25T08:50:57.579721Z","shell.execute_reply.started":"2021-05-25T08:50:57.267493Z","shell.execute_reply":"2021-05-25T08:50:57.578858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train_ds = train_ds.map(lambda x, y: (data_augmentation(x, training=True), y), \n#                 num_parallel_calls=tf.data.experimental.AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:57.583346Z","iopub.execute_input":"2021-05-25T08:50:57.583661Z","iopub.status.idle":"2021-05-25T08:50:57.587462Z","shell.execute_reply.started":"2021-05-25T08:50:57.583631Z","shell.execute_reply":"2021-05-25T08:50:57.586518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test if datset is fetching and decoding images correctly\nfor images, labels in train_ds.take(1):\n    images = data_augmentation(images, training=True)\n    print(images.shape, labels.shape)\n    plt.figure(figsize=(10, 10))\n    labels = np.argmax(labels.numpy(), -1)\n    for i in range(8):\n        ax = plt.subplot(3, 3, i + 1)\n        plt.imshow(images.numpy()[i])\n        plt.title(class_map[str(labels[i])])\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:50:57.588969Z","iopub.execute_input":"2021-05-25T08:50:57.589687Z","iopub.status.idle":"2021-05-25T08:51:07.061262Z","shell.execute_reply.started":"2021-05-25T08:50:57.589643Z","shell.execute_reply":"2021-05-25T08:51:07.060316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_ds)//batch_size","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.062363Z","iopub.execute_input":"2021-05-25T08:51:07.062703Z","iopub.status.idle":"2021-05-25T08:51:07.069309Z","shell.execute_reply.started":"2021-05-25T08:51:07.062671Z","shell.execute_reply":"2021-05-25T08:51:07.068178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model Training\n### Baseline\nLet's first train a baseline model to see the performance, baseline model would simple do transfer learning on a pretrained model, without data augmentation and anything specific to balance the dataset.","metadata":{}},{"cell_type":"code","source":"def plot_metrics(history, metrics= ['loss', 'accuracy']):\n    for n, metric in enumerate(metrics):\n        name = metric.replace(\"_\",\" \").capitalize()\n        plt.subplot(2,2,n+1)\n        plt.plot(history.epoch, history.history[metric],  label='Train')\n        plt.plot(history.epoch, history.history['val_'+metric], linestyle=\"--\", label='Val')\n        plt.xlabel('Epoch')\n        plt.ylabel(name)\n        if metric == 'loss':\n            plt.ylim([0, plt.ylim()[1]])\n        else:\n            plt.ylim([0, 1])\n\n    plt.legend()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.070946Z","iopub.execute_input":"2021-05-25T08:51:07.071633Z","iopub.status.idle":"2021-05-25T08:51:07.080129Z","shell.execute_reply.started":"2021-05-25T08:51:07.071594Z","shell.execute_reply":"2021-05-25T08:51:07.079188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_cm(labels, predictions):\n    cm = confusion_matrix(labels, predictions)\n    plt.figure(figsize=(5,5))\n    sns.heatmap(cm, annot=True, fmt=\"d\")\n    plt.title('Confusion matrix')\n    plt.ylabel('Actual label')\n    plt.xlabel('Predicted label')\n\n    print('True Negatives: ', cm[0][0])\n    print('False Positives: ', cm[0][1])\n    print('False Negatives: ', cm[1][0])\n    print('True Positives: ', cm[1][1])\n    print('Total: ', np.sum(cm[1]))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.081715Z","iopub.execute_input":"2021-05-25T08:51:07.082326Z","iopub.status.idle":"2021-05-25T08:51:07.090398Z","shell.execute_reply.started":"2021-05-25T08:51:07.082286Z","shell.execute_reply":"2021-05-25T08:51:07.089513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow.keras.backend as K\ndef sigmoid_focal_crossentropy(y_true, y_pred, alpha=0.5, gamma=0.5, from_logits=False):\n    \"\"\"Implements the focal loss function.\n    Focal loss was first introduced in the RetinaNet paper\n    (https://arxiv.org/pdf/1708.02002.pdf). Focal loss is extremely useful for\n    classification when you have highly imbalanced classes. It down-weights\n    well-classified examples and focuses on hard examples. The loss value is\n    much high for a sample which is misclassified by the classifier as compared\n    to the loss value corresponding to a well-classified example. One of the\n    best use-cases of focal loss is its usage in object detection where the\n    imbalance between the background class and other classes is extremely high.\n    Args:\n        y_true: true targets tensor.\n        y_pred: predictions tensor.\n        alpha: balancing factor.\n        gamma: modulating factor.\n    Returns:\n        Weighted loss float `Tensor`. If `reduction` is `NONE`,this has the\n        same shape as `y_true`; otherwise, it is scalar.\n    \"\"\"\n    if gamma and gamma < 0:\n        raise ValueError(\"Value of gamma should be greater than or equal to zero\")\n\n    y_pred = tf.convert_to_tensor(y_pred)\n    y_true = tf.convert_to_tensor(y_true, dtype=y_pred.dtype)\n\n    # Get the cross_entropy for each entry\n    ce = K.binary_crossentropy(y_true, y_pred, from_logits=from_logits)\n\n    # If logits are provided then convert the predictions into probabilities\n    if from_logits:\n        pred_prob = tf.sigmoid(y_pred)\n    else:\n        pred_prob = y_pred\n\n    p_t = (y_true * pred_prob) + ((1 - y_true) * (1 - pred_prob))\n    alpha_factor = 1.0\n    modulating_factor = 1.0\n\n    if alpha:\n        alpha = tf.convert_to_tensor(alpha, dtype=K.floatx())\n        alpha_factor = y_true * alpha + (1 - y_true) * (1 - alpha)\n\n    if gamma:\n        gamma = tf.convert_to_tensor(gamma, dtype=K.floatx())\n        modulating_factor = tf.pow((1.0 - p_t), gamma)\n\n    # compute the final loss and return\n    return tf.reduce_sum(alpha_factor * modulating_factor * ce, axis=-1)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.091850Z","iopub.execute_input":"2021-05-25T08:51:07.092418Z","iopub.status.idle":"2021-05-25T08:51:07.104371Z","shell.execute_reply.started":"2021-05-25T08:51:07.092359Z","shell.execute_reply":"2021-05-25T08:51:07.103476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_efficient_model(input_layer, input_shape, model_inputs, num_classes, dropout_rate=0.2):\n\n    model = tf.keras.applications.EfficientNetB3(weights='/kaggle/input/efficientnetb3notop/efficientnetb3_notop.h5', \n                              include_top=False, \n                                input_shape=input_shape, \n                              drop_connect_rate=dropout_rate)\n    \n    # Freeze the pretrained weights\n    model.trainable = False\n    model_output = model(model_inputs, training=False)\n    # Rebuild top\n    x = tf.keras.layers.GlobalAveragePooling2D(name=\"avg_pool\")(model_output)\n#     x = tf.keras.layers.BatchNormalization()(x)\n\n#     x = tf.keras.layers.Dropout(dropout_rate, name=\"top_dropout\")(x)\n    outputs = tf.keras.layers.Dense(num_classes, activation=\"softmax\", name=\"pred\")(x)\n\n    # Compile\n    model = tf.keras.Model(input_layer, outputs, name=\"EfficientNet\")\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.105835Z","iopub.execute_input":"2021-05-25T08:51:07.106605Z","iopub.status.idle":"2021-05-25T08:51:07.115714Z","shell.execute_reply.started":"2021-05-25T08:51:07.106565Z","shell.execute_reply":"2021-05-25T08:51:07.114745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_shape = (512, 512, 3)\ndropout_rate=0.2\nnum_classes = len(class_map)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.117569Z","iopub.execute_input":"2021-05-25T08:51:07.118178Z","iopub.status.idle":"2021-05-25T08:51:07.128514Z","shell.execute_reply.started":"2021-05-25T08:51:07.118123Z","shell.execute_reply":"2021-05-25T08:51:07.127728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# build the complete model, the tf implementation already has a rescaling layer in efficient net \n\ninput_layer = tf.keras.layers.Input([None, None, 3], dtype = tf.uint8)\nx = tf.cast(input_layer, tf.float32)\nx = data_augmentation(x, training=False)\nx = tf.keras.layers.experimental.preprocessing.Resizing(input_shape[0], input_shape[1])(x)\n\nbase_model = tf.keras.applications.EfficientNetB5(weights='/kaggle/input/efficientnetb5notop/efficientnetb5.h5', \n                              include_top=False, \n                                input_shape=input_shape, \n                              drop_connect_rate=dropout_rate)\n    \n# Freeze the pretrained weights\nbase_model.trainable = False\nmodel_output = base_model(x, training=False)\n# Rebuild top\nx = tf.keras.layers.GlobalAveragePooling2D(name=\"avg_pool\")(model_output)\n#     x = tf.keras.layers.BatchNormalization()(x)\n\n#     x = tf.keras.layers.Dropout(dropout_rate, name=\"top_dropout\")(x)\noutputs = tf.keras.layers.Dense(num_classes, activation=\"softmax\", name=\"pred\")(x)\n\n# Compile\nmodel = tf.keras.Model(input_layer, outputs, name=\"EfficientNet\")\n    \n# model = build_efficient_model(input_layer, input_shape, x, len(class_map))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:36.408807Z","iopub.execute_input":"2021-05-25T08:51:36.409246Z","iopub.status.idle":"2021-05-25T08:51:44.209767Z","shell.execute_reply.started":"2021-05-25T08:51:36.409215Z","shell.execute_reply":"2021-05-25T08:51:44.208835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:44.211599Z","iopub.execute_input":"2021-05-25T08:51:44.212156Z","iopub.status.idle":"2021-05-25T08:51:44.259204Z","shell.execute_reply.started":"2021-05-25T08:51:44.212113Z","shell.execute_reply":"2021-05-25T08:51:44.258376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"layers = [layer.name for layer in base_model.layers]\nfine_tune_at = layers.index('block7a_expand_conv')\nbase_model.trainable = True\nfor layer in base_model.layers[:fine_tune_at]:\n    layer.trainable =  False","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-05-25T08:51:46.766006Z","iopub.execute_input":"2021-05-25T08:51:46.766323Z","iopub.status.idle":"2021-05-25T08:51:46.806931Z","shell.execute_reply.started":"2021-05-25T08:51:46.766296Z","shell.execute_reply":"2021-05-25T08:51:46.806114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# since the class is imbalanced, it is helpful to include other metrics than accuracy\nMETRICS = [\n      tf.keras.metrics.CategoricalAccuracy(name='accuracy'),\n      tf.keras.metrics.Precision(name='precision'),\n      tf.keras.metrics.Recall(name='recall'),\n      tf.keras.metrics.AUC(name='auc')\n]\n\noptimizer = tf.keras.optimizers.Adam()\n\ncallbacks = [tf.keras.callbacks.ModelCheckpoint(filepath='best_model.h5', monitor='val_accuracy', save_best_only=False)]","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:48.660565Z","iopub.execute_input":"2021-05-25T08:51:48.660900Z","iopub.status.idle":"2021-05-25T08:51:48.689467Z","shell.execute_reply.started":"2021-05-25T08:51:48.660870Z","shell.execute_reply":"2021-05-25T08:51:48.688720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(\n    optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=METRICS\n)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:50.712028Z","iopub.execute_input":"2021-05-25T08:51:50.712350Z","iopub.status.idle":"2021-05-25T08:51:50.736189Z","shell.execute_reply.started":"2021-05-25T08:51:50.712319Z","shell.execute_reply":"2021-05-25T08:51:50.735187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist = model.fit(train_ds, epochs=4, validation_data=val_ds, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:52.035780Z","iopub.execute_input":"2021-05-25T08:51:52.036099Z","iopub.status.idle":"2021-05-25T08:53:02.288313Z","shell.execute_reply.started":"2021-05-25T08:51:52.036071Z","shell.execute_reply":"2021-05-25T08:53:02.284973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_metrics(hist, ['loss', 'auc', 'precision', 'recall'])","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.529259Z","iopub.status.idle":"2021-05-25T08:51:07.530038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_preds = model.predict(val_ds)\nval_preds = tf.math.argmax(val_preds, -1)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.531353Z","iopub.status.idle":"2021-05-25T08:51:07.532043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_cm(val.label.values, val_preds.numpy())","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.533561Z","iopub.status.idle":"2021-05-25T08:51:07.534348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.mean(np.where(val.label.values==val_preds, 1, 0))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.535763Z","iopub.status.idle":"2021-05-25T08:51:07.536568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fine_tune_at = layers.index('block7a_expand_conv')\n# base_model.trainable = True\n# for layer in base_model.layers[:fine_tune_at]:\n#     layer.trainable =  False\n\n# model.compile(\n#     optimizer=tf.keras.optimizers.Adam(tf.keras.experimental.CosineDecay(1e-4, 300*10)), \n#     loss='categorical_crossentropy', metrics=METRICS\n# )","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.537738Z","iopub.status.idle":"2021-05-25T08:51:07.538421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fine_tune_epochs = 5\n# total_epochs =  5 + fine_tune_epochs\n\n# history_fine = model.fit(train_ds,\n#                          epochs=total_epochs,\n#                          initial_epoch=hist.epoch[-1], \n#                          validation_data=val_ds, callbacks=callbacks)","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-05-25T08:51:07.539686Z","iopub.status.idle":"2021-05-25T08:51:07.540350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# %%time\n\n# pred_list = []\n# for i in range(5):\n#     print(i)\n#     each_loop = np.empty((0, ))\n#     for images, labels in val_ds:\n#         images = data_augmentation(images, training=True)\n# #         print(images.shape)\n#         val_preds = efficient.predict(images)\n#         val_preds = tf.math.argmax(val_preds, -1)\n#         each_loop = np.concatenate((each_loop, val_preds), 0) \n#     pred_list.append(each_loop)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.541621Z","iopub.status.idle":"2021-05-25T08:51:07.542302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# pred_list = np.array(pred_list)\n# pred_list.shape","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.543608Z","iopub.status.idle":"2021-05-25T08:51:07.544279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# pred_list[:, 0]","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.545717Z","iopub.status.idle":"2021-05-25T08:51:07.546405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# np.mean(np.where(val.label.values==stats.mode(pred_list)[0].reshape((-1,)), 1, 0))","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.547774Z","iopub.status.idle":"2021-05-25T08:51:07.548505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## predict on test data","metadata":{}},{"cell_type":"code","source":"@tf.function\ndef process_img(path):\n    img = tf.io.read_file(path)\n    img = tf.image.decode_jpeg(img, channels=3) \n    return img","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.549874Z","iopub.status.idle":"2021-05-25T08:51:07.550659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_FILENAMES = tf.io.gfile.glob('../input/cassava-leaf-disease-classification/test_images/*.jpg')\n# TEST_FILENAMES","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.551862Z","iopub.status.idle":"2021-05-25T08:51:07.552560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = tf.data.Dataset.from_tensor_slices((TEST_FILENAMES))\\\n                .map(process_img, num_parallel_calls = tf.data.experimental.AUTOTUNE)\\\n                .batch(batch_size)\\\n                .prefetch(tf.data.experimental.AUTOTUNE) ","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.554029Z","iopub.status.idle":"2021-05-25T08:51:07.554904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"probabilities = model.predict(test_ds)\npredictions = np.argmax(probabilities, axis=-1)\n# print(predictions)","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.556190Z","iopub.status.idle":"2021-05-25T08:51:07.556957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ids = [os.path.split(path)[1] for path in TEST_FILENAMES]\n# test_ids\nsubmission = pd.DataFrame({'image_id': test_ids, 'label': predictions})\n\nsubmission.to_csv('submission.csv', index = False)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2021-05-25T08:51:07.558111Z","iopub.status.idle":"2021-05-25T08:51:07.558791Z"},"trusted":true},"execution_count":null,"outputs":[]}]}