📋 このステップで学ぶこと
- 1段階検出 vs 2段階検出の違い
- YOLOv1の革新的なアイデア(グリッド分割、直接予測)
- YOLOv2/v3の改良(Anchor Box、マルチスケール予測)
- YOLOv4/v5の進化(Mosaic、CSPNet、PyTorch実装)
- YOLOv8の最新技術(Anchor-Free、タスク統合)
- Ultralytics YOLOv8の実装(推論、訓練、エクスポート)
- カスタムデータセットでのYOLO訓練
⚡ 1. YOLO(You Only Look Once)の革命
YOLO(You Only Look Once)は、2015年にJoseph Redmonらによって発表された物体検出モデルです。「画像を1回見るだけで検出完了」という名前の通り、従来の2段階検出に対して1段階検出という革新的なアプローチを提案しました。
1-1. 2段階検出 vs 1段階検出
【2段階検出(Two-Stage Detection)】
例: R-CNN、Fast R-CNN、Faster R-CNN
処理の流れ:
┌─────────────────────────────────────────────────────┐
│ Stage 1: Region Proposal(領域提案) │
│ │
│ 「物体がありそうな場所」を約2,000個提案 │
│ ・Selective Search(R-CNN、Fast R-CNN) │
│ ・RPN(Faster R-CNN) │
│ │
│ → 時間がかかる(特にSelective Search) │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Stage 2: 分類 + Bounding Box回帰 │
│ │
│ 各候補領域を個別に処理 │
│ ・クラス分類(何の物体か?) │
│ ・位置の微調整(正確な位置は?) │
│ │
│ → また時間がかかる │
└─────────────────────────────────────────────────────┘
特徴:
・精度は高い(丁寧に2段階で処理)
・速度は遅い(200ms〜1秒/枚)
・リアルタイム処理は困難
─────────────────────────────────────────────────────
【1段階検出(One-Stage Detection)】
例: YOLO、SSD、RetinaNet
処理の流れ:
┌─────────────────────────────────────────────────────┐
│ 1回のCNN処理で完結 │
│ │
│ 画像全体を入力 │
│ ↓ │
│ CNN(特徴抽出) │
│ ↓ │
│ グリッドごとに直接予測 │
│ ・クラス(何の物体か?) │
│ ・位置(どこにあるか?) │
│ ・信頼度(物体らしさ) │
│ │
│ → 1回で完結!超高速! │
└─────────────────────────────────────────────────────┘
特徴:
・速度が非常に速い(20ms〜50ms/枚)
・リアルタイム処理が可能(30fps以上)
・精度は2段階検出にやや劣る(でも改善中)
1-2. YOLOの革新的なアイデア
💡 YOLOの核心アイデア
「物体検出を回帰問題として解く」
従来: 「領域提案」→「分類」という2つの問題に分離
YOLO: 画像から直接「クラス + 位置 + 信頼度」を予測
名前の由来: “You Only Look Once”
画像を1回見るだけで検出が完了するから
【YOLOの3つの特徴】
1. 超高速(Extremely Fast)
・リアルタイム検出が可能(30fps以上)
・Faster R-CNNの10倍以上高速
・自動運転、監視カメラなどで実用可能
2. グローバルな文脈理解(Global Context)
・画像全体を一度に見る
・背景と物体の関係を理解
・誤検出(背景を物体と誤認)が少ない
3. シンプルなアーキテクチャ(Simple Architecture)
・1つのニューラルネットワークで完結
・エンドツーエンドで学習可能
・実装・改良がしやすい
1-3. YOLOの応用分野
| 分野 |
用途 |
YOLOが選ばれる理由 |
具体例 |
| 自動運転 |
歩行者・車両・標識検出 |
リアルタイム性が必須 |
Tesla、Waymo |
| 監視カメラ |
人物・異常行動検出 |
複数カメラを同時処理 |
防犯システム |
| ロボティクス |
物体認識・掴み取り |
即座の判断が必要 |
ピッキングロボット |
| スポーツ分析 |
選手・ボール追跡 |
高速移動物体の追跡 |
VAR、戦術分析 |
| 医療 |
細胞・病変検出 |
大量画像の高速処理 |
顕微鏡画像分析 |
🔍 2. YOLOv1の仕組み(2015年)
YOLOv1は、画像をグリッドに分割し、各グリッドセルが物体を検出するという斬新なアイデアで登場しました。まずはこの基本的な仕組みを理解しましょう。
2-1. グリッド分割による検出
【YOLOv1のアイデア】
■ 基本コンセプト
「物体の中心がどのグリッドセルにあるか」で担当を決める
入力画像(448×448)を 7×7 = 49個のグリッドに分割
┌──┬──┬──┬──┬──┬──┬──┐
│ │ │ │ │ │ │ │
├──┼──┼──┼──┼──┼──┼──┤
│ │ │🐱│ │ │ │ │ ← 猫の中心がここなら
├──┼──┼──┼──┼──┼──┼──┤ このセルが猫を検出する
│ │ │ │ │ │ │ │
├──┼──┼──┼──┼──┼──┼──┤
│ │ │ │ │🐕│ │ │ ← 犬の中心がここなら
├──┼──┼──┼──┼──┼──┼──┤ このセルが犬を検出する
│ │ │ │ │ │ │ │
├──┼──┼──┼──┼──┼──┼──┤
│ │ │ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┘
■ 重要なポイント
・物体の中心がセル内にあれば、そのセルが担当
・Bounding Boxはセルの外にはみ出してもOK
・1セル = 1物体を担当(YOLOv1の制約)
2-2. 各グリッドセルの予測内容
【各グリッドセルが予測するもの】
1つのグリッドセルの出力(30次元):
┌─────────────────────────────────────────────────────┐
│ │
│ Bounding Box 1(5値): │
│ ・x, y: 中心座標(セル内の相対位置、0〜1) │
│ ・w, h: 幅と高さ(画像全体に対する比率、0〜1) │
│ ・confidence: 信頼度(物体がある確率 × IoU) │
│ │
│ Bounding Box 2(5値): │
│ ・x, y, w, h, confidence(同上) │
│ │
│ クラス確率(20値): │
│ ・P(class=cat | 物体あり) = 0.8 │
│ ・P(class=dog | 物体あり) = 0.1 │
│ ・P(class=car | 物体あり) = 0.05 │
│ ・… (PASCAL VOCの20クラス) │
│ │
└─────────────────────────────────────────────────────┘
合計: 5 × 2 + 20 = 30次元/セル
全体の出力: 7 × 7 × 30 = 1,470値
─────────────────────────────────────────────────────
【Confidenceスコアの意味】
confidence = P(物体あり) × IoU(予測Box, 正解Box)
・物体がない場合: confidence → 0
・物体があり、Boxが正確: confidence → 1
最終的なクラススコア:
score = confidence × P(class | 物体あり)
例: 猫の検出スコア
= 0.9 × 0.8 = 0.72
2-3. YOLOv1のネットワーク構造
【YOLOv1のアーキテクチャ】
入力画像(448×448×3)
↓
┌─────────────────────────────────────────────────────┐
│ 畳み込み層(24層) │
│ │
│ GoogLeNetを参考にした構造 │
│ ・7×7 Conv(stride=2) │
│ ・Maxpool │
│ ・3×3 Conv │
│ ・1×1 Conv(次元削減) │
│ ・… │
│ │
│ 出力: 7×7×1024 │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 全結合層(2層) │
│ │
│ FC1: 7×7×1024 → 4096 │
│ FC2: 4096 → 7×7×30 = 1470 │
│ │
│ ※YOLOv2以降は全結合層を使わない │
└─────────────────────────────────────────────────────┘
↓
出力テンソル(7×7×30)
↓
┌─────────────────────────────────────────────────────┐
│ 後処理 │
│ │
│ 1. 信頼度が閾値以下のBoxを除去 │
│ 2. NMS(Non-Maximum Suppression)で重複除去 │
└─────────────────────────────────────────────────────┘
↓
最終結果: [(クラス, Box, スコア), …]
2-4. YOLOv1の損失関数
【YOLOv1の損失関数(5つの要素)】
L = λ_coord × L_coord + L_conf_obj + λ_noobj × L_conf_noobj + L_class
─────────────────────────────────────────────────────
1. 座標損失(L_coord)- 物体があるセルのみ
L_xy = Σ [(x予測 – x正解)² + (y予測 – y正解)²]
L_wh = Σ [(√w予測 – √w正解)² + (√h予測 – √h正解)²]
※幅と高さは√を取る理由:
・大きい物体: 10ピクセルのズレは小さな誤差
・小さい物体: 10ピクセルのズレは大きな誤差
→ √で小さい物体の誤差を相対的に大きく
λ_coord = 5(座標を重視)
─────────────────────────────────────────────────────
2. 信頼度損失(物体あり: L_conf_obj)
L_conf_obj = Σ (confidence予測 – IoU正解)²
・正解のIoUに近づけるように学習
─────────────────────────────────────────────────────
3. 信頼度損失(物体なし: L_conf_noobj)
L_conf_noobj = Σ (confidence予測 – 0)²
λ_noobj = 0.5(物体なしセルの重みを下げる)
※理由: 物体なしセルの方が圧倒的に多いので、
そのままだと「全部0と予測」に収束してしまう
─────────────────────────────────────────────────────
4. クラス損失(L_class)- 物体があるセルのみ
L_class = Σ (P_c予測 – P_c正解)²
・正解クラスは1、それ以外は0
2-5. YOLOv1の限界
⚠️ YOLOv1の限界
1. 小さい物体が苦手
7×7グリッドでは解像度が低い。小さい物体は検出されにくい。
2. 密集した物体が苦手
1セル = 1物体の制約があるため、同じセルに複数の物体があると1つしか検出できない。
3. 位置精度が低い
グリッドサイズに制約されるため、Faster R-CNNより位置精度が低い。
4. 新しいアスペクト比に弱い
訓練時と異なる縦横比の物体は検出しにくい。
🚀 3. YOLOv2 / YOLOv3の進化
3-1. YOLOv2(2016年)の改良
【YOLOv2(YOLO9000)の主な改良】
1. Batch Normalization
・すべての畳み込み層に追加
・学習を安定化、正則化効果
→ mAP +2%向上
2. 高解像度分類器
・ImageNetで224×224 → 448×448で追加訓練
・高解像度の特徴を学習
→ mAP +4%向上
3. Anchor Boxes導入(重要!)
・事前定義された形状のBoxを使用
・Faster R-CNNと同様のコンセプト
→ リコール大幅向上
4. 次元クラスタリング
・K-meansでデータセットからAnchor形状を自動決定
・手動設定より良い形状
→ 精度向上
5. 細かいグリッド
・7×7 → 13×13
→ 小さい物体の検出性能向上
6. Darknet-19バックボーン
・19層の畳み込み(VGGより効率的)
・全結合層を廃止
→ 高速かつ高精度
結果(PASCAL VOC 2007):
・YOLOv1: 63.4 mAP
・YOLOv2: 78.6 mAP(+15.2%!)
3-2. Anchor Boxとは
💡 Anchor Boxの考え方
YOLOv1の問題:
各セルがBounding Boxのサイズを「自由に」予測
→ 学習が不安定、極端なサイズが出やすい
Anchor Boxの解決策:
「よくある形状」を事前に定義しておき、
その形状からの「調整量」を予測する
【Anchor Boxの仕組み】
■ 事前定義されたAnchor(例: 5個)
Anchor 1: 細長い(人間向け)
┌──┐
│ │
│ │
└──┘
Anchor 2: やや縦長(動物向け)
┌───┐
│ │
└───┘
Anchor 3: 正方形(顔向け)
┌───┐
│ │
└───┘
Anchor 4: 横長(車向け)
┌─────────┐
│ │
└─────────┘
Anchor 5: 大きい正方形
┌───────┐
│ │
│ │
└───────┘
■ 予測するもの
YOLOv1: (x, y, w, h) を直接予測
→ 予測値の範囲が広い(学習困難)
YOLOv2: Anchorからの調整量を予測
tx, ty: 中心位置の調整
tw, th: サイズの調整
→ 予測値の範囲が狭い(学習容易)
■ K-meansでAnchorを決定
訓練データのBounding Boxをクラスタリング
→ データセットに最適なAnchor形状を自動決定
COCOデータセットの場合:
(10,13), (16,30), (33,23), (30,61), (62,45),
(59,119), (116,90), (156,198), (373,326)
3-3. YOLOv3(2018年)のマルチスケール予測
YOLOv3はマルチスケール予測を導入し、小さい物体から大きい物体まで効果的に検出できるようになりました。
【YOLOv3のマルチスケール予測】
入力画像(416×416)
↓
Darknet-53(バックボーン)
↓
3つの異なるスケールで予測
─────────────────────────────────────────────────────
■ スケール1: 13×13グリッド(大きい物体用)
┌─────────────────┐
│ 13×13グリッド │ ← 1セル = 32×32ピクセル相当
│ │
│ 大きい物体 │ Anchor: (116,90), (156,198), (373,326)
│ (車、人全身) │
└─────────────────┘
予測数: 13×13×3 = 507個のBox
─────────────────────────────────────────────────────
■ スケール2: 26×26グリッド(中くらいの物体用)
┌─────────────────┐
│ 26×26グリッド │ ← 1セル = 16×16ピクセル相当
│ │
│ 中くらいの物体 │ Anchor: (30,61), (62,45), (59,119)
│ (犬、椅子) │
└─────────────────┘
予測数: 26×26×3 = 2,028個のBox
─────────────────────────────────────────────────────
■ スケール3: 52×52グリッド(小さい物体用)
┌─────────────────┐
│ 52×52グリッド │ ← 1セル = 8×8ピクセル相当
│ │
│ 小さい物体 │ Anchor: (10,13), (16,30), (33,23)
│ (顔、ボール) │
└─────────────────┘
予測数: 52×52×3 = 8,112個のBox
─────────────────────────────────────────────────────
合計予測数: 507 + 2,028 + 8,112 = 10,647個のBox
→ NMSで重複除去 → 最終的に数個〜数十個
【YOLOv3のネットワーク構造(FPN風)】
入力画像
↓
┌─────────────────────────────────────────────────────┐
│ Darknet-53(バックボーン) │
│ │
│ 残差接続を持つ53層のCNN │
│ ResNetに匹敵する性能 │
│ │
│ ├─→ 52×52特徴マップ(浅い層) │
│ ├─→ 26×26特徴マップ(中間層) │
│ └─→ 13×13特徴マップ(深い層) │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ FPN風の特徴融合 │
│ │
│ 13×13(深い特徴) │
│ ↓ アップサンプリング │
│ + 26×26(中間特徴)→ 結合 │
│ ↓ アップサンプリング │
│ + 52×52(浅い特徴)→ 結合 │
│ │
│ ※深い層の意味的特徴と浅い層の位置特徴を融合 │
└─────────────────────────────────────────────────────┘
↓
3つのスケールで予測
3-4. YOLOv3の性能
| モデル |
mAP(COCO) |
速度(fps) |
特徴 |
| YOLOv3-320 |
51.5 |
45fps |
高速版(入力320×320) |
| YOLOv3-416 |
55.3 |
35fps |
標準版(入力416×416) |
| YOLOv3-608 |
57.9 |
20fps |
高精度版(入力608×608) |
| Faster R-CNN |
36.2 |
7fps |
比較用(2段階検出) |
🎯 4. YOLOv4 / YOLOv5(2020年)
4-1. YOLOv4(2020年4月)
【YOLOv4の主な改良】
開発者: Alexey Bochkovskiy(元祖YOLOチームではない)
フレームワーク: Darknet(C言語)
■ アーキテクチャ改良
1. CSPDarknet53バックボーン
・Cross Stage Partial connections
・計算量削減しつつ精度維持
2. SPP(Spatial Pyramid Pooling)
・複数サイズのプーリングを並列実行
・受容野を拡大
3. PANet(Path Aggregation Network)
・FPNの拡張版
・Bottom-up path追加で特徴融合強化
■ 訓練テクニック(Bag of Freebies)
1. Mosaicデータ拡張(革新的!)
・4枚の画像を1枚に合成
・多様な文脈を学習
┌───────┬───────┐
│ 画像1 │ 画像2 │
├───────┼───────┤
│ 画像3 │ 画像4 │
└───────┴───────┘
↓
┌───────────────┐
│ 合成画像 │
│ 多数の物体 │
└───────────────┘
2. CIoU Loss
・IoUに加えて、中心距離とアスペクト比も考慮
3. Label Smoothing
・過学習を防ぐ正則化
■ 推論テクニック(Bag of Specials)
1. Mish活性化関数
・ReLUより滑らか
2. DIoU-NMS
・中心距離を考慮したNMS
4-2. YOLOv5(2020年6月)
💡 YOLOv5の特徴
開発: Ultralytics社(Glenn Jocher)
フレームワーク: PyTorch(使いやすい!)
YOLOv5が広く使われる理由:
・PyTorchで実装(学習・改良が容易)
・優れたドキュメントとサポート
・モデルサイズのバリエーション(n/s/m/l/x)
・自動Anchor学習
・簡単なAPIでたった数行で使える
| モデル |
パラメータ |
mAP(COCO) |
速度 |
推奨用途 |
| YOLOv5n |
1.9M |
28.0 |
220fps |
モバイル、IoT、超軽量 |
| YOLOv5s |
7.2M |
37.4 |
140fps |
エッジデバイス、軽量 |
| YOLOv5m |
21.2M |
45.4 |
90fps |
バランス型、一般用途 |
| YOLOv5l |
46.5M |
49.0 |
60fps |
高精度が必要な場合 |
| YOLOv5x |
86.7M |
50.7 |
50fps |
最高精度、コンペ |
🚀 5. YOLOv8(2023年)- 最新版
2023年1月、Ultralytics社がYOLOv8を発表しました。YOLOv5の後継として、さらなる精度向上と使いやすさを実現しています。
5-1. YOLOv8の改良点
【YOLOv8の主な改良】
1. Anchor-Free検出(重要な変更!)
・事前定義されたAnchorを使わない
・各グリッドセルが直接、物体の中心点を予測
・より柔軟な検出が可能
2. 新しいバックボーン
・C2fモジュール(CSPBottleneckの改良)
・より効率的な特徴抽出
・勾配の流れを改善
3. デカップルドヘッド
・分類と位置推定を分離(別々のヘッド)
・YOLOv5は1つのヘッドで両方を予測
→ 各タスクに特化した学習が可能
4. Task-Aligned Assigner
・より良いラベル割り当て戦略
・訓練の安定化と精度向上
5. タスク統合(1つのフレームワークで全対応)
├─ Detect: 物体検出
├─ Segment: インスタンスセグメンテーション
├─ Pose: 姿勢推定(キーポイント検出)
├─ Classify: 画像分類
└─ OBB: 回転Bounding Box
6. 改善されたAPI
・さらに簡単に使える
・訓練、推論、エクスポートが統一されたインターフェース
5-2. YOLOv8のモデルファミリー
| モデル |
パラメータ |
mAP |
速度 |
推奨用途 |
| YOLOv8n |
3.2M |
37.3 |
80fps |
モバイル、Raspberry Pi、超軽量 |
| YOLOv8s |
11.2M |
44.9 |
60fps |
エッジデバイス、監視カメラ |
| YOLOv8m |
25.9M |
50.2 |
40fps |
バランス型、一般的な用途 |
| YOLOv8l |
43.7M |
52.9 |
30fps |
高精度が必要な場合 |
| YOLOv8x |
68.2M |
53.9 |
25fps |
最高精度、コンペティション |
💻 6. YOLOv8の実装
6-1. インストール
# YOLOv8のインストール(ultralyticsパッケージ)
pip install ultralytics
実行結果:
Successfully installed ultralytics-8.x.x
6-2. 基本的な推論
※ コードが横に長い場合は横スクロールできます
# ===================================================
# YOLOv8の基本的な使い方
# ===================================================
from ultralytics import YOLO
# モデルのロード
# ‘yolov8n.pt’ はnano(最軽量)モデル
# 初回実行時に自動でダウンロードされる
model = YOLO(‘yolov8n.pt’)
# 他のモデルサイズ:
# model = YOLO(‘yolov8s.pt’) # small
# model = YOLO(‘yolov8m.pt’) # medium
# model = YOLO(‘yolov8l.pt’) # large
# model = YOLO(‘yolov8x.pt’) # xlarge(最高精度)
print(“モデルをロードしました”)
print(f”モデル: {model.model}”)
# ===================================================
# 画像に対する推論
# ===================================================
# 画像ファイルに対して推論
# ‘image.jpg’ を実際の画像パスに置き換えてください
results = model(‘image.jpg’)
# 結果を画面に表示
results[0].show()
# 結果を画像として保存
results[0].save(‘result.jpg’)
# ===================================================
# 動画に対する推論
# ===================================================
# 動画ファイルに対して推論
results = model(‘video.mp4’)
# ===================================================
# Webカメラでリアルタイム推論
# ===================================================
# 0はデフォルトのWebカメラ
results = model(0, show=True) # show=Trueで画面表示
6-3. 検出結果の詳細取得
from ultralytics import YOLO
import cv2
# ===================================================
# モデルのロードと推論
# ===================================================
model = YOLO(‘yolov8s.pt’)
# 推論を実行
# conf: 信頼度の閾値(これ以下は無視)
# iou: NMSのIoU閾値
results = model(‘image.jpg’, conf=0.25, iou=0.45)
# ===================================================
# 検出結果の取り出し
# ===================================================
# resultsはリスト(バッチ処理の場合は複数要素)
# 1枚の画像の場合は results[0] を使用
result = results[0]
# Bounding Boxの情報を取得
boxes = result.boxes
print(f”検出数: {len(boxes)}”)
print(f”利用可能な属性: {dir(boxes)}”)
# 各検出について情報を取り出す
for i, box in enumerate(boxes):
# 座標(xyxy形式: x1, y1, x2, y2)
x1, y1, x2, y2 = box.xyxy[0].tolist()
# 座標(xywh形式: 中心x, 中心y, 幅, 高さ)
cx, cy, w, h = box.xywh[0].tolist()
# 信頼度スコア
confidence = box.conf[0].item()
# クラスID
class_id = int(box.cls[0].item())
# クラス名(model.namesはクラスIDと名前の辞書)
class_name = model.names[class_id]
print(f”\n検出 {i+1}:”)
print(f” クラス: {class_name}”)
print(f” 信頼度: {confidence:.2f}”)
print(f” 座標: ({x1:.0f}, {y1:.0f}) – ({x2:.0f}, {y2:.0f})”)
print(f” サイズ: {w:.0f} x {h:.0f}”)
# ===================================================
# 結果を画像に描画
# ===================================================
# plot()で検出結果を描画した画像を取得
annotated_image = result.plot()
# OpenCVで表示
cv2.imshow(‘YOLOv8 Detection’, annotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 画像として保存
cv2.imwrite(‘detection_result.jpg’, annotated_image)
実行結果:
検出数: 3
利用可能な属性: [‘cls’, ‘conf’, ‘data’, ‘id’, ‘is_track’, ‘orig_shape’, ‘shape’, ‘xywh’, ‘xywhn’, ‘xyxy’, ‘xyxyn’]
検出 1:
クラス: person
信頼度: 0.92
座標: (100, 50) – (300, 400)
サイズ: 200 x 350
検出 2:
クラス: dog
信頼度: 0.87
座標: (400, 200) – (550, 380)
サイズ: 150 x 180
検出 3:
クラス: car
信頼度: 0.76
座標: (50, 300) – (200, 400)
サイズ: 150 x 100
6-4. カスタムデータセットでの訓練
自分のデータセットでYOLOv8を訓練する方法を説明します。まず、データセットの構造とYAMLファイルの作成が必要です。
【データセットの構造(YOLO形式)】
project/
├── dataset.yaml ← データセット設定ファイル
├── images/
│ ├── train/ ← 訓練画像
│ │ ├── img001.jpg
│ │ ├── img002.jpg
│ │ └── …
│ └── val/ ← 検証画像
│ ├── img100.jpg
│ └── …
└── labels/
├── train/ ← 訓練ラベル(画像と同名の.txt)
│ ├── img001.txt
│ ├── img002.txt
│ └── …
└── val/ ← 検証ラベル
├── img100.txt
└── …
─────────────────────────────────────────────────────
【ラベルファイルの形式(img001.txt)】
各行に1つの物体:
<class_id> <x_center> <y_center> <width> <height>
すべての値は0〜1に正規化(画像サイズで割る)
例(犬と猫を検出するデータセット):
0 0.5 0.4 0.3 0.5 ← クラス0(犬)、中心(0.5, 0.4)、サイズ(0.3, 0.5)
1 0.2 0.3 0.15 0.2 ← クラス1(猫)、中心(0.2, 0.3)、サイズ(0.15, 0.2)
─────────────────────────────────────────────────────
【dataset.yamlの内容】
# データセットのルートパス
path: /path/to/project
# 訓練・検証画像のパス(pathからの相対パス)
train: images/train
val: images/val
# クラス数
nc: 2
# クラス名(順序がclass_idに対応)
names:
0: dog
1: cat
# ===================================================
# YOLOv8のカスタム訓練
# ===================================================
from ultralytics import YOLO
# ===================================================
# 1. モデルの準備
# ===================================================
# 事前学習済みモデルをロード(転移学習)
# COCO 80クラスで事前学習済み
model = YOLO(‘yolov8n.pt’)
# または、ゼロから訓練する場合(非推奨)
# model = YOLO(‘yolov8n.yaml’) # 設定ファイルから
# ===================================================
# 2. 訓練の実行
# ===================================================
# train()メソッドで訓練を開始
results = model.train(
# データセット設定ファイル
data=’dataset.yaml’,
# エポック数(訓練の繰り返し回数)
epochs=100,
# 入力画像サイズ(大きいほど精度↑、速度↓)
imgsz=640,
# バッチサイズ(GPUメモリに応じて調整)
batch=16,
# 実験名(結果の保存先フォルダ名)
name=’my_yolov8_training’,
# Early Stopping(指定エポック改善なしで停止)
patience=50,
# デバイス(0=GPU、’cpu’=CPU、’0,1’=複数GPU)
device=0,
# データローダーのワーカー数
workers=8,
# 結果の保存先ディレクトリ
project=’runs/detect’,
# モデルを保存するか
save=True,
# 訓練画像を保存するか(確認用)
plots=True,
)
# 訓練結果は runs/detect/my_yolov8_training/ に保存される
# ├── weights/
# │ ├── best.pt ← 最良モデル
# │ └── last.pt ← 最終モデル
# ├── results.csv ← 訓練ログ
# └── …(各種グラフ)
6-5. 訓練済みモデルの使用と評価
# ===================================================
# 訓練済みモデルの使用
# ===================================================
from ultralytics import YOLO
# ベストモデルをロード
model = YOLO(‘runs/detect/my_yolov8_training/weights/best.pt’)
# 推論
results = model(‘test_image.jpg’)
results[0].show()
# ===================================================
# モデルの評価
# ===================================================
# 検証データセットで評価
metrics = model.val()
# 評価結果の表示
print(f”mAP50: {metrics.box.map50:.4f}”) # IoU=0.5でのmAP
print(f”mAP50-95: {metrics.box.map:.4f}”) # IoU=0.5:0.95でのmAP
print(f”Precision: {metrics.box.mp:.4f}”) # 適合率
print(f”Recall: {metrics.box.mr:.4f}”) # 再現率
# ===================================================
# モデルのエクスポート(デプロイ用)
# ===================================================
# ONNX形式(汎用、様々なフレームワークで使用可能)
model.export(format=’onnx’)
# TensorRT形式(NVIDIA GPU向け、高速推論)
model.export(format=’engine’)
# CoreML形式(iOS向け)
model.export(format=’coreml’)
# TFLite形式(モバイル、エッジデバイス向け)
model.export(format=’tflite’)
print(“エクスポート完了”)
実行結果:
mAP50: 0.8542
mAP50-95: 0.6231
Precision: 0.8765
Recall: 0.8123
エクスポート完了
6-6. リアルタイム検出(Webカメラ)
from ultralytics import YOLO
import cv2
import time
# ===================================================
# モデルのロード
# ===================================================
# 軽量モデルを使用(リアルタイム向け)
model = YOLO(‘yolov8n.pt’)
# ===================================================
# Webカメラの設定
# ===================================================
# Webカメラを開く(0はデフォルトカメラ)
cap = cv2.VideoCapture(0)
# フレームサイズを設定
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
# FPS計算用
prev_time = time.time()
print(“Webカメラを開始しました”)
print(“‘q’キーで終了”)
# ===================================================
# リアルタイム検出ループ
# ===================================================
while True:
# フレームを読み込み
ret, frame = cap.read()
if not ret:
print(“フレームの取得に失敗しました”)
break
# 推論を実行
# verbose=False で推論ログを非表示
results = model(frame, verbose=False)
# 結果を描画
annotated_frame = results[0].plot()
# FPSを計算
current_time = time.time()
fps = 1 / (current_time – prev_time)
prev_time = current_time
# FPSを画面に表示
cv2.putText(
annotated_frame,
f’FPS: {fps:.1f}’,
(10, 30),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 255, 0),
2
)
# 検出数を表示
num_detections = len(results[0].boxes)
cv2.putText(
annotated_frame,
f’Objects: {num_detections}’,
(10, 70),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 255, 0),
2
)
# 画面に表示
cv2.imshow(‘YOLOv8 Real-time Detection’, annotated_frame)
# ‘q’キーで終了
if cv2.waitKey(1) & 0xFF == ord(‘q’):
break
# ===================================================
# 後処理
# ===================================================
cap.release()
cv2.destroyAllWindows()
print(“終了しました”)
📊 7. YOLOバージョンの比較とモデル選択
| バージョン |
年 |
主な特徴 |
mAP |
備考 |
| YOLOv1 |
2015 |
1段階検出の提案 |
63.4(VOC) |
革命的だが精度は低い |
| YOLOv2 |
2016 |
Anchor Box導入 |
78.6(VOC) |
精度大幅向上 |
| YOLOv3 |
2018 |
マルチスケール予測 |
57.9(COCO) |
実用化の決定版 |
| YOLOv4 |
2020/04 |
Mosaic、CSPNet |
43.5 AP |
Darknet(C言語) |
| YOLOv5 |
2020/06 |
PyTorch、使いやすさ |
50.7(v5x) |
最も普及している |
| YOLOv8 |
2023 |
Anchor-Free、タスク統合 |
53.9(v8x) |
最新、最高性能 |
🎯 どのバージョンを使うべき?
初心者・プロトタイピング: YOLOv8
→ 使いやすさ◎、ドキュメント充実
実務プロジェクト: YOLOv8
→ 最新、最高性能、継続的なアップデート
論文での比較: YOLOv5またはYOLOv8
→ 広く使われており、比較しやすい
レガシーシステム: YOLOv3
→ 安定、実績あり、リソース消費が少ない
学習目的: YOLOv1〜v3
→ 原理理解に最適
📝 練習問題
問題1:1段階検出 vs 2段階検出(基礎)
以下の質問に答えてください。
- YOLOが「1段階検出」と呼ばれる理由を説明してください。
- 2段階検出(Faster R-CNNなど)と比べた際の、YOLOの長所と短所を挙げてください。
1. 「1段階検出」と呼ばれる理由
2段階検出(Faster R-CNNなど)は「(1)領域提案 → (2)分類・位置調整」という2つのステップを経て検出を行います。一方、YOLOは画像全体を1回CNNに通すだけで、クラス・位置・信頼度をすべて同時に予測します。この「1回の処理で完結」する特性から「1段階検出(One-Stage Detection)」と呼ばれます。名前の”You Only Look Once”もこれを表しています。
2. YOLOの長所と短所
【長所】
・超高速(30fps以上のリアルタイム処理が可能)
・シンプルなアーキテクチャ(実装・改良が容易)
・グローバルな文脈理解(背景誤検出が少ない)
・エンドツーエンド学習が可能
【短所】
・小さい物体の検出が苦手(特にYOLOv1/v2)
・密集した物体の検出が苦手
・位置精度がやや低い(Faster R-CNNと比較して)
・新しいアスペクト比への対応が難しい(特にYOLOv1)
※ただし、YOLOv3以降はマルチスケール予測などの改良により、
これらの短所は大幅に改善されています。
問題2:マルチスケール予測の計算(中級)
YOLOv3は13×13、26×26、52×52の3つのスケールで予測を行います。416×416の入力画像に対して、各スケールで3個のAnchorを使用する場合、合計で何個のBounding Boxを予測しますか?
解答:
【各スケールでの予測数】
スケール1(13×13グリッド):
13 × 13 × 3 = 507個
スケール2(26×26グリッド):
26 × 26 × 3 = 2,028個
スケール3(52×52グリッド):
52 × 52 × 3 = 8,112個
【合計】
507 + 2,028 + 8,112 = 10,647個
※この10,647個のBoxから、NMSで重複を除去して
最終的に数個〜数十個の検出結果になります。
問題3:YOLOv8のAPIの理解(中級)
以下のYOLOv8コードの各行が何をしているか説明してください。
from ultralytics import YOLO
model = YOLO(‘yolov8s.pt’)
results = model(‘image.jpg’, conf=0.5, iou=0.45)
boxes = results[0].boxes
print(model.names[int(boxes[0].cls[0])])
解答:
# ultralyticsライブラリからYOLOクラスをインポート
from ultralytics import YOLO
# YOLOv8のsmallモデル(事前学習済み)をロード
model = YOLO(‘yolov8s.pt’)
# image.jpgに対して推論を実行
# conf=0.5: 信頼度0.5未満の検出を無視
# iou=0.45: NMSのIoU閾値(重複除去の基準)
results = model(‘image.jpg’, conf=0.5, iou=0.45)
# 最初の画像の検出結果からBounding Box情報を取得
# results[0]は最初の画像の結果(バッチ処理の場合は複数)
boxes = results[0].boxes
# 最初の検出物体のクラス名を表示
# boxes[0].cls[0]: 最初のBoxのクラスID
# model.names: クラスIDと名前の辞書(例: {0: ‘person’, 1: ‘bicycle’, …})
print(model.names[int(boxes[0].cls[0])])
問題4:カスタムデータセットの準備(応用)
犬と猫を検出するデータセットを作成するとします。以下の情報からYOLO形式のラベルファイル(txt)の内容を書いてください。
- 画像サイズ: 640×480
- 犬(クラスID: 0): 左上(100, 50)、右下(300, 250)
- 猫(クラスID: 1): 左上(400, 200)、右下(550, 350)
解答:
【計算過程】
■ 犬(クラスID: 0)
左上: (100, 50)、右下: (300, 250)
中心x = (100 + 300) / 2 = 200
中心y = (50 + 250) / 2 = 150
幅 = 300 – 100 = 200
高さ = 250 – 50 = 200
正規化(画像サイズで割る):
x_center = 200 / 640 = 0.3125
y_center = 150 / 480 = 0.3125
width = 200 / 640 = 0.3125
height = 200 / 480 = 0.4167
■ 猫(クラスID: 1)
左上: (400, 200)、右下: (550, 350)
中心x = (400 + 550) / 2 = 475
中心y = (200 + 350) / 2 = 275
幅 = 550 – 400 = 150
高さ = 350 – 200 = 150
正規化:
x_center = 475 / 640 = 0.7422
y_center = 275 / 480 = 0.5729
width = 150 / 640 = 0.2344
height = 150 / 480 = 0.3125
【ラベルファイルの内容】
0 0.3125 0.3125 0.3125 0.4167
1 0.7422 0.5729 0.2344 0.3125
問題5:YOLOv8の訓練コード(総合)
以下の要件でYOLOv8の訓練コードを書いてください。
- モデル: YOLOv8n(軽量版)
- データセット設定: ‘custom_dataset.yaml’
- エポック数: 50
- バッチサイズ: 8
- 画像サイズ: 416
- Early Stopping: 20エポック
解答:
from ultralytics import YOLO
# YOLOv8n(nano)の事前学習済みモデルをロード
model = YOLO(‘yolov8n.pt’)
# 訓練を実行
results = model.train(
# データセット設定ファイル
data=’custom_dataset.yaml’,
# エポック数
epochs=50,
# バッチサイズ(GPUメモリに応じて調整)
batch=8,
# 入力画像サイズ
imgsz=416,
# Early Stopping(20エポック改善なしで停止)
patience=20,
# 実験名
name=’custom_yolov8n_training’,
# その他のオプション
save=True, # モデルを保存
device=0, # GPU 0を使用(CPUの場合は’cpu’)
workers=4, # データローダーのワーカー数
)
# 訓練後の評価
metrics = model.val()
print(f”mAP50: {metrics.box.map50:.4f}”)
print(f”mAP50-95: {metrics.box.map:.4f}”)
# ベストモデルをロードして推論テスト
best_model = YOLO(‘runs/detect/custom_yolov8n_training/weights/best.pt’)
results = best_model(‘test_image.jpg’)
results[0].show()
📝 STEP 11 のまとめ
✅ このステップで学んだこと
1. YOLOの革命
・1段階検出でリアルタイム物体検出を実現
・「画像を1回見るだけ」で検出完了
2. YOLOの進化
・YOLOv1: グリッド分割、直接予測
・YOLOv2: Anchor Box導入
・YOLOv3: マルチスケール予測
・YOLOv4/v5: Mosaic、CSPNet、PyTorch実装
・YOLOv8: Anchor-Free、タスク統合
3. YOLOv8の実装
・ultralyticsパッケージで簡単に使用可能
・推論、訓練、評価、エクスポートが統一されたAPI
・カスタムデータセットでの訓練方法
💡 重要ポイント
YOLOは物体検出に革命をもたらしました。従来の2段階検出に対し、1段階検出という新しいアプローチでリアルタイム検出を実現しました。YOLOv8は現時点で最も高性能かつ使いやすいバージョンで、実務での第一選択肢となっています。
次のSTEP 12では、「その他の検出手法と評価指標」を学びます。SSD、RetinaNet、EfficientDetなどの手法と、mAP、IoUなどの評価指標を理解していきます。