エンタープライズ対応のセキュリティ: ISO 27001 + SOC 2 Type I準拠。

Link to this sectionYOLOv7: Trainable Bag-of-Freebies#

2022年7月にリリースされたYOLOv7は、リリース当時、リアルタイム物体検出において重要な進歩を遂げました。GPU V100上で56.8%のAPを達成し、登場時に新たなベンチマークを打ち立てました。YOLOv7は、速度と精度において、YOLOR、YOLOX、Scaled-YOLOv4、YOLOv5といった当時の物体検出器を上回りました。このモデルは、他のデータセットや事前学習済み重みを使用せず、MS COCOデータセットでゼロから学習されています。YOLOv7のソースコードはGitHubで公開されています。なお、YOLO11YOLO26などの新しいモデルは、その後、効率性の向上とともにさらなる高精度を達成していることに留意してください。

YOLOv7とSOTA物体検出器の比較

Link to this sectionSOTA物体検出器の比較#

YOLO比較表の結果から、提案手法が速度と精度のトレードオフにおいて総合的に最も優れていることが分かります。YOLOv7-tiny-SiLUとYOLOv5-N (r6.1)を比較すると、本手法は127 fps高速であり、APにおいて10.7%高い精度を誇ります。さらに、YOLOv7は161 fpsのフレームレートで51.4%のAPを達成していますが、同じAPを持つPPYOLOE-Lのフレームレートは78 fpsにとどまります。パラメータ使用量に関しては、YOLOv7はPPYOLOE-Lより41%少なくなっています。

推論速度114 fpsのYOLOv7-Xと、99 fpsのYOLOv5-L (r6.1)を比較すると、YOLOv7-XはAPを3.9%向上させることができます。YOLOv7-Xを同程度の規模のYOLOv5-X (r6.1)と比較した場合、YOLOv7-Xの推論速度は31 fps高速です。さらに、パラメータ数と計算量に関しては、YOLOv7-XはYOLOv5-X (r6.1)と比較してパラメータを22%、計算量を8%削減しながらも、APを2.2%向上させています(ソース)。

性能
モデルパラメータ
(M)
FLOPs
(G)
サイズ
(ピクセル)
FPSAPテスト / 検証
50-95
APテスト
50
APテスト
75
APテスト
S
APテスト
M
APテスト
L
YOLOX-S9.026.864010240.5% / 40.5%-----
YOLOX-M25.373.86408147.2% / 46.9%-----
YOLOX-L54.2155.66406950.1% / 49.7%-----
YOLOX-X99.1281.96405851.5% / 51.1%-----
PPYOLOE-S7.917.464020843.1% / 42.7%60.5%46.6%23.2%46.4%56.9%
PPYOLOE-M23.449.964012348.9% / 48.6%66.5%53.0%28.6%52.9%63.8%
PPYOLOE-L52.2110.16407851.4% / 50.9%68.9%55.6%31.4%55.3%66.1%
PPYOLOE-X98.4206.66404552.2% / 51.9%69.9%56.5%33.3%56.3%66.4%
YOLOv5-N (r6.1)1.94.5640159- / 28.0%-----
YOLOv5-S (r6.1)7.216.5640156- / 37.4%-----
YOLOv5-M (r6.1)21.249.0640122- / 45.4%-----
YOLOv5-L (r6.1)46.5109.164099- / 49.0%-----
YOLOv5-X (r6.1)86.7205.764083- / 50.7%-----
YOLOR-CSP52.9120.464010651.1% / 50.8%69.6%55.7%31.7%55.3%64.7%
YOLOR-CSP-X96.9226.86408753.0% / 52.7%71.4%57.9%33.7%57.1%66.8%
YOLOv7-tiny-SiLU6.213.864028638.7% / 38.7%56.7%41.7%18.8%42.4%51.9%
YOLOv736.9104.764016151.4% / 51.2%69.7%55.9%31.8%55.5%65.0%
YOLOv7-X71.3189.964011453.1% / 52.9%71.2%57.8%33.8%57.1%67.4%
YOLOv5-N6 (r6.1)3.218.41280123- / 36.0%-----
YOLOv5-S6 (r6.1)12.667.21280122- / 44.8%-----
YOLOv5-M6 (r6.1)35.7200.0128090- / 51.3%-----
YOLOv5-L6 (r6.1)76.8445.6128063- / 53.7%-----
YOLOv5-X6 (r6.1)140.7839.2128038- / 55.0%-----
YOLOR-P637.2325.612807653.9% / 53.5%71.4%58.9%36.1%57.7%65.6%
YOLOR-W679.8453.212806655.2% / 54.8%72.7%60.5%37.7%59.1%67.1%
YOLOR-E6115.8683.212804555.8% / 55.7%73.4%61.1%38.4%59.7%67.7%
YOLOR-D6151.7935.612803456.5% / 56.1%74.1%61.9%38.9%60.4%68.7%
YOLOv7-W670.4360.012808454.9% / 54.6%72.6%60.1%37.3%58.7%67.1%
YOLOv7-E697.2515.212805656.0% / 55.9%73.5%61.2%38.0%59.9%68.4%
YOLOv7-D6154.7806.812804456.6% / 56.3%74.0%61.8%38.8%60.1%69.5%
YOLOv7-E6E151.7843.212803656.8% / 56.8%74.4%62.1%39.3%60.5%69.0%

Link to this section概要#

Real-time object detection is an important component in many computer vision systems, including multi-object tracking, autonomous driving, robotics, and medical image analysis. In recent years, real-time object detection development has focused on designing efficient architectures and improving the inference speed of various CPUs, GPUs, and neural processing units (NPUs). YOLOv7 supports both mobile GPU and GPU devices, from the edge to the cloud.

アーキテクチャの最適化に重点を置く従来のリアルタイム物体検出器とは異なり、YOLOv7は学習プロセスの最適化に焦点を当てています。これには、推論コストを増加させることなく物体検出の精度を向上させるように設計されたモジュールや最適化手法が含まれており、このコンセプトは「訓練可能なBag-of-Freebies」として知られています。

Link to this section主な特徴#

YOLOv7にはいくつかの重要な機能が導入されています。

  1. モデルの再パラメータ化: YOLOv7は、勾配伝播パスのコンセプトを用いて、異なるネットワーク内のレイヤーに適用可能な戦略である、計画的な再パラメータ化モデルを提案しています。

  2. 動的ラベル割り当て: 複数の出力レイヤーを持つモデルの学習には、「異なるブランチの出力に対してどのように動的なターゲットを割り当てるか?」という新たな課題があります。この問題を解決するために、YOLOv7は「粗から細へ(coarse-to-fine)」のリードガイド付きラベル割り当てと呼ばれる新しいラベル割り当て手法を導入しました。

  3. 拡張および複合スケーリング: YOLOv7は、パラメータと計算量を効果的に活用できる、リアルタイム物体検出器のための「拡張(extend)」および「複合スケーリング(compound scaling)」手法を提案しています。

  4. 効率性: YOLOv7が提案する手法は、最先端のリアルタイム物体検出器と比較して、パラメータ数を約40%、計算量を約50%削減することができ、より高速な推論速度と高い検出精度を実現しています。

Link to this section使用例#

Ultralyticsはyolov7.ptの事前学習済み重みやultralytics/cfg/models/v7/のYAMLファイルを提供しておらず、YOLOv7のネイティブなPyTorch学習および推論は、Ultralytics Pythonパッケージではサポートされていません。ただし、公式のYOLOv7リポジトリで学習されたYOLOv7チェックポイントを、以下に示すようにONNXまたはTensorRTにエクスポートすることで、Ultralyticsに取り込むことができます。

Link to this sectionONNXエクスポート#

YOLOv7 ONNXモデルをUltralyticsで使用するには、以下の手順に従います。

  1. (オプション)必要な依存関係を自動的にインストールするために、UltralyticsをインストールしてONNXモデルをエクスポートします:

    pip install ultralytics
    yolo export model=yolo26n.pt format=onnx
  2. YOLOv7リポジトリのエクスポーターを使用して、目的の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
  3. 以下のスクリプトを使用して、Ultralyticsと互換性を持つようにONNXモデルグラフを変更します:

    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. その後、変更されたONNXモデルを読み込み、Ultralyticsで通常通り推論を実行できます:

    from ultralytics import ASSETS, YOLO
    
    model = YOLO("yolov7-ultralytics.onnx", task="detect")
    
    results = model(ASSETS / "bus.jpg")

Link to this sectionTensorRTエクスポート#

  1. ONNXエクスポートセクションの手順1〜2に従ってください。

  2. TensorRT Pythonパッケージをインストールします:

    pip install tensorrt
  3. 以下のスクリプトを実行して、変更されたONNXモデルをTensorRTエンジンに変換します:

    from ultralytics.utils.export import export_engine
    
    export_engine("yolov7-ultralytics.onnx", half=True)
  4. Ultralyticsでモデルを読み込んで実行します:

    from ultralytics import ASSETS, YOLO
    
    model = YOLO("yolov7-ultralytics.engine", task="detect")
    
    results = model(ASSETS / "bus.jpg")

Link to this section引用と謝辞#

リアルタイム物体検出の分野に対する多大な貢献に対し、YOLOv7の著者に感謝の意を表します:

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

公式のYOLOv7論文はCVF 2023 Open Accessで公開され、arXivにプレプリントが掲載されました。著者は研究成果を公開しており、コードベースはGitHubで入手可能です。私たちは、この分野の発展に寄与し、広範なコミュニティが成果を利用できるようにした彼らの努力を称賛します。

Link to this sectionよくある質問 (FAQ)#

Link to this sectionYOLOv7とは何か、そしてなぜリアルタイム物体検出におけるブレイクスルーと見なされているのでしょうか?#

2022年7月にリリースされたYOLOv7は、当時のリアルタイム物体検出モデルとして非常に優れており、優れた速度と精度を達成しました。パラメータの使用量と推論速度の両面で、当時のYOLOX、YOLOv5、PPYOLOEなどのモデルを凌駕しました。YOLOv7の顕著な特徴は、推論コストを増大させることなく性能を最適化するモデルの再パラメータ化と動的ラベル割り当てです。そのアーキテクチャや他の最先端物体検出器との比較指標に関する技術的な詳細については、YOLOv7の論文を参照してください。

Link to this sectionYOLOv7は、YOLOv4やYOLOv5といった従来のYOLOモデルと比較してどのように改善されていますか?#

YOLOv7は、モデルの再パラメータ化や動的ラベル割り当てなど、学習プロセスを強化し推論精度を向上させるいくつかの革新的な技術を導入しています。YOLOv5と比較して、YOLOv7は速度と精度が大幅に向上しています。例えば、YOLOv7-XはYOLOv5-Xと比較して精度が2.2%向上し、パラメータ数が22%削減されています。詳細な比較は、性能テーブル最先端物体検出器との比較で確認できます。

Link to this sectionYOLOv7をUltralyticsのツールやプラットフォームで使用できますか?#

現時点では、UltralyticsはYOLOv7のONNXおよびTensorRT推論のみをサポートしています。UltralyticsでONNXおよびTensorRTエクスポート版のYOLOv7を実行するには、使用例セクションを確認してください。

Link to this sectionカスタムデータセットを使用してカスタムYOLOv7モデルを学習するにはどうすればよいですか?#

カスタムYOLOv7モデルをインストールして学習するには、以下の手順に従ってください:

  1. YOLOv7リポジトリをクローンします:

    git clone https://github.com/WongKinYiu/yolov7
  2. クローンしたディレクトリに移動し、依存関係をインストールします:

    cd yolov7
    pip install -r requirements.txt
  3. リポジトリで提供されている使用方法に従ってデータセットを準備し、モデルパラメータを設定します。 詳細なガイダンスについては、最新の情報とアップデートが記載されているYOLOv7 GitHubリポジトリをご覧ください。

  4. 学習後、使用例に示すようにモデルをONNXまたはTensorRTにエクスポートして、Ultralyticsで使用できます。

Link to this sectionYOLOv7で導入された主な機能と最適化は何ですか?#

YOLOv7は、リアルタイム物体検出を革新するいくつかの主要な機能を提供します:

  • モデルの再パラメータ化: 勾配伝播パスを最適化することでモデルの性能を向上させます。
  • 動的ラベル割り当て: 「粗から細へ」のリードガイド付き手法を使用して、異なるブランチ間の出力に対して動的にターゲットを割り当て、精度を向上させます。
  • 拡張および複合スケーリング: パラメータと計算量を効率的に活用し、さまざまなリアルタイムアプリケーション向けにモデルをスケーリングします。
  • 効率性: 他の最先端モデルと比較して、パラメータ数を40%、計算量を50%削減しながら、より高速な推論速度を実現しています。

これらの機能の詳細については、YOLOv7概要セクションを参照してください。

コメント