From 8a5be64c059da4ed4a6394bd4dcbfddb3f8557e0 Mon Sep 17 00:00:00 2001 From: LinasKo Date: Thu, 24 Oct 2024 16:07:02 -0500 Subject: [PATCH] Clean up: Yolov5 Classification --- ...yolov5-classification-on-custom-data.ipynb | 504 ++++++++++++++---- 1 file changed, 404 insertions(+), 100 deletions(-) diff --git a/notebooks/train-yolov5-classification-on-custom-data.ipynb b/notebooks/train-yolov5-classification-on-custom-data.ipynb index 8a54852..4276c5e 100644 --- a/notebooks/train-yolov5-classification-on-custom-data.ipynb +++ b/notebooks/train-yolov5-classification-on-custom-data.ipynb @@ -3,7 +3,9 @@ "nbformat_minor": 0, "metadata": { "colab": { - "provenance": [] + "provenance": [], + "machine_shape": "hm", + "gpuType": "A100" }, "kernelspec": { "name": "python3", @@ -12,8 +14,7 @@ "language_info": { "name": "python" }, - "accelerator": "GPU", - "gpuClass": "standard" + "accelerator": "GPU" }, "cells": [ { @@ -49,11 +50,57 @@ }, { "cell_type": "code", - "execution_count": null, + "source": [ + "# save the working directory path for later use\n", + "\n", + "import os\n", + "HOME = os.getcwd()\n", + "print(HOME)" + ], + "metadata": { + "id": "6W8YIH8ft0D5", + "outputId": "0f12c5fa-4e52-4f3e-cd31-84c048418e23", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "execution_count": 4, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/content/yolov5\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 1, "metadata": { - "id": "pIM7fOwm8A7l" + "id": "pIM7fOwm8A7l", + "outputId": "b6fc23a5-a582-40c3-f8c2-dec1efeee37c", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "outputs": [], + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "YOLOv5 ๐Ÿš€ v7.0-378-g2f74455a Python-3.10.12 torch-2.5.0+cu121 CUDA:0 (NVIDIA A100-SXM4-40GB, 40514MiB)\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Setup complete โœ… (12 CPUs, 83.5 GB RAM, 32.0/235.7 GB disk)\n" + ] + } + ], "source": [ "!git clone https://github.com/ultralytics/yolov5 # clone\n", "%cd yolov5\n", @@ -87,10 +134,36 @@ " attempt_download(f'weights/yolov5{x}.pt')" ], "metadata": { - "id": "o2scLEh6EYnL" + "id": "o2scLEh6EYnL", + "outputId": "292d9f5c-06ce-4dcf-f099-d834ae2aeba5", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5n-cls.pt to weights/yolov5n-cls.pt...\n", + "100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 4.87M/4.87M [00:00<00:00, 59.3MB/s]\n", + "\n", + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s-cls.pt to weights/yolov5s-cls.pt...\n", + "100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 10.5M/10.5M [00:00<00:00, 93.8MB/s]\n", + "\n", + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5m-cls.pt to weights/yolov5m-cls.pt...\n", + "100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 24.9M/24.9M [00:00<00:00, 112MB/s]\n", + "\n", + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5l-cls.pt to weights/yolov5l-cls.pt...\n", + "100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 50.9M/50.9M [00:00<00:00, 91.3MB/s]\n", + "\n", + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5x-cls.pt to weights/yolov5x-cls.pt...\n", + "100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 92.0M/92.0M [00:00<00:00, 133MB/s]\n", + "\n" + ] + } + ] }, { "cell_type": "markdown", @@ -104,31 +177,62 @@ { "cell_type": "code", "source": [ - "#Download example image\n", - "import requests\n", - "image_url = \"https://i.imgur.com/OczPfaz.jpg\"\n", - "response = requests.get(image_url)\n", - "response.raise_for_status()\n", - "with open('bananas.jpg', 'wb') as handler:\n", - " handler.write(response.content)" + "PATH_TO_IMAGE = f\"{HOME}/bananas.jpg\"\n", + "!curl https://i.imgur.com/OczPfaz.jpg -o {PATH_TO_IMAGE}" ], "metadata": { - "id": "L9objhVHnS-h" + "id": "M8VGa2t8tpQm", + "outputId": "938e5cd5-5f33-492a-a272-a3035652cc50", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " % Total % Received % Xferd Average Speed Time Time Time Current\n", + " Dload Upload Total Spent Left Speed\n", + "100 408k 100 408k 0 0 2097k 0 --:--:-- --:--:-- --:--:-- 2107k\n" + ] + } + ] }, { "cell_type": "code", "source": [ - "#Infer using classify/predict.py\n", + "# Infer using classify/predict.py\n", "!python classify/predict.py --weights ./weigths/yolov5s-cls.pt --source bananas.jpg" ], "metadata": { - "id": "qqxF5pHCrLd3" + "id": "qqxF5pHCrLd3", + "outputId": "db59a5a0-0f27-48e8-94c0-88843c0634a3", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 6, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\u001b[34m\u001b[1mclassify/predict: \u001b[0mweights=['./weigths/yolov5s-cls.pt'], source=bananas.jpg, data=data/coco128.yaml, imgsz=[224, 224], device=, view_img=False, save_txt=False, nosave=False, augment=False, visualize=False, update=False, project=runs/predict-cls, name=exp, exist_ok=False, half=False, dnn=False, vid_stride=1\n", + "YOLOv5 ๐Ÿš€ v7.0-378-g2f74455a Python-3.10.12 torch-2.5.0+cu121 CUDA:0 (NVIDIA A100-SXM4-40GB, 40514MiB)\n", + "\n", + "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s-cls.pt to weigths/yolov5s-cls.pt...\n", + "100% 10.5M/10.5M [00:00<00:00, 110MB/s]\n", + "\n", + "Fusing layers... \n", + "Model summary: 117 layers, 5447688 parameters, 0 gradients, 11.4 GFLOPs\n", + "image 1/1 /content/yolov5/bananas.jpg: 224x224 banana 0.96, zucchini 0.00, acorn squash 0.00, spaghetti squash 0.00, green mamba 0.00, 3.8ms\n", + "Speed: 0.5ms pre-process, 3.8ms inference, 59.6ms NMS per image at shape (1, 3, 224, 224)\n", + "Results saved to \u001b[1mruns/predict-cls/exp\u001b[0m\n" + ] + } + ] }, { "cell_type": "markdown", @@ -142,64 +246,18 @@ { "cell_type": "markdown", "source": [ - "## 2. (Optional) Validate\n", - "\n", - "Use the `classify/val.py` script to run validation for the model. This will show us the model's performance on each class.\n", - "\n", - "First, we need to download ImageNet." - ], - "metadata": { - "id": "5EosQzyDCk3W" - } - }, - { - "cell_type": "code", - "source": [ - "# # WARNING: takes ~20 minutes\n", - "# !bash data/scripts/get_imagenet.sh --val" - ], - "metadata": { - "id": "HwAYptjCq-C_" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# # run the validation script\n", - "# !python classify/val.py --weights ./weigths/yolov5s-cls.pt --data ../datasets/imagenet" - ], - "metadata": { - "id": "CoHdKXWc8hrD" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "The output shows accuracy metrics for the ImageNet validation dataset including per class accuracy." - ], - "metadata": { - "id": "r2coOcIjuzCO" - } - }, - { - "cell_type": "markdown", - "source": [ - "# 3. Train On Custom Data\n", + "# 2. Train On Custom Data\n", "\n", "To train on custom data, we need to prepare a dataset with custom labels.\n", "\n", - "To prepare custom data, we'll use [Roboflow](https://roboflow.com). Roboflow enables easy dataset prep with your team, including labeling, formatting into the right export format, deploying, and active learning with a `pip` package. \n", + "To prepare custom data, we'll use [Roboflow](https://roboflow.com). Roboflow enables easy dataset prep with your team, including labeling, formatting into the right export format, deploying, and active learning with a `pip` package.\n", "\n", "If you need custom data, there are over 66M open source images from the community on [Roboflow Universe](https://universe.roboflow.com).\n", "\n", "(For more guidance, here's a detailed blog on [training YOLOv5 classification on custom data](https://blog.roboflow.com/train-YOLOv5-classification-custom-data).)\n", "\n", "\n", - "Create a free Roboflow account, upload your data, and label. \n", + "Create a free Roboflow account, upload your data, and label.\n", "\n", "![](https://s4.gifyu.com/images/fruit-labeling.gif)" ], @@ -253,27 +311,104 @@ "%cd ../datasets/" ], "metadata": { - "id": "6IIgJbP7G6Th" + "id": "6IIgJbP7G6Th", + "outputId": "97d1fa28-b4d4-4be0-a27b-66d577172ee6", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/content/datasets\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!pip install roboflow==1.1.48 -q" + ], + "metadata": { + "id": "gnmezvmAucvw", + "outputId": "aa44dc75-ebf2-4291-e870-5df08abedc7d", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\u001b[?25l \u001b[90mโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\u001b[0m \u001b[32m0.0/80.3 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90mโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\u001b[0m \u001b[32m80.3/80.3 kB\u001b[0m \u001b[31m4.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90mโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\u001b[0m \u001b[32m66.8/66.8 kB\u001b[0m \u001b[31m7.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90mโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\u001b[0m \u001b[32m54.5/54.5 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h" + ] + } + ] }, { "cell_type": "code", "source": [ "# REPLACE the below with your exported code snippet from above\n", - "!pip install roboflow\n", + "import roboflow\n", + "roboflow.login()\n", "\n", - "from roboflow import Roboflow\n", - "rf = Roboflow(api_key=\"YOUR API KEY\")\n", - "project = rf.workspace(\"yolov5-classification\").project(\"banana-ripeness-classification\")\n", + "rf = roboflow.Roboflow()\n", + "project = rf.workspace(\"model-examples\").project(\"banana-ripeness-classification-3dyre\")\n", "dataset = project.version(1).download(\"folder\")" ], "metadata": { - "id": "He6JwHIlG-W_" + "id": "He6JwHIlG-W_", + "outputId": "68bd7ec3-be6c-432b-cf6c-3566c74f2efe", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 9, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\rvisit https://app.roboflow.com/auth-cli to get your authentication token.\n", + "Paste the authentication token here: ยทยทยทยทยทยทยทยทยทยท\n", + "loading Roboflow workspace...\n", + "loading Roboflow project...\n", + "Exporting format folder in progress : 85.0%\n", + "Version export complete for folder format\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Downloading Dataset Version Zip in Banana-Ripeness-Classification-1 to folder:: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 152300/152300 [00:02<00:00, 73930.67it/s]" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "\n", + "Extracting Dataset Version Zip to Banana-Ripeness-Classification-1 in folder:: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 5639/5639 [00:00<00:00, 6735.45it/s]\n" + ] + } + ] }, { "cell_type": "code", @@ -285,7 +420,7 @@ "metadata": { "id": "wLQbThFICpn4" }, - "execution_count": null, + "execution_count": 10, "outputs": [] }, { @@ -294,7 +429,7 @@ "### Train On Custom Data ๐ŸŽ‰\n", "Here, we use the DATASET_NAME environment variable to pass our dataset to the `--data` parameter.\n", "\n", - "Note: we're training for 100 epochs here. We're also starting training from the pretrained weights. Larger datasets will likely benefit from longer training. " + "Note: we're training for 30 epochs here. We're also starting training from the pretrained weights. Larger datasets will likely benefit from longer training, frequently going as high as 1000-3000." ], "metadata": { "id": "-5z7Yv42FGrK" @@ -304,13 +439,87 @@ "cell_type": "code", "source": [ "%cd ../yolov5\n", - "!python classify/train.py --model yolov5s-cls.pt --data $DATASET_NAME --epochs 100 --img 128 --pretrained weights/yolov5s-cls.pt" + "!python classify/train.py --model yolov5s-cls.pt --data $DATASET_NAME --epochs 30 --img 128 --pretrained weights/yolov5s-cls.pt" ], "metadata": { - "id": "MXWTTN2BEaqe" + "id": "MXWTTN2BEaqe", + "outputId": "cdc90fce-4716-4550-becf-f6ef6f9a99de", + "colab": { + "base_uri": "https://localhost:8080/" + } }, - "execution_count": null, - "outputs": [] + "execution_count": 21, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/content/yolov5\n", + "2024-10-24 18:18:39.078290: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:485] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n", + "2024-10-24 18:18:39.098773: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:8454] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n", + "2024-10-24 18:18:39.104998: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1452] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n", + "\u001b[34m\u001b[1mclassify/train: \u001b[0mmodel=yolov5s-cls.pt, data=Banana-Ripeness-Classification-1, epochs=30, batch_size=64, imgsz=128, nosave=False, cache=None, device=, workers=8, project=runs/train-cls, name=exp, exist_ok=False, pretrained=weights/yolov5s-cls.pt, optimizer=Adam, lr0=0.001, decay=5e-05, label_smoothing=0.1, cutoff=None, dropout=None, verbose=False, seed=0, local_rank=-1\n", + "\u001b[34m\u001b[1mgithub: \u001b[0mup to date with https://github.com/ultralytics/yolov5 โœ…\n", + "YOLOv5 ๐Ÿš€ v7.0-378-g2f74455a Python-3.10.12 torch-2.5.0+cu121 CUDA:0 (NVIDIA A100-SXM4-40GB, 40514MiB)\n", + "\n", + "\u001b[34m\u001b[1mTensorBoard: \u001b[0mStart with 'tensorboard --logdir runs/train-cls', view at http://localhost:6006/\n", + "\u001b[34m\u001b[1malbumentations: \u001b[0mRandomResizedCrop(p=1.0, size=(128, 128), scale=(0.08, 1.0), ratio=(0.75, 1.3333333333333333), interpolation=1), HorizontalFlip(p=0.5), ColorJitter(p=0.5, brightness=(0.6, 1.4), contrast=(0.6, 1.4), saturation=(0.6, 1.4), hue=(0.0, 0.0)), Normalize(p=1.0, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225), max_pixel_value=255.0, normalization='standard'), ToTensorV2(p=1.0, transpose_mask=False)\n", + "Model summary: 149 layers, 4180166 parameters, 4180166 gradients, 10.5 GFLOPs\n", + "\u001b[34m\u001b[1moptimizer:\u001b[0m Adam(lr=0.001) with parameter groups 32 weight(decay=0.0), 33 weight(decay=5e-05), 33 bias\n", + "/content/yolov5/classify/train.py:201: FutureWarning: `torch.cuda.amp.GradScaler(args...)` is deprecated. Please use `torch.amp.GradScaler('cuda', args...)` instead.\n", + " scaler = amp.GradScaler(enabled=cuda)\n", + "Image sizes 128 train, 128 test\n", + "Using 8 dataloader workers\n", + "Logging results to \u001b[1mruns/train-cls/exp\u001b[0m\n", + "Starting yolov5s-cls.pt training on Banana-Ripeness-Classification-1 dataset with 6 classes for 30 epochs...\n", + "\n", + " Epoch GPU_mem train_loss test_loss top1_acc top5_acc\n", + " 0% 0/62 [00:00