4.4 ニューラルネットワークと CNN

ディープラーニングへの扉を開く

image-20260331170612103

前章までに、従来のコンピュータビジョン手法は現実世界でしばしば失敗することを見てきました。それらの成功は通常、安定した照明、きれいな背景、固定された視点、予測可能な物体形状など、シーンが特定のパターンまたは前提条件のセットに合致しているかどうかに依存します。これらの条件が変わると、性能は急速に低下します。一方、ディープラーニングは大きく異なるアプローチを取ります。手作りのルールに主に頼るのではなく、大量のデータから直接有用な視覚パターンを学習します。これにより、見え方、背景、スケール、照明、姿勢のはるかに大きな変動に対応できます。その結果、ディープラーニングはコンピュータビジョンを実世界の応用に対してはるかに堅牢で実用的にしました。

ルールから学習された表現へ

古典的ビジョンでは、ルールを明示的に書きます:

  • 画像をぼかす
  • エッジを見つける
  • 輪郭を抽出する

ニューラルネットワークでは、モデルに例から有用なパターンを学習させます。

これが鍵となる概念上のシフトです: システムは手動で設計された特徴のみに頼るのではなく、表現を学習します。

ニューラルネットワークとは何か

image-20260401094617887

ニューラルネットワークは、入力データを段階的に変換する層から構成される関数です。

各層はパラメータを学習します。学習中、これらのパラメータは調整され、ネットワークの出力がそのタスクに対してより有用になるようにされます。

コードでの NN はどう見えるか?

python
import torch
import torch.nn as nn
import torch.nn.functional as F

# 1. Define the Network Structure
class SimpleMLP(nn.Module):
    def __init__(self, input_size=784, hidden_size=128, num_classes=10):
        super(SimpleMLP, self).__init__()
        
        # --- Fully Connected Layers (Dense Layers) ---
        
        # First layer: Maps input features to the first hidden layer
        self.fc1 = nn.Linear(input_size, hidden_size)
        
        # Second layer: Maps first hidden layer to the second hidden layer
        self.fc2 = nn.Linear(hidden_size, 64)
        
        # Output layer: Maps second hidden layer to the number of classes
        self.fc3 = nn.Linear(64, num_classes)
        
        # Optional: Dropout layer to prevent overfitting (drops 20% of neurons)
        self.dropout = nn.Dropout(p=0.2)

    # 2. Define the Data Flow (Forward Pass)
    def forward(self, x):
        # Flatten the input tensor
        # Converts (batch_size, channels, height, width) to (batch_size, -1)
        # Example: 28x28 image becomes a 784-dimensional vector
        x = x.view(x.size(0), -1)  
        
        # First hidden layer: Linear transformation -> ReLU Activation -> Dropout
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        
        # Second hidden layer: Linear transformation -> ReLU Activation
        x = F.relu(self.fc2(x))
        
        # Output layer: Linear transformation (no activation here, usually handled by loss function)
        x = self.fc3(x)
        
        return x

# 3. Instantiate the Model
model = SimpleMLP()
print(model)

試してみる

bash
cd 4.4-Neural-Networks-and-CNNs/code
python powerful_neural_network.py

🚀 自分のニューラルネットワークを学習させて、その性能を確認してください!

nn

なぜ CNN は画像に適しているのか

CNN (畳み込みニューラルネットワーク) が画像に向いている理由は、画像が単なるランダムな数字ではないからです。画像では、近隣のピクセルは通常、同じエッジ、形状、テクスチャに属するため、局所的なパターンが大きな意味を持ちます。CNN は画像上をスキャンする小さなフィルタを使ってこれを活用し、エッジ、コーナー、簡単な形状などの有用な特徴を探します。ネットワークが深くなるにつれ、これらの小さな特徴を物体の部品、最終的には物体全体といった大きな特徴に組み合わせていきます。これが CNN が画像を効率よく正確に理解するのに特に優れている理由です。

Input Shape : (1, 9, 9) - Output Shape : (1, 7, 7) - K : (3, 3) - P : (0, 0) - S : (1, 1) - D : (1, 1) - G : 1.gif

CNN は通常、画像をより高次の視覚的理解に変えるための階層構造を持ちます。入力画像から始まり、エッジ、テクスチャ、形状などの局所パターンを学習する複数の畳み込み層を通します。それらの後にはしばしば ReLU のような活性化関数と、空間サイズを縮小しながら重要な情報を保つプーリング層が続きます。そのようなブロックをいくつか経た後、特徴マップはフラット化されたりプーリングされてコンパクトな表現になり、最後に 1 つ以上の全結合層に渡されてクラスラベルなどの最終予測が出力されます。要するに、一般的な CNN は次のように見えます:

入力 → 畳み込み + 活性化 → プーリング → 特徴抽出ブロックの繰り返し → 全結合層 → 出力

image-20260401175822373

畳み込みの利点:

  • 局所パターンの抽出

畳み込みは、エッジ、コーナー、テクスチャ、簡単な形状など、画像内の小さくて有用なパターンを見つけるのに役立ちます。これらの小さなパターンは、より大きな物体を理解するための基本的な構成要素です。

image-20260401150136006

  • パラメータ共有

同じフィルタが画像の異なる場所で使用されます。つまり、モデルは位置ごとに新しい重みのセットを学習する必要がなく、より効率的でパラメータ数も少なくて済みます。

  • 平行移動への頑健性

物体が画像の別の位置に移動しても、畳み込みフィルタはそれを検出できます。言い換えれば、モデルは位置が変わっても同じパターンを認識できます。

特徴マップ

畳み込み層が画像を処理すると、特徴マップが生成されます。これらのマップは次のようなパターンに反応します:

  • エッジ
  • コーナー
  • テクスチャ
  • より深い層では、より大きな意味的構造

image-20260401100245367

プーリングとダウンサンプリング

プーリングは重要な情報を保ちながら空間サイズを縮小します。

image-20260401103259828 image-20260401104155947

これは次に役立ちます:

  • 計算量の削減
  • 頑健性の向上
  • よりコンパクトな表現の構築

試してみる

bash
cd 4.4-Neural-Networks-and-CNNs/code
python cnn_process_visualization.py

🚀 スクリプトを実行して、畳み込みネットワークによる画像処理プロセスを体験してください。

conv

学習と推論

  • Training: モデルが重みを更新して学習する
  • Inference: 学習済みモデルが重みを更新せずに予測を行う

この区別が重要なのは、後のデプロイの章では主に推論に焦点を当てるためです。

コードでの CNN はどう見えるか?

python
mport torch
import torch.nn as nn

class TinyCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(32 * 56 * 56, 64),
            nn.ReLU(),
            nn.Linear(64, 10)
        )

    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

model = TinyCNN()
dummy = torch.randn(1, 3, 224, 224)
output = model(dummy)
print(output.shape)

よくある誤解

  • 「CNN は文字通り人間の目のように見ている。」
    • CNN は数値パターンを処理します。アナロジーは助けになりますが、文字通りではありません。
  • 「層が多いほど常に性能が上がる。」
    • より深いモデルはより強力になり得ますが、学習やデプロイも難しくなります。
  • 「コードを理解すれば、自動的に学習も理解できる。」
    • 学習はデータ、損失、最適化、評価にも依存します。

演習 / リフレクション

  1. 畳み込みが単純な全結合層よりも画像に適している理由を、自分の言葉で説明してください。
  2. tiny CNN の例を実行し、出力の形状を表示してください。
  3. 最初の畳み込みの出力チャンネル数を変更し、モデル構造がどう変わるか観察してください。
  4. CNN がぼかしやエッジ検出といった古典的フィルタとどう異なるか考えてみてください。

まとめ

ニューラルネットワークはデータから表現を学習し、CNN は局所構造を活用するため特に画像に有効です。畳み込み、特徴マップ、プーリング、学習と推論の違いを理解することで、現代のビジョンタスクに備えることができます。

推奨される次のステップ

4.5 ディープラーニングのコンピュータビジョンタスク に進んでください。

参考文献