{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":936546,"sourceType":"datasetVersion","datasetId":504915}],"dockerImageVersionId":30683,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Cassava Leaf Disease Classification\n\n## Using CNN classifier in Tensorflow\n<!-- [asd](#DataLoading) -->\n- [X] 18-04-2024: made basic data loading scripts and model training scripts\n- [X] 19-04-2024: loading weights from dataset, added comet for logging, added metrics f1 score and confusion matrix\n- [X] 20-04-2024: read discussion section,trained on 512 image_size,\n- [ ] 21-04-2024:\n- [ ] 22-04-2024:\n- [ ] 23-04-2024:\n- [ ] 24-04-2024:\n\n## Problems :-\n- Huge Class imbalance specially for the class idx 3 with more than 12000 examples and others are around 2000\n- Noisy training logs indicating mislabeled data\n\n## Ideas :-\n- [X] **baseline :** (public/private) (0.7605/0.7483)\n- [X] **use image_size = 512 :** does helps (public/private) (0.7875/0.7938)\n- [X] **use label smoothing handling training with mislabeled data:** does helps too (0.7718/0.7748)\n- [X] **use class weights for class imbalance :** doesn't helps (0.7375/0.7542)\n- [X] **use augmentation+dropout+label_smoothing+60_epochs:** (0.8253/0.8383)\n- [ ] **use undersampling for class imbalance**\n- [ ] **use oversampling for class imbalance**\n","metadata":{}},{"cell_type":"markdown","source":"## Configs","metadata":{}},{"cell_type":"code","source":"image_size = 224\n# image_size = 512","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:26.884634Z","iopub.execute_input":"2024-04-21T13:09:26.884983Z","iopub.status.idle":"2024-04-21T13:09:26.895521Z","shell.execute_reply.started":"2024-04-21T13:09:26.884954Z","shell.execute_reply":"2024-04-21T13:09:26.894658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install comet_ml --quiet","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:28.011935Z","iopub.execute_input":"2024-04-21T13:09:28.012524Z","iopub.status.idle":"2024-04-21T13:09:28.016226Z","shell.execute_reply.started":"2024-04-21T13:09:28.012497Z","shell.execute_reply":"2024-04-21T13:09:28.015337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Loading","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\n\ndataset_dir = Path('/kaggle/input/cassava-leaf-disease-classification')\n!ls {dataset_dir}","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-21T13:09:29.411928Z","iopub.execute_input":"2024-04-21T13:09:29.412254Z","iopub.status.idle":"2024-04-21T13:09:30.346773Z","shell.execute_reply.started":"2024-04-21T13:09:29.412231Z","shell.execute_reply":"2024-04-21T13:09:30.345842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from comet_ml import Experiment\nimport os, shutil\nfrom glob import glob\nimport cv2\nimport pandas as pd\nimport json\nimport random\nimport math\nfrom pathlib import Path\nimport numpy as np\nimport matplotlib.pyplot as plt\n\ntrain_dir = str(dataset_dir / Path(\"train_images\"))\ntest_dir = str(dataset_dir / Path(\"test_images\"))\n\ntrain_df = pd.read_csv(dataset_dir / Path(\"train.csv\"))\ntrain_df[\"image_id\"] = train_dir+\"/\"+train_df[\"image_id\"] \n\nidx_to_label = json.load(open(dataset_dir / Path(\"label_num_to_disease_map.json\"),\"r\"))\nidx_to_label = {int(idx):label for idx,label in idx_to_label.items()}\nlabel_to_idx = {label:idx for idx,label in idx_to_label.items()}\nnum_classes = len(idx_to_label)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:30.348466Z","iopub.execute_input":"2024-04-21T13:09:30.348739Z","iopub.status.idle":"2024-04-21T13:09:31.456917Z","shell.execute_reply.started":"2024-04-21T13:09:30.348715Z","shell.execute_reply":"2024-04-21T13:09:31.455989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:31.458600Z","iopub.execute_input":"2024-04-21T13:09:31.458956Z","iopub.status.idle":"2024-04-21T13:09:31.475921Z","shell.execute_reply.started":"2024-04-21T13:09:31.458926Z","shell.execute_reply":"2024-04-21T13:09:31.474995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.iloc[0][\"image_id\"]","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:32.250187Z","iopub.execute_input":"2024-04-21T13:09:32.250526Z","iopub.status.idle":"2024-04-21T13:09:32.256808Z","shell.execute_reply.started":"2024-04-21T13:09:32.250500Z","shell.execute_reply":"2024-04-21T13:09:32.255901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check for missing value\ncolumns_isna_sum = train_df.isna().sum()\nfor value in columns_isna_sum:\n    assert(value==0)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:37.833416Z","iopub.execute_input":"2024-04-21T13:09:37.834049Z","iopub.status.idle":"2024-04-21T13:09:37.842938Z","shell.execute_reply.started":"2024-04-21T13:09:37.834000Z","shell.execute_reply":"2024-04-21T13:09:37.841946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# shuffle the dataset\nrandom.seed(65)\nrandom_idxs = np.random.permutation(np.arange(0,len(train_df)))\ntrain_df = train_df.iloc[random_idxs]","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:38.412143Z","iopub.execute_input":"2024-04-21T13:09:38.412488Z","iopub.status.idle":"2024-04-21T13:09:38.424933Z","shell.execute_reply.started":"2024-04-21T13:09:38.412461Z","shell.execute_reply":"2024-04-21T13:09:38.424056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# split data\ntrain_split_ratio = 0.9\nsplit_idx = math.floor(len(train_df)*train_split_ratio)\ntrain_split,val_split = train_df.iloc[:split_idx],train_df.iloc[split_idx:]\n\nprint(\"train_split examples:\\t\",len(train_split))\nprint(\"val_split examples:\\t\",len(val_split))","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:42.773210Z","iopub.execute_input":"2024-04-21T13:09:42.773561Z","iopub.status.idle":"2024-04-21T13:09:42.780009Z","shell.execute_reply.started":"2024-04-21T13:09:42.773535Z","shell.execute_reply":"2024-04-21T13:09:42.778976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure()\nplt.title(\"dataset split\")\nplt.bar(\"train\",len(train_split),color=\"blue\",width=0.7)\nplt.bar(\"val\",len(val_split),color=\"purple\",width=0.7)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:09:45.981960Z","iopub.execute_input":"2024-04-21T13:09:45.982667Z","iopub.status.idle":"2024-04-21T13:09:46.231601Z","shell.execute_reply.started":"2024-04-21T13:09:45.982634Z","shell.execute_reply":"2024-04-21T13:09:46.230667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## tf.data.Dataset pipeline","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport albumentations as A\n\ntrain_aug = A.Compose([\n    A.VerticalFlip(p=0.5),\n    A.HorizontalFlip(p=0.5),\n    A.RandomBrightnessContrast(p=0.6,brightness_limit=(-0.2,0.5),contrast_limit=(-0.5,0.5)),\n    A.Rotate(limit=(-40,40)),\n    A.CoarseDropout(p=0.8, max_holes=15, max_height=15, max_width=15)\n])\n\ndef load_image(imagename):\n    img = tf.io.read_file(imagename)\n    img = tf.image.decode_image(img,3,expand_animations=False)\n    img = tf.image.resize(img,[image_size,image_size])\n    return img\n\ndef load_data(imagename,label_idx):\n    # load image\n    img = load_image(imagename)\n    \n    # one_hot encode\n    one_hot = tf.one_hot(label_idx,num_classes)\n    \n    return img,one_hot\n\ndef tf_augment(image,one_hot):\n    def f(image):\n        return train_aug(image=image/255.0)[\"image\"]*255.0\n    image = tf.numpy_function(f,[image],tf.float32)\n    image.set_shape((image_size,image_size,3))\n    return image,one_hot\n    \ndef get_dataset(df,batch_size=4,shuffle=False,prefetch=False,cache=False,is_val=False):\n    ds = tf.data.Dataset.from_tensor_slices((df[\"image_id\"].to_numpy(),df[\"label\"].to_numpy()))\n    if shuffle:    ds = ds.shuffle(len(df))\n    ds = ds.map(load_data,num_parallel_calls=tf.data.AUTOTUNE)\n    if not is_val: ds = ds.map(tf_augment,num_parallel_calls=tf.data.AUTOTUNE)\n    ds = ds.batch(batch_size,num_parallel_calls=tf.data.AUTOTUNE,drop_remainder=not is_val)\n    \n    if prefetch:    ds = ds.prefetch(tf.data.AUTOTUNE)\n    if cache:    ds = ds.cache()\n    \n    return ds\n\nget_dataset(train_split)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:18:50.281135Z","iopub.execute_input":"2024-04-21T13:18:50.281975Z","iopub.status.idle":"2024-04-21T13:18:50.380629Z","shell.execute_reply.started":"2024-04-21T13:18:50.281943Z","shell.execute_reply":"2024-04-21T13:18:50.379678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Visualization","metadata":{}},{"cell_type":"code","source":"plt.figure()\nplt.title(\"dataset class images distribution\")\nfor idx in idx_to_label:\n    count = (train_df[\"label\"]==idx).sum()\n    plt.bar(str(idx), count, color ='maroon', width = 0.4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:18:51.416643Z","iopub.execute_input":"2024-04-21T13:18:51.417501Z","iopub.status.idle":"2024-04-21T13:18:51.598994Z","shell.execute_reply.started":"2024-04-21T13:18:51.417470Z","shell.execute_reply":"2024-04-21T13:18:51.598155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure()\nplt.title(\"Train dataset class images distribution\")\nfor idx in idx_to_label:\n    count = (train_split[\"label\"]==idx).sum()\n    plt.bar(str(idx), count, color ='blue', width = 0.4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:18:51.716520Z","iopub.execute_input":"2024-04-21T13:18:51.716876Z","iopub.status.idle":"2024-04-21T13:18:51.957012Z","shell.execute_reply.started":"2024-04-21T13:18:51.716849Z","shell.execute_reply":"2024-04-21T13:18:51.956072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure()\nplt.title(\"Val dataset class images distribution\")\nfor idx in idx_to_label:\n    count = (val_split[\"label\"]==idx).sum()\n    plt.bar(str(idx), count, color ='purple', width = 0.4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:18:52.049656Z","iopub.execute_input":"2024-04-21T13:18:52.050475Z","iopub.status.idle":"2024-04-21T13:18:52.290411Z","shell.execute_reply.started":"2024-04-21T13:18:52.050442Z","shell.execute_reply":"2024-04-21T13:18:52.289455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def single_plot(img,label_idx):\n    plt.title(idx_to_label[label_idx])\n#     plt.title(f\"{img.min()},{img.max()}\")\n    plt.axis(\"off\")\n    plt.imshow(img.astype('uint8'))\n\ndef see_batch(df, cols=3, batch_size=6, shuffle=False):\n\n    ds = get_dataset(df,batch_size,shuffle=shuffle)\n    rows = math.ceil(batch_size/cols)\n    fig = plt.figure(figsize=(cols*5,rows*5))\n    data = next(iter(ds))\n    for i in range(batch_size):\n        img,one_hot = data[0][i].numpy(),data[1][i].numpy()\n        label_idx = np.argmax(one_hot)\n        fig.add_subplot(rows,cols,i+1)\n        single_plot(img,label_idx)\n    plt.show()\n    \nsee_batch(train_split)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T13:18:52.599730Z","iopub.execute_input":"2024-04-21T13:18:52.600102Z","iopub.status.idle":"2024-04-21T13:18:53.813580Z","shell.execute_reply.started":"2024-04-21T13:18:52.600073Z","shell.execute_reply":"2024-04-21T13:18:53.812667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# see_batch(train_split)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:37:59.786064Z","iopub.execute_input":"2024-04-21T07:37:59.786478Z","iopub.status.idle":"2024-04-21T07:37:59.790770Z","shell.execute_reply.started":"2024-04-21T07:37:59.786445Z","shell.execute_reply":"2024-04-21T07:37:59.789824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize label 0\n# see_batch(train_df[train_df[\"label\"]==0])","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.143756Z","iopub.execute_input":"2024-04-21T06:37:59.144054Z","iopub.status.idle":"2024-04-21T06:37:59.157223Z","shell.execute_reply.started":"2024-04-21T06:37:59.144028Z","shell.execute_reply":"2024-04-21T06:37:59.156402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize label 1\n# see_batch(train_df[train_df[\"label\"]==1],shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.158498Z","iopub.execute_input":"2024-04-21T06:37:59.158820Z","iopub.status.idle":"2024-04-21T06:37:59.167027Z","shell.execute_reply.started":"2024-04-21T06:37:59.158794Z","shell.execute_reply":"2024-04-21T06:37:59.166055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize label 2\n# see_batch(train_df[train_df[\"label\"]==2])","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.168148Z","iopub.execute_input":"2024-04-21T06:37:59.168521Z","iopub.status.idle":"2024-04-21T06:37:59.177013Z","shell.execute_reply.started":"2024-04-21T06:37:59.168490Z","shell.execute_reply":"2024-04-21T06:37:59.176071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize label 3\n# see_batch(train_df[train_df[\"label\"]==3])","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.178142Z","iopub.execute_input":"2024-04-21T06:37:59.178762Z","iopub.status.idle":"2024-04-21T06:37:59.186776Z","shell.execute_reply.started":"2024-04-21T06:37:59.178730Z","shell.execute_reply":"2024-04-21T06:37:59.186018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize label 4\n# see_batch(train_df[train_df[\"label\"]==4],shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.189545Z","iopub.execute_input":"2024-04-21T06:37:59.189797Z","iopub.status.idle":"2024-04-21T06:37:59.196510Z","shell.execute_reply.started":"2024-04-21T06:37:59.189776Z","shell.execute_reply":"2024-04-21T06:37:59.195672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# cv2.imread(glob(train_dir+\"/*\")[0]).shape","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:37:59.197583Z","iopub.execute_input":"2024-04-21T06:37:59.197918Z","iopub.status.idle":"2024-04-21T06:37:59.206026Z","shell.execute_reply.started":"2024-04-21T06:37:59.197885Z","shell.execute_reply":"2024-04-21T06:37:59.205186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating a Model","metadata":{}},{"cell_type":"code","source":"resnet50_notop_weights_path = '/kaggle/input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:38:05.040482Z","iopub.execute_input":"2024-04-21T07:38:05.040842Z","iopub.status.idle":"2024-04-21T07:38:05.045565Z","shell.execute_reply.started":"2024-04-21T07:38:05.040816Z","shell.execute_reply":"2024-04-21T07:38:05.044555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras import layers,Model,Sequential\n\n# pretrained resnet50 model with added dense layers\n\ndef resnet50():\n    backbone = tf.keras.applications.ResNet50(include_top=False, weights=resnet50_notop_weights_path)\n    \n    x_input_layer = layers.Input(shape=[image_size,image_size,3])\n    x = layers.Lambda(tf.keras.applications.resnet50.preprocess_input)(x_input_layer)\n    x = backbone(x)\n    x = layers.GlobalMaxPooling2D()(x)\n    x = layers.Dropout(0.3)(x)\n    x = layers.Dense(512,activation=\"relu\")(x)\n    x = layers.Dense(256,activation=\"relu\")(x)\n    x = layers.Dense(256,activation=\"relu\")(x)\n    x = layers.Dense(256,activation=\"relu\")(x)\n    x = layers.Dense(128,activation=\"relu\")(x)\n    x = layers.Dense(num_classes,activation=\"softmax\")(x)\n    model = Model(x_input_layer,x,name=\"resnet50_model\")\n    return model\n\nmodel = resnet50()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:45:22.959971Z","iopub.execute_input":"2024-04-21T07:45:22.960343Z","iopub.status.idle":"2024-04-21T07:45:25.191540Z","shell.execute_reply.started":"2024-04-21T07:45:22.960312Z","shell.execute_reply":"2024-04-21T07:45:25.190559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test Model run","metadata":{}},{"cell_type":"code","source":"data = next(iter(get_dataset(val_split)))\ny_pred = model.predict(data[0])\nprint(\"y_pred shape:\\t\",y_pred.shape)\nprint(\"y_pred:\\t\",y_pred)\nprint(\"y_pred label:\\t\",np.argmax(y_pred,axis=-1))","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:45:25.193251Z","iopub.execute_input":"2024-04-21T07:45:25.193561Z","iopub.status.idle":"2024-04-21T07:45:29.601219Z","shell.execute_reply.started":"2024-04-21T07:45:25.193536Z","shell.execute_reply":"2024-04-21T07:45:29.600242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Metrics","metadata":{}},{"cell_type":"code","source":"from tqdm import tqdm\nimport sklearn.metrics\nfrom sklearn.utils.class_weight import compute_class_weight\n\ndef get_all_metrics(y_true,y_pred,class_idx):\n    TP = 0\n    FP = 0\n    TN = 0\n    FN = 0\n    for i in range(len(y_true)):\n        if class_idx == y_true[i]:\n            if class_idx == y_pred[i]:\n                TP+=1\n            else:\n                FN+=1\n        else:\n            if class_idx == y_pred[i]:\n                FP+=1\n            else:\n                TN+=1\n    \n    return TP,FP,TN,FN\n\ndef get_metrics(y_true,y_pred,class_idx):\n    epsilon = 1e-8\n    TP,FP,TN,FN = get_all_metrics(y_true,y_pred,class_idx)\n    precision = TP / (TP+FP+epsilon)   # number of times we correctly classified it positive out of all the times we said it positive\n    recall = TP / (TP+FN+epsilon)    # number of time we correctly classified it positive out of all the actual positive examples\n    accuracy = (TP+TN) / (TP+TN+FP+FN+epsilon) # correct / total\n    f1 = (2*precision*recall)/(precision+recall+epsilon)\n    # support = \n    return {\n        \"precision\":precision,\n        \"recall\":recall,\n        \"accuracy\":accuracy,\n        \"f1\":f1,\n    }\n\ndef ds_to_ytrue_ypred(ds):\n    y_true = np.array([])\n    y_pred = np.array([])\n    for data in tqdm(ds):\n        y_true_batch = data[1].numpy()\n        y_pred_batch = model.predict(data[0],verbose=0)\n        \n        y_true_batch = y_true_batch.argmax(axis=-1)\n        y_pred_batch = y_pred_batch.argmax(axis=-1)\n        \n        y_true = np.r_[y_true,y_true_batch]\n        y_pred = np.r_[y_pred,y_pred_batch]\n        \n    return y_true,y_pred\n\ndef classification_analysis(ds,logger=None,epoch=0):\n    y_true,y_pred = ds_to_ytrue_ypred(ds)\n    for i in range(num_classes):\n        metrics = get_metrics(y_true,y_pred,class_idx=i)\n        print(\"precision:{:0.2f} recall:{:0.2f} acc:{:0.2f} f1:{:0.2f}\\tclass index:{} class name:{}\"\n              .format(metrics['precision'],metrics['recall'],metrics['accuracy'],metrics['f1'],i,idx_to_label[i]))\n        \n        if logger:\n            logger.log_metric(f\"{i}_precision\", metrics['precision'], epoch=epoch)\n            logger.log_metric(f\"{i}_recall\", metrics['recall'], epoch=epoch)\n            logger.log_metric(f\"{i}_acc\", metrics['accuracy'], epoch=epoch)\n            logger.log_metric(f\"{i}_f1_score\", metrics['f1'], epoch=epoch)\n        \n    confusion_matrix = sklearn.metrics.confusion_matrix(y_true,y_pred)\n    print(\"Confusion Matrix:\\n\",confusion_matrix)\n    if logger:\n        classes = [idx_to_label[i] for i in range(num_classes)]\n        logger.log_confusion_matrix(matrix=confusion_matrix,labels=classes,epoch=epoch)\n            \n# classification_analysis(val_ds.take(2))","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:45:29.602837Z","iopub.execute_input":"2024-04-21T07:45:29.603511Z","iopub.status.idle":"2024-04-21T07:45:29.621067Z","shell.execute_reply.started":"2024-04-21T07:45:29.603476Z","shell.execute_reply":"2024-04-21T07:45:29.620035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Callback","metadata":{}},{"cell_type":"code","source":"class MetricsCallback(tf.keras.callbacks.Callback):\n    def __init__(self,ds,logger=None):\n        self.ds = ds\n        self.logger = logger\n        \n    def on_epoch_end(self, epoch, logs=None):\n        classification_analysis(self.ds,logger=self.logger,epoch=epoch)\n        print()\n        ","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:45:29.623163Z","iopub.execute_input":"2024-04-21T07:45:29.623966Z","iopub.status.idle":"2024-04-21T07:45:29.635678Z","shell.execute_reply.started":"2024-04-21T07:45:29.623932Z","shell.execute_reply":"2024-04-21T07:45:29.634947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model Training","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import backend as K\n\nexperiment = None\n\n# from kaggle_secrets import UserSecretsClient\n# user_secrets = UserSecretsClient()\n# comet_api_key = user_secrets.get_secret(\"comet_api_key\")\n\n# experiment = Experiment(\n#   api_key=comet_api_key,\n#   project_name=\"cassava-leaf-disease-classification\",\n#   workspace=\"anujpanthri\"\n# )\n# class_weights = [2,1,1,0.2,1]\nclass_weights = compute_class_weight(class_weight=\"balanced\",\n                                     classes=list(range(num_classes)),\n                                     y=train_split['label'].to_list())\nclass_weights_dict = {i:weight for i,weight in enumerate(class_weights)}\n# print(class_weights_dict)\n\nhyper_params = {\n  \"learning_rate\": 0.001,\n  \"epochs\": 60,\n  \"batch_size\": 32,\n#   \"class_weights\": class_weights\n}\nif experiment:\n    experiment.log_parameters(hyper_params)\n    \ndef weighted_categorical_crossentropy(class_weights):\n    tf_class_weights = tf.constant([class_weights])#,dtype=tf.float32)  \n    epsilon_ = tf.constant(tf.keras.backend.epsilon())\n\n    def loss(y_true,y_pred):\n        y_pred = tf.clip_by_value(y_pred, epsilon_, 1.0 - epsilon_)\n        errors = -tf.reduce_sum(tf_class_weights*y_true*K.log(y_pred),axis=-1)\n        return errors\n    return loss\n\nmodel = resnet50()\nmodel.compile(\n#               loss=\"categorical_crossentropy\",\n#               loss=weighted_categorical_crossentropy(hyper_params[\"class_weights\"]),\n              loss=tf.keras.losses.CategoricalCrossentropy(label_smoothing=0.25),\n              optimizer=tf.keras.optimizers.Adam(learning_rate=hyper_params['learning_rate']),\n              metrics=[\"acc\"])","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:47:34.817236Z","iopub.execute_input":"2024-04-21T07:47:34.817629Z","iopub.status.idle":"2024-04-21T07:47:37.187033Z","shell.execute_reply.started":"2024-04-21T07:47:34.817598Z","shell.execute_reply":"2024-04-21T07:47:37.186185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"checkpoint_filepath = 'ckpt/checkpoint.model.weights.h5'\nmodel_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(\n    filepath=checkpoint_filepath,\n    monitor='val_acc',\n    mode='max',\n    save_best_only=True,\n    save_weights_only=True,\n    verbose=1)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:47:37.188634Z","iopub.execute_input":"2024-04-21T07:47:37.188944Z","iopub.status.idle":"2024-04-21T07:47:37.194013Z","shell.execute_reply.started":"2024-04-21T07:47:37.188916Z","shell.execute_reply":"2024-04-21T07:47:37.192900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = hyper_params['batch_size']\nepochs = hyper_params['epochs']\ntrain_ds = get_dataset(train_split,batch_size=batch_size,shuffle=True,prefetch=True,cache=False)\nval_ds = get_dataset(val_split,batch_size=batch_size,shuffle=False,prefetch=True,cache=False,is_val=True)\ncallbacks = [MetricsCallback(val_ds,logger=experiment),model_checkpoint_callback]\n\nhistory = model.fit(train_ds,validation_data=val_ds,epochs=epochs, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:47:37.195093Z","iopub.execute_input":"2024-04-21T07:47:37.195400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving Model","metadata":{}},{"cell_type":"code","source":"# !rm model.h5 mymodel.h5 mymodel.keras\n!ls .","metadata":{"execution":{"iopub.status.busy":"2024-04-19T06:44:53.963883Z","iopub.execute_input":"2024-04-19T06:44:53.964265Z","iopub.status.idle":"2024-04-19T06:44:56.102093Z","shell.execute_reply.started":"2024-04-19T06:44:53.964236Z","shell.execute_reply":"2024-04-19T06:44:56.100845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights('ckpt/checkpoint.model.weights.h5')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save(\"model.keras\")\nmodel.save_weights(\"model.weights.h5\")","metadata":{"execution":{"iopub.status.busy":"2024-04-20T03:54:03.267998Z","iopub.execute_input":"2024-04-20T03:54:03.268598Z","iopub.status.idle":"2024-04-20T03:54:05.602674Z","shell.execute_reply.started":"2024-04-20T03:54:03.268566Z","shell.execute_reply":"2024-04-20T03:54:05.601828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if experiment:\n    experiment.log_model(\"resnet50 model\", \"model.keras\")\n    experiment.log_model(\"resnet50 model\", \"model.weights.h5\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T06:45:17.487677Z","iopub.execute_input":"2024-04-19T06:45:17.488454Z","iopub.status.idle":"2024-04-19T06:45:17.492889Z","shell.execute_reply.started":"2024-04-19T06:45:17.488423Z","shell.execute_reply":"2024-04-19T06:45:17.491819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if experiment:\n    experiment.end()","metadata":{"execution":{"iopub.status.busy":"2024-04-19T06:47:14.663335Z","iopub.execute_input":"2024-04-19T06:47:14.664123Z","iopub.status.idle":"2024-04-19T06:47:14.668438Z","shell.execute_reply.started":"2024-04-19T06:47:14.664091Z","shell.execute_reply":"2024-04-19T06:47:14.667424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model validation","metadata":{}},{"cell_type":"code","source":"# model.loss","metadata":{"execution":{"iopub.status.busy":"2024-04-20T03:54:23.635874Z","iopub.execute_input":"2024-04-20T03:54:23.636705Z","iopub.status.idle":"2024-04-20T03:54:23.640628Z","shell.execute_reply.started":"2024-04-20T03:54:23.636674Z","shell.execute_reply":"2024-04-20T03:54:23.639539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classification_analysis(train_ds)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:13:58.394187Z","iopub.execute_input":"2024-04-21T07:13:58.395071Z","iopub.status.idle":"2024-04-21T07:15:01.578746Z","shell.execute_reply.started":"2024-04-21T07:13:58.395036Z","shell.execute_reply":"2024-04-21T07:15:01.577705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classification_analysis(val_ds)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:15:01.580673Z","iopub.execute_input":"2024-04-21T07:15:01.581386Z","iopub.status.idle":"2024-04-21T07:15:17.772981Z","shell.execute_reply.started":"2024-04-21T07:15:01.581349Z","shell.execute_reply":"2024-04-21T07:15:17.772035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# help(model)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T06:45:30.356291Z","iopub.execute_input":"2024-04-21T06:45:30.356657Z","iopub.status.idle":"2024-04-21T06:45:30.360714Z","shell.execute_reply.started":"2024-04-21T06:45:30.356629Z","shell.execute_reply":"2024-04-21T06:45:30.359727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model results visualization","metadata":{}},{"cell_type":"code","source":"# model.load_weights(\"/kaggle/input/cassava-leaf-disease-classification-tensorflow/model.weights.h5\")","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:09:06.582781Z","iopub.execute_input":"2024-04-21T07:09:06.583596Z","iopub.status.idle":"2024-04-21T07:09:07.860047Z","shell.execute_reply.started":"2024-04-21T07:09:06.583561Z","shell.execute_reply":"2024-04-21T07:09:07.859237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:17:12.794070Z","iopub.execute_input":"2024-04-21T07:17:12.794955Z","iopub.status.idle":"2024-04-21T07:17:12.802466Z","shell.execute_reply.started":"2024-04-21T07:17:12.794919Z","shell.execute_reply":"2024-04-21T07:17:12.801420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_true = np.array([])\nlabel_pred = np.array([])\nlosses = np.array([])\n\nfor data in tqdm(val_ds):\n    batch_y_true = data[1]\n#     batch_y_pred = model(data[0],training=False)\n    batch_y_pred = tf.cast(model.predict(data[0],verbose=0),dtype=\"float32\")\n    batch_loss = tf.keras.losses.CategoricalCrossentropy(reduction=None)(batch_y_true,batch_y_pred).numpy()\n    batch_label_true = batch_y_true.numpy().argmax(axis=-1)\n    batch_label_pred = batch_y_pred.numpy().argmax(axis=-1)\n    \n    label_true = batch_label_true if len(label_true)==0 else np.r_[label_true,batch_label_true]\n    label_pred = batch_label_pred if len(label_pred)==0 else np.r_[label_pred,batch_label_pred]\n    losses = batch_loss if len(losses)==0 else np.r_[losses,batch_loss]","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:17:37.124049Z","iopub.execute_input":"2024-04-21T07:17:37.124442Z","iopub.status.idle":"2024-04-21T07:17:57.612425Z","shell.execute_reply.started":"2024-04-21T07:17:37.124410Z","shell.execute_reply":"2024-04-21T07:17:57.611497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def single_plot_result(img,title):\n    plt.title(title)\n    plt.axis(\"off\")\n    plt.imshow(img.astype('uint8'))\n    \ntop_n = 10\nidxs = np.argsort(losses)[-top_n:][::-1]\n\ncols = 4\nrows = math.ceil(top_n/cols)\nfig = plt.figure(figsize=(cols*3,rows*3))\n\nfor i,idx in enumerate(idxs):\n    fig.add_subplot(rows,cols,i+1)\n    title = f\"{label_true[idx]}/{label_pred[idx]} loss:{losses[idx]:0.2f}\"\n    img_path = val_split.iloc[idx]['image_id']\n    img = cv2.imread(img_path)[:,:,::-1]\n    single_plot_result(img,title)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T07:17:58.054112Z","iopub.execute_input":"2024-04-21T07:17:58.054907Z","iopub.status.idle":"2024-04-21T07:17:59.801615Z","shell.execute_reply.started":"2024-04-21T07:17:58.054875Z","shell.execute_reply":"2024-04-21T07:17:59.800728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Calculating results on test data","metadata":{}},{"cell_type":"code","source":"test_list = glob(test_dir+\"/*\")\ntest_image_ids = list(map(lambda x:Path(x).name,test_list))\n                      \ntest_ds = tf.data.Dataset.from_tensor_slices(test_list)\ntest_ds = test_ds.map(load_image,num_parallel_calls=tf.data.AUTOTUNE)\ntest_ds = test_ds.batch(batch_size)\ntest_ds","metadata":{"execution":{"iopub.status.busy":"2024-04-19T05:47:37.371182Z","iopub.execute_input":"2024-04-19T05:47:37.371479Z","iopub.status.idle":"2024-04-19T05:47:37.401529Z","shell.execute_reply.started":"2024-04-19T05:47:37.371453Z","shell.execute_reply":"2024-04-19T05:47:37.400777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_preds = model.predict(test_ds)\ny_preds = y_preds.argmax(axis=-1)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T05:47:37.402522Z","iopub.execute_input":"2024-04-19T05:47:37.402818Z","iopub.status.idle":"2024-04-19T05:47:40.374791Z","shell.execute_reply.started":"2024-04-19T05:47:37.402794Z","shell.execute_reply":"2024-04-19T05:47:40.373850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test_image_ids,y_preds\ntest_df = pd.DataFrame(zip(test_image_ids,y_preds),columns=[\"image_id\",\"label\"])\ntest_df.to_csv(\"submission.csv\",index=False)\ntest_df.head()\n","metadata":{"execution":{"iopub.status.busy":"2024-04-19T05:47:40.376195Z","iopub.execute_input":"2024-04-19T05:47:40.376841Z","iopub.status.idle":"2024-04-19T05:47:40.390286Z","shell.execute_reply.started":"2024-04-19T05:47:40.376806Z","shell.execute_reply":"2024-04-19T05:47:40.389454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!head submission.csv","metadata":{"execution":{"iopub.status.busy":"2024-04-19T05:47:40.392752Z","iopub.execute_input":"2024-04-19T05:47:40.393033Z","iopub.status.idle":"2024-04-19T05:47:41.443065Z","shell.execute_reply.started":"2024-04-19T05:47:40.393010Z","shell.execute_reply":"2024-04-19T05:47:41.441980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plt.imshow(cv2.imread(test_list[0])[:,:,::-1])","metadata":{"execution":{"iopub.status.busy":"2024-04-20T03:53:29.146213Z","iopub.execute_input":"2024-04-20T03:53:29.147033Z","iopub.status.idle":"2024-04-20T03:53:29.150669Z","shell.execute_reply.started":"2024-04-20T03:53:29.146999Z","shell.execute_reply":"2024-04-20T03:53:29.149684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}