YOLOv7: Eğitilebilir Bag-of-Freebies
YOLOv7, 5 FPS ile 160 FPS arasındaki hız ve doğruluk aralığında bilinen tüm nesne dedektörlerini geride bırakan, son teknoloji ürünü bir gerçek zamanlı nesne dedektörüdür. GPU V100 üzerinde 30 FPS veya daha yüksek hızda çalışan tüm bilinen gerçek zamanlı nesne dedektörleri arasında en yüksek doğruluğa (%56,8 AP) sahiptir. Dahası, YOLOv7 hız ve doğruluk açısından YOLOR, YOLOX, Scaled-YOLOv4, YOLOv5 ve diğer birçok nesne dedektöründen daha iyi performans gösterir. Model, başka herhangi bir veri kümesi veya önceden eğitilmiş ağırlıklar kullanılmadan sıfırdan MS COCO veri kümesi üzerinde eğitilmiştir. YOLOv7 için kaynak kodu GitHub'da mevcuttur.
SOTA nesne dedektörlerinin karşılaştırılması
YOLO karşılaştırma tablosundaki sonuçlardan, önerilen yöntemin kapsamlı bir şekilde en iyi hız-doğruluk dengesine sahip olduğunu biliyoruz. YOLOv7-tiny-SiLU'yu YOLOv5-N (r6.1) ile karşılaştırırsak, yöntemimiz 127 fps daha hızlı ve AP'de %10,7 daha doğrudur. Ek olarak, YOLOv7 161 fps kare hızında %51,4 AP'ye sahipken, aynı AP'ye sahip PPYOLOE-L yalnızca 78 fps kare hızına sahiptir. Parametre kullanımı açısından YOLOv7, PPYOLOE-L'den %41 daha azdır.
Eğer 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ı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ıldığında, 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'e (r6.1) kıyasla parametrelerin %22'sini ve hesaplamanın %8'ini azaltır, ancak AP'yi %2.2 oranında iyileştirir (Kaynak).
Performans
Model | Parametreler (M) |
FLOP'lar (G) |
Boyut (piksel) |
FPS (Saniyedeki Kare Sayısı) | 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 algılama, çoklu nesne takibi, otonom sürüş, robotik ve tıbbi görüntü analizi dahil olmak üzere birçok bilgisayar görüşü sisteminde önemli bir bileşendir. Son yıllarda, gerçek zamanlı nesne algılama geliştirme çalışmaları, çeşitli CPU'ların, GPU'ların ve nöral işlem birimlerinin (NPU'lar) verimli mimarilerini tasarlamaya ve çıkarım hızını artırmaya odaklanmıştır. YOLOv7, uçtan buluta hem mobil GPU hem de GPU cihazlarını destekler.
Mimarinin optimizasyonuna odaklanan geleneksel gerçek zamanlı nesne dedektörlerinin aksine, YOLOv7 eğitim sürecinin optimizasyonuna odaklanmayı getiriyor. Bu, çıkarım maliyetini artırmadan nesne tespitinin doğruluğunu artırmak için tasarlanmış modüller ve optimizasyon yöntemlerini içerir; bu, "eğitilebilir bedava hediyeler çantası" olarak bilinir.
Temel Özellikler
YOLOv7 çeşitli temel özellikleri sunar:
-
Model Yeniden Parametreleme: YOLOv7, gradyan yayılım yolu kavramıyla farklı ağlardaki katmanlara uygulanabilir bir strateji olan planlı bir yeniden parametrelendirilmiş model önermektedir.
-
Dinamik Etiket Atama: Çoklu çıktı katmanı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, coarse-to-fine lead guided etiket atama adı verilen yeni bir etiket atama yöntemi sunar.
-
Genişletilmiş ve Bileşik Ölçeklendirme: YOLOv7, parametreleri ve hesaplamayı etkin bir şekilde kullanabilen gerçek zamanlı nesne dedektörü için "genişletme" ve "bileşik ölçeklendirme" yöntemleri önermektedir.
-
Verimlilik: YOLOv7 tarafından önerilen yöntem, son teknoloji ürünü gerçek zamanlı nesne dedektörünün yaklaşık %40 parametresini ve %50 hesaplamasını etkili bir şekilde azaltabilir ve daha hızlı çıkarım hızına ve daha yüksek algılama doğruluğuna sahiptir.
Kullanım Örnekleri
Bu yazının yazıldığı sırada, Ultralytics yalnızca YOLOv7 için ONNX ve TensorRT çıkarımını desteklemektedir.
ONNX Dışa Aktarma
Ultralytics ile YOLOv7 ONNX modelini kullanmak için:
-
(İsteğe bağlı) Gerekli bağımlılıkların otomatik olarak yüklenmesi için Ultralytics'i kurun ve bir ONNX modeli dışa aktarın:
pip install ultralytics yolo export model=yolo11n.pt format=onnx
-
YOLOv7 deposundaki dışa aktarıcıyı kullanarak istediğiniz YOLOv7 modelini dışa aktarın:
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 komut dosyasını kullanarak ONNX model grafiğini Ultralytics ile uyumlu olacak şekilde değiştirin:
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")
-
Daha sonra değiştirilmiş ONNX modelini yükleyebilir ve Ultralytics'te normal şekilde çıkarım yapabilirsiniz:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.onnx", task="detect") results = model(ASSETS / "bus.jpg")
TensorRT Dışa Aktarma
-
ONNX Dışa Aktarma bölümündeki 1-2 arasındaki adımları izleyin.
-
Şunu yükleyin:
TensorRT
python paketi:pip install tensorrt
-
Değiştirilmiş ONNX modelini TensorRT motoruna dönüştürmek için aşağıdaki betiği çalıştırın:
from ultralytics.utils.export import export_engine export_engine("yolov7-ultralytics.onnx", half=True)
-
Modeli Ultralytics'te yükleyin ve çalıştırın:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.engine", task="detect") results = model(ASSETS / "bus.jpg")
Alıntılar ve Teşekkürler
Gerçek zamanlı nesne algılama alanındaki önemli katkılarından dolayı YOLOv7 yazarlarına teşekkür ederiz:
@article{wang2022yolov7,
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},
journal={arXiv preprint arXiv:2207.02696},
year={2022}
}
Orijinal YOLOv7 makalesine arXiv üzerinden ulaşılabilir. Yazarlar çalışmalarını kamuya açık hale getirmişlerdir ve kod tabanına GitHub üzerinden erişilebilir. Alanı geliştirmedeki ve çalışmalarını daha geniş bir topluluğa erişilebilir kılmadaki çabalarını takdir ediyoruz.
SSS
YOLOv7 nedir ve neden gerçek zamanlı nesne tespiti alanında bir atılım olarak kabul edilir?
YOLOv7, benzersiz hız ve doğruluk sağlayan son teknoloji ürünü bir gerçek zamanlı nesne algılama modelidir. Parametre kullanımı ve çıkarım hızı açısından YOLOX, YOLOv5 ve PPYOLOE gibi diğer modelleri geride bırakır. YOLOv7'nin ayırt edici özellikleri, çıkarım maliyetlerini artırmadan performansını optimize eden model yeniden parametrelendirmesi ve dinamik etiket atamasıdır. Mimarisi ve diğer son teknoloji nesne dedektörleriyle karşılaştırma metrikleri hakkında daha fazla teknik ayrıntı için YOLOv7 makalesine bakın.
YOLOv7, YOLOv4 ve YOLOv5 gibi önceki YOLO modellerine göre nasıl bir gelişme sunar?
YOLOv7, eğitim sürecini geliştiren ve çıkarım doğruluğunu artıran model yeniden parametrelendirme ve dinamik etiket atama gibi ç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'e kıyasla doğruluğu %2,2 artırır ve parametreleri %22 azaltır. Ayrıntılı karşılaştırmalar, SOTA nesne dedektörleriyle YOLOv7 karşılaştırması performans tablosunda bulunabilir.
YOLOv7'yi Ultralytics araçları ve platformlarıyla kullanabilir miyim?
Şu an itibarıyla Ultralytics yalnızca YOLOv7 ONNX ve TensorRT çıkarımını desteklemektedir. YOLOv7'nin ONNX ve TensorRT ile dışa aktarılmış sürümünü Ultralytics ile çalıştırmak için Kullanım Örnekleri bölümüne bakın.
Veri setimi kullanarak özel bir YOLOv7 modelini nasıl eğitirim?
Özel bir YOLOv7 modelini kurmak ve eğitmek için şu adımları izleyin:
- YOLOv7 deposunu klonlayın:
git clone https://github.com/WongKinYiu/yolov7
- Klonlanan dizine gidin ve bağımlılıkları yükleyin:
cd yolov7 pip install -r requirements.txt
-
Veri kümenizi hazırlayın ve model parametrelerini depoda sağlanan kullanım talimatlarına göre yapılandırın. Daha fazla rehberlik için, en son bilgiler ve güncellemeler için YOLOv7 GitHub deposunu ziyaret edin.
-
Eğitimden sonra, modeli Kullanım Örnekleri'nde gösterildiği gibi Ultralytics'te kullanılmak üzere ONNX veya TensorRT'ye aktarabilirsiniz.
YOLOv7'de tanıtılan temel özellikler ve optimizasyonlar nelerdir?
YOLOv7, gerçek zamanlı nesne algılamada devrim yaratan çeşitli temel özellikler sunar:
- Model Yeniden Parametreleme: Gradyan yayılımı yollarını optimize ederek modelin performansını artırır.
- Dinamik Etiket Atama: Doğruluğu artırmak için farklı dallardaki çıktılar için dinamik hedefler atamak üzere coarse-to-fine lead guided yöntemini kullanır.
- Genişletilmiş ve Bileşik Ölçeklendirme: Modeli çeşitli gerçek zamanlı uygulamalar için ölçeklendirmek üzere parametreleri ve hesaplamayı verimli bir şekilde kullanır.
- Verimlilik: Diğer son teknoloji modellere kıyasla parametre sayısını %40 ve hesaplamayı %50 azaltırken daha hızlı çıkarım hızları elde eder.
Bu özelliklerle ilgili daha fazla ayrıntı için YOLOv7 Genel Bakış bölümüne bakın.