🖼️ 🔄 🎨

FCN をイチから理解する

Fully Convolutional Network ── セマンティックセグメンテーションの元祖

🤔 FCN って何?(ひとことで)

🏆
ひとことで言うと
画像分類用のCNN(VGGなど)を改造して、セマンティックセグメンテーションができるようにした最初のモデル
2015年発表。セグメンテーション分野の出発点であり、SegNetやU-Netなどの後続モデルは全てFCNの考え方の上に成り立っている。
名前の意味:
FCN = Fully Convolutional Network = 「全部畳み込み」ネットワーク
従来のCNNにあった「全結合層」を取り除いて、全ての層を畳み込み層に置き換えたのが名前の由来。

😱 前提:従来のCNN(VGGなど)はなぜセグメンテーションに使えなかったのか?

画像分類のCNN(VGG16など)の構造を思い出してみよう。

VGG16の構造(画像分類用)

入力画像
224×224
Conv層
×13
特徴抽出
Pool
×5
縮小
全結合層
×3
4096→4096→1000
出力
「猫」

↑ この「全結合層」が問題!

全結合層の2つの問題

💡
そこでFCNの発想
「全結合層がダメなら、全結合層を畳み込み層に置き換えてしまえ!
畳み込み層は空間情報を保持するし、入力サイズも自由。
これがFCNの核心アイデア。

🔧 FCNの核心:全結合層 → 1×1 畳み込みに変換

🎓
たとえ話:アンケート集計
全結合層=教室の全員に1人ずつ聞いて回って、最後に1つの答えを出す。席順は関係ない。
1×1畳み込み=各席に座ったまま、全員に同じ質問用紙を配ってその場で回答させる。席順(位置情報)がそのまま残る。

全結合層 vs 1×1畳み込み層

1×1畳み込みとは:
フィルターのサイズが 1×1。周囲のピクセルは見ず、各ピクセルのチャネル方向だけを計算する。
つまり「この位置の512チャネルの特徴を見て、この位置が猫か犬か背景かを判断する」。
空間の縦横サイズは一切変わらないのがポイント。

ちなみにGoogLeNetのInceptionモジュールにも1×1畳み込みがあったけど、あちらは「チャネル数の削減(次元削減)」が目的。FCNでは「全結合層の代替」が目的。

📐 でも出力が小さすぎる問題 → アップサンプリング

1×1畳み込みで空間情報は保てたけど、エンコーダ部分のプーリングで画像が1/32に縮小されている。
元が224×224なら、この時点で7×7しかない。セグメンテーションには元のサイズに戻す必要がある。

🔎
たとえ話:低解像度の地図を拡大する
7×7ピクセルのミニ画像から224×224の大きな画像を作るのは、
モザイクだらけの小さい地図を鮮明な大きい地図に戻すようなもの。

FCNではこれにTransposed Convolution(逆畳み込み / 転置畳み込み)を使う。

Transposed Convolution(逆畳み込み)とは

Transposed Convolutionは「学習可能なアップサンプリング」。
単純な引き伸ばしではなく、フィルターの重みを学習して賢く拡大する。

🧠 FCNの全体構造

VGG16ベースのFCNの流れ

入力画像
H×W×3
VGG16の
Conv + Pool
13層のConv
5回のPool
(1/32に縮小)
エンコーダ部分
(そのまま流用)
全結合層

1×1 Conv
チャネル数を
クラス数Nに変換
← FCNの核心!
Transposed
Conv
1/32サイズ →
元のサイズに復元
アップサンプリング
出力マップ
H×W×N
ピクセルごとの
クラス予測
FCNのポイント:
✅ VGG16の学習済み重みをそのまま流用できる(転移学習
✅ 全結合層 → 1×1 Conv に置き換え(位置情報を保持)
✅ Transposed Convolution で元のサイズに復元
✅ 入力画像のサイズが自由(全結合層がないので)

🔢 FCN-32s / FCN-16s / FCN-8s ── 精度の段階

一気に32倍に拡大すると、どうしても輪郭がガタガタになる。
そこでFCNは「中間層の特徴マップを足し合わせる」ことで精度を改善した。

3つのバリエーション

FCN-32s
最もシンプル
最終層
1/32サイズ
──×32拡大──→
出力

1/32から一気に32倍拡大 → 輪郭がガタガタ 😢

FCN-16s
少し改善
最終層
1/32
×2→
Pool4層と
足し算
1/16
──×16拡大──→
出力

中間層(Pool4)の情報を足す → 少し精度UP 😊

FCN-8s
最も高精度
最終層
1/32
×2→
+Pool4
1/16
×2→
+Pool3
1/8
──×8拡大──→
出力

中間層2つ(Pool4 + Pool3)の情報を足す → 輪郭がかなり正確 😍

🏔️
たとえ話:地図の復元
FCN-32s:県レベルの粗い地図だけで詳細な地図を復元しようとする → ざっくり
FCN-16s:県レベル+市レベルの情報も使う → もう少し正確
FCN-8s:県+市+町レベルの情報を全部使う → かなり正確

粗い情報に、より細かい中間層の情報を段階的に足していくことで精度が向上する。
「s」の意味:stride(ストライド)のs。最終的なアップサンプリングの倍率を示す。
FCN-32s → 32倍拡大(粗い) / FCN-16s → 16倍拡大(中間) / FCN-8s → 8倍拡大(細かい)

数字が小さいほど高精度。ただし計算コストは増える。

📜 FCNはなぜ歴史的に重要なのか?

FCNが切り開いた3つの道

🔓
①「全結合層は不要」の発見

全結合層を畳み込みに置き換えるだけでセグメンテーションが可能に。入力サイズも自由に。

♻️
② 転移学習の活用

VGG16等の学習済みモデルをそのまま流用できることを示した。ゼロから学習する必要がない。

🌱
③ 後続モデルの礎

SegNet、U-Net、PSPNet、DeepLab、Mask R-CNN… 全てFCNの発想が土台

FCNと後続モデルの関係:
FCNの弱点は「プーリングで失われた位置情報をどう復元するか」。
この弱点を異なる方法で解決したのが後続モデル:

FCNの弱点 → SegNet(Pooling Indicesで位置を記憶)
FCNの弱点 → U-Net(スキップ結合で特徴マップを丸ごと渡す)
FCNの弱点 → PSPNet(ピラミッドプーリングで広い文脈を理解)
FCNの弱点 → DeepLab(Dilated Convで受容野を広げる)

🏁 全体まとめ

FCNの仕組み 3ステップ

1
VGG16のConv+Pool部分で特徴抽出
学習済みの重みをそのまま使える(転移学習)。画像は1/32に縮小される。
2
全結合層 → 1×1畳み込みに置き換え
空間情報を保ったまま、各ピクセルのクラス分類を行う。FCNの名前の由来。
3
Transposed Convolutionで元のサイズに復元
学習可能なアップサンプリング。FCN-8sでは中間層の情報も足して精度向上。
G検定で問われるFCNのキーワード:

Fully Convolutional Network(全結合層を使わず全て畳み込み)
全結合層 → 1×1畳み込みに置き換え(位置情報を保持)
Transposed Convolution(逆畳み込み / 転置畳み込み)でアップサンプリング
VGG16ベース(転移学習が可能)
FCN-32s / 16s / 8s(数字が小さいほど精度が高い)
セマンティックセグメンテーションの元祖(2015年。後続モデルの土台)
任意サイズの入力を処理可能(全結合層がないから)

セグメンテーションの系譜:
FCN(元祖)→ SegNet(位置メモ)→ U-Net(スキップ結合)→ PSPNet(ピラミッド)→ DeepLab(穴あきConv)→ Mask R-CNN(インスタンスSeg)