2026年版 PyTorchでコンピュータビジョン:CNN、転移学習、面接対策完全ガイド

PyTorchを使ったコンピュータビジョンの実践ガイド。CNNの基礎から転移学習、画像分類、面接でよく聞かれる質問まで網羅的に解説します。

2026年版 PyTorchでコンピュータビジョン:CNN、転移学習、面接対策完全ガイド

コンピュータビジョンは機械学習の中でも最も実用的な分野の一つであり、自動運転、医療画像診断、セキュリティシステムなど、様々な産業で活用されています。本記事では、PyTorchを使用したコンピュータビジョンの実装について、基礎から応用まで体系的に解説します。

PyTorch 2.5以降では、torch.compile()による最適化が大幅に改善されています。本記事のコード例は最新のベストプラクティスに基づいています。

畳み込みニューラルネットワーク(CNN)の基礎

畳み込みニューラルネットワークは、画像認識タスクにおいて標準的なアーキテクチャとなっています。CNNは畳み込み層、プーリング層、全結合層で構成され、画像の空間的な特徴を効率的に抽出できます。

PyTorchでのCNN実装

以下は、画像分類用の基本的なCNNモデルの実装例です。

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

class SimpleCNN(nn.Module):
    def __init__(self, num_classes: int = 10):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(32)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.bn3 = nn.BatchNorm2d(128)
        self.pool = nn.MaxPool2d(2, 2)
        self.dropout = nn.Dropout(0.5)
        self.fc1 = nn.Linear(128 * 4 * 4, 512)
        self.fc2 = nn.Linear(512, num_classes)
    
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.pool(F.relu(self.bn1(self.conv1(x))))
        x = self.pool(F.relu(self.bn2(self.conv2(x))))
        x = self.pool(F.relu(self.bn3(self.conv3(x))))
        x = x.view(-1, 128 * 4 * 4)
        x = self.dropout(F.relu(self.fc1(x)))
        x = self.fc2(x)
        return x

このモデルでは、バッチ正規化とドロップアウトを使用して、過学習を防止しながら学習を安定させています。

データの前処理とデータ拡張

画像データの前処理は、モデルの性能に大きく影響します。PyTorchではtorchvision.transformsを使用して、効率的にデータ拡張を実装できます。

python
from torchvision import transforms
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder

train_transform = transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(15),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

val_transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

train_dataset = ImageFolder('data/train', transform=train_transform)
train_loader = DataLoader(
    train_dataset,
    batch_size=32,
    shuffle=True,
    num_workers=4,
    pin_memory=True
)

正規化の値はImageNetデータセットの統計値を使用しており、事前学習済みモデルとの互換性を確保しています。

転移学習の実践

転移学習は、大規模データセットで学習済みのモデルを、新しいタスクに適用する手法です。特に学習データが限られている場合に効果的です。

ResNetを使った転移学習

python
import torchvision.models as models

def create_transfer_model(num_classes: int, freeze_backbone: bool = True):
    model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V2)
    
    if freeze_backbone:
        for param in model.parameters():
            param.requires_grad = False
    
    num_features = model.fc.in_features
    model.fc = nn.Sequential(
        nn.Dropout(0.5),
        nn.Linear(num_features, 512),
        nn.ReLU(),
        nn.Dropout(0.3),
        nn.Linear(512, num_classes)
    )
    
    return model

model = create_transfer_model(num_classes=5)

転移学習では、最初にバックボーンを凍結して分類ヘッドのみを学習し、その後全体を微調整する2段階アプローチが効果的です。

Vision Transformerの活用

近年では、Vision Transformer(ViT)がCNNを上回る性能を示すケースも増えています。

python
from torchvision.models import vit_b_16, ViT_B_16_Weights

def create_vit_model(num_classes: int):
    model = vit_b_16(weights=ViT_B_16_Weights.IMAGENET1K_V1)
    
    for param in model.parameters():
        param.requires_grad = False
    
    model.heads = nn.Sequential(
        nn.Linear(model.heads.head.in_features, 512),
        nn.GELU(),
        nn.Dropout(0.3),
        nn.Linear(512, num_classes)
    )
    
    for param in model.heads.parameters():
        param.requires_grad = True
    
    return model

学習ループの実装

PyTorchでは、学習ループを明示的に記述する必要があります。以下は、混合精度学習とグラデーションクリッピングを含む実装例です。

python
from torch.amp import GradScaler, autocast
from torch.optim import AdamW
from torch.optim.lr_scheduler import CosineAnnealingLR

def train_model(
    model: nn.Module,
    train_loader: DataLoader,
    val_loader: DataLoader,
    epochs: int = 50,
    device: str = 'cuda'
):
    model = model.to(device)
    optimizer = AdamW(model.parameters(), lr=1e-4, weight_decay=0.01)
    scheduler = CosineAnnealingLR(optimizer, T_max=epochs)
    scaler = GradScaler()
    criterion = nn.CrossEntropyLoss()
    
    best_val_acc = 0.0
    
    for epoch in range(epochs):
        model.train()
        train_loss = 0.0
        
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            
            optimizer.zero_grad()
            
            with autocast(device_type='cuda'):
                outputs = model(images)
                loss = criterion(outputs, labels)
            
            scaler.scale(loss).backward()
            scaler.unscale_(optimizer)
            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
            scaler.step(optimizer)
            scaler.update()
            
            train_loss += loss.item()
        
        val_acc = evaluate(model, val_loader, device)
        scheduler.step()
        
        if val_acc > best_val_acc:
            best_val_acc = val_acc
            torch.save(model.state_dict(), 'best_model.pth')
        
        print(f'Epoch {epoch+1}/{epochs}, Loss: {train_loss/len(train_loader):.4f}, Val Acc: {val_acc:.4f}')
    
    return model

def evaluate(model: nn.Module, loader: DataLoader, device: str) -> float:
    model.eval()
    correct = 0
    total = 0
    
    with torch.no_grad():
        for images, labels in loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    return correct / total

モデルの最適化とデプロイ

PyTorch 2.x では、torch.compile()を使用してモデルを最適化できます。

python
import torch

model = create_transfer_model(num_classes=10)
model = torch.compile(model, mode='reduce-overhead')

# ONNX形式でエクスポート
torch.onnx.export(
    model,
    torch.randn(1, 3, 224, 224),
    'model.onnx',
    input_names=['input'],
    output_names=['output'],
    dynamic_axes={
        'input': {0: 'batch_size'},
        'output': {0: 'batch_size'}
    }
)

Data Science & MLの面接対策はできていますか?

インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。

面接でよく聞かれるコンピュータビジョンの質問

データサイエンスや機械学習エンジニアの面接では、コンピュータビジョンに関する技術的な質問が多く出題されます。

CNNに関する質問

Q: 畳み込み層とプーリング層の違いは何ですか?

畳み込み層は学習可能なフィルタを使用して特徴を抽出し、プーリング層は固定された操作(最大値または平均値の選択)でダウンサンプリングを行います。畳み込み層はパラメータを持ちますが、プーリング層は持ちません。

Q: バッチ正規化の目的と、なぜ効果的なのかを説明してください。

バッチ正規化は、各層の入力を正規化することで内部共変量シフトを軽減します。これにより、より高い学習率を使用でき、学習が安定し、正則化効果も得られます。

Q: 受容野(Receptive Field)とは何ですか?

受容野は、出力の1つのニューロンが「見る」ことができる入力画像の領域です。深い層ほど受容野が大きくなり、より広い文脈を捉えることができます。

転移学習に関する質問

Q: 転移学習を使用するタイミングと、全体を再学習するタイミングの判断基準は?

転移学習は、ターゲットデータセットが小さい場合や、ソースドメインとターゲットドメインが類似している場合に効果的です。データセットが十分に大きく、ドメインが大きく異なる場合は、全体を再学習する方が良い結果が得られることがあります。

Q: Fine-tuningの際、どの層を凍結すべきですか?

一般的には、初期の層は汎用的な特徴(エッジ、テクスチャなど)を学習しているため凍結し、後半の層はタスク固有の特徴を学習するため解凍します。データ量が少ない場合は、より多くの層を凍結します。

実装に関する質問

Q: 過学習を防ぐためにどのような手法を使用しますか?

データ拡張、ドロップアウト、正則化(L2/Weight Decay)、早期停止、バッチ正規化などがあります。また、より小さいモデルを使用したり、転移学習を活用することも効果的です。

Q: 混合精度学習(Mixed Precision Training)のメリットは?

混合精度学習は、float16とfloat32を組み合わせて使用することで、メモリ使用量を削減し、計算速度を向上させます。精度の低下はほとんどなく、特に大規模モデルの学習で効果的です。

パフォーマンス最適化のベストプラクティス

本番環境でのモデル運用には、効率的な推論が重要です。

python
class OptimizedInference:
    def __init__(self, model_path: str, device: str = 'cuda'):
        self.device = device
        self.model = self._load_model(model_path)
        self.transform = val_transform
    
    def _load_model(self, path: str) -> nn.Module:
        model = create_transfer_model(num_classes=10)
        model.load_state_dict(torch.load(path, map_location=self.device))
        model = model.to(self.device)
        model.eval()
        return torch.compile(model, mode='reduce-overhead')
    
    @torch.inference_mode()
    def predict(self, image: torch.Tensor) -> tuple[int, float]:
        image = self.transform(image).unsqueeze(0).to(self.device)
        output = self.model(image)
        probabilities = F.softmax(output, dim=1)
        confidence, predicted = torch.max(probabilities, 1)
        return predicted.item(), confidence.item()
    
    @torch.inference_mode()
    def predict_batch(self, images: list) -> list[tuple[int, float]]:
        batch = torch.stack([self.transform(img) for img in images])
        batch = batch.to(self.device)
        outputs = self.model(batch)
        probabilities = F.softmax(outputs, dim=1)
        confidences, predictions = torch.max(probabilities, 1)
        return list(zip(predictions.tolist(), confidences.tolist()))

まとめ

本記事では、PyTorchを使用したコンピュータビジョンの実装について、CNNの基礎から転移学習、面接対策まで幅広く解説しました。重要なポイントは以下の通りです。

  1. CNNの基本構造を理解し、適切にモデルを設計する
  2. データ拡張を活用して過学習を防止する
  3. 転移学習を効果的に活用し、限られたデータでも高精度を実現する
  4. 混合精度学習やtorch.compile()で学習・推論を最適化する
  5. 面接では理論的な理解と実装経験の両方が求められる

コンピュータビジョンは急速に発展している分野であり、最新の研究やベストプラクティスを常にキャッチアップすることが重要です。PyTorchのエコシステムを活用することで、効率的に高性能なモデルを構築できます。

Anthony Fillion-Maillet

執筆

Anthony Fillion-Maillet

フルスタック開発者、SharpSkill 創業者

10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。

2026年8月14日 更新

共有

関連記事