{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":24800,"databundleVersionId":1831594,"sourceType":"competition"},{"sourceId":1810938,"sourceType":"datasetVersion","datasetId":1075803}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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)\n\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":"2024-04-12T15:31:19.627018Z","iopub.execute_input":"2024-04-12T15:31:19.627695Z","iopub.status.idle":"2024-04-12T15:31:21.234054Z","shell.execute_reply.started":"2024-04-12T15:31:19.627653Z","shell.execute_reply":"2024-04-12T15:31:21.233268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display generic output messages\n!pip install colorama\n\n# Library for visualizing bounding boxes\n!pip install bbox-visualizer\n\n# Install ONNX library, will be used to convert from pytorch model to a tf model\n!pip install onnx onnxruntime onnxsim onnx-tf","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:31:21.238315Z","iopub.execute_input":"2024-04-12T15:31:21.238559Z","iopub.status.idle":"2024-04-12T15:32:04.850491Z","shell.execute_reply.started":"2024-04-12T15:31:21.238536Z","shell.execute_reply":"2024-04-12T15:32:04.849221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import bbox_visualizer as bbv\nimport cv2\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport shutil, os\nimport tensorflow as tf\nimport yaml\n\nfrom colorama import Fore, Back, Style\nfrom IPython.display import Image, display, clear_output\nfrom sklearn.model_selection import GroupShuffleSplit \nfrom tqdm.notebook import tqdm\nfrom typing import List","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:32:04.854785Z","iopub.execute_input":"2024-04-12T15:32:04.855593Z","iopub.status.idle":"2024-04-12T15:32:26.372227Z","shell.execute_reply.started":"2024-04-12T15:32:04.855558Z","shell.execute_reply":"2024-04-12T15:32:26.371404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !rm -rf /kaggle/working/data\n!mkdir -p /kaggle/working/data","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:32:26.373331Z","iopub.execute_input":"2024-04-12T15:32:26.373846Z","iopub.status.idle":"2024-04-12T15:32:27.361782Z","shell.execute_reply.started":"2024-04-12T15:32:26.373821Z","shell.execute_reply":"2024-04-12T15:32:27.36034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp -r /kaggle/input/vinbigdata-chest-xray-resized-png-1024x1024/* /kaggle/working/data/","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:32:27.363641Z","iopub.execute_input":"2024-04-12T15:32:27.364092Z","iopub.status.idle":"2024-04-12T15:38:30.85547Z","shell.execute_reply.started":"2024-04-12T15:32:27.364051Z","shell.execute_reply":"2024-04-12T15:38:30.854334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp /kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv /kaggle/working/data/","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:30.857063Z","iopub.execute_input":"2024-04-12T15:38:30.857399Z","iopub.status.idle":"2024-04-12T15:38:31.900197Z","shell.execute_reply.started":"2024-04-12T15:38:30.85737Z","shell.execute_reply":"2024-04-12T15:38:31.89909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Clone the YoloV9 repository, install the libray, and obtain the model\n!git clone https://github.com/WongKinYiu/yolov9.git\n!wget https://github.com/WongKinYiu/yolov9/releases/download/v0.1/yolov9-e.pt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:31.901595Z","iopub.execute_input":"2024-04-12T15:38:31.901907Z","iopub.status.idle":"2024-04-12T15:38:36.224529Z","shell.execute_reply.started":"2024-04-12T15:38:31.901879Z","shell.execute_reply":"2024-04-12T15:38:36.223553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!wget https://github.com/WongKinYiu/yolov9/releases/download/v0.1/yolov9-c.pt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:36.226109Z","iopub.execute_input":"2024-04-12T15:38:36.226538Z","iopub.status.idle":"2024-04-12T15:38:37.983395Z","shell.execute_reply.started":"2024-04-12T15:38:36.226498Z","shell.execute_reply":"2024-04-12T15:38:37.982313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!wget https://github.com/WongKinYiu/yolov9/releases/download/v0.1/gelan-c.pt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:37.986858Z","iopub.execute_input":"2024-04-12T15:38:37.987166Z","iopub.status.idle":"2024-04-12T15:38:39.56736Z","shell.execute_reply.started":"2024-04-12T15:38:37.987138Z","shell.execute_reply":"2024-04-12T15:38:39.566282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -r /kaggle/working/yolov9/requirements.txt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:39.568842Z","iopub.execute_input":"2024-04-12T15:38:39.569188Z","iopub.status.idle":"2024-04-12T15:38:53.408602Z","shell.execute_reply.started":"2024-04-12T15:38:39.569137Z","shell.execute_reply":"2024-04-12T15:38:53.407472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMAGE_SIZE = 1024\nTRAIN_IMAGES_DIRECTORY = '/kaggle/working/data/train/'\nTEST_IMAGES_DIRECTORY = '/kaggle/working/data/test/'\n\nTRAIN_IMAGES_PATH_REFACTORED = '/kaggle/working/refactored_data/images/train/'\nTRAIN_LABELS_PATH_REFACTORED = '/kaggle/working/refactored_data/labels/train/'\nVALID_IMAGES_PATH_REFACTORED = '/kaggle/working/refactored_data/images/val/'\nVALID_LABELS_PATH_REFACTORED = '/kaggle/working/refactored_data/labels/val/'","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:53.410248Z","iopub.execute_input":"2024-04-12T15:38:53.41063Z","iopub.status.idle":"2024-04-12T15:38:53.416769Z","shell.execute_reply.started":"2024-04-12T15:38:53.410592Z","shell.execute_reply":"2024-04-12T15:38:53.415866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prime_dataset() -> List[pd.DataFrame]:\n    \"\"\"\n    Ready the dataset and partition it into training and validation folders.\n\n    :return: Two datasets, one raw and another preprocessed\n    \"\"\"\n\n    # Read dataset manifest\n    train_df = pd.read_csv('/kaggle/working/data/train.csv')\n    train_meta_df = pd.read_csv('/kaggle/working/data/train_meta.csv')\n\n    # YOLO does not need images with no classes\n    train_df = train_df[train_df['class_name'] != 'No finding']\n\n    # Merge train_meta_df with train_df, to obtain the image's width and height\n    train_df = train_df.merge(train_meta_df, on='image_id')\n\n    # Modify the manifest to be compatible with YOLO; since it requires the absolute center position, in addition to \n    # the width and height\n    train_df['x_min'] = train_df['x_min'] / train_df['dim1']\n    train_df['y_min'] = train_df['y_min'] / train_df['dim0']\n\n    train_df['x_max'] = train_df['x_max'] / train_df['dim1']\n    train_df['y_max'] = train_df['y_max'] / train_df['dim0']\n\n    train_df['x_center'] = (train_df['x_max'] + train_df['x_min']) / 2\n    train_df['y_center'] = (train_df['y_max'] + train_df['y_min']) / 2\n\n    train_df['w'] = (train_df['x_max'] - train_df['x_min'])\n    train_df['h'] = (train_df['y_max'] - train_df['y_min'])\n\n    # Training/validation splitting\n    splitter = GroupShuffleSplit(test_size=0.1)\n    split = splitter.split(train_df, groups=train_df['image_id'])\n    train_inds, valid_inds = next(split)\n\n    valid_df = train_df.iloc[valid_inds]\n    train_df = train_df.iloc[train_inds]\n\n    # Create images and labels directories for both training and validation\n    for folder in [\n        TRAIN_IMAGES_PATH_REFACTORED,\n        TRAIN_LABELS_PATH_REFACTORED,\n        VALID_IMAGES_PATH_REFACTORED,\n        VALID_LABELS_PATH_REFACTORED,\n    ]:\n        os.makedirs(folder, exist_ok=True)\n\n    # Copy training images to its designated directory, and create a txt file for each image denoting its classes and their positions\n    for image in tqdm(train_df['image_id'].unique()):\n        records = train_df[train_df['image_id'] == image]\n        attributes = records[['class_id', 'x_center', 'y_center', 'w', 'h']].values\n        attributes = np.array(attributes)\n        np.savetxt(\n            os.path.join(\n                TRAIN_LABELS_PATH_REFACTORED,\n                f'{image}.txt'\n            ),\n            attributes,\n            fmt=['%d', '%f', '%f', '%f', '%f']\n        )\n        shutil.copy(\n            os.path.join(\n                TRAIN_IMAGES_DIRECTORY,\n                f'{image}.png'\n            ),\n            TRAIN_IMAGES_PATH_REFACTORED\n        )\n\n    # Copy validation images to its designated directory, and create a txt file for each image denoting its classes and their positions\n    for image in tqdm(valid_df['image_id'].unique()):\n        records = valid_df[valid_df['image_id'] == image]\n        attributes = records[['class_id', 'x_center', 'y_center', 'w', 'h']].values\n        attributes = np.array(attributes)\n        np.savetxt(\n            os.path.join(\n                VALID_LABELS_PATH_REFACTORED,\n                f'{image}.txt'\n            ),\n            attributes,\n            fmt=['%d', '%f', '%f', '%f', '%f']\n        )\n        shutil.copy(\n            os.path.join(\n                TRAIN_IMAGES_DIRECTORY,\n                f'{image}.png'\n            ),\n            VALID_IMAGES_PATH_REFACTORED\n        )\n\n    # Order the classes based on the class ID numerical value (in an ascending order)\n    class_ids, class_names = list(zip(*set(zip(train_df['class_id'], train_df['class_name']))))\n    classes = list(np.array(class_names)[np.argsort(class_ids)])\n    classes = list(map(lambda x: str(x), classes))\n\n    # Store a list containing the path of each training image in a TXT file\n    with open('train.txt', 'w') as f:\n        for path in os.listdir(TRAIN_IMAGES_PATH_REFACTORED):\n            f.write(f'{TRAIN_IMAGES_PATH_REFACTORED}{path}\\n')\n\n    # Store a list containing the path of each validation image in a TXT file\n    with open('valid.txt', 'w') as f:\n        for path in os.listdir(VALID_IMAGES_PATH_REFACTORED):\n            f.write(f'{VALID_IMAGES_PATH_REFACTORED}{path}\\n')\n\n    # Create a dictionary containing the necessary configurations to run YOLO\n    data = dict(\n        train='train.txt',\n        val='valid.txt',\n        nc=14,\n        names=classes\n    )\n\n    # Store the configurations in a YAML file, to be absorbed later by YOLO\n    with open('yolo.yaml', 'w') as outfile:\n        yaml.dump(data, outfile, default_flow_style=False)\n\n    return [pd.read_csv('/kaggle/working/data/train.csv'), train_df]","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:53.418143Z","iopub.execute_input":"2024-04-12T15:38:53.41847Z","iopub.status.idle":"2024-04-12T15:38:53.439006Z","shell.execute_reply.started":"2024-04-12T15:38:53.418446Z","shell.execute_reply":"2024-04-12T15:38:53.438121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(\n        visualize: bool = False,\n        export_as_onnx: bool = False,\n        export_as_tf: bool = False,\n        export_as_tflite: bool = False,\n):\n    \"\"\"\n    Builds the model, and export a PyTorch model.\n\n    :param bool visualize: Specify whether to carry out the evaluation metrics on the created model or not (show plots containing multiple evaluation metrics, including the confusion matrix and the precision-recall curve)\n    :param bool export_as_onnx: Specify whether to export the model in a notation that is interpretable by ONNX or not\n    :param bool export_as_tf: Specify whether to export the model in a notation that is interpretable by TensorFlow or not, ignores export_as_onnx value when set to True\n    :param bool export_as_tflite: Specify whether to export the model in a notation that is interpretable by TensorFlow and optimized on edge devices or not, ignores export_as_onnx and export_as_tf values when set to True\n    \"\"\"\n\n    !torchrun --nproc_per_node=2 --master_port 9527 /kaggle/working/yolov9/train_dual.py --device 0,1 --sync-bn --img {IMAGE_SIZE} --cfg /kaggle/working/yolov9/models/detect/yolov9-c.yaml --batch-size 8 --epochs 50 --data yolo.yaml --weights /kaggle/working/yolov9-c.pt --hyp /kaggle/working/yolov9/data/hyps/hyp.scratch-high.yaml --min-items 0 --close-mosaic 15\n    # !torchrun --nproc_per_node=2 --master_port 9527 /kaggle/working/yolov9/train_dual.py --device 0,1 --sync-bn --img {IMAGE_SIZE} --cfg /kaggle/working/yolov9/models/detect/yolov9-c.yaml --batch-size 8 --epochs 50 --data yolo.yaml --resume /kaggle/working/yolov9/runs/train/exp6/weights/last.pt\n\n    if visualize:\n        # Modify matplotlib figure size, and remove axis lines and ticks\n        plt.rcParams.update({\n            'figure.figsize': (15, 8),\n            'axes.spines.left': False,\n            'axes.spines.right': False,\n            'axes.spines.bottom': False,\n            'axes.spines.top': False,\n            'xtick.bottom': False,\n            'xtick.labelbottom': False,\n            'ytick.labelleft': False,\n            'ytick.left': False,\n        })\n\n        plt.imshow(plt.imread('runs/train/exp/results.png'))\n        plt.imshow(plt.imread('runs/train/exp/PR_curve.png'))\n        plt.imshow(plt.imread('runs/train/exp/confusion_matrix.png'))\n\n        plt.rcParams.update(plt.rcParamsDefault)\n        plt.rcParams.update({'figure.figsize': (15, 8)})\n\n    if export_as_onnx or export_as_tf or export_as_tflite:\n        !python yolov9/export.py --weights yolov9-c.pt --img-size {IMAGE_SIZE} {IMAGE_SIZE} --max-wh {IMAGE_SIZE} --grid --end2end --simplify\n\n        if export_as_tf or export_as_tflite:\n            !onnx-tf convert -i yolov9.onnx -o ./\n\n            if export_as_tflite:\n                converter = tf.lite.TFLiteConverter.from_saved_model('./')\n                tflite_model = converter.convert()\n                with open('yolov9.tflite', 'wb') as f:\n                    f.write(tflite_model)","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:53.440342Z","iopub.execute_input":"2024-04-12T15:38:53.440627Z","iopub.status.idle":"2024-04-12T15:38:53.467144Z","shell.execute_reply.started":"2024-04-12T15:38:53.440604Z","shell.execute_reply":"2024-04-12T15:38:53.466141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"raw_df, preprocessed_df = prime_dataset()","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:38:53.468072Z","iopub.execute_input":"2024-04-12T15:38:53.468323Z","iopub.status.idle":"2024-04-12T15:39:28.655498Z","shell.execute_reply.started":"2024-04-12T15:38:53.468303Z","shell.execute_reply":"2024-04-12T15:39:28.654499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip uninstall -y wandb","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:39:28.656872Z","iopub.execute_input":"2024-04-12T15:39:28.657271Z","iopub.status.idle":"2024-04-12T15:39:33.094498Z","shell.execute_reply.started":"2024-04-12T15:39:28.657236Z","shell.execute_reply":"2024-04-12T15:39:33.093343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# rm -rf /kaggle/output/yolov7.pt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:39:33.096142Z","iopub.execute_input":"2024-04-12T15:39:33.096535Z","iopub.status.idle":"2024-04-12T15:39:33.10133Z","shell.execute_reply.started":"2024-04-12T15:39:33.096506Z","shell.execute_reply":"2024-04-12T15:39:33.100499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp /kaggle/working/valid.txt /kaggle/working/yolov9/valid.txt\n!cp /kaggle/working/train.txt /kaggle/working/yolov9/train.txt","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:39:33.102505Z","iopub.execute_input":"2024-04-12T15:39:33.102776Z","iopub.status.idle":"2024-04-12T15:39:36.538492Z","shell.execute_reply.started":"2024-04-12T15:39:33.102752Z","shell.execute_reply":"2024-04-12T15:39:36.537305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# rm -rf /kaggle/working/yolov9/runs","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:39:36.539966Z","iopub.execute_input":"2024-04-12T15:39:36.540307Z","iopub.status.idle":"2024-04-12T15:39:36.54495Z","shell.execute_reply.started":"2024-04-12T15:39:36.540276Z","shell.execute_reply":"2024-04-12T15:39:36.544093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_model()","metadata":{"execution":{"iopub.status.busy":"2024-04-12T15:39:36.546149Z","iopub.execute_input":"2024-04-12T15:39:36.546416Z"},"trusted":true},"execution_count":null,"outputs":[]}]}