どうもニコイチです。これまでの流れでは、以下のように段階的に進めてきました。
- はじめに
- 画像読み込みと欠損の確認
- 画像の特徴理解
- 集めたデータの確認
- データセット作成
- 転移学習なしのモデルの選定と作成
- 転移学習なしのモデル学習
- 転移学習なしの学習済みモデルでの推論
- 転移学習ありのモデルの選定と作成
- 転移学習ありのモデル精度改善 ← 今回
ここでは最終回として、転移学習ありのモデルをさらに精度改善するためのテクニックを紹介します。
大きく分けて下記のステップで取り組みます。
ステップ1:転移学習の復習と改善の方向性
- 転移学習ありモデルでは、すでに学習済みの重み(例:ImageNetで学習した重み)を利用し、自分のデータセットに合わせて最後の数層を学習し直すことで効率よく高精度を狙えます。
- 前回(9章) では転移学習用のモデルを選定・構築し、ある程度の精度を得られることを確認しました。
- ただし、そのままの設定ではデータ特性が十分反映されない場合があります。もっと大量のデータがあれば理想的ですが、現実的には難しいことも多いです。
そこで、データオーグメンテーション(Data Augmentation)を活用して学習用データを擬似的に増やしたり、各種のハイパーパラメータ(学習率やバッチサイズなど)を調整することで、さらなる精度改善を目指します。
ステップ2:Data Augmentation(データオーグメンテーション)の活用
Data Augmentationは、元の画像を様々に変形・加工することで学習データを「水増し」し、モデルの汎化性能を高める手法です。
具体的な例としては以下があります。
- 左右/上下反転
transforms.RandomHorizontalFlip()
/transforms.RandomVerticalFlip()
- 引数
p
によって反転が起きる確率を調整
- ランダムグリッドシャッフル
albumentations.RandomGridShuffle(grid=(3,3), p=1.0)
など- 画像をパズルのように分割し、マスをシャッフル
- カットアウト(Cutout)
albumentations.Cutout(num_holes=8, max_h_size=20, max_w_size=20, fill_value=0, p=1.0)
- 画像の一部領域を塗りつぶすことで、モデルが特定の箇所だけに依存しないようにする
- その他
- 画像の色味を変える(Brightness, Contrast, Hue など)
- 回転 (Rotation)
- ランダムに一部を拡大したり切り抜いたりする (RandomResizedCrop など)
など、組み合わせれば多彩なオーグメンテーションが可能です。
なぜオーグメンテーションが効くのか?
- データが少なくても見た目を多様化させることで、モデルに「いろいろなパターン」を覚えさせられます。
- ノイズや予期せぬ撮影条件にも強いモデルが作れます(汎化性能の向上)。
客観的なデータ・統計(参考)
- 一般的に、ImageNetやCIFARなどの大規模データセットでData Augmentationを導入すると、数%から10%程度の精度向上が見込めるケースが多いと報告されています(※文献:11, 22 など)。
- 特に医療画像や製造業での不良検知など、データが取りづらいケースでは数%の向上が結果に大きく影響することもあります。
11 Krizhevsky, Alex, et al. “ImageNet Classification with Deep Convolutional Neural Networks.” (2012)
22 Howard, Andrew G., et al. “Mobilenets: Efficient Convolutional Neural Networks for Mobile Vision Applications.” (2017)
ステップ3:転移学習ありモデル + Data Augmentation での再学習
3-1. コード例
以下は、前回(9章)で使用した「転移学習ありのモデル」に、Albumentationsを使ったオーグメンテーションを組み込むサンプルフローです。
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, models, transforms
import albumentations
from albumentations.pytorch import ToTensorV2
import numpy as np
from PIL import Image
# 1) Albumentationsでいくつかオーグメンテーションを定義
albu_transforms = albumentations.Compose([
albumentations.RandomGridShuffle(grid=(2, 2), p=0.5),
albumentations.Cutout(num_holes=4, max_h_size=15, max_w_size=15, fill_value=0, p=0.5),
# 他にも必要に応じて追加可能
])
# 2) Albumentations -> PIL への変換関数
def albumentations_transform(image, transform=albu_transforms):
image_np = np.array(image)
augmented = transform(image=image_np)
image = Image.fromarray(augmented['image'])
return image
# 3) 最終的なtransforms.Composeでまとめる
train_data_transform = transforms.Compose([
transforms.Lambda(albumentations_transform),
# torchvisionでテンソル化・正規化
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
# 4) データセットの用意 (学習用)
train_dataset = datasets.ImageFolder(
root='./train_data',
transform=train_data_transform
)
# 5) DataLoaderの作成
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=32,
shuffle=True,
num_workers=2
)
# 6) 事前学習済みモデルの読み込み (例: ResNet18)
model = models.resnet18(pretrained=True)
# 7) 転移学習用に最終層などを作り変える
# クラス数を自分のデータに合わせる (例: 2クラス)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)
# 8) 損失関数と最適化手法の設定
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 9) 学習ループ
num_epochs = 10
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for images, labels in train_loader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
epoch_loss = running_loss / len(train_loader)
print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}")
print("学習完了")
- ポイント
- Albumentationsで好きなオーグメンテーションを定義し、それを
transforms.Lambda()
でPyTorchのパイプラインへ組み込みます。 - モデルは9章で使用した転移学習用のベースを流用し、最終層を付け替えています。
- Data Augmentationで画像を多様化することで、過学習しづらい・汎化性能の高いモデルを期待できます。
- Albumentationsで好きなオーグメンテーションを定義し、それを
3-2. ハイパーパラメータの見直し
- 学習率 (learning rate) を少し下げてみる(例:
lr=0.0001
)
→ 過学習の抑制や微調整に役立つ - ミニバッチサイズ (batch_size) を見直す
→ 大きすぎるとメモリ負荷が大きい、また小さすぎると学習が進みにくい
→ 自分のGPU/CPU環境に合わせて調整
3-3. 学習スケジュールの工夫
- 学習率を途中で変化させる (Learning Rate Scheduler)
→ 途中から学習率を下げると、より微妙な調整が可能 - 早期終了 (Early Stopping)
→ バリデーションセットの精度が一定以上改善しなくなったら学習を打ち切り、過学習を防ぐ
ステップ4:モデル評価と推論
4-1. バリデーション・テストデータでの評価
- 学習中は、バリデーションセット で損失や精度を確認し、過学習や学習の停滞が起きていないかチェックします。
- 最終的なテストデータ(全く学習に使っていないデータ)でモデルの精度を計測しましょう。
4-2. 推論の流れ
- 学習が完了したら、前回(8章, 9章)と同様に推論用のパイプラインを組みます。
- Data Augmentationは通常、学習時のみに適用して、推論時には適用しません(必要に応じてリサイズや正規化など最低限の処理は行う)。
ステップ5:追加のポイントとまとめ
- Data Augmentationの効果
- 単純な左右反転だけでも2~3%精度が上がる報告がある一方、CutoutやRandomGridShuffleのように複雑な手法を組み合わせるとさらに大きな精度向上が期待できます。
- パラメータのバランス
- 極端なオーグメンテーション(画像が崩れすぎるなど)は、かえって学習を妨げる場合もあるため注意が必要です。試行錯誤して、最適な組み合わせや確率を探ります。
- 転移学習 × Data Augmentation
- 事前学習済みモデルは多様な画像をすでに学習しているため、適度なオーグメンテーションを加えるだけでも効果が出やすいです。
- 最後に
- 本シリーズの流れを通じて、Python初心者でも、データの扱い → モデル作成 → 転移学習 → データオーグメンテーション という一連の実装フローを学ぶことができました。
- 様々な処理を組み合わせて試行錯誤することが大事ですが、必ず前進・成長していけると信じて取り組んでみてください。
チェックテスト
今回の内容をしっかり理解できたか、下記のクイズで試してみましょう。
- Data Augmentation を実施する主な目的は何でしょうか?
- A. 学習用の画像データを擬似的に増やし、汎化性能を上げるため
- B. 画像のサイズを縮小して処理を速くするため
- C. クラスラベルを自動付与するため
- Albumentations の
RandomGridShuffle(grid=(3,3))
を使うとどのようなことが行われますか?- A. 画像を 3×3 のマスに分割し、マスごとの位置をシャッフルする
- B. 画像のピクセルを 3 倍に拡大する
- C. ラベルを 3 つに増やす
- カットアウト(Cutout) とはどのような手法でしょうか?
- A. 学習画像を強制的に白黒にする
- B. 画像の一部を矩形領域でくり抜き、塗りつぶす
- C. 画像を左右に繰り返し配置する
回答
- → A
- → A
- → B
となります。自信をもって回答できればOKです。もし間違えてしまっても、理解を深めるチャンスだと考えて復習してみてください。
まとめ
- 転移学習モデルの精度向上にはData Augmentationが効果的です。
- オーグメンテーションの組み合わせは無数にあり、試行錯誤が大切です。
- 最終的なテストデータできちんと評価し、過学習を防ぐためのチューニングも合わせて行いましょう。
本シリーズ(全10回)を通して、初心者でも画像データを扱った欠陥検知モデルの大まかな流れを体験できたかと思います。まだまだ奥は深いですが、必ず前進・成長していけると信じて、ぜひ色々な手法を取り入れてみてください。
以上で全10回の内容は完了です。ここまで学んだことをベースに、ご自身のプロジェクトや学習したい課題へ応用してみることをおすすめします。
何か追加で知りたいことや、もう少し詳しく聞きたいポイントがありましたら、ぜひ教えてください。
コメント