ViT事前学習モデルを用いた画像分類の実装手法

ViTモデルの基本構造

Vision Transformer(ViT)はトランスフォーマーアーキテクチャを画像処理に応用したモデルです。画像を固定サイズのパッチに分割し、各パッチを埋め込みベクトルに変換します。位置情報を付加した後、トランスフォーマーエンコーダーで特徴抽出を行います。

class VisionTransformer(nn.Module):
    def __init__(self, image_dim=224, patch_dim=16, embed_size=768, layers=12, heads=12):
        super().__init__()
        self.patch_embed = PatchProjection(image_dim, patch_dim, 3, embed_size)
        self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_size))
        self.pos_embed = nn.Parameter(torch.randn(1, self.patch_embed.num_patches + 1, embed_size) * 0.02)
        self.encoder_blocks = nn.Sequential(
            *[TransformerBlock(embed_size, heads) for _ in range(layers)]
        )
        self.normalize = nn.LayerNorm(embed_size)
        self.classifier = nn.Linear(embed_size, num_classes)

事前学習モデルの取得

timmライブラリを使用して事前学習済みViTモデルをロードします:

import timm

classification_model = timm.create_model('vit_base_patch16_224', pretrained=True, num_classes=10)
total_params = sum(param.numel() for param in classification_model.parameters())
print(f"モデルパラメータ総数: {total_params:,}")

データセット準備

画像データセットの前処理とデータローダー作成:

from timm.data import create_dataset, create_loader

preprocess = timm.data.create_transform(
    input_size=(224, 224),
    is_training=True,
    auto_augment='rand-m9-mstd0.5',
    mean=(0.485, 0.456, 0.406),
    std=(0.229, 0.224, 0.225)
)

image_dataset = create_dataset(
    root='dataset_path',
    transform=preprocess
)

data_loader = create_loader(
    image_dataset,
    batch_size=64,
    shuffle=True
)

モデル訓練プロセス

カスタム訓練ループの実装例:

optimizer = torch.optim.AdamW(classification_model.parameters(), lr=0.0001)
loss_fn = nn.CrossEntropyLoss()

for epoch in range(10):
    classification_model.train()
    
    for images, labels in data_loader:
        optimizer.zero_grad()
        predictions = classification_model(images)
        loss_value = loss_fn(predictions, labels)
        loss_value.backward()
        optimizer.step()

モデル評価方法

検証データでの精度計測:

def calculate_accuracy(model, data_loader):
    model.eval()
    correct = 0
    total = 0
    
    with torch.no_grad():
        for images, labels in data_loader:
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    return 100 * correct / total

accuracy = calculate_accuracy(classification_model, validation_loader)
print(f"検証精度: {accuracy:.2f}%")

推論最適化手法

混合精度訓練の実装:

scaler = torch.cuda.amp.GradScaler()

for images, labels in data_loader:
    optimizer.zero_grad()
    
    with torch.cuda.amp.autocast():
        outputs = classification_model(images)
        loss = loss_fn(outputs, labels)
    
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()

ONNX形式へのモデルエクスポート:

sample_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
    classification_model,
    sample_input,
    "vit_model.onnx",
    input_names=["input"],
    output_names=["output"]
)

タグ: ViT PyTorch timm 画像分類 ファインチューニング

7月6日 00:16 投稿