STEP 18:Swin TransformerとDETR

🏛️ STEP 18: Swin TransformerとDETR

Shifted Window Attention、階層的構造、
Transformerベース物体検出、Bipartite Matchingを学びます

📋 このステップで学ぶこと

  • ViTの課題とSwin Transformerの解決策
  • Window-based Self-Attentionによる効率化
  • Shifted Window Attentionの仕組み
  • Patch Mergingによるダウンサンプリング
  • DETR(DEtection TRansformer)の全体構造
  • Object Queriesの概念
  • Bipartite Matching(二部マッチング)
  • なぜNMSが不要になるのか
  • 実装:SwinとDETRの利用方法

🪟 1. Swin Transformer

Swin Transformer(Shifted Window Transformer)は、ViTの課題を解決した効率的なTransformerモデルです。Microsoftが2021年に発表し、画像分類だけでなく物体検出やセグメンテーションにも適用可能な汎用的なモデルとなっています。

1-1. ViTの課題

まず、STEP 16で学んだViT(Vision Transformer)の課題を整理しましょう。

【ViTの3つの課題】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 課題1: グローバルAttentionの計算コスト ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ViTのSelf-Attention: すべてのパッチ間でAttentionを計算 計算量: O(N²) ← Nはパッチ数 具体例: 224×224画像(パッチサイズ16): パッチ数 = 14×14 = 196 計算量 = 196² = 38,416 ← 許容範囲 1024×1024画像(パッチサイズ16): パッチ数 = 64×64 = 4,096 計算量 = 4,096² = 16,777,216 ← 約440倍! → 高解像度画像では計算量が爆発的に増加 → 実用的でない ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 課題2: 単一スケールの特徴マップ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ViTの構造: 入力 → パッチ分割 → Transformer → 出力 特徴マップのサイズは一定(14×14など) 問題: 物体検出やセグメンテーションには 複数スケールの特徴が必要 例: Faster R-CNNのFPN(Feature Pyramid Network) ・1/4スケール: 小さい物体用 ・1/8スケール: 中くらいの物体用 ・1/16スケール: 大きい物体用 ・1/32スケール: 非常に大きい物体用 → ViTには複数スケールの特徴がない → 物体検出への直接適用が難しい ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 課題3: 固定解像度への依存 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ViTの制約: 224×224で訓練 → 224×224でしか使えない (位置埋め込みが固定サイズ) 問題: 異なる解像度の画像に対応できない 位置埋め込みの補間が必要

1-2. Swin Transformerの解決策

💡 Swin Transformerの3つの革新

1. Window-based Attention
グローバルAttentionの代わりに、局所的なWindow内でのみAttention
→ 計算量をO(N²)からO(N)に削減

2. Shifted Window
Window間の情報交換のため、Windowの位置をずらす
→ 局所性を維持しながらグローバルな情報も学習

3. 階層的構造
Patch Mergingでダウンサンプリング
→ CNNのような複数スケールの特徴マップを生成
→ 物体検出、セグメンテーションに対応

1-3. Swin Transformerの全体構造

【Swin Transformerのアーキテクチャ】 入力画像(例: 224×224×3) ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Patch Partition(パッチ分割) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 画像を4×4のパッチに分割 224×224 → 56×56パッチ 各パッチ: 4×4×3 = 48次元 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Linear Embedding(線形埋め込み) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 各パッチを埋め込み次元に変換 48次元 → C次元(Swin-Tの場合 C=96) 出力: 56×56×96 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Swin Transformer Block × 2 ・Window-based Self-Attention ・Shifted Window-based Self-Attention 出力: 56×56×96(解像度維持) ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Patch Merging ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2×2パッチを1つに統合 56×56×96 → 28×28×192 解像度1/2、チャンネル2倍 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 2 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Swin Transformer Block × 2 出力: 28×28×192 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Patch Merging ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 28×28×192 → 14×14×384 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 3 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Swin Transformer Block × 6 出力: 14×14×384 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Patch Merging ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14×14×384 → 7×7×768 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 4 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Swin Transformer Block × 2 出力: 7×7×768 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Classification Head(分類の場合) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Global Average Pooling → Linear → クラス数 【CNNとの類似性】 Swin Transformer CNN(ResNet) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 1: 56×56 conv2: 56×56 Stage 2: 28×28 conv3: 28×28 Stage 3: 14×14 conv4: 14×14 Stage 4: 7×7 conv5: 7×7 → 同じような階層構造 → 物体検出のFPNにそのまま使える!

1-4. Window-based Self-Attention

Swin Transformerの核心技術であるWindow-based Self-Attentionについて詳しく見ていきましょう。

【Window-based Self-Attentionの仕組み】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 基本アイデア ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ViT: 全パッチ間でAttention(グローバル) Swin: Window内のパッチ間のみAttention(ローカル) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 視覚的な説明 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56×56の特徴マップをWindowに分割(Windowサイズ: 7×7): ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐ │ Win1 │ Win2 │ Win3 │ Win4 │ Win5 │ Win6 │ Win7 │ Win8 │ │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ ├───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │ Win9 │ Win10 │ Win11 │ Win12 │ Win13 │ Win14 │ Win15 │ Win16 │ │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ ├───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │ … │ … │ … │ … │ … │ … │ … │ … │ └───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘ Window数: 8×8 = 64個 各Windowのパッチ数: 7×7 = 49個 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Attention計算 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Window内のパッチ間のみでAttention: Window 1内: パッチ1 ↔ パッチ2, パッチ3, … パッチ49 パッチ2 ↔ パッチ1, パッチ3, … パッチ49 … → 49×49のAttention行列 同じ計算を64個のWindowで独立に実行 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 計算量の比較 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ グローバルAttention(ViT): 全パッチ数: 56×56 = 3,136 計算量: 3,136² = 9,830,496 Window-based Attention(Swin): 1 Windowの計算量: 49² = 2,401 全Windowの計算量: 2,401 × 64 = 153,664 削減率: 153,664 / 9,830,496 ≈ 1.56% → 約64倍の効率化! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 計算量のオーダー ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ViT: O(N²) ← Nはパッチ数 Swin: O(N × M²) ← MはWindow内パッチ数(固定) = O(N) ← Mは定数なので → 画像サイズに対して線形! → 高解像度画像にも対応可能

1-5. Shifted Window Attention

Window-based Attentionには1つ問題があります。Window間の情報交換ができないことです。Shifted Window Attentionはこの問題を解決します。

【Window-based Attentionの問題】 物体がWindowの境界をまたぐ場合: ┌───────┬───────┐ │ 🐱 │ │ ← 猫の左半分はWindow 1 │ 左半分 │ │ ├───────┼───────┤ │ │ 🐱 │ ← 猫の右半分はWindow 4 │ │ 右半分 │ └───────┴───────┘ 問題: ・猫の左半分と右半分が別々のWindowで処理 ・Window間でAttentionがないので情報交換できない ・猫全体として認識できない!
【Shifted Window Attentionの解決策】 アイデア: 奇数層(Layer 1, 3, 5, …): 通常のWindow分割 偶数層(Layer 2, 4, 6, …): Windowをシフト(ずらす) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Layer L(通常のWindow分割) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┌─────────┬─────────┬─────────┬─────────┐ │ Window1 │ Window2 │ Window3 │ Window4 │ │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ ├─────────┼─────────┼─────────┼─────────┤ │ Window5 │ Window6 │ Window7 │ Window8 │ │ 7×7 │ 7×7 │ 7×7 │ 7×7 │ ├─────────┼─────────┼─────────┼─────────┤ │ : │ : │ : │ : │ └─────────┴─────────┴─────────┴─────────┘ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Layer L+1(Shifted Window分割) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Windowを右と下に floor(M/2) = 3 パッチずらす: ┌──┬────────┬────────┬────────┬──┐ │ │ │ │ │ │ ├──┼────────┼────────┼────────┼──┤ │ │ Win1′ │ Win2′ │ Win3′ │ │ │ │ 7×7 │ 7×7 │ 7×7 │ │ ├──┼────────┼────────┼────────┼──┤ │ │ Win4′ │ Win5′ │ Win6′ │ │ │ │ 7×7 │ 7×7 │ 7×7 │ │ ├──┼────────┼────────┼────────┼──┤ │ │ : │ : │ : │ │ └──┴────────┴────────┴────────┴──┘ → 境界の位置が変わる! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 効果: Window間の情報交換 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 猫がWindow境界をまたぐ場合: Layer L: ┌─────┬─────┐ │🐱左 │ │ 猫の左半分: Window 1 ├─────┼─────┤ │ │🐱右 │ 猫の右半分: Window 4 └─────┴─────┘ → 左右が分離、情報交換なし Layer L+1(シフト後): ┌───┬─────┬───┐ │ │🐱全体│ │ 猫全体: Window 1′ ├───┼─────┼───┤ │ │ │ │ └───┴─────┴───┘ → 猫全体が同じWindowに! → 左右の情報を統合できる 2層を交互に繰り返すことで: すべての領域でWindow間の情報交換が実現
【シフトの実装: Cyclic Shift】 シフト後、端にできる小さなWindowの扱い: 問題: シフトすると端に半端なWindowができる サイズが異なるとバッチ処理できない 解決策: Cyclic Shift(循環シフト) 特徴マップを「輪っか」のように扱う ┌──────────────────┐ ┌──────────────────┐ │ A │ B │ C │ │ B │ C │ A │ │────┼─────┼─────│ → │────┼─────┼─────│ │ D │ E │ F │ │ E │ F │ D │ └──────────────────┘ └──────────────────┘ Aの部分が右端に移動(循環) → すべてのWindowが同じサイズ → バッチ処理可能! マスクによる制御: 循環でつながった不正なAttentionを マスクで無効化

1-6. Patch Merging

Patch Mergingは、特徴マップのダウンサンプリングを行う層です。CNNのPooling層に相当します。

【Patch Mergingの仕組み】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 目的 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. 解像度を下げる(1/2倍) 2. チャンネル数を増やす(2倍) 3. 階層的な特徴を構築 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 処理手順 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 入力: 56×56×96 の特徴マップ ステップ1: 2×2パッチをグループ化 ━━━━━━━━━━━━━━━━━━━━━━━━━━ 元の特徴マップ(4×4の例で説明): ┌───┬───┬───┬───┐ │ 1 │ 2 │ 5 │ 6 │ ← 各セルは96次元ベクトル ├───┼───┼───┼───┤ │ 3 │ 4 │ 7 │ 8 │ ├───┼───┼───┼───┤ │ 9 │10 │13 │14 │ ├───┼───┼───┼───┤ │11 │12 │15 │16 │ └───┴───┴───┴───┘ 2×2ずつグループ化: ┌───────┬───────┐ │[1,2, │[5,6, │ │ 3,4] │ 7,8] │ ├───────┼───────┤ │[9,10,│[13,14│ │11,12]│15,16]│ └───────┴───────┘ ステップ2: 各グループを結合(Concatenate) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ グループ[1,2,3,4]の結合: パッチ1: 96次元 パッチ2: 96次元 パッチ3: 96次元 パッチ4: 96次元 結合: 96×4 = 384次元 ステップ3: 線形変換で次元削減 ━━━━━━━━━━━━━━━━━━━━━━━━━━ 384次元 → 192次元(Linear層) これにより: ・情報量を保持しながら ・適切な次元数に調整 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 結果 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 入力: 56×56×96 出力: 28×28×192 ・解像度: 1/2に ・チャンネル数: 2倍に ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 各Stageでの特徴マップサイズ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Stage 1: 56×56×96 (1/4解像度) ↓ Patch Merging Stage 2: 28×28×192 (1/8解像度) ↓ Patch Merging Stage 3: 14×14×384 (1/16解像度) ↓ Patch Merging Stage 4: 7×7×768 (1/32解像度) → FPN(Feature Pyramid Network)の入力として使用可能!

1-7. Swin Transformerのバリエーション

モデル 埋め込み次元 層数(各Stage) パラメータ数 ImageNet精度 特徴
Swin-T 96 2, 2, 6, 2 29M 81.3% 軽量
Swin-S 96 2, 2, 18, 2 50M 83.0% バランス
Swin-B 128 2, 2, 18, 2 88M 83.5% 標準
Swin-L 192 2, 2, 18, 2 197M 86.3% 高精度
🎯 Swin Transformerの利点まとめ

1. 効率性
・Window-based Attentionで計算量O(N)に削減
・高解像度画像にも対応可能

2. 階層性
・Patch Mergingで複数スケールの特徴マップ
・CNNの階層構造と互換性あり

3. 汎用性
・画像分類、物体検出、セグメンテーションすべてに対応
・既存のCNNベースフレームワーク(Detectron2など)と連携可能

4. 性能
・ViTより効率的で同等以上の精度
・ResNetを置き換えるバックボーンとして最適

🎯 2. DETR(DEtection TRansformer)

DETR(DEtection TRansformer)は、Transformerを使ったEnd-to-Endの物体検出モデルです。Facebook AI(現Meta)が2020年に発表し、物体検出のパラダイムを大きく変えました。

2-1. 従来の物体検出の問題点

【従来の物体検出パイプライン】 例: Faster R-CNN 入力画像 ↓ ━━━━━━━━━━━━━━━━━━━━ 1. CNNバックボーン ━━━━━━━━━━━━━━━━━━━━ ResNet-50などで特徴抽出 ↓ ━━━━━━━━━━━━━━━━━━━━ 2. RPN(Region Proposal Network) ━━━━━━━━━━━━━━━━━━━━ Anchor Boxを使って候補領域を生成 ※ Anchor Box: 事前に定義されたサイズ・アスペクト比の矩形 例: [(32×32), (64×64), (128×128)] × [1:1, 1:2, 2:1] 問題: ・データセットに合わせて手動で設計が必要 ・不適切なAnchorでは精度が低下 ↓ ━━━━━━━━━━━━━━━━━━━━ 3. RoI Pooling ━━━━━━━━━━━━━━━━━━━━ 候補領域を固定サイズに切り出し ↓ ━━━━━━━━━━━━━━━━━━━━ 4. 分類 + Box回帰 ━━━━━━━━━━━━━━━━━━━━ 各候補領域のクラスとBoxを予測 → 同じ物体に複数の検出が発生 ↓ ━━━━━━━━━━━━━━━━━━━━ 5. NMS(Non-Maximum Suppression) ━━━━━━━━━━━━━━━━━━━━ 重複した検出を削除 処理: 1. 信頼度でソート 2. 最高信頼度の検出を採用 3. IoU > 閾値の検出を削除 4. 繰り返し 問題: ・IoU閾値の調整が必要 ・微分不可能(End-to-End学習の妨げ) ・ヒューリスティックな後処理 ↓ 最終的な検出結果 【従来手法の問題点まとめ】 1. 複雑なパイプライン ・多段階の処理 ・各段階で別々の設計・チューニング 2. 手作業の設計 ・Anchor Boxの設計 ・NMSの閾値調整 3. End-to-Endでない ・NMSが微分不可能 ・全体最適化ができない

2-2. DETRのアプローチ

💡 DETRの革新的なアイデア

物体検出を「集合予測問題」として定式化

従来: 「画像のどこに何がいるか?を繰り返し予測」
DETR: 「画像に含まれる物体の集合を一度に予測」

利点:
・NMS不要(一意な予測)
・Anchor不要(Object Queriesから直接予測)
・シンプルなEnd-to-Endパイプライン

2-3. DETRの全体構造

【DETRのアーキテクチャ】 入力画像(例: 800×1333×3) ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. CNNバックボーン(ResNet-50) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 畳み込みによる特徴抽出 800×1333 → 25×42の特徴マップ チャンネル数: 2048 出力: 25×42×2048 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2. 1×1畳み込み(次元削減) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ チャンネル数を削減 2048 → 256(hidden dimension) 出力: 25×42×256 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3. Flatten + Positional Encoding ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2D特徴マップを1Dシーケンスに変換 25×42 = 1050個のトークン 各トークンに位置情報を追加(2D positional encoding) 出力: 1050×256 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4. Transformer Encoder(6層) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 画像特徴のSelf-Attention 各トークンが画像全体の文脈を理解 出力: 1050×256(Memory) ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5. Transformer Decoder(6層) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 入力: ・Object Queries: 100×256(学習可能なパラメータ) ・Memory: 1050×256(Encoderの出力) 処理: ・Self-Attention: Object Queries間 ・Cross-Attention: Queries → Memory 出力: 100×256 ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6. Prediction Heads(並列) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 各Object Query(100個)に対して: 分類ヘッド(FFN): 256 → 91+1クラス (COCOの91クラス + “no object”クラス) Box回帰ヘッド(FFN): 256 → 4(cx, cy, w, h) (中心座標と幅高さ、0-1に正規化) ↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7. 出力 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100個の予測: Query 1: (クラス1, [0.25, 0.30, 0.10, 0.15]) Query 2: (クラス2, [0.60, 0.70, 0.20, 0.25]) Query 3: (no_object, _) Query 4: (no_object, _) … Query 100: (no_object, _) “no_object”以外を最終結果として出力

2-4. Object Queries

Object Queriesは、DETRの最も重要な概念の一つです。「画像に何がいるか?」を質問するベクトルと考えることができます。

【Object Queriesとは】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 基本概念 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Object Queries: ・100個の学習可能なベクトル(パラメータ) ・各Queryが1つの物体を担当 ・形状: (100, 256) イメージ: 「この画像に物体はいますか?」と 100人の専門家が同時に質問 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 訓練による役割分担 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 訓練前(ランダム初期化): Query 1: [0.23, -0.45, 0.12, …, 0.89] Query 2: [0.67, 0.34, -0.21, …, -0.12] Query 3: [-0.56, 0.11, 0.78, …, 0.33] … → 特に意味はない 訓練後: 各Queryが特定の役割を学習 例(COCOデータセットで訓練後): Query 1: 「画像中央の大きな物体」を担当 Query 2: 「左上の小さな物体」を担当 Query 3: 「右下の中くらいの物体」を担当 … → データから自動的に役割分担を学習! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Decoderでの処理 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Decoder Layer 1: Self-Attention: Object Queries間でAttention → 「Query 1が大きな物体を見ているなら、 私(Query 2)は別の物体を見よう」 Cross-Attention: Object Queries ← Encoder出力(画像特徴) → 各Queryが画像特徴を「見て」 担当する物体を探す 例: Query 1: 「中央に猫がいる!」 Query 2: 「左上に車がある!」 Query 3: 「物体は見つからない…」 Decoder Layer 2-6: さらに精緻化 Query 1: 「猫の位置をもっと正確に…」 Query 2: 「車の大きさを調整…」 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 最終出力 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 各Queryから1つの予測: Query 1: (猫, 0.95, [0.45, 0.50, 0.30, 0.40]) Query 2: (車, 0.88, [0.15, 0.20, 0.20, 0.25]) Query 3: (no_obj, 0.92, _) Query 4: (no_obj, 0.85, _) … → 100個の独立した予測 → 重複がほとんどない(学習で抑制) → NMS不要!

2-5. Bipartite Matching(二部マッチング)

DETRの学習では、Bipartite Matching(二部マッチング)という手法を使って、予測と正解を一意に対応付けます。これがNMSを不要にする鍵です。

【Bipartite Matchingとは】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 問題設定 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 正解物体: N個(例: 3個) 予測: M個(例: 100個、M >> N) 課題: どの予測がどの正解に対応するかを決める 従来手法の問題: 1つの正解に複数の予測が対応してしまう → NMSで重複を削除 DETRの解決策: Bipartite Matching で一意に対応付け → 各正解に対して最大1つの予測のみ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 具体例 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 画像に3個の物体(猫、車、犬)がある場合: 正解: 物体1: 猫, Box [100, 50, 200, 150] 物体2: 車, Box [300, 200, 450, 350] 物体3: 犬, Box [500, 100, 600, 200] 予測(100個のObject Queries): Query 1: 猫, 0.75, [102, 51, 202, 151] ← 猫に近い Query 2: 犬, 0.82, [502, 102, 602, 202] ← 犬に近い Query 3: 車, 0.88, [305, 202, 455, 352] ← 車に近い Query 4: no_object, 0.91, _ Query 5: 猫, 0.45, [150, 80, 250, 180] ← 猫っぽいが位置がずれてる … Query 100: no_object, 0.85, _ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ステップ1: コスト行列の計算 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 各(正解、予測)ペアのコストを計算: コスト = λ_cls × L_cls + λ_box × L_box + λ_giou × L_giou L_cls: 分類損失(クロスエントロピー) L_box: Box損失(L1距離) L_giou: GIoU損失(位置の一致度) λ_cls = 1, λ_box = 5, λ_giou = 2(論文の設定) コスト行列(一部): Query1 Query2 Query3 Query4 Query5 … Query100 正解1(猫) 0.25 0.85 0.90 0.95 0.55 0.92 正解2(車) 0.88 0.82 0.30 0.91 0.87 0.89 正解3(犬) 0.91 0.22 0.87 0.93 0.89 0.91 解説: ・正解1(猫)とQuery1のコストが0.25(低い = 似ている) ・正解2(車)とQuery3のコストが0.30(低い = 似ている) ・正解3(犬)とQuery2のコストが0.22(低い = 似ている) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ステップ2: Hungarian Algorithm(ハンガリアン法) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 総コストを最小化する一意な割り当てを見つける 制約: ・各正解は最大1つの予測にマッチ ・各予測は最大1つの正解にマッチ 結果: 正解1(猫) → Query1(コスト0.25) 正解2(車) → Query3(コスト0.30) 正解3(犬) → Query2(コスト0.22) 総コスト: 0.25 + 0.30 + 0.22 = 0.77(最小) 重要: Query5も猫を予測しているが、 Query1の方がコストが低いのでQuery1がマッチ → Query5は「no_object」として学習される ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ステップ3: 損失の計算 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ マッチしたQuery: L1 = L_cls(Query1, 猫) + L_box(Query1, 猫Box) L2 = L_cls(Query3, 車) + L_box(Query3, 車Box) L3 = L_cls(Query2, 犬) + L_box(Query2, 犬Box) マッチしなかったQuery: L4 = L_cls(Query4, no_object) L5 = L_cls(Query5, no_object) ← 猫を予測したが不採用 … L100 = L_cls(Query100, no_object) 総損失: L_total = L1 + L2 + L3 + L4 + … + L100
【なぜNMSが不要になるのか】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 理由1: 一意な対応付け ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 訓練時: Bipartite Matchingにより 各正解物体に1つのQueryのみがマッチ → 同じ物体を検出するQueryは1つだけ → 重複予測にペナルティ(no_objectとして学習) 学習結果: 各Queryが異なる物体を担当するように学習 Query 1: 「私は大きな物体を担当」 Query 2: 「私は小さな物体を担当」 Query 3: 「私は左側の物体を担当」 … → 自然に役割分担 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 理由2: Set Predictionとしての定式化 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 従来手法: 予測 = リスト(順序あり、重複あり) [検出1, 検出2, 検出3, …] → 同じ物体が複数回出現可能 DETR: 予測 = 集合(順序なし、重複なし) {検出1, 検出2, 検出3, …} → 各要素は一意 Bipartite Matchingにより: 予測集合と正解集合を一意に対応付け → 重複が本質的に存在しない ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 理由3: 損失関数による学習 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ もし複数のQueryが同じ物体を予測すると: 例: Query1とQuery5が両方とも猫を予測 Bipartite Matching: コストが低い方(Query1)のみがマッチ 学習: Query1: 「猫」として正しく学習 Query5: 「no_object」として学習(ペナルティ) 結果: Query5は猫を予測すると損失が増加 → 学習により、Query5は猫を避けるようになる → 重複予測が減少 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 推論時の動作 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 推論: 100個のQueryから予測を取得 Query1: 猫, 0.95 Query2: 犬, 0.88 Query3: 車, 0.92 Query4: no_object, 0.96 … Query100: no_object, 0.89 フィルタリング: 信頼度閾値(例: 0.7)でフィルタ no_object以外を採用 最終結果: 猫, 犬, 車の3つの検出 → 重複がない(学習で抑制済み) → NMSは不要!

2-6. DETRの特徴と課題

項目 利点 課題
アーキテクチャ シンプル、End-to-End 学習が遅い(500 epochs必要)
NMS 不要(一意な予測)
Anchor 不要(Object Queries)
大きい物体 高精度
小さい物体 精度がやや低い
推論速度 中程度(約28FPS) YOLOより遅い
【DETRの改良版】 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Deformable DETR(2020年) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 改良点: ・Deformable Attentionの導入 → 全ピクセルではなく、 学習された少数の点のみAttention ・Multi-Scale特徴の利用 効果: ・学習が10倍高速(50 epochs) ・小さい物体の精度向上 ・メモリ使用量削減 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DINO(2022年) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 改良点: ・Contrastive DeNoising ・Mixed Query Selection ・Look Forward Twice 効果: ・COCO mAP 63.3%(最高精度) ・収束が安定 → 現在の最先端DETR系モデル

💻 3. 実装:SwinとDETRの利用

3-1. Swin Transformerで画像分類

※ コードが横に長い場合は横スクロールできます

# =================================================== # Swin Transformerで画像分類 # =================================================== # 必要なライブラリをインポート from transformers import AutoImageProcessor, SwinForImageClassification import torch from PIL import Image import requests from io import BytesIO # =================================================== # 1. モデルとプロセッサのロード # =================================================== # モデル名を指定 # microsoft/swin-tiny-patch4-window7-224: # – swin-tiny: Swin-Tサイズ(29Mパラメータ) # – patch4: パッチサイズ4×4 # – window7: Windowサイズ7×7 # – 224: 入力画像サイズ224×224 model_name = “microsoft/swin-tiny-patch4-window7-224″ # AutoImageProcessor: 画像の前処理を自動的に行う # – リサイズ # – 正規化 # – テンソル変換 processor = AutoImageProcessor.from_pretrained(model_name) # SwinForImageClassification: 分類用Swinモデル # – ImageNetの1000クラス分類用に事前学習済み model = SwinForImageClassification.from_pretrained(model_name) # 評価モードに設定 # – Dropoutを無効化 # – BatchNormを固定 model.eval() # モデル情報を表示 print(f”モデル: {model_name}”) print(f”パラメータ数: {sum(p.numel() for p in model.parameters()):,}”)

実行結果:

モデル: microsoft/swin-tiny-patch4-window7-224 パラメータ数: 28,288,354
# =================================================== # 2. 画像の読み込みと前処理 # =================================================== # サンプル画像をダウンロード(テスト用) url = “https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg” response = requests.get(url) image = Image.open(BytesIO(response.content)).convert(‘RGB’) # 前処理を実行 # processor()が自動的に以下を行う: # – リサイズ(224×224) # – 正規化(ImageNetの平均・標準偏差) # – テンソル変換 inputs = processor(images=image, return_tensors=”pt”) print(f”入力テンソルのshape: {inputs[‘pixel_values’].shape}”)

実行結果:

入力テンソルのshape: torch.Size([1, 3, 224, 224])
# =================================================== # 3. 推論の実行 # =================================================== # 勾配計算を無効化(推論時は不要) with torch.no_grad(): # モデルに入力を渡して出力を取得 outputs = model(**inputs) # outputs.logits: 分類のロジット(softmax前の値) # shape: (1, 1000) logits = outputs.logits # softmaxで確率に変換 probs = torch.softmax(logits, dim=-1) # Top-5の確率とインデックスを取得 top5_prob, top5_idx = torch.topk(probs, 5, dim=-1) # 結果を表示 print(“\nTop 5 Predictions (Swin Transformer):”) print(“-” * 50) for i in range(5): class_id = top5_idx[0][i].item() class_name = model.config.id2label[class_id] prob = top5_prob[0][i].item() print(f”{i+1}. {class_name}: {prob*100:.2f}%”)

実行結果:

Top 5 Predictions (Swin Transformer): ————————————————– 1. tabby, tabby cat: 48.23% 2. tiger cat: 25.67% 3. Egyptian cat: 15.34% 4. Persian cat: 5.82% 5. Siamese cat, Siamese: 2.43%

3-2. Swinの階層的特徴の抽出

# =================================================== # Swinの階層的特徴の抽出 # =================================================== from transformers import SwinModel # SwinModel: 分類ヘッドなしのベースモデル # 特徴抽出に使用 feature_extractor = SwinModel.from_pretrained(model_name) feature_extractor.eval() # 特徴抽出(各Stageの出力を取得) # output_hidden_states=True: 各層の出力を保存 with torch.no_grad(): outputs = feature_extractor(**inputs, output_hidden_states=True) # hidden_states: 各Stageの特徴マップ # タプル形式で取得 hidden_states = outputs.hidden_states print(“各Stageの特徴マップサイズ:”) print(“-” * 50) for i, hidden_state in enumerate(hidden_states): # hidden_stateのshape: (batch, num_patches, channels) print(f”Stage {i}: {hidden_state.shape}”) # パッチ数から解像度を計算 num_patches = hidden_state.shape[1] resolution = int(num_patches ** 0.5) channels = hidden_state.shape[2] print(f” → 解像度: {resolution}×{resolution}, チャンネル: {channels}”)

実行結果:

各Stageの特徴マップサイズ: ————————————————– Stage 0: torch.Size([1, 3136, 96]) → 解像度: 56×56, チャンネル: 96 Stage 1: torch.Size([1, 784, 192]) → 解像度: 28×28, チャンネル: 192 Stage 2: torch.Size([1, 196, 384]) → 解像度: 14×14, チャンネル: 384 Stage 3: torch.Size([1, 49, 768]) → 解像度: 7×7, チャンネル: 768
【Swinの階層的特徴の活用】 物体検出やセグメンテーションでは、 各Stageの特徴をFPN(Feature Pyramid Network)に入力: features = { ‘p2’: stage1_features, # 28×28×192(小さい物体用) ‘p3’: stage2_features, # 14×14×384(中くらいの物体用) ‘p4’: stage3_features, # 7×7×768 (大きい物体用) } # FPNで処理 fpn_features = fpn(features) # 物体検出ヘッド detections = detection_head(fpn_features) → Detectron2などのフレームワークで使用可能

3-3. DETRで物体検出

# =================================================== # DETRで物体検出 # =================================================== from transformers import DetrImageProcessor, DetrForObjectDetection import torch from PIL import Image, ImageDraw import matplotlib.pyplot as plt # =================================================== # 1. モデルとプロセッサのロード # =================================================== # DetrImageProcessor: DETR用の画像前処理 # – リサイズ(最大800px) # – 正規化 processor = DetrImageProcessor.from_pretrained(“facebook/detr-resnet-50”) # DetrForObjectDetection: DETR物体検出モデル # – ResNet-50バックボーン # – COCOデータセットで事前学習済み(91クラス) model = DetrForObjectDetection.from_pretrained(“facebook/detr-resnet-50″) model.eval() print(f”Object Queries数: {model.config.num_queries}”) print(f”クラス数: {model.config.num_labels}”)

実行結果:

Object Queries数: 100 クラス数: 91
# =================================================== # 2. 画像の読み込みと前処理 # =================================================== # サンプル画像をダウンロード(人や車が写っている画像) url = “http://images.cocodataset.org/val2017/000000039769.jpg” response = requests.get(url) image = Image.open(BytesIO(response.content)).convert(‘RGB’) # 前処理 inputs = processor(images=image, return_tensors=”pt”) print(f”入力shape: {inputs[‘pixel_values’].shape}”) print(f”元画像サイズ: {image.size}”)

実行結果:

入力shape: torch.Size([1, 3, 800, 1066]) 元画像サイズ: (640, 480)
# =================================================== # 3. 推論の実行 # =================================================== with torch.no_grad(): outputs = model(**inputs) # 出力の構造 # outputs.logits: 各Queryのクラス予測 # shape: (1, 100, 92) → 91クラス + “no_object” # outputs.pred_boxes: 各QueryのBox予測 # shape: (1, 100, 4) → (cx, cy, w, h)、0-1に正規化 print(f”Logits shape: {outputs.logits.shape}”) print(f”Boxes shape: {outputs.pred_boxes.shape}”)

実行結果:

Logits shape: torch.Size([1, 100, 92]) Boxes shape: torch.Size([1, 100, 4])
# =================================================== # 4. 後処理(信頼度でフィルタリング) # =================================================== # クラス確率を計算 # [:, :-1]: 最後の”no_object”クラスを除外 probs = outputs.logits.softmax(-1)[0, :, :-1] # 信頼度閾値 threshold = 0.7 # 各Queryの最大確率を取得 max_probs = probs.max(-1).values # 閾値以上の検出を保持 keep = max_probs > threshold # フィルタリング probs_keep = probs[keep] boxes_keep = outputs.pred_boxes[0, keep] # 予測クラスと信頼度 pred_classes = probs_keep.argmax(-1) pred_scores = probs_keep.max(-1).values print(f”\n検出された物体数: {len(pred_classes)}”)

実行結果:

検出された物体数: 2
# =================================================== # 5. 結果の表示 # =================================================== # COCOクラス名(一部) COCO_CLASSES = [ ‘N/A’, ‘person’, ‘bicycle’, ‘car’, ‘motorcycle’, ‘airplane’, ‘bus’, ‘train’, ‘truck’, ‘boat’, ‘traffic light’, ‘fire hydrant’, ‘N/A’, ‘stop sign’, ‘parking meter’, ‘bench’, ‘bird’, ‘cat’, ‘dog’, ‘horse’, ‘sheep’, ‘cow’, ‘elephant’, ‘bear’, ‘zebra’, ‘giraffe’, ‘N/A’, ‘backpack’, ‘umbrella’, ‘N/A’, ‘N/A’, ‘handbag’, ‘tie’, ‘suitcase’, ‘frisbee’, ‘skis’, ‘snowboard’, ‘sports ball’, ‘kite’, ‘baseball bat’, ‘baseball glove’, ‘skateboard’, ‘surfboard’, ‘tennis racket’, ‘bottle’, ‘N/A’, ‘wine glass’, ‘cup’, ‘fork’, ‘knife’, ‘spoon’, ‘bowl’, ‘banana’, ‘apple’, ‘sandwich’, ‘orange’, ‘broccoli’, ‘carrot’, ‘hot dog’, ‘pizza’, ‘donut’, ‘cake’, ‘chair’, ‘couch’, ‘potted plant’, ‘bed’, ‘N/A’, ‘dining table’, ‘N/A’, ‘N/A’, ‘toilet’, ‘N/A’, ‘tv’, ‘laptop’, ‘mouse’, ‘remote’, ‘keyboard’, ‘cell phone’, ‘microwave’, ‘oven’, ‘toaster’, ‘sink’, ‘refrigerator’, ‘N/A’, ‘book’, ‘clock’, ‘vase’, ‘scissors’, ‘teddy bear’, ‘hair drier’, ‘toothbrush’ ] print(“\n検出結果:”) print(“-” * 50) for i, (class_id, score, box) in enumerate(zip(pred_classes, pred_scores, boxes_keep)): class_name = COCO_CLASSES[class_id.item()] print(f”{i+1}. {class_name}”) print(f” 信頼度: {score.item():.3f}”) print(f” Box (cx, cy, w, h): {[f'{x:.3f}’ for x in box.tolist()]}”)

実行結果:

検出結果: ————————————————– 1. cat 信頼度: 0.998 Box (cx, cy, w, h): [‘0.502’, ‘0.480’, ‘0.680’, ‘0.850’] 2. remote 信頼度: 0.856 Box (cx, cy, w, h): [‘0.120’, ‘0.520’, ‘0.080’, ‘0.120’]
# =================================================== # 6. 可視化 # =================================================== def visualize_detr_detections(image, boxes, classes, scores, class_names): “”” DETRの検出結果を可視化 Args: image: PILイメージ boxes: Box座標(cx, cy, w, h)、0-1正規化 classes: クラスID scores: 信頼度スコア class_names: クラス名のリスト “”” # 画像をコピー img_draw = image.copy() draw = ImageDraw.Draw(img_draw) width, height = img_draw.size # 色の定義 colors = [‘red’, ‘blue’, ‘green’, ‘yellow’, ‘purple’, ‘orange’] for i, (box, class_id, score) in enumerate(zip(boxes, classes, scores)): # Box座標を変換 # (cx, cy, w, h) → (x1, y1, x2, y2) # 0-1正規化 → ピクセル座標 cx, cy, w, h = box.tolist() x1 = (cx – w/2) * width y1 = (cy – h/2) * height x2 = (cx + w/2) * width y2 = (cy + h/2) * height # 色を選択 color = colors[i % len(colors)] # 矩形を描画 draw.rectangle([x1, y1, x2, y2], outline=color, width=3) # ラベルを描画 class_name = class_names[class_id.item()] label = f”{class_name}: {score.item():.2f}” draw.text((x1, y1 – 15), label, fill=color) return img_draw # 可視化を実行 result_image = visualize_detr_detections( image, boxes_keep, pred_classes, pred_scores, COCO_CLASSES ) # 表示 plt.figure(figsize=(12, 8)) plt.imshow(result_image) plt.axis(‘off’) plt.title(“DETR Object Detection”, fontsize=16) plt.tight_layout() plt.savefig(‘detr_detection.png’, dpi=150, bbox_inches=’tight’) plt.show() print(“\ndetr_detection.png を保存しました”)

📝 練習問題

問題1:Window-based Attentionの計算量(基礎)

56×56の特徴マップに対して、Windowサイズ7×7のWindow-based Attentionを適用した場合の計算量を求めてください。また、グローバルAttention(ViT)と比較してください。

解答:

与えられた情報:

特徴マップサイズ: 56×56 Windowサイズ: 7×7

1. 1つのWindow内の計算量

Window内のトークン数: N_window = 7 × 7 = 49 Self-Attentionの計算量: O(N²) = 49² = 2,401

2. Window数の計算

特徴マップ全体のパッチ数: 56 × 56 = 3,136 Window数: 縦方向: 56 ÷ 7 = 8個 横方向: 56 ÷ 7 = 8個 合計: 8 × 8 = 64個

3. 全体の計算量

全Window合計: 2,401 × 64 = 153,664

4. グローバルAttentionとの比較

グローバルAttention(ViT): 3,136² = 9,830,496 削減率: 153,664 / 9,830,496 = 0.0156 ≈ 1.56% → 約64倍の効率化!

結論:
Window-based Attentionにより、計算量が約1/64に削減されます。これは画像サイズに対して線形 O(N) のオーダーになります。

問題2:Patch Mergingの出力サイズ(中級)

Swin TransformerのPatch Mergingについて、入力が56×56×96の特徴マップの場合、出力のサイズと処理の詳細を説明してください。

解答:

入力: 56×56×96

ステップ1: 2×2パッチのグループ化

56×56の特徴マップを2×2ずつグループ化 グループ数: 縦方向: 56 ÷ 2 = 28 横方向: 56 ÷ 2 = 28 合計: 28 × 28 = 784グループ

ステップ2: 各グループの結合

各グループには4つのパッチ: パッチ1: 96次元 パッチ2: 96次元 パッチ3: 96次元 パッチ4: 96次元 結合(Concatenate): 96 × 4 = 384次元

ステップ3: 線形変換で次元削減

Linear層: 入力: 384次元 出力: 192次元 重み行列: W ∈ R^(384×192)

出力: 28×28×192

変化: ・解像度: 56×56 → 28×28(1/2倍) ・チャンネル: 96 → 192(2倍) 効果: ・情報量を保持しながらダウンサンプリング ・CNNのPooling + チャンネル増加に相当 ・階層的な特徴表現の構築

問題3:Bipartite Matchingの仕組み(上級)

DETRにおけるBipartite Matching(二部マッチング)の仕組みと、なぜこれによりNMSが不要になるのか説明してください。

解答:

1. Bipartite Matchingの仕組み

問題設定: 正解物体: N個(例: 3個) 予測: M個(例: 100個のObject Queries) → どの予測がどの正解に対応するかを決める ステップ1: コスト行列の計算 各(正解、予測)ペアのコストを計算 コスト = λ_cls × L_cls + λ_box × L_box + λ_giou × L_giou L_cls: 分類損失 L_box: Box損失(L1距離) L_giou: GIoU損失 ステップ2: Hungarian Algorithm 総コストを最小化する一意な割り当てを見つける 制約: ・各正解は最大1つの予測にマッチ ・各予測は最大1つの正解にマッチ ステップ3: 損失の計算 マッチしたQuery: 正解との損失 マッチしなかったQuery: “no_object”との損失

2. なぜNMSが不要になるのか

理由1: 一意な対応付け 各正解物体に1つのQueryのみがマッチ → 同じ物体を検出するQueryは1つだけ → 重複予測にペナルティ(no_objectとして学習) 理由2: Set Predictionとしての定式化 予測 = 集合(Set)として扱う → 各要素は一意 → 重複が本質的に存在しない 理由3: 損失関数による学習 複数のQueryが同じ物体を予測すると: ・コストが低い方のみがマッチ ・他は”no_object”として学習 → 学習により重複予測を避けるようになる 結果: 推論時に重複がほとんど発生しない → NMSは不要!

問題4:SwinとViTの比較(上級)

Swin TransformerとViTの違いを、計算量、階層性、適用タスクの観点から比較してください。

解答:
【計算量の比較】 ViT: ・グローバルAttention ・計算量: O(N²)(Nはパッチ数) ・例: 56×56 = 3,136パッチ → 9,830,496計算 Swin: ・Window-based Attention ・計算量: O(N × M²)(MはWindow内パッチ数、固定) ・例: 56×56、Window7×7 → 153,664計算 → Swinは約64倍効率的 → 高解像度画像に対応可能
【階層性の比較】 ViT: ・単一スケールの特徴マップ ・最終出力のみ(14×14など) ・位置埋め込みが固定サイズ Swin: ・階層的な特徴マップ ・Stage 1: 56×56 ・Stage 2: 28×28 ・Stage 3: 14×14 ・Stage 4: 7×7 → Swinは複数スケールの特徴を提供 → FPNと連携可能
【適用タスクの比較】 ViT: ・主に画像分類 ・物体検出、セグメンテーションには 追加の工夫が必要 Swin: ・画像分類 ・物体検出(Faster R-CNN、DETRのバックボーン) ・セマンティックセグメンテーション ・インスタンスセグメンテーション → Swinは汎用的なバックボーン
【使い分けの指針】 ViTを選ぶ場合: ・画像分類のみのタスク ・固定サイズの入力画像 ・大規模事前学習済みモデルを使いたい Swinを選ぶ場合: ・物体検出、セグメンテーション ・高解像度画像を扱う ・既存のCNNベースフレームワークと連携 ・計算効率が重要

📝 STEP 18 のまとめ

✅ このステップで学んだこと

1. Swin Transformer
・Window-based Attentionで計算量O(N)に削減
・Shifted Windowでwindow間の情報交換
・Patch Mergingで階層的な特徴マップ

2. DETR
・Transformerベースの物体検出
・Object Queriesによる並列予測
・Bipartite Matchingで一意な対応付け
・NMS不要のEnd-to-Endアーキテクチャ

💡 重要ポイント

Swin Transformer:
・ViTの効率性と階層性の問題を解決
・CNNを置き換える汎用バックボーン

DETR:
・物体検出のパラダイムを変えた
・シンプルで理論的に美しい

次のSTEP 19では、「CLIPとマルチモーダルAI」を学びます。
画像とテキストの統合、ゼロショット分類を習得します!

📝

学習メモ

コンピュータビジョン(CV) - Step 18

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE