YOLOv7: Eğitilebilir 'Bag-of-Freebies'#
YOLOv7, Temmuz 2022'de yayınlandığı dönemde gerçek zamanlı nesne tespiti alanında önemli bir ilerlemeydi. V100 GPU üzerinde %56.8 AP elde ederek çıktığı zaman yeni kıyas ölçütleri belirledi. YOLOv7, hız ve doğruluk açısından YOLOR, YOLOX, Scaled-YOLOv4 ve YOLOv5 gibi dönemin nesne dedektörlerini geride bıraktı. Model, başka hiçbir veri seti veya önceden eğitilmiş ağırlık kullanılmadan sıfırdan MS COCO veri seti üzerinde eğitilir. YOLOv7'nin kaynak kodu GitHub üzerinde mevcuttur. YOLO11 ve YOLO26 gibi daha yeni modellerin o zamandan beri gelişmiş verimlilikle daha yüksek doğruluk elde ettiğini unutma.

SOTA nesne tespit edicilerinin karşılaştırması#
YOLO karşılaştırma tablosundaki sonuçlardan, önerilen yöntemin hız-doğruluk dengesi açısından kapsamlı bir şekilde en iyisi olduğunu biliyoruz. YOLOv7-tiny-SiLU ile YOLOv5-N (r6.1) modelini karşılaştırırsak, yöntemimiz 127 fps daha hızlı ve AP açısından %10,7 daha doğrudur. Ayrıca, YOLOv7 161 fps kare hızında %51,4 AP değerine sahipken, aynı AP'ye sahip PPYOLOE-L modeli yalnızca 78 fps kare hızına sahiptir. Parametre kullanımı açısından YOLOv7, PPYOLOE-L'den %41 daha azdır.
114 fps çıkarım hızına sahip YOLOv7-X'i 99 fps çıkarım hızına sahip YOLOv5-L (r6.1) ile karşılaştırırırsak, YOLOv7-X AP'yi %3.9 oranında iyileştirebilir. YOLOv7-X benzer ölçekteki YOLOv5-X (r6.1) ile karşılaştırılırsa, YOLOv7-X'in çıkarım hızı 31 fps daha hızlıdır. Ek olarak, parametre ve hesaplama miktarı açısından YOLOv7-X, YOLOv5-X (r6.1) ile karşılaştırıldığında parametrelerde %22 ve hesaplamada %8 azalma sağlar, ancak AP'yi %2.2 oranında artırır (Kaynak).
| Model | Parametreler (M) | FLOPs (G) | Boyut (piksel) | FPS | APtest / val 50-95 | APtest 50 | APtest 75 | APtest S | APtest M | APtest L |
|---|---|---|---|---|---|---|---|---|---|---|
| YOLOX-S | 9.0 | 26.8 | 640 | 102 | 40.5% / 40.5% | - | - | - | - | - |
| YOLOX-M | 25.3 | 73.8 | 640 | 81 | 47.2% / 46.9% | - | - | - | - | - |
| YOLOX-L | 54.2 | 155.6 | 640 | 69 | 50.1% / 49.7% | - | - | - | - | - |
| YOLOX-X | 99.1 | 281.9 | 640 | 58 | 51.5% / 51.1% | - | - | - | - | - |
| PPYOLOE-S | 7.9 | 17.4 | 640 | 208 | 43.1% / 42.7% | 60.5% | 46.6% | 23.2% | 46.4% | 56.9% |
| PPYOLOE-M | 23.4 | 49.9 | 640 | 123 | 48.9% / 48.6% | 66.5% | 53.0% | 28.6% | 52.9% | 63.8% |
| PPYOLOE-L | 52.2 | 110.1 | 640 | 78 | 51.4% / 50.9% | 68.9% | 55.6% | 31.4% | 55.3% | 66.1% |
| PPYOLOE-X | 98.4 | 206.6 | 640 | 45 | 52.2% / 51.9% | 69.9% | 56.5% | 33.3% | 56.3% | 66.4% |
| YOLOv5-N (r6.1) | 1.9 | 4.5 | 640 | 159 | - / 28.0% | - | - | - | - | - |
| YOLOv5-S (r6.1) | 7.2 | 16.5 | 640 | 156 | - / 37.4% | - | - | - | - | - |
| YOLOv5-M (r6.1) | 21.2 | 49.0 | 640 | 122 | - / 45.4% | - | - | - | - | - |
| YOLOv5-L (r6.1) | 46.5 | 109.1 | 640 | 99 | - / 49.0% | - | - | - | - | - |
| YOLOv5-X (r6.1) | 86.7 | 205.7 | 640 | 83 | - / 50.7% | - | - | - | - | - |
| YOLOR-CSP | 52.9 | 120.4 | 640 | 106 | 51.1% / 50.8% | 69.6% | 55.7% | 31.7% | 55.3% | 64.7% |
| YOLOR-CSP-X | 96.9 | 226.8 | 640 | 87 | 53.0% / 52.7% | 71.4% | 57.9% | 33.7% | 57.1% | 66.8% |
| YOLOv7-tiny-SiLU | 6.2 | 13.8 | 640 | 286 | 38.7% / 38.7% | 56.7% | 41.7% | 18.8% | 42.4% | 51.9% |
| YOLOv7 | 36.9 | 104.7 | 640 | 161 | 51.4% / 51.2% | 69.7% | 55.9% | 31.8% | 55.5% | 65.0% |
| YOLOv7-X | 71.3 | 189.9 | 640 | 114 | 53.1% / 52.9% | 71.2% | 57.8% | 33.8% | 57.1% | 67.4% |
| YOLOv5-N6 (r6.1) | 3.2 | 18.4 | 1280 | 123 | - / 36.0% | - | - | - | - | - |
| YOLOv5-S6 (r6.1) | 12.6 | 67.2 | 1280 | 122 | - / 44.8% | - | - | - | - | - |
| YOLOv5-M6 (r6.1) | 35.7 | 200.0 | 1280 | 90 | - / 51.3% | - | - | - | - | - |
| YOLOv5-L6 (r6.1) | 76.8 | 445.6 | 1280 | 63 | - / 53.7% | - | - | - | - | - |
| YOLOv5-X6 (r6.1) | 140.7 | 839.2 | 1280 | 38 | - / 55.0% | - | - | - | - | - |
| YOLOR-P6 | 37.2 | 325.6 | 1280 | 76 | 53.9% / 53.5% | 71.4% | 58.9% | 36.1% | 57.7% | 65.6% |
| YOLOR-W6 | 79.8 | 453.2 | 1280 | 66 | 55.2% / 54.8% | 72.7% | 60.5% | 37.7% | 59.1% | 67.1% |
| YOLOR-E6 | 115.8 | 683.2 | 1280 | 45 | 55.8% / 55.7% | 73.4% | 61.1% | 38.4% | 59.7% | 67.7% |
| YOLOR-D6 | 151.7 | 935.6 | 1280 | 34 | 56.5% / 56.1% | 74.1% | 61.9% | 38.9% | 60.4% | 68.7% |
| YOLOv7-W6 | 70.4 | 360.0 | 1280 | 84 | 54.9% / 54.6% | 72.6% | 60.1% | 37.3% | 58.7% | 67.1% |
| YOLOv7-E6 | 97.2 | 515.2 | 1280 | 56 | 56.0% / 55.9% | 73.5% | 61.2% | 38.0% | 59.9% | 68.4% |
| YOLOv7-D6 | 154.7 | 806.8 | 1280 | 44 | 56.6% / 56.3% | 74.0% | 61.8% | 38.8% | 60.1% | 69.5% |
| YOLOv7-E6E | 151.7 | 843.2 | 1280 | 36 | 56.8% / 56.8% | 74.4% | 62.1% | 39.3% | 60.5% | 69.0% |
Genel Bakış#
Gerçek zamanlı nesne tespiti; çoklu nesne takibi, otonom sürüş, robotik ve tıbbi görüntü analizi dahil olmak üzere birçok computer vision sisteminde önemli bir bileşendir. Son yıllarda gerçek zamanlı nesne tespiti geliştirme çalışmaları, verimli mimariler tasarlamaya ve çeşitli CPU, GPU ve sinirsel işleme birimlerinin (NPU) çıkarım hızını iyileştirmeye odaklanmıştır. YOLOv7, uç cihazlardan buluta kadar hem mobil GPU'ları hem de GPU cihazlarını destekler.
Mimari optimizasyona odaklanan geleneksel gerçek zamanlı nesne dedektörlerinin aksine YOLOv7, eğitim sürecinin optimizasyonuna odaklanır. Bu, "eğitilebilir ücretsiz avantajlar paketi" (trainable bag-of-freebies) olarak bilinen bir kavram olan, çıkarım maliyetini artırmadan nesne tespiti doğruluğunu iyileştirmek için tasarlanmış modülleri ve optimizasyon yöntemlerini içerir.
Temel Özellikler#
YOLOv7 birkaç temel özellik sunar:
-
Model Yeniden Parametrelendirme: YOLOv7, gradyan yayılım yolu kavramıyla farklı ağlardaki katmanlara uygulanabilir bir strateji olan planlı bir yeniden parametrelendirilmiş model önerir.
-
Dinamik Etiket Atama: Çoklu çıktı katmanlarına sahip modelin eğitimi yeni bir sorun ortaya çıkarır: "Farklı dalların çıktıları için dinamik hedefler nasıl atanır?" Bu sorunu çözmek için YOLOv7, kabadan inceye (coarse-to-fine) lider yönlendirmeli etiket atama adında yeni bir etiket atama yöntemi sunar.
-
Genişletilmiş ve Bileşik Ölçekleme: YOLOv7, parametreleri ve hesaplamayı etkili bir şekilde kullanabilen gerçek zamanlı nesne dedektörü için "genişletme" ve "bileşik ölçekleme" yöntemleri önerir.
-
Verimlilik: YOLOv7 tarafından önerilen yöntem, en gelişmiş gerçek zamanlı nesne dedektörünün parametrelerini yaklaşık %40, hesaplamasını ise %50 oranında etkili bir şekilde azaltabilir; ayrıca daha hızlı çıkarım hızına ve daha yüksek tespit doğruluğuna sahiptir.
Kullanım Örnekleri#
Ultralytics, yolov7.pt önceden eğitilmiş ağırlıklarını veya ultralytics/cfg/models/v7/ YAML dosyalarını yayınlamaz ve YOLOv7 için yerel PyTorch eğitimi ile çıkarımı Ultralytics Python paketi tarafından desteklenmez. Ancak, aşağıda gösterildiği gibi ana YOLOv7 deposunda eğitilmiş bir YOLOv7 kontrol noktasını ONNX veya TensorRT'ye dışarı aktararak Ultralytics'e getirebilirsin.
ONNX Dışa Aktarımı#
YOLOv7 ONNX modelini Ultralytics ile kullanmak için:
-
(İsteğe bağlı) Ultralytics'i kur ve gerekli bağımlılıkların otomatik olarak yüklenmesi için bir ONNX modelini dışa aktar:
pip install ultralytics yolo export model=yolo26n.pt format=onnx -
YOLOv7 deposundaki dışarı aktarıcıyı kullanarak istediğin YOLOv7 modelini dışarı aktar:
git clone https://github.com/WongKinYiu/yolov7 cd yolov7 python export.py --weights yolov7-tiny.pt --grid --end2end --simplify --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 --img-size 640 640 --max-wh 640 -
Aşağıdaki betiği kullanarak ONNX model grafiğini Ultralytics ile uyumlu olacak şekilde değiştir:
import numpy as np import onnx from onnx import helper, numpy_helper # Load the ONNX model model_path = "yolov7/yolov7-tiny.onnx" # Replace with your model path model = onnx.load(model_path) graph = model.graph # Fix input shape to batch size 1 input_shape = graph.input[0].type.tensor_type.shape input_shape.dim[0].dim_value = 1 # Define the output of the original model original_output_name = graph.output[0].name # Create slicing nodes sliced_output_name = f"{original_output_name}_sliced" # Define initializers for slicing (remove the first value) start = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_start") end = numpy_helper.from_array(np.array([7], dtype=np.int64), name="slice_end") axes = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_axes") steps = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_steps") graph.initializer.extend([start, end, axes, steps]) slice_node = helper.make_node( "Slice", inputs=[original_output_name, "slice_start", "slice_end", "slice_axes", "slice_steps"], outputs=[sliced_output_name], name="SliceNode", ) graph.node.append(slice_node) # Define segment slicing seg1_start = numpy_helper.from_array(np.array([0], dtype=np.int64), name="seg1_start") seg1_end = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg1_end") seg2_start = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg2_start") seg2_end = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg2_end") seg3_start = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg3_start") seg3_end = numpy_helper.from_array(np.array([6], dtype=np.int64), name="seg3_end") graph.initializer.extend([seg1_start, seg1_end, seg2_start, seg2_end, seg3_start, seg3_end]) # Create intermediate tensors for segments segment_1_name = f"{sliced_output_name}_segment1" segment_2_name = f"{sliced_output_name}_segment2" segment_3_name = f"{sliced_output_name}_segment3" # Add segment slicing nodes graph.node.extend( [ helper.make_node( "Slice", inputs=[sliced_output_name, "seg1_start", "seg1_end", "slice_axes", "slice_steps"], outputs=[segment_1_name], name="SliceSegment1", ), helper.make_node( "Slice", inputs=[sliced_output_name, "seg2_start", "seg2_end", "slice_axes", "slice_steps"], outputs=[segment_2_name], name="SliceSegment2", ), helper.make_node( "Slice", inputs=[sliced_output_name, "seg3_start", "seg3_end", "slice_axes", "slice_steps"], outputs=[segment_3_name], name="SliceSegment3", ), ] ) # Concatenate the segments concat_output_name = f"{sliced_output_name}_concat" concat_node = helper.make_node( "Concat", inputs=[segment_1_name, segment_3_name, segment_2_name], outputs=[concat_output_name], axis=1, name="ConcatSwapped", ) graph.node.append(concat_node) # Reshape to [1, -1, 6] reshape_shape = numpy_helper.from_array(np.array([1, -1, 6], dtype=np.int64), name="reshape_shape") graph.initializer.append(reshape_shape) final_output_name = f"{concat_output_name}_batched" reshape_node = helper.make_node( "Reshape", inputs=[concat_output_name, "reshape_shape"], outputs=[final_output_name], name="AddBatchDimension", ) graph.node.append(reshape_node) # Get the shape of the reshaped tensor shape_node_name = f"{final_output_name}_shape" shape_node = helper.make_node( "Shape", inputs=[final_output_name], outputs=[shape_node_name], name="GetShapeDim", ) graph.node.append(shape_node) # Extract the second dimension dim_1_index = numpy_helper.from_array(np.array([1], dtype=np.int64), name="dim_1_index") graph.initializer.append(dim_1_index) second_dim_name = f"{final_output_name}_dim1" gather_node = helper.make_node( "Gather", inputs=[shape_node_name, "dim_1_index"], outputs=[second_dim_name], name="GatherSecondDim", ) graph.node.append(gather_node) # Subtract from 100 to determine how many values to pad target_size = numpy_helper.from_array(np.array([100], dtype=np.int64), name="target_size") graph.initializer.append(target_size) pad_size_name = f"{second_dim_name}_padsize" sub_node = helper.make_node( "Sub", inputs=["target_size", second_dim_name], outputs=[pad_size_name], name="CalculatePadSize", ) graph.node.append(sub_node) # Build the [2, 3] pad array: # 1st row -> [0, 0, 0] (no padding at the start of any dim) # 2nd row -> [0, pad_size, 0] (pad only at the end of the second dim) pad_starts = numpy_helper.from_array(np.array([0, 0, 0], dtype=np.int64), name="pad_starts") graph.initializer.append(pad_starts) zero_scalar = numpy_helper.from_array(np.array([0], dtype=np.int64), name="zero_scalar") graph.initializer.append(zero_scalar) pad_ends_name = "pad_ends" concat_pad_ends_node = helper.make_node( "Concat", inputs=["zero_scalar", pad_size_name, "zero_scalar"], outputs=[pad_ends_name], axis=0, name="ConcatPadEnds", ) graph.node.append(concat_pad_ends_node) pad_values_name = "pad_values" concat_pad_node = helper.make_node( "Concat", inputs=["pad_starts", pad_ends_name], outputs=[pad_values_name], axis=0, name="ConcatPadStartsEnds", ) graph.node.append(concat_pad_node) # Create Pad operator to pad with zeros pad_output_name = f"{final_output_name}_padded" pad_constant_value = numpy_helper.from_array( np.array([0.0], dtype=np.float32), name="pad_constant_value", ) graph.initializer.append(pad_constant_value) pad_node = helper.make_node( "Pad", inputs=[final_output_name, pad_values_name, "pad_constant_value"], outputs=[pad_output_name], mode="constant", name="PadToFixedSize", ) graph.node.append(pad_node) # Update the graph's final output to [1, 100, 6] new_output_type = onnx.helper.make_tensor_type_proto( elem_type=graph.output[0].type.tensor_type.elem_type, shape=[1, 100, 6] ) new_output = onnx.helper.make_value_info(name=pad_output_name, type_proto=new_output_type) # Replace the old output with the new one graph.output.pop() graph.output.extend([new_output]) # Save the modified model onnx.save(model, "yolov7-ultralytics.onnx") -
Ardından değiştirilmiş ONNX modelini yükleyebilir ve Ultralytics içinde normal bir şekilde çıkarım çalıştırabilirsin:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.onnx", task="detect") results = model(ASSETS / "bus.jpg")
TensorRT Dışa Aktarımı#
-
ONNX Dışa Aktarımı bölümündeki 1-2 adımlarını takip et.
-
TensorRTPython paketini yükle:pip install tensorrt -
Değiştirilmiş ONNX modelini TensorRT motoruna dönüştürmek için aşağıdaki betiği çalıştır:
from ultralytics.utils.export import export_engine export_engine("yolov7-ultralytics.onnx", half=True) -
Modeli Ultralytics içinde yükle ve çalıştır:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.engine", task="detect") results = model(ASSETS / "bus.jpg")
Alıntılar ve Teşekkür#
Gerçek zamanlı nesne tespiti alanına yaptıkları önemli katkılardan dolayı YOLOv7 yazarlarına teşekkür ederiz:
@inproceedings{wang2023yolov7,
title={YOLOv7: Trainable Bag-of-Freebies Sets New State-of-the-Art for Real-Time Object Detectors},
author={Wang, Chien-Yao and Bochkovskiy, Alexey and Liao, Hong-Yuan Mark},
booktitle={Proceedings of the IEEE/CVF conference on Computer Vision and Pattern Recognition (CVPR)},
pages={7464--7475},
year={2023}
}Resmi YOLOv7 makalesi CVF 2023 Açık Erişim içinde yayınlandı ve arXiv üzerinde bir ön baskısı bulunmaktadır. Yazarlar çalışmalarını halka açık hale getirdiler ve kod tabanına GitHub üzerinden erişilebilir. Alanı ilerlettikleri ve çalışmalarını daha geniş topluluk için erişilebilir kıldıkları için çabalarını takdir ediyoruz.
SSS#
YOLOv7 nedir ve gerçek zamanlı nesne tespitinde neden bir çığır açan gelişme olarak kabul edilir?#
YOLOv7, Temmuz 2022'de yayınlanan, çıktığı dönemde mükemmel hız ve doğruluk elde eden önemli bir gerçek zamanlı nesne tespiti modeliydi. Hem parametre kullanımı hem de çıkarım hızı açısından YOLOX, YOLOv5 ve PPYOLOE gibi dönemin modellerini geride bıraktı. YOLOv7'nin ayırt edici özellikleri arasında, çıkarım maliyetlerini artırmadan performansını optimize eden model yeniden parametrelendirmesi ve dinamik etiket ataması yer alır. Mimarisi ve diğer güncel nesne dedektörleriyle karşılaştırma ölçütleri hakkında daha fazla teknik detay için YOLOv7 makalesine göz at.
YOLOv7, YOLOv4 ve YOLOv5 gibi önceki YOLO modellerine göre nasıl bir iyileştirme sağlıyor?#
YOLOv7, eğitim sürecini geliştiren ve çıkarım doğruluğunu artıran model yeniden parametrelendirmesi ve dinamik etiket ataması dahil olmak üzere çeşitli yenilikler sunar. YOLOv5 ile karşılaştırıldığında YOLOv7 hızı ve doğruluğu önemli ölçüde artırır. Örneğin, YOLOv7-X, YOLOv5-X ile karşılaştırıldığında doğruluğu %2.2 oranında artırır ve parametreleri %22 oranında azaltır. Ayrıntılı karşılaştırmalar YOLOv7 comparison with SOTA object detectors performans tablosunda bulunabilir.
YOLOv7'yi Ultralytics araçları ve platformları ile kullanabilir miyim?#
Şu itibarıyla Ultralytics yalnızca YOLOv7 ONNX ve TensorRT çıkarımını desteklemektedir. YOLOv7'nin ONNX ve TensorRT olarak dışarı aktarılan versiyonunu Ultralytics ile çalıştırmak için Kullanım Örnekleri bölümünü kontrol et.
Kendi veri setimi kullanarak özel bir YOLOv7 modelini nasıl eğitebilirim?#
Özel bir YOLOv7 modelini kurmak ve eğitmek için şu adımları izle:
-
YOLOv7 deposunu klonla:
git clone https://github.com/WongKinYiu/yolov7 -
Klonlanan dizine git ve bağımlılıkları yükle:
cd yolov7 pip install -r requirements.txt -
Veri setini haznele ve depoda sağlanan kullanım talimatlarına göre model parametrelerini yapılandır. Daha fazla rehberlik için en son bilgi ve güncellemeler amacıyla YOLOv7 GitHub deposunu ziyaret et.
-
Eğitimden sonra, Kullanım Örnekleri bölümünde gösterildiği gibi modeli Ultralytics'te kullanmak üzere ONNX veya TensorRT formatına dışarı aktarabilirsin.
YOLOv7'de sunulan temel özellikler ve optimizasyonlar nelerdir?#
YOLOv7, gerçek zamanlı nesne tespitinde devrim yaratan çeşitli temel özellikler sunar:
- Model Yeniden Parametrelendirme: Gradyan yayılım yollarını optimize ederek modelin performansını artırır.
- Dinamik Etiket Atama: Farklı dallardaki çıktılar için dinamik hedefler atamak amacıyla kabadan inceye lider yönlendirmeli bir yöntem kullanır ve doğruluğu iyileştirir.
- Genişletilmiş ve Bileşik Ölçekleme: Modeli çeşitli gerçek zamanlı uygulamalar için ölçeklendirmek amacıyla parametreleri ve hesaplamayı verimli bir şekilde kullanır.
- Verimlilik: Diğer en gelişmiş modellere kıyasla parametre sayısını %40, hesaplamayı ise %50 oranında azaltırken daha hızlı çıkarım hızlarına ulaşır.
Bu özellikler hakkında daha fazla ayrıntı için YOLOv7 Genel Bakış bölümüne bakın.