YOLOv7: Eğitilebilir Ücretsiz Çantalar
YOLOv7, 5 FPS ila 160 FPS aralığında hem hız hem de doğruluk açısından bilinen tüm nesne dedektörlerini geride bırakan son teknoloji ürünü bir gerçek zamanlı nesne dedektörüdür. GPU V100 adresinde 30 FPS veya daha yüksek hızda bilinen tüm gerçek zamanlı nesne dedektörleri arasında en yüksek doğruluğa (%56,8 AP) sahiptir. Ayrıca, YOLOv7, YOLOR, YOLOX, Scaled-YOLOv4, YOLOv5 ve diğerleri gibi diğer nesne dedektörlerinden hız ve doğruluk açısından daha iyi performans gösterir. Model, başka veri kümeleri 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ı olarak en iyi hız-doğruluk dengesine sahip olduğunu biliyoruz. YOLOv7-tiny-SiLU'yu YOLOv5(r6.1) ile karşılaştırırsak, yöntemimizin 127 fps daha hızlı ve AP'de %10,7 daha doğru olduğunu görürüz. Buna ek olarak, YOLOv7 161 fps kare hızında %51,4 AP'ye sahipken, aynı AP'ye sahip PPYOLOE-L sadece 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(r6.1) ile karşılaştırırsak, YOLOv7-X AP'yi %3,9 oranında iyileştirebilir. YOLOv7-X, benzer ölçekteki YOLOv5(r6.1) ile karşılaştırıldığında, YOLOv7-X'in çıkarım hızının 31 fps daha hızlı olduğu görülmektedir. Ayrıca, parametre ve hesaplama miktarı açısından YOLOv7-X, YOLOv5(r6.1) ile karşılaştırıldığında parametreleri %22 ve hesaplamayı %8 oranında azaltırken AP'yi %2,2 oranında iyileştirmektedir(Kaynak).
Performans
Model | Params (M) |
FLOP'lar (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 algılama, çoklu nesnetakibi, otonom sürüş, robotik ve tıbbi görüntü analizi dahil olmak üzere birçok bilgisayarla görme sisteminde önemli bir bileşendir. Son yıllarda, gerçek zamanlı nesne algılama gelişimi, verimli mimariler tasarlamaya ve çeşitli CPU'ların, GPU'ların ve sinir işleme birimlerinin (NPU'lar) çıkarım hızını artırmaya odaklanmıştır. YOLOv7, uçtan buluta kadar hem mobil GPU hem de GPU cihazlarını destekler.
Mimari optimizasyonuna odaklanan geleneksel gerçek zamanlı nesne dedektörlerinin aksine, YOLOv7 eğitim sürecinin optimizasyonuna odaklanmaktadır. Bu, "eğitilebilir ücretsiz torba" olarak bilinen bir kavram olan çıkarım maliyetini artırmadan nesne algılama doğruluğunu artırmak için tasarlanmış modülleri ve optimizasyon yöntemlerini içerir.
Temel Özellikler
YOLOv7 birkaç temel özellik sunuyor:
-
Model Yeniden Parametrelendirme: YOLOv7, gradyan yayılım yolu kavramı ile farklı ağlardaki katmanlara uygulanabilen bir strateji olan planlı bir yeniden parametreli model önermektedir.
-
Dinamik Etiket Ataması: Birden fazla çıktı katmanına sahip modelin eğitimi yeni bir sorun ortaya çıkarmaktadır: "Farklı dalların çıktıları için dinamik hedefler nasıl atanır?" Bu sorunu çözmek için YOLOv7, kabadan inceye kılavuzlu etiket ataması adı verilen yeni bir etiket atama yöntemi sunmaktadır.
-
Genişletilmiş ve Bileşik Ölçeklendirme: YOLOv7, gerçek zamanlı nesne dedektörü için parametreleri ve hesaplamayı etkin bir şekilde kullanabilen "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 tespit doğruluğuna sahiptir.
Kullanım Örnekleri
Yazma zamanı itibariyle Ultralytics , YOLOv7 için yalnızca ONNX ve TensorRT çıkarımını desteklemektedir.
ONNX İhracat
YOLOv7 ONNX modelini Ultralytics ile kullanmak için:
- (İsteğe bağlı) Ultralytics 'i yükleyin ve gerekli bağımlılıkların otomatik olarak yüklenmesi için bir ONNX modelini dışa aktarın:
pip install ultralytics
yolo export model=yolo11n.pt format=onnx
- İstediğiniz YOLOv7 modelini YOLOv7 reposundaki dışa aktarıcıyı kullanarak 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 olarak çıkarım yapabilirsiniz:
from ultralytics import ASSETS, YOLO
model = YOLO("yolov7-ultralytics.onnx", task="detect")
results = model(ASSETS / "bus.jpg")
TensorRT Dışa Aktarma
pip install tensorrt
- Değiştirilmiş ONNX modelini TensorRT motoruna dönüştürmek için aşağıdaki komut dosyasını çalıştırın:
# Based off of https://github.com/NVIDIA/TensorRT/blob/release/10.7/samples/python/introductory_parser_samples/onnx_resnet50.py
import tensorrt as trt
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
def GiB(val):
return val * 1 << 30
def build_engine_onnx(model_file):
builder = trt.Builder(TRT_LOGGER)
network = builder.create_network(0)
config = builder.create_builder_config()
parser = trt.OnnxParser(network, TRT_LOGGER)
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, GiB(4))
with open(model_file, "rb") as model:
if not parser.parse(model.read()):
print("ERROR: Failed to parse the ONNX file.")
for error in range(parser.num_errors):
print(parser.get_error(error))
return None
config.set_flag(trt.BuilderFlag.FP16)
engine_bytes = builder.build_serialized_network(network, config)
with open(model_file.replace("onnx", "engine"), "wb") as f:
f.write(engine_bytes)
build_engine_onnx("yolov7-ultralytics.onnx") # path to the modified ONNX file
- Modeli Ultralytics'e yükleyin ve çalıştırın:
from ultralytics import ASSETS, YOLO
model = YOLO("yolov7-ultralytics.engine", task="detect")
results = model(ASSETS / "bus.jpg")
Atıflar ve Teşekkür
YOLOv7 yazarlarına gerçek zamanlı nesne algılama alanındaki önemli katkılarından dolayı 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 makalesi arXiv'de bulunabilir. Yazarlar çalışmalarını kamuya açık hale getirmişlerdir ve kod tabanına GitHub üzerinden erişilebilir. Alanı ilerletme ve çalışmalarını daha geniş bir topluluk için erişilebilir hale getirme çabalarını takdir ediyoruz.
SSS
YOLOv7 nedir ve neden gerçek zamanlı nesne algılamada bir çığır açtığı düşünülüyor?
YOLOv7, benzersiz hız ve doğruluğa ulaşan son teknoloji ürünü bir gerçek zamanlı nesne algılama modelidir. Hem parametre kullanımı hem de çıkarım hızı açısından YOLOX, YOLOv5 ve PPYOLOE gibi diğer modelleri geride bırakmaktadır. YOLOv7'nin ayırt edici özellikleri arasında modelin yeniden parametrelendirilmesi ve çıkarım maliyetlerini artırmadan performansını optimize eden dinamik etiket ataması yer almaktadı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 modellerini nasıl geliştiriyor?
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 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'nin SOTA nesne dedektörleriyle karşılaştırıldığı performans tablosunda bulunabilir.
YOLOv7'yi Ultralytics araçları ve platformları ile kullanabilir miyim?
Şu an itibariyle, Ultralytics yalnızca YOLOv7 ONNX ve TensorRT çıkarımını desteklemektedir. YOLOv7'nin ONNX ve TensorRT dışa aktarılmış sürümünü Ultralytics ile çalıştırmak için Kullanım Örnekleri bölümünü kontrol edin.
Veri kümemi kullanarak özel bir YOLOv7 modelini nasıl eğitebilirim?
Özel bir YOLOv7 modeli kurmak ve eğitmek için aşağıdaki adımları izleyin:
- YOLOv7 deposunu klonlayın:
git clone https://github.com/WongKinYiu/yolov7
- Klonlanmış dizine gidin ve bağımlılıkları yükleyin:
cd yolov7 pip install -r requirements.txt
-
Veri setinizi 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, Kullanım Örnekleri'nde gösterildiği gibi Ultralytics 'te kullanmak için modeli ONNX veya TensorRT 'ye aktarabilirsiniz.
YOLOv7'de sunulan temel özellikler ve optimizasyonlar nelerdir?
YOLOv7, gerçek zamanlı nesne algılamada devrim yaratan birkaç temel özellik sunar:
- Model Yeniden Parametrelendirme: Gradyan yayılım yollarını optimize ederek modelin performansını artırır.
- Dinamik Etiket Atama: Farklı branşlardaki çıktılar için dinamik hedefler atamak için kabadan inceye kılavuzlu bir yöntem kullanır ve doğruluğu artırır.
- Genişletilmiş ve Bileşik Ölçeklendirme: Çeşitli gerçek zamanlı uygulamalar için modeli ö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 yüksek çıkarım hızlarına ulaşır.
Bu özellikler hakkında daha fazla ayrıntı için YOLOv7'ye Genel Bakış bölümüne bakın.