ImageNet names, classify inference, resume fixes (#712)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Laughing <61612323+Laughing-q@users.noreply.github.com>
single_channel
Glenn Jocher 2 years ago committed by GitHub
parent aecd17d455
commit 522f1937ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -31,11 +31,11 @@ repos:
name: Upgrade code name: Upgrade code
args: [ --py37-plus ] args: [ --py37-plus ]
- repo: https://github.com/PyCQA/isort # - repo: https://github.com/PyCQA/isort
rev: 5.11.4 # rev: 5.11.4
hooks: # hooks:
- id: isort # - id: isort
name: Sort imports # name: Sort imports
- repo: https://github.com/pre-commit/mirrors-yapf - repo: https://github.com/pre-commit/mirrors-yapf
rev: v0.32.0 rev: v0.32.0

@ -57,10 +57,9 @@
"metadata": { "metadata": {
"id": "wbvMlHd_QwMG", "id": "wbvMlHd_QwMG",
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/"
"height": 1000
}, },
"outputId": "5006941e-44ff-4e27-f53e-31bf87221334" "outputId": "9bda69d4-e57f-404b-b6fe-117234e24677"
}, },
"source": [ "source": [
"# Pip install method (recommended)\n", "# Pip install method (recommended)\n",
@ -68,14 +67,14 @@
"import ultralytics\n", "import ultralytics\n",
"ultralytics.checks()" "ultralytics.checks()"
], ],
"execution_count": null, "execution_count": 1,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
"name": "stderr", "name": "stderr",
"text": [ "text": [
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n", "Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"Setup complete ✅ (2 CPUs, 12.7 GB RAM, 23.0/166.8 GB disk)\n" "Setup complete ✅ (2 CPUs, 12.7 GB RAM, 30.8/166.8 GB disk)\n"
] ]
} }
] ]
@ -111,28 +110,27 @@
"colab": { "colab": {
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"outputId": "3136de6b-2995-4731-e84c-962acb233d89" "outputId": "abe002b5-3df9-4324-9e50-1587394398a2"
}, },
"source": [ "source": [
"# Run inference on an image with YOLOv8n\n", "# Run inference on an image with YOLOv8n\n",
"!yolo task=detect mode=predict model=yolov8n.pt conf=0.25 source='https://ultralytics.com/images/zidane.jpg'" "!yolo predict model=yolov8n.pt source='https://ultralytics.com/images/zidane.jpg'"
], ],
"execution_count": null, "execution_count": 2,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
"name": "stdout", "name": "stdout",
"text": [ "text": [
"Downloading https://ultralytics.com/images/zidane.jpg to zidane.jpg...\n",
"100% 165k/165k [00:00<00:00, 12.0MB/s]\n",
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"Downloading https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt to yolov8n.pt...\n", "Downloading https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt to yolov8n.pt...\n",
"100% 6.24M/6.24M [00:00<00:00, 58.7MB/s]\n", "\r 0% 0.00/6.23M [00:00<?, ?B/s]\r100% 6.23M/6.23M [00:00<00:00, 266MB/s]\n",
"Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"YOLOv8n summary (fused): 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n",
"\n", "\n",
"Fusing layers... \n", "Downloading https://ultralytics.com/images/zidane.jpg to zidane.jpg...\n",
"YOLOv8n summary: 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n", "100% 165k/165k [00:00<00:00, 87.4MB/s]\n",
"image 1/1 /content/zidane.jpg: 384x640 2 persons, 1 tie, 13.6ms\n", "image 1/1 /content/zidane.jpg: 384x640 2 persons, 1 tie, 13.3ms\n",
"Speed: 0.4ms pre-process, 13.6ms inference, 52.1ms postprocess per image at shape (1, 3, 640, 640)\n", "Speed: 0.5ms pre-process, 13.3ms inference, 43.5ms postprocess per image at shape (1, 3, 640, 640)\n",
"Results saved to \u001b[1mruns/detect/predict\u001b[0m\n" "Results saved to \u001b[1mruns/detect/predict\u001b[0m\n"
] ]
} }
@ -176,37 +174,35 @@
"cell_type": "code", "cell_type": "code",
"metadata": { "metadata": {
"id": "X58w8JLpMnjH", "id": "X58w8JLpMnjH",
"outputId": "3e8689b5-e6e6-4764-c1d9-2626f53355f2", "outputId": "df71d7a8-f42f-473a-c143-75f033c58433",
"colab": { "colab": {
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
} }
}, },
"source": [ "source": [
"# Validate YOLOv8n on COCO128 val\n", "# Validate YOLOv8n on COCO128 val\n",
"!yolo task=detect mode=val model=yolov8n.pt data=coco128.yaml" "!yolo val model=yolov8n.pt data=coco128.yaml"
], ],
"execution_count": null, "execution_count": 3,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
"name": "stdout", "name": "stdout",
"text": [ "text": [
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n", "Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"Downloading https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt to yolov8n.pt...\n", "YOLOv8n summary (fused): 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n",
"100% 6.24M/6.24M [00:01<00:00, 6.32MB/s]\n",
"\n", "\n",
"Fusing layers... \n", "Dataset 'coco128.yaml' not found ⚠️, missing paths ['/content/datasets/coco128/images/train2017']\n",
"YOLOv8n summary: 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n", "Downloading https://ultralytics.com/assets/coco128.zip to /content/datasets/coco128.zip...\n",
"100% 6.66M/6.66M [00:00<00:00, 50.5MB/s]\n",
"Unzipping /content/datasets/coco128.zip...\n",
"Dataset download success ✅ (0.5s), saved to \u001b[1m/content/datasets\u001b[0m\n",
"\n", "\n",
"Dataset not found ⚠️, missing paths ['/datasets/coco128/images/train2017']\n",
"Downloading https://ultralytics.com/assets/coco128.zip to coco128.zip...\n",
"100% 6.66M/6.66M [00:00<00:00, 71.9MB/s]\n",
"Dataset download success ✅ (0.8s), saved to \u001b[1m/datasets\u001b[0m\n",
"Downloading https://ultralytics.com/assets/Arial.ttf to /root/.config/Ultralytics/Arial.ttf...\n", "Downloading https://ultralytics.com/assets/Arial.ttf to /root/.config/Ultralytics/Arial.ttf...\n",
"100% 755k/755k [00:00<00:00, 44.6MB/s]\n", "100% 755k/755k [00:00<00:00, 99.8MB/s]\n",
"\u001b[34m\u001b[1mval: \u001b[0mScanning /datasets/coco128/labels/train2017... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<00:00, 1451.73it/s]\n", "\u001b[34m\u001b[1mval: \u001b[0mScanning /content/datasets/coco128/labels/train2017... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<00:00, 1290.29it/s]\n",
"\u001b[34m\u001b[1mval: \u001b[0mNew cache created: /datasets/coco128/labels/train2017.cache\n", "\u001b[34m\u001b[1mval: \u001b[0mNew cache created: /content/datasets/coco128/labels/train2017.cache\n",
" Class Images Instances Box(P R mAP50 mAP50-95): 100% 8/8 [00:05<00:00, 1.53it/s]\n", " Class Images Instances Box(P R mAP50 mAP50-95): 100% 8/8 [00:06<00:00, 1.22it/s]\n",
" all 128 929 0.64 0.537 0.605 0.446\n", " all 128 929 0.64 0.537 0.605 0.446\n",
" person 128 254 0.797 0.677 0.764 0.538\n", " person 128 254 0.797 0.677 0.764 0.538\n",
" bicycle 128 6 0.514 0.333 0.315 0.264\n", " bicycle 128 6 0.514 0.333 0.315 0.264\n",
@ -279,7 +275,7 @@
" scissors 128 1 1 0 0.249 0.0746\n", " scissors 128 1 1 0 0.249 0.0746\n",
" teddy bear 128 21 0.877 0.333 0.591 0.394\n", " teddy bear 128 21 0.877 0.333 0.591 0.394\n",
" toothbrush 128 5 0.743 0.6 0.638 0.374\n", " toothbrush 128 5 0.743 0.6 0.638 0.374\n",
"Speed: 1.1ms pre-process, 5.7ms inference, 0.0ms loss, 3.7ms post-process per image\n" "Speed: 2.4ms pre-process, 7.8ms inference, 0.0ms loss, 3.3ms post-process per image\n"
] ]
} }
] ]
@ -301,23 +297,23 @@
"cell_type": "code", "cell_type": "code",
"metadata": { "metadata": {
"id": "1NcFxRcFdJ_O", "id": "1NcFxRcFdJ_O",
"outputId": "3e6ce168-7f91-4253-d2f1-84c8254a66ee", "outputId": "e0978a9a-ef1d-4a20-8082-19c8049d8c7e",
"colab": { "colab": {
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
} }
}, },
"source": [ "source": [
"# Train YOLOv8n on COCO128 for 3 epochs\n", "# Train YOLOv8n on COCO128 for 3 epochs\n",
"!yolo task=detect mode=train model=yolov8n.pt data=coco128.yaml epochs=3 imgsz=640" "!yolo train model=yolov8n.pt data=coco128.yaml epochs=3 imgsz=640"
], ],
"execution_count": null, "execution_count": 4,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
"name": "stdout", "name": "stdout",
"text": [ "text": [
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n", "Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"\u001b[34m\u001b[1myolo/engine/trainer: \u001b[0mtask=detect, mode=train, model=yolov8n.pt, data=coco128.yaml, epochs=3, patience=50, batch=16, imgsz=640, save=True, cache=False, device=, workers=8, project=None, name=None, exist_ok=False, pretrained=False, optimizer=SGD, verbose=False, seed=0, deterministic=True, single_cls=False, image_weights=False, rect=False, cos_lr=False, close_mosaic=10, resume=False, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, show=False, save_txt=False, save_conf=False, save_crop=False, hide_labels=False, hide_conf=False, vid_stride=1, line_thickness=3, visualize=False, augment=False, agnostic_nms=False, retina_masks=False, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=17, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, fl_gamma=0.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, cfg=None, hydra={'output_subdir': None, 'run': {'dir': '.'}}, v5loader=False, save_dir=runs/detect/train\n", "\u001b[34m\u001b[1myolo/engine/trainer: \u001b[0mtask=detect, mode=train, model=yolov8n.pt, data=coco128.yaml, epochs=3, patience=50, batch=16, imgsz=640, save=True, cache=False, device=None, workers=8, project=None, name=None, exist_ok=False, pretrained=False, optimizer=SGD, verbose=True, seed=0, deterministic=True, single_cls=False, image_weights=False, rect=False, cos_lr=False, close_mosaic=10, resume=False, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, show=False, save_txt=False, save_conf=False, save_crop=False, hide_labels=False, hide_conf=False, vid_stride=1, line_thickness=3, visualize=False, augment=False, agnostic_nms=False, classes=None, retina_masks=False, boxes=True, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=None, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, fl_gamma=0.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, cfg=None, v5loader=False, save_dir=runs/detect/train\n",
"\n", "\n",
" from n params module arguments \n", " from n params module arguments \n",
" 0 -1 1 464 ultralytics.nn.modules.Conv [3, 16, 3, 2] \n", " 0 -1 1 464 ultralytics.nn.modules.Conv [3, 16, 3, 2] \n",
@ -347,38 +343,37 @@
"\n", "\n",
"Transferred 355/355 items from pretrained weights\n", "Transferred 355/355 items from pretrained weights\n",
"\u001b[34m\u001b[1moptimizer:\u001b[0m SGD(lr=0.01) with parameter groups 57 weight(decay=0.0), 64 weight(decay=0.0005), 63 bias\n", "\u001b[34m\u001b[1moptimizer:\u001b[0m SGD(lr=0.01) with parameter groups 57 weight(decay=0.0), 64 weight(decay=0.0005), 63 bias\n",
"\u001b[34m\u001b[1mtrain: \u001b[0mScanning /datasets/coco128/labels/train2017.cache... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<?, ?it/s]\n", "\u001b[34m\u001b[1mtrain: \u001b[0mScanning /content/datasets/coco128/labels/train2017.cache... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<?, ?it/s]\n",
"\u001b[34m\u001b[1malbumentations: \u001b[0mBlur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01), CLAHE(p=0.01, clip_limit=(1, 4.0), tile_grid_size=(8, 8))\n", "\u001b[34m\u001b[1malbumentations: \u001b[0mBlur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01), CLAHE(p=0.01, clip_limit=(1, 4.0), tile_grid_size=(8, 8))\n",
"\u001b[34m\u001b[1mval: \u001b[0mScanning /datasets/coco128/labels/train2017.cache... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<?, ?it/s]\n", "\u001b[34m\u001b[1mval: \u001b[0mScanning /content/datasets/coco128/labels/train2017.cache... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<?, ?it/s]\n",
"Image sizes 640 train, 640 val\n", "Image sizes 640 train, 640 val\n",
"Using 2 dataloader workers\n", "Using 2 dataloader workers\n",
"Logging results to \u001b[1mruns/detect/train\u001b[0m\n", "Logging results to \u001b[1mruns/detect/train\u001b[0m\n",
"Starting training for 3 epochs...\n", "Starting training for 3 epochs...\n",
"\n", "\n",
" Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n", " Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n",
" 1/3 4.31G 1.221 1.429 1.241 196 640: 100% 8/8 [00:09<00:00, 1.18s/it]\n", " 1/3 4.31G 1.221 1.429 1.241 196 640: 100% 8/8 [00:08<00:00, 1.01s/it]\n",
" Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:02<00:00, 1.95it/s]\n", " Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:01<00:00, 2.18it/s]\n",
" all 128 929 0.671 0.516 0.617 0.457\n", " all 128 929 0.671 0.516 0.617 0.457\n",
"\n", "\n",
" Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n", " Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n",
" 2/3 5.31G 1.186 1.306 1.255 287 640: 100% 8/8 [00:06<00:00, 1.33it/s]\n", " 2/3 5.31G 1.186 1.306 1.255 287 640: 100% 8/8 [00:04<00:00, 1.63it/s]\n",
" Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:02<00:00, 1.92it/s]\n", " Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:01<00:00, 2.23it/s]\n",
" all 128 929 0.668 0.582 0.637 0.473\n", " all 128 929 0.668 0.582 0.637 0.473\n",
"\n", "\n",
" Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n", " Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size\n",
" 3/3 5.31G 1.17 1.408 1.267 189 640: 100% 8/8 [00:06<00:00, 1.19it/s]\n", " 3/3 5.31G 1.17 1.408 1.267 189 640: 100% 8/8 [00:04<00:00, 1.64it/s]\n",
" Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:04<00:00, 1.16s/it]\n", " Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:03<00:00, 1.03it/s]\n",
" all 128 929 0.638 0.601 0.645 0.483\n", " all 128 929 0.638 0.601 0.645 0.483\n",
"\n", "\n",
"3 epochs completed in 0.011 hours.\n", "3 epochs completed in 0.009 hours.\n",
"Optimizer stripped from runs/detect/train/weights/last.pt, 6.5MB\n", "Optimizer stripped from runs/detect/train/weights/last.pt, 6.5MB\n",
"Optimizer stripped from runs/detect/train/weights/best.pt, 6.5MB\n", "Optimizer stripped from runs/detect/train/weights/best.pt, 6.5MB\n",
"\n", "\n",
"Validating runs/detect/train/weights/best.pt...\n", "Validating runs/detect/train/weights/best.pt...\n",
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n", "Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CUDA:0 (Tesla T4, 15110MiB)\n",
"Fusing layers... \n", "Model summary (fused): 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n",
"Model summary: 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n", " Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:04<00:00, 1.05s/it]\n",
" Class Images Instances Box(P R mAP50 mAP50-95): 100% 4/4 [00:05<00:00, 1.31s/it]\n",
" all 128 929 0.638 0.602 0.644 0.483\n", " all 128 929 0.638 0.602 0.644 0.483\n",
" person 128 254 0.703 0.709 0.769 0.548\n", " person 128 254 0.703 0.709 0.769 0.548\n",
" bicycle 128 6 0.455 0.333 0.322 0.254\n", " bicycle 128 6 0.455 0.333 0.322 0.254\n",
@ -451,8 +446,7 @@
" scissors 128 1 1 0 0.142 0.0426\n", " scissors 128 1 1 0 0.142 0.0426\n",
" teddy bear 128 21 0.587 0.476 0.63 0.458\n", " teddy bear 128 21 0.587 0.476 0.63 0.458\n",
" toothbrush 128 5 0.784 0.736 0.898 0.544\n", " toothbrush 128 5 0.784 0.736 0.898 0.544\n",
"Speed: 0.2ms pre-process, 5.1ms inference, 0.0ms loss, 3.3ms post-process per image\n", "Speed: 2.0ms pre-process, 4.0ms inference, 0.0ms loss, 2.5ms post-process per image\n",
"Saving runs/detect/train/predictions.json...\n",
"Results saved to \u001b[1mruns/detect/train\u001b[0m\n" "Results saved to \u001b[1mruns/detect/train\u001b[0m\n"
] ]
} }
@ -492,31 +486,30 @@
{ {
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"!yolo mode=export model=yolov8n.pt format=torchscript" "!yolo export model=yolov8n.pt format=torchscript"
], ],
"metadata": { "metadata": {
"colab": { "colab": {
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "CYIjW4igCjqD", "id": "CYIjW4igCjqD",
"outputId": "3bb45917-f90e-4951-959d-7bcd26680f2e" "outputId": "69cab2fb-cbfa-4acf-8e29-9c4fb6f4a38f"
}, },
"execution_count": null, "execution_count": 5,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
"name": "stdout", "name": "stdout",
"text": [ "text": [
"Ultralytics YOLOv8.0.5 🚀 Python-3.8.16 torch-1.13.1+cu116 CPU\n", "Ultralytics YOLOv8.0.24 🚀 Python-3.8.10 torch-1.13.1+cu116 CPU\n",
"Fusing layers... \n", "YOLOv8n summary (fused): 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n",
"YOLOv8n summary: 168 layers, 3151904 parameters, 0 gradients, 8.7 GFLOPs\n",
"\n", "\n",
"\u001b[34m\u001b[1mPyTorch:\u001b[0m starting from yolov8n.pt with output shape (1, 84, 8400) (6.2 MB)\n", "\u001b[34m\u001b[1mPyTorch:\u001b[0m starting from yolov8n.pt with output shape (1, 84, 8400) (6.2 MB)\n",
"\n", "\n",
"\u001b[34m\u001b[1mTorchScript:\u001b[0m starting export with torch 1.13.1+cu116...\n", "\u001b[34m\u001b[1mTorchScript:\u001b[0m starting export with torch 1.13.1+cu116...\n",
"\u001b[34m\u001b[1mTorchScript:\u001b[0m export success ✅ 1.9s, saved as yolov8n.torchscript (12.4 MB)\n", "\u001b[34m\u001b[1mTorchScript:\u001b[0m export success ✅ 1.7s, saved as yolov8n.torchscript (12.4 MB)\n",
"\n", "\n",
"Export complete (2.6s)\n", "Export complete (2.2s)\n",
"Results saved to \u001b[1m/content\u001b[0m\n", "Results saved to \u001b[1m/content\u001b[0m\n",
"Predict: yolo task=detect mode=predict model=yolov8n.torchscript -WARNING ⚠️ not yet supported for YOLOv8 exported models\n", "Predict: yolo task=detect mode=predict model=yolov8n.torchscript -WARNING ⚠️ not yet supported for YOLOv8 exported models\n",
"Validate: yolo task=detect mode=val model=yolov8n.torchscript -WARNING ⚠️ not yet supported for YOLOv8 exported models\n", "Validate: yolo task=detect mode=val model=yolov8n.torchscript -WARNING ⚠️ not yet supported for YOLOv8 exported models\n",

@ -59,7 +59,7 @@ def test_predict_segment():
def test_predict_classify(): def test_predict_classify():
run(f"yolo predict segment model={MODEL}-cls.pt source={ROOT / 'assets'} imgsz=32") run(f"yolo predict classify model={MODEL}-cls.pt source={ROOT / 'assets'} imgsz=32")
# Export checks -------------------------------------------------------------------------------------------------------- # Export checks --------------------------------------------------------------------------------------------------------

@ -1,6 +1,6 @@
# Ultralytics YOLO 🚀, GPL-3.0 license # Ultralytics YOLO 🚀, GPL-3.0 license
__version__ = "8.0.24" __version__ = "8.0.25"
from ultralytics.yolo.engine.model import YOLO from ultralytics.yolo.engine.model import YOLO
from ultralytics.yolo.utils import ops from ultralytics.yolo.utils import ops

@ -226,10 +226,13 @@ class AutoBackend(nn.Module):
f"https://docs.ultralytics.com/reference/nn/") f"https://docs.ultralytics.com/reference/nn/")
# class names # class names
if 'names' not in locals(): if 'names' not in locals(): # names missing
names = yaml_load(data)['names'] if data else {i: f'class{i}' for i in range(999)} names = yaml_load(data)['names'] if data else {i: f'class{i}' for i in range(999)} # assign default
if names[0] == 'n01440764' and len(names) == 1000: # ImageNet elif isinstance(names, list): # names is a list
names = yaml_load(ROOT / 'yolo/data/datasets/ImageNet.yaml')['names'] # human-readable names names = dict(enumerate(names)) # convert to dict
if isinstance(names[0], str) and names[0].startswith('n0'): # imagenet class codes, i.e. 'n01440764'
map = yaml_load(ROOT / 'yolo/data/datasets/ImageNet.yaml')['map'] # human-readable names
names = {k: map[v] for k, v in names.items()}
self.__dict__.update(locals()) # assign all variables to self self.__dict__.update(locals()) # assign all variables to self

@ -162,7 +162,7 @@ def load_inference_source(source=None, transforms=None, imgsz=640, vid_stride=1,
""" """
# source # source
source, webcam, screenshot, from_img, in_memory = check_source(source) source, webcam, screenshot, from_img, in_memory = check_source(source)
source_type = SourceTypes(webcam, screenshot, from_img) if not in_memory else source.source_type source_type = source.source_type if in_memory else SourceTypes(webcam, screenshot, from_img)
# Dataloader # Dataloader
if in_memory: if in_memory:

@ -29,7 +29,7 @@ class SourceTypes:
class LoadStreams: class LoadStreams:
# YOLOv8 streamloader, i.e. `python detect.py --source 'rtsp://example.com/media.mp4' # RTSP, RTMP, HTTP streams` # YOLOv8 streamloader, i.e. `yolo predict source='rtsp://example.com/media.mp4' # RTSP, RTMP, HTTP streams`
def __init__(self, sources='file.streams', imgsz=640, stride=32, auto=True, transforms=None, vid_stride=1): def __init__(self, sources='file.streams', imgsz=640, stride=32, auto=True, transforms=None, vid_stride=1):
torch.backends.cudnn.benchmark = True # faster for fixed-size inference torch.backends.cudnn.benchmark = True # faster for fixed-size inference
self.mode = 'stream' self.mode = 'stream'
@ -49,9 +49,9 @@ class LoadStreams:
import pafy # noqa import pafy # noqa
s = pafy.new(s).getbest(preftype="mp4").url # YouTube URL s = pafy.new(s).getbest(preftype="mp4").url # YouTube URL
s = eval(s) if s.isnumeric() else s # i.e. s = '0' local webcam s = eval(s) if s.isnumeric() else s # i.e. s = '0' local webcam
if s == 0: if s == 0 and (is_colab() or is_kaggle()):
assert not is_colab(), '--source 0 webcam unsupported on Colab. Rerun command in a local environment.' raise NotImplementedError("'source=0' webcam not supported in Colab and Kaggle notebooks."
assert not is_kaggle(), '--source 0 webcam unsupported on Kaggle. Rerun command in a local environment.' "Try running 'source=0' in a local environment.")
cap = cv2.VideoCapture(s) cap = cv2.VideoCapture(s)
if not cap.isOpened(): if not cap.isOpened():
raise ConnectionError(f'{st}Failed to open {s}') raise ConnectionError(f'{st}Failed to open {s}')
@ -118,7 +118,7 @@ class LoadStreams:
class LoadScreenshots: class LoadScreenshots:
# YOLOv8 screenshot dataloader, i.e. `python detect.py --source "screen 0 100 100 512 256"` # YOLOv8 screenshot dataloader, i.e. `yolo predict source=screen`
def __init__(self, source, imgsz=640, stride=32, auto=True, transforms=None): def __init__(self, source, imgsz=640, stride=32, auto=True, transforms=None):
# source = [screen_number left top width height] (pixels) # source = [screen_number left top width height] (pixels)
check_requirements('mss') check_requirements('mss')
@ -168,7 +168,7 @@ class LoadScreenshots:
class LoadImages: class LoadImages:
# YOLOv8 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4` # YOLOv8 image/video dataloader, i.e. `yolo predict source=image.jpg/vid.mp4`
def __init__(self, path, imgsz=640, stride=32, auto=True, transforms=None, vid_stride=1): def __init__(self, path, imgsz=640, stride=32, auto=True, transforms=None, vid_stride=1):
if isinstance(path, str) and Path(path).suffix == ".txt": # *.txt file with img/vid/dir on each line if isinstance(path, str) and Path(path).suffix == ".txt": # *.txt file with img/vid/dir on each line
path = Path(path).read_text().rsplit() path = Path(path).read_text().rsplit()

File diff suppressed because it is too large Load Diff

@ -2,6 +2,7 @@
from pathlib import Path from pathlib import Path
import sys
from ultralytics import yolo # noqa from ultralytics import yolo # noqa
from ultralytics.nn.tasks import (ClassificationModel, DetectionModel, SegmentationModel, attempt_load_one_weight, from ultralytics.nn.tasks import (ClassificationModel, DetectionModel, SegmentationModel, attempt_load_one_weight,
guess_model_task) guess_model_task)
@ -142,7 +143,8 @@ class YOLO:
self.predictor.setup_model(model=self.model) self.predictor.setup_model(model=self.model)
else: # only update args if predictor is already setup else: # only update args if predictor is already setup
self.predictor.args = get_cfg(self.predictor.args, overrides) self.predictor.args = get_cfg(self.predictor.args, overrides)
return self.predictor(source=source, stream=stream) is_cli = sys.argv[0].endswith('yolo') or sys.argv[0].endswith('ultralytics')
return self.predictor.predict_cli(source=source) if is_cli else self.predictor(source=source, stream=stream)
@smart_inference_mode() @smart_inference_mode()
def val(self, data=None, **kwargs): def val(self, data=None, **kwargs):

@ -113,9 +113,9 @@ class BasePredictor:
else: else:
return list(self.stream_inference(source, model)) # merge list of Result into one return list(self.stream_inference(source, model)) # merge list of Result into one
def predict_cli(self): def predict_cli(self, source=None, model=None):
# Method used for CLI prediction. It uses always generator as outputs as not required by CLI mode # Method used for CLI prediction. It uses always generator as outputs as not required by CLI mode
gen = self.stream_inference() gen = self.stream_inference(source, model)
for _ in gen: # running CLI inference without accumulating any outputs (do not modify) for _ in gen: # running CLI inference without accumulating any outputs (do not modify)
pass pass

@ -28,7 +28,7 @@ class Results:
def __init__(self, boxes=None, masks=None, probs=None, orig_shape=None) -> None: def __init__(self, boxes=None, masks=None, probs=None, orig_shape=None) -> None:
self.boxes = Boxes(boxes, orig_shape) if boxes is not None else None # native size boxes self.boxes = Boxes(boxes, orig_shape) if boxes is not None else None # native size boxes
self.masks = Masks(masks, orig_shape) if masks is not None else None # native size or imgsz masks self.masks = Masks(masks, orig_shape) if masks is not None else None # native size or imgsz masks
self.probs = probs.softmax(0) if probs is not None else None self.probs = probs if probs is not None else None
self.orig_shape = orig_shape self.orig_shape = orig_shape
self.comp = ["boxes", "masks", "probs"] self.comp = ["boxes", "masks", "probs"]

@ -21,7 +21,7 @@ from torch.optim import lr_scheduler
from tqdm import tqdm from tqdm import tqdm
from ultralytics import __version__ from ultralytics import __version__
from ultralytics.nn.tasks import attempt_load_one_weight from ultralytics.nn.tasks import attempt_load_one_weight, attempt_load_weights
from ultralytics.yolo.cfg import get_cfg from ultralytics.yolo.cfg import get_cfg
from ultralytics.yolo.data.utils import check_cls_dataset, check_det_dataset from ultralytics.yolo.data.utils import check_cls_dataset, check_det_dataset
from ultralytics.yolo.utils import (DEFAULT_CFG, LOGGER, RANK, SETTINGS, TQDM_BAR_FORMAT, callbacks, colorstr, emojis, from ultralytics.yolo.utils import (DEFAULT_CFG, LOGGER, RANK, SETTINGS, TQDM_BAR_FORMAT, callbacks, colorstr, emojis,
@ -515,14 +515,15 @@ class BaseTrainer:
def check_resume(self): def check_resume(self):
resume = self.args.resume resume = self.args.resume
if resume: if resume:
last = Path(check_file(resume) if isinstance(resume, (str, Path)) else get_latest_run()) try:
args_yaml = last.parent.parent / 'args.yaml' # train options yaml last = Path(
assert args_yaml.is_file(), \ check_file(resume) if isinstance(resume, (str,
FileNotFoundError(f'Resume checkpoint {last} not found. ' Path)) and Path(resume).exists() else get_latest_run())
'Please pass a valid checkpoint to resume from, i.e. yolo resume=path/to/last.pt') self.args = get_cfg(attempt_load_weights(last).args)
args = get_cfg(args_yaml) # replace self.args.model, resume = str(last), True # reinstate
args.model, resume = str(last), True # reinstate except Exception as e:
self.args = args raise FileNotFoundError("Resume checkpoint not found. Please pass a valid checkpoint to resume from, "
"i.e. 'yolo train resume model=path/to/last.pt'") from e
self.resume = resume self.resume = resume
def resume_training(self, ckpt): def resume_training(self, ckpt):
@ -541,7 +542,7 @@ class BaseTrainer:
f'{self.args.model} training to {self.epochs} epochs is finished, nothing to resume.\n' \ f'{self.args.model} training to {self.epochs} epochs is finished, nothing to resume.\n' \
f"Start a new training without --resume, i.e. 'yolo task=... mode=train model={self.args.model}'" f"Start a new training without --resume, i.e. 'yolo task=... mode=train model={self.args.model}'"
LOGGER.info( LOGGER.info(
f'Resuming training from {self.args.model} from epoch {start_epoch} to {self.epochs} total epochs') f'Resuming training from {self.args.model} from epoch {start_epoch + 1} to {self.epochs} total epochs')
if self.epochs < start_epoch: if self.epochs < start_epoch:
LOGGER.info( LOGGER.info(
f"{self.model} has been trained for {ckpt['epoch']} epochs. Fine-tuning for {self.epochs} more epochs.") f"{self.model} has been trained for {ckpt['epoch']} epochs. Fine-tuning for {self.epochs} more epochs.")

@ -479,7 +479,7 @@ def set_sentry():
if SETTINGS['sync'] and \ if SETTINGS['sync'] and \
not is_pytest_running() and \ not is_pytest_running() and \
not is_github_actions_ci() and \ not is_github_actions_ci() and \
(is_pip_package() or ((is_pip_package() and not is_git_dir()) or
(get_git_origin_url() == "https://github.com/ultralytics/ultralytics.git" and get_git_branch() == "main")): (get_git_origin_url() == "https://github.com/ultralytics/ultralytics.git" and get_git_branch() == "main")):
import sentry_sdk # noqa import sentry_sdk # noqa
@ -493,6 +493,10 @@ def set_sentry():
before_send=before_send, before_send=before_send,
ignore_errors=[KeyboardInterrupt]) ignore_errors=[KeyboardInterrupt])
# Disable all sentry logging
for logger in "sentry_sdk", "sentry_sdk.errors":
logging.getLogger(logger).setLevel(logging.CRITICAL)
def get_settings(file=USER_CONFIG_DIR / 'settings.yaml', version='0.0.1'): def get_settings(file=USER_CONFIG_DIR / 'settings.yaml', version='0.0.1'):
""" """

@ -52,21 +52,22 @@ def autobatch(model, imgsz=640, fraction=0.7, batch_size=16):
try: try:
img = [torch.empty(b, 3, imgsz, imgsz) for b in batch_sizes] img = [torch.empty(b, 3, imgsz, imgsz) for b in batch_sizes]
results = profile(img, model, n=3, device=device) results = profile(img, model, n=3, device=device)
except Exception as e:
LOGGER.warning(f'{prefix}{e}')
# Fit a solution # Fit a solution
y = [x[2] for x in results if x] # memory [2] y = [x[2] for x in results if x] # memory [2]
p = np.polyfit(batch_sizes[:len(y)], y, deg=1) # first degree polynomial fit p = np.polyfit(batch_sizes[:len(y)], y, deg=1) # first degree polynomial fit
b = int((f * fraction - p[1]) / p[0]) # y intercept (optimal batch size) b = int((f * fraction - p[1]) / p[0]) # y intercept (optimal batch size)
if None in results: # some sizes failed if None in results: # some sizes failed
i = results.index(None) # first fail index i = results.index(None) # first fail index
if b >= batch_sizes[i]: # y intercept above failure point if b >= batch_sizes[i]: # y intercept above failure point
b = batch_sizes[max(i - 1, 0)] # select prior safe point b = batch_sizes[max(i - 1, 0)] # select prior safe point
if b < 1 or b > 1024: # b outside of safe range if b < 1 or b > 1024: # b outside of safe range
b = batch_size b = batch_size
LOGGER.warning(f'{prefix}WARNING ⚠️ CUDA anomaly detected, recommend restart environment and retry command.') LOGGER.info(f'{prefix}WARNING ⚠️ CUDA anomaly detected, using default batch-size {batch_size}.')
fraction = (np.polyval(p, b) + r + a) / t # actual fraction predicted fraction = (np.polyval(p, b) + r + a) / t # actual fraction predicted
LOGGER.info(f'{prefix}Using batch-size {b} for {d} {t * fraction:.2f}G/{t:.2f}G ({fraction * 100:.0f}%) ✅') LOGGER.info(f'{prefix}Using batch-size {b} for {d} {t * fraction:.2f}G/{t:.2f}G ({fraction * 100:.0f}%) ✅')
return b return b
except Exception as e:
LOGGER.warning(f'{prefix}WARNING ⚠️ error detected: {e}, using default batch-size {batch_size}.')
return batch_size

@ -41,7 +41,7 @@ class DetectionPredictor(BasePredictor):
if len(im.shape) == 3: if len(im.shape) == 3:
im = im[None] # expand for batch dim im = im[None] # expand for batch dim
self.seen += 1 self.seen += 1
im0 = im0.copy() imc = im0.copy() if self.args.save_crop else im0
if self.source_type.webcam or self.source_type.from_img: # batch_size >= 1 if self.source_type.webcam or self.source_type.from_img: # batch_size >= 1
log_string += f'{idx}: ' log_string += f'{idx}: '
frame = self.dataset.count frame = self.dataset.count
@ -73,7 +73,6 @@ class DetectionPredictor(BasePredictor):
self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}') self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}')
self.annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True)) self.annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True))
if self.args.save_crop: if self.args.save_crop:
imc = im0.copy()
save_one_box(d.xyxy, save_one_box(d.xyxy,
imc, imc,
file=self.save_dir / 'crops' / self.model.model.names[c] / f'{self.data_path.stem}.jpg', file=self.save_dir / 'crops' / self.model.model.names[c] / f'{self.data_path.stem}.jpg',

@ -43,6 +43,7 @@ class SegmentationPredictor(DetectionPredictor):
if len(im.shape) == 3: if len(im.shape) == 3:
im = im[None] # expand for batch dim im = im[None] # expand for batch dim
self.seen += 1 self.seen += 1
imc = im0.copy() if self.args.save_crop else im0
if self.source_type.webcam or self.source_type.from_img: # batch_size >= 1 if self.source_type.webcam or self.source_type.from_img: # batch_size >= 1
log_string += f'{idx}: ' log_string += f'{idx}: '
frame = self.dataset.count frame = self.dataset.count
@ -91,7 +92,6 @@ class SegmentationPredictor(DetectionPredictor):
self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}') self.model.names[c] if self.args.hide_conf else f'{self.model.names[c]} {conf:.2f}')
self.annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True)) if self.args.boxes else None self.annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True)) if self.args.boxes else None
if self.args.save_crop: if self.args.save_crop:
imc = im0.copy()
save_one_box(d.xyxy, save_one_box(d.xyxy,
imc, imc,
file=self.save_dir / 'crops' / self.model.model.names[c] / f'{self.data_path.stem}.jpg', file=self.save_dir / 'crops' / self.model.model.names[c] / f'{self.data_path.stem}.jpg',

Loading…
Cancel
Save