İçeriğe geç

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.

YOLOv7'nin SOTA nesne dedektörleriyle karşılaştırılması

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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:

  1. (İ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
    
  2. 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
    
  3. 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")
    
  4. 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

  1. ONNX Dışa Aktarma bölümündeki 1-2 arasındaki adımları izleyin.

  2. Şunu yükleyin: TensorRT python paketi:

    pip install tensorrt
    
  3. 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)
    
  4. 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:

  1. YOLOv7 deposunu klonlayın:
    git clone https://github.com/WongKinYiu/yolov7
    
  2. Klonlanan dizine gidin ve bağımlılıkları yükleyin:
    cd yolov7
    pip install -r requirements.txt
    
  3. 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.

  4. 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.



📅 1 yıl önce oluşturuldu ✏️ 1 ay önce güncellendi

Yorumlar