Deep

Deepラーニングのメモです

34

90 views

U-Netとは?セマンティックセグメンテーションの基礎と深掘り解説

セマンティックセグメンテーションを学ぶ上で、まず最初に理解しておきたい代表的なネットワークが U-Net です。この記事では、U-Netの基本構造から始まり、スキップ接続の有無や層を深くする意味についても掘り下げていきます。さらに、簡単なPyTorchによるサンプルコードも紹介します。


U-Netとは?

U-Netは2015年に医用画像解析向けに提案されたCNNベースのセマンティックセグメンテーションモデルです。名前の通り、ネットワーク構造が「U字型」をしており、エンコーダ(下り)デコーダ(上り)の2つのパートから構成されています。

  • エンコーダでは、畳み込みとプーリングにより特徴を抽出しながら解像度を下げていきます。
  • デコーダでは、アップサンプリングにより元の解像度へ戻していきます。
  • 特徴的なのは、スキップ接続によりエンコーダの中間層の出力をデコーダに渡す点です。

このスキップ接続によって、深い層で失われがちな空間的な情報("どこにあるか")を補完し、精度の高いセグメンテーションが可能になります。


スキップ接続をなくすとどうなるか?

スキップ接続は、U-Netの性能に大きく貢献する重要な要素です。これを取り除くと、以下のような問題が発生します:

  • 境界がぼやける
  • 小さな物体をうまく検出できない
  • セグメンテーションマップ全体が不正確になる

理由は、エンコーダの深い層になるほど、抽象的な情報は得られても、空間的な位置情報が失われるためです。スキップ接続はこの情報を補い、デコーダでの復元に活用されます。


層を深くする意味とは?

「スキップ接続で浅い層の情報を使うなら、深くする意味はあるのか?」という疑問を持つ人も多いかもしれません。

答えは YES です。層を深くすることで得られるメリットは以下の通り:

  • より抽象的で意味的な特徴を学習できる("これは猫か犬か"のような概念)
  • ノイズに強くなる
  • グローバルな文脈を捉えることができる

つまり、U-Netは浅い層の空間情報深い層の意味的情報の両方を活用する構造になっており、どちらが欠けても性能が落ちるのです。


U-Netの簡易実装(PyTorch)

  1. import torch
  2. import torch.nn as nn
  3. class UNetBlock(nn.Module):
  4. def __init__(self, in_channels, out_channels):
  5. super().__init__()
  6. self.conv = nn.Sequential(
  7. nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
  8. nn.ReLU(),
  9. nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
  10. nn.ReLU(),
  11. )
  12. def forward(self, x):
  13. return self.conv(x)
  14. class UNet(nn.Module):
  15. def __init__(self):
  16. super().__init__()
  17. self.enc1 = UNetBlock(1, 64)
  18. self.pool1 = nn.MaxPool2d(2)
  19. self.enc2 = UNetBlock(64, 128)
  20. self.pool2 = nn.MaxPool2d(2)
  21. self.bottleneck = UNetBlock(128, 256)
  22. self.up2 = nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2)
  23. self.dec2 = UNetBlock(256, 128)
  24. self.up1 = nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2)
  25. self.dec1 = UNetBlock(128, 64)
  26. self.final = nn.Conv2d(64, 2, kernel_size=1) # 2クラス分類
  27. def forward(self, x):
  28. e1 = self.enc1(x)
  29. e2 = self.enc2(self.pool1(e1))
  30. b = self.bottleneck(self.pool2(e2))
  31. d2 = self.up2(b)
  32. d2 = self.dec2(torch.cat([d2, e2], dim=1)) # skip connection
  33. d1 = self.up1(d2)
  34. d1 = self.dec1(torch.cat([d1, e1], dim=1)) # skip connection
  35. return self.final(d1)

このコードでは、2層のU-Netを定義しています。特徴マップをスキップ接続でデコーダに渡す構造が反映されています。


まとめ

  • U-Netはセマンティックセグメンテーションにおける代表的モデルで、シンプルながら高性能
  • スキップ接続をなくすと空間情報が失われ、性能が大幅に落ちる
  • 層を深くすることで意味的な理解が可能となり、ノイズに強い出力が得られる

セマンティックセグメンテーションを学ぶなら、U-Netの構造とその意味をしっかり理解することが大切です。今後はU-Net++やAttention U-Netといった派生モデルも視野に入れていくと、より深い理解につながるでしょう。

Page 31 of 33.

前のページ 次のページ



[添付ファイル]


お問い合わせ

プロフィール

すぺぺぺ

自己紹介

本サイトの作成者。
プログラムは趣味と勉強を兼ねて、のんびり本サイトを作っています。
フレームワークはdjango。
ChatGPTで自動プログラム作成に取り組み中。

サイト/ブログ

https://www.osumoi-stdio.com/novel/

ツイッター

@darkimpact0626