はじめに: CNN は世界をどう見ているか
Le 畳み込みニューラル ネットワーク (CNN) 彼らはコンピュータービジョンに革命をもたらし、 超人的な精度で画像を自動的に認識することが可能になります。 完全に接続されたネットワークとは異なり、CNN は 空間構造 データの: 隣接するピクセルは相関する傾向があり、局所的なパターン (エッジ、テクスチャ) が繰り返されます。 画像のさまざまな位置にあります。
CNN の重要な考え方とその運用 畳み込み: フィルター (カーネル) が流れる 局所的な特徴を抽出することによって画像上に表示されます。ネットワークは層ごとに階層を構築します。 ますます抽象化される特徴: 単純なエッジから複雑な形状、完全なオブジェクトに至るまで。
何を学ぶか
- 畳み込み演算: カーネル、ストライド、パディング
- プーリング: 次元削減と位置不変性
- 歴史的アーキテクチャ: LeNet、AlexNet、VGG、ResNet
- ディープネットワークにおけるスキップ接続と勾配消失問題
- 転移学習: ImageNet で事前トレーニングされたモデルを再利用する
- モデルの堅牢性を向上させるデータ拡張
- トレーニングと評価を行って PyTorch での実装を完了する
畳み込み演算
CNN の心臓部と 畳み込み層。小さなフィルター(カーネル)、 通常は 3x3 または 5x5 のサイズで、画像上をスクロールして要素ごとに計算します。 フィルターとその下にある画像部分の間の要素。結果は1つです 機能マップ これにより、各位置に特定のパターンが存在することが強調されます。
2 つのパラメーターは、畳み込みの動作を制御します。
- ストライド: カーネルが移動するペース。 Stride=1 は同じサイズの特徴マップを生成し、stride=2 はサイズを半分にします。
- パディング: 画像の端にゼロを追加します。 「同じ」パディングでは元のサイズが維持され、「有効」パディングではサイズが縮小されます。
import torch
import torch.nn as nn
# Convoluzione 2D: 3 canali input (RGB), 16 filtri output, kernel 3x3
conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3,
stride=1, padding=1)
# Input: batch di 4 immagini RGB 32x32
x = torch.randn(4, 3, 32, 32)
output = conv_layer(x)
print(f"Input shape: {x.shape}") # [4, 3, 32, 32]
print(f"Output shape: {output.shape}") # [4, 16, 32, 32]
# Con stride=2 e padding=1
conv_stride2 = nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1)
output_s2 = conv_stride2(x)
print(f"Stride 2 output: {output_s2.shape}") # [4, 16, 16, 16]
プーリング: 次元削減
畳み込み後の層は、 プーリング ~の空間寸法を縮小する 特徴マップを作成し、パラメータの数と計算コストを削減します。プーリングの導入 の一種でもあります 翻訳の不変性: オブジェクトの小さな動き 画像では、抽出された特徴は変わりません。
主なタイプは次の 2 つです。
- 最大プーリング: 各ウィンドウで最大値を選択します。最も優れた機能を保持しており、最も使用されているタイプです
- 平均プーリング: 各ウィンドウの平均を計算します。より滑らかな特徴を生成し、通常は出力前に使用されます
CNN がうまく機能する理由
CNN は、画像の 3 つの基本的な特性を活用します。 地域性 (機能 重要なのはローカルです)、 負担の分担 (同じフィルターがどこにでも適用されます。 パラメータを大幅に削減) e 翻訳の不変性 (猫 画像の中央と隅に猫がいます)。これらの特性により CNN は注文を受けます 空間的に構造化されたデータの場合、完全に接続されたネットワークよりもサイズ効率が高くなります。
歴史的建造物: LeNet から ResNet まで
LeNet-5 (1998)
Yann LeCun によって手書き数字認識用に設計されました。 ルネット-5 そして最初に成功したCNN。わずか 5 つのレイヤー (2 つの畳み込み + 3 つの完全接続) を使用して、次のことを示します。 畳み込みネットワークは、従来の特徴量エンジニアリング手法を打ち負かす可能性があります。
VGG (2014)
VGGネット 深さが重要であることを証明します: スタックされた 3x3 カーネルのみを使用する 16 または 19 レイヤーで、ImageNet 上で優れたパフォーマンスを達成しました。 2 つの 3x3 フィルターを連続してカバー 5x5 フィルターと同じ受容野ですが、パラメーターが少なく、非線形性が高くなります。
レスネット (2015)
レスネット (Residual Network) は、非常に深いネットワークのトレーニングの問題を解決しました 彼らと一緒に 接続をスキップする: 直接変換 F(x) を学習する代わりに、それぞれ ブロックは残差 F(x) + x を学習します。これにより、グラデーションが直接流れるようになります。 これにより、152 以上のレイヤーでネットワークをトレーニングできるようになります。
import torch
import torch.nn as nn
class ResidualBlock(nn.Module):
"""Blocco residuo base di ResNet"""
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(channels)
self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
self.bn2 = nn.BatchNorm2d(channels)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
identity = x # Skip connection
out = self.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += identity # Residual: F(x) + x
return self.relu(out)
class SimpleCNN(nn.Module):
"""CNN per classificazione CIFAR-10"""
def __init__(self, num_classes=10):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2), # 32x32 -> 16x16
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2), # 16x16 -> 8x8
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.AdaptiveAvgPool2d((1, 1)) # 8x8 -> 1x1
)
self.classifier = nn.Linear(128, num_classes)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
return self.classifier(x)
model = SimpleCNN()
x = torch.randn(8, 3, 32, 32)
print(f"Output: {model(x).shape}") # [8, 10]
転移学習: 事前トレーニングされたモデルの再利用
大規模なデータセットで CNN をゼロからトレーニングするには、膨大な計算リソースが必要です。の 転移学習 この問題は、事前にトレーニングされたモデルを使用することで解決されます。 巨大なデータセット (通常は 1,400 万枚の画像を含む ImageNet) を使用して、それを独自のデータセットに適応させます。 特定のタスク。
最も一般的な戦略には、次の 2 つのフェーズが含まれます。
- 特徴抽出: 事前トレーニングされたモデルの重みは固定され、最終分類器のみが置き換えられます。
- 微調整: 一部の上位層は解凍され、非常に低い学習率で再トレーニングされます。
import torchvision.models as models
# Caricare ResNet50 pre-addestrato su ImageNet
model = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
# Congelare tutti i parametri
for param in model.parameters():
param.requires_grad = False
# Sostituire il classificatore finale per 5 classi
num_features = model.fc.in_features
model.fc = nn.Sequential(
nn.Dropout(0.3),
nn.Linear(num_features, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 5) # 5 classi custom
)
# Solo i parametri del nuovo classificatore saranno addestrati
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
total = sum(p.numel() for p in model.parameters())
print(f"Trainable: {trainable:,} / {total:,} parametri")
データの拡張: 変換による堅牢性
La データ拡張 そして人工的に正則化手法を強化する 画像にランダムな変換を適用することで、トレーニング データセットの多様性を実現します。回転、 カット、水平反転、色のバリエーションは、ネットワークに次のことを教えます。 不変 これらの変革に。
from torchvision import transforms
# Pipeline di data augmentation per training
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomRotation(15),
transforms.ColorJitter(brightness=0.2, contrast=0.2,
saturation=0.2, hue=0.1),
transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225]),
transforms.RandomErasing(p=0.1)
])
# Per validation/test: solo resize e normalize
val_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
シリーズの次のステップ
- 次の記事では、 リカレント ニューラル ネットワーク (RNN) と LSTM シーケンス処理用
- LSTM がどのように勾配消失を解決し、時間依存関係をモデル化するかを見ていきます。
- 感情分析とテキスト生成モデルを実装します。







