Bỏ qua nội dung

YOLOv7: Túi quà miễn phí có thể huấn luyện

YOLOv7 là một máy dò vật thể thời gian thực hiện đại vượt trội hơn tất cả các máy dò vật thể đã biết về cả tốc độ và độ chính xác trong phạm vi từ 5 FPS đến 160 FPS. Nó có độ chính xác cao nhất (56,8% AP) trong số tất cả các máy dò vật thể thời gian thực đã biết với 30 FPS trở lên trên GPU V100. Hơn nữa, YOLOv7 vượt trội hơn các bộ phát hiện đối tượng khác như YOLOR, YOLOX, Scaled-YOLOv4, YOLOv5 , và nhiều thứ khác về tốc độ và độ chính xác. Mô hình được đào tạo trên tập dữ liệu MS COCO từ đầu mà không sử dụng bất kỳ tập dữ liệu hoặc trọng số được đào tạo trước nào khác. Mã nguồn cho YOLOv7 có sẵn trên GitHub.

So sánh YOLOv7 với các máy dò đối tượng SOTA

So sánh các máy dò vật thể SOTA

Từ các kết quả trong YOLO bảng so sánh chúng ta biết rằng phương pháp đề xuất có sự đánh đổi tốc độ-độ chính xác tốt nhất một cách toàn diện. Nếu chúng ta so sánh YOLOv7-tiny-SiLU với YOLOv5 -N (r6.1), phương pháp của chúng tôi nhanh hơn 127 fps và chính xác hơn 10,7% trên AP. Ngoài ra, YOLOv7 có 51,4% AP ở tốc độ khung hình 161 fps, trong khi PPYOLOE-L với cùng AP chỉ có tốc độ khung hình 78 fps. Về mặt sử dụng tham số, YOLOv7 ít hơn PPYOLOE-L 41%.

Nếu chúng ta so sánh YOLOv7-X với tốc độ suy luận 114 fps YOLOv5 -L (r6.1) với tốc độ suy luận 99 fps, YOLOv7-X có thể cải thiện AP lên 3,9%. Nếu YOLOv7-X được so sánh với YOLOv5 -X (r6.1) có quy mô tương tự, tốc độ suy luận của YOLOv7-X nhanh hơn 31 fps. Ngoài ra, về mặt số lượng tham số và tính toán, YOLOv7-X giảm 22% tham số và 8% tính toán so với YOLOv5 -X (r6.1), nhưng cải thiện AP 2,2% ( Nguồn ).

Hiệu suất

Người mẫu Tham số
(Nam)
Thất bại
(G)
Kích cỡ
(điểm ảnh)
FPS Kiểm tra AP / val
50-95
Bài kiểm tra AP
50
Bài kiểm tra AP
75
Bài kiểm tra AP
S
Bài kiểm tra AP
Tôi
Bài kiểm tra AP
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%

Tổng quan

Phát hiện đối tượng theo thời gian thực là một thành phần quan trọng trong nhiều hệ thống thị giác máy tính , bao gồm theo dõi nhiều đối tượng , lái xe tự động, rô bốtphân tích hình ảnh y tế . Trong những năm gần đây, phát triển phát hiện đối tượng theo thời gian thực đã tập trung vào việc thiết kế các kiến trúc hiệu quả và cải thiện tốc độ suy luận của nhiều CPU, GPU và bộ xử lý thần kinh (NPU). YOLOv7 hỗ trợ cả thiết bị di động GPU Và GPU thiết bị, từ biên đến đám mây.

Không giống như các bộ phát hiện đối tượng thời gian thực truyền thống tập trung vào tối ưu hóa kiến trúc, YOLOv7 tập trung vào tối ưu hóa quy trình đào tạo. Điều này bao gồm các mô-đun và phương pháp tối ưu hóa được thiết kế để cải thiện độ chính xác của việc phát hiện đối tượng mà không làm tăng chi phí suy luận, một khái niệm được gọi là "túi miễn phí có thể đào tạo".

Các tính năng chính

YOLOv7 giới thiệu một số tính năng chính:

  1. Tham số hóa lại mô hình : YOLOv7 đề xuất một mô hình tham số hóa lại theo kế hoạch, đây là một chiến lược có thể áp dụng cho các lớp trong các mạng khác nhau với khái niệm đường truyền lan truyền theo độ dốc.

  2. Gán nhãn động : Việc đào tạo mô hình với nhiều lớp đầu ra lại nảy sinh một vấn đề mới: "Làm thế nào để gán các mục tiêu động cho đầu ra của các nhánh khác nhau?" Để giải quyết vấn đề này, YOLOv7 giới thiệu một phương pháp gán nhãn mới gọi là gán nhãn theo hướng dẫn từ thô đến tinh.

  3. Mở rộng và tăng quy mô : YOLOv7 đề xuất các phương pháp "mở rộng" và "tăng quy mô" cho bộ phát hiện đối tượng thời gian thực có thể sử dụng hiệu quả các tham số và tính toán.

  4. Hiệu quả : Phương pháp do YOLOv7 đề xuất có thể giảm hiệu quả khoảng 40% tham số và 50% phép tính của bộ phát hiện đối tượng thời gian thực hiện đại, có tốc độ suy luận nhanh hơn và độ chính xác phát hiện cao hơn.

Ví dụ sử dụng

Tính đến thời điểm viết bài, Ultralytics chỉ hỗ trợ ONNX Và TensorRT suy luận cho YOLOv7.

ONNX Xuất khẩu

Để sử dụng YOLOv7 ONNX mô hình với Ultralytics :

  1. (Tùy chọn) Cài đặt Ultralytics và xuất khẩu một ONNX mô hình để tự động cài đặt các phụ thuộc cần thiết:
pip install ultralytics
yolo export model=yolo11n.pt format=onnx
  1. Xuất mô hình YOLOv7 mong muốn bằng cách sử dụng trình xuất trong kho lưu trữ YOLOv7 :
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
  1. Sửa đổi ONNX đồ thị mô hình để tương thích với Ultralytics sử dụng đoạn mã sau:
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")
  1. Sau đó bạn có thể tải bản đã sửa đổi ONNX mô hình và chạy suy luận với nó trong Ultralytics thông thường:
from ultralytics import ASSETS, YOLO

model = YOLO("yolov7-ultralytics.onnx", task="detect")

results = model(ASSETS / "bus.jpg")

TensorRT Xuất khẩu

  1. Thực hiện theo các bước 1-2 trong phần Xuất ONNX .

  2. Cài đặt TensorRT Python bưu kiện:

pip install tensorrt
  1. Chạy tập lệnh sau để chuyển đổi đã sửa đổi ONNX mô hình để TensorRT động cơ:
# 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
  1. Tải và chạy mô hình trong Ultralytics :
from ultralytics import ASSETS, YOLO

model = YOLO("yolov7-ultralytics.engine", task="detect")

results = model(ASSETS / "bus.jpg")

Trích dẫn và Lời cảm ơn

Chúng tôi muốn ghi nhận những đóng góp quan trọng của các tác giả YOLOv7 trong lĩnh vực phát hiện đối tượng theo thời gian thực:

@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}
}

Bài báo gốc YOLOv7 có thể được tìm thấy trên arXiv . Các tác giả đã công khai công trình của họ và có thể truy cập cơ sở mã trên GitHub . Chúng tôi đánh giá cao những nỗ lực của họ trong việc thúc đẩy lĩnh vực này và giúp công trình của họ tiếp cận được với cộng đồng rộng lớn hơn.

CÂU HỎI THƯỜNG GẶP

YOLOv7 là gì và tại sao nó được coi là bước đột phá trong phát hiện vật thể theo thời gian thực?

YOLOv7 là mô hình phát hiện đối tượng thời gian thực tiên tiến đạt được tốc độ và độ chính xác vô song. Nó vượt trội hơn các mô hình khác, chẳng hạn như YOLOX, YOLOv5 và PPYOLOE, về cả cách sử dụng tham số và tốc độ suy luận. Các tính năng nổi bật của YOLOv7 bao gồm tham số hóa lại mô hình và gán nhãn động, giúp tối ưu hóa hiệu suất mà không làm tăng chi phí suy luận. Để biết thêm chi tiết kỹ thuật về kiến trúc và số liệu so sánh với các bộ phát hiện đối tượng tiên tiến khác, hãy tham khảo bài báo YOLOv7 .

YOLOv7 cải thiện như thế nào so với trước đây YOLO các mô hình như YOLOv4 và YOLOv5 ?

YOLOv7 giới thiệu một số cải tiến, bao gồm tham số hóa lại mô hình và gán nhãn động, giúp tăng cường quá trình đào tạo và cải thiện độ chính xác suy luận. So với YOLOv5 , YOLOv7 tăng đáng kể tốc độ và độ chính xác. Ví dụ, YOLOv7-X cải thiện độ chính xác 2,2% và giảm tham số 22% so với YOLOv5 -X. Có thể tìm thấy những so sánh chi tiết trong bảng hiệu suất so sánh YOLOv7 với các bộ phát hiện đối tượng SOTA .

Tôi có thể sử dụng YOLOv7 với Ultralytics công cụ và nền tảng?

Tính đến thời điểm hiện tại, Ultralytics chỉ hỗ trợ YOLOv7 ONNX Và TensorRT suy luận. Để chạy ONNX Và TensorRT phiên bản xuất khẩu của YOLOv7 với Ultralytics , hãy kiểm tra phần Ví dụ sử dụng .

Làm thế nào để đào tạo mô hình YOLOv7 tùy chỉnh bằng tập dữ liệu của tôi?

Để cài đặt và đào tạo mô hình YOLOv7 tùy chỉnh, hãy làm theo các bước sau:

  1. Sao chép kho lưu trữ YOLOv7:
    git clone https://github.com/WongKinYiu/yolov7
    
  2. Điều hướng đến thư mục đã sao chép và cài đặt các phần phụ thuộc:
    cd yolov7
    pip install -r requirements.txt
    
  3. Chuẩn bị tập dữ liệu của bạn và cấu hình các tham số mô hình theo hướng dẫn sử dụng được cung cấp trong kho lưu trữ. Để biết thêm hướng dẫn, hãy truy cập kho lưu trữ GitHub YOLOv7 để biết thông tin và cập nhật mới nhất.

  4. Sau khi đào tạo, bạn có thể xuất mô hình sang ONNX hoặc TensorRT để sử dụng trong Ultralytics như được thể hiện trong Ví dụ sử dụng .

Những tính năng và tối ưu hóa chính nào được giới thiệu trong YOLOv7?

YOLOv7 cung cấp một số tính năng chính giúp cách mạng hóa việc phát hiện đối tượng theo thời gian thực:

  • Tham số hóa lại mô hình : Nâng cao hiệu suất của mô hình bằng cách tối ưu hóa đường truyền gradient.
  • Gán nhãn động : Sử dụng phương pháp hướng dẫn từ thô đến chi tiết để gán các mục tiêu động cho đầu ra trên các nhánh khác nhau, giúp cải thiện độ chính xác.
  • Mở rộng và hợp chất : Sử dụng hiệu quả các tham số và tính toán để mở rộng mô hình cho nhiều ứng dụng thời gian thực khác nhau.
  • Hiệu quả : Giảm 40% số lượng tham số và 50% khối lượng tính toán so với các mô hình tiên tiến khác trong khi vẫn đạt được tốc độ suy luận nhanh hơn.

Để biết thêm chi tiết về các tính năng này, hãy xem phần Tổng quan về YOLOv7 .



📅 Được tạo ra cách đây 1 năm ✏️ Đã cập nhật cách đây 5 ngày

Bình luận