転移学習で少量データから画像分類器を作る - Fine-tuning 実践ガイド
転移学習とは - 少量データで高精度モデルを構築する戦略
転移学習 (Transfer Learning) は、大規模データセットで事前訓練されたモデルの知識を、少量のデータしかない新しいタスクに活用する手法です。ImageNet の 1400 万枚で訓練された特徴抽出器を、数百枚のデータしかない独自の分類タスクに転用することで、ゼロから訓練するよりも遥かに高い精度を短時間で達成できます。
なぜ転移学習が有効なのか:
CNN の浅い層は汎用的な特徴 (エッジ、テクスチャ、色のパターン) を学習し、深い層はタスク固有の特徴を学習します。浅い層の特徴は多くの画像認識タスクで共通して有用なため、事前訓練済みモデルの浅い層をそのまま再利用し、深い層のみを新しいタスクに適応させることで効率的な学習が可能です。
転移学習の効果:
- 訓練データが 100-1000 枚程度でも実用的な精度を達成可能
- 訓練時間がゼロからの学習と比較して 1/10-1/100 に短縮
- GPU リソースが限られた環境でも高性能モデルを構築可能
- 過学習のリスクが大幅に低減される
事前訓練モデルの選択肢:
PyTorch の torchvision.models や timm ライブラリから、ResNet、EfficientNet、Vision Transformer (ViT) など多数のモデルが利用可能です。ImageNet-1K (1000 クラス) や ImageNet-21K (21000 クラス) で訓練されたモデルが一般的です。
ファインチューニングの基本手順 - PyTorch 実装
ファインチューニング (Fine-tuning) は、事前訓練済みモデルの重みを初期値として、新しいデータセットで追加訓練を行う手法です。最終層 (分類ヘッド) を新しいタスクのクラス数に合わせて置き換え、全体または一部の層を訓練します。
実装手順:
1. 事前訓練済みモデルをロード: model = timm.create_model('efficientnet_b0', pretrained=True, num_classes=10) で最終層が自動的に置き換わります。2. データローダーを準備: 訓練データに適切な前処理 (リサイズ、正規化) と拡張を適用します。3. 学習率を設定: 事前訓練済み層には小さな学習率 (1e-4 程度)、新しい層には大きな学習率 (1e-3 程度) を設定する差分学習率が効果的です。4. 訓練ループを実行します。
差分学習率 (Discriminative Learning Rates):
モデルの各層に異なる学習率を設定する手法です。浅い層は汎用的な特徴を既に学習しているため小さな学習率で微調整し、深い層はタスク固有の適応が必要なため大きな学習率で訓練します。PyTorch では optimizer = optim.Adam([{'params': model.features.parameters(), 'lr': 1e-4}, {'params': model.classifier.parameters(), 'lr': 1e-3}]) で設定します。
段階的解凍 (Gradual Unfreezing):
最初は最終層のみを訓練し、徐々に深い層から浅い層へと訓練対象を拡大する手法です。ULMFiT で提案され、過学習を防ぎながら効果的にモデルを適応させます。各段階で数エポック訓練し、安定したら次の層を解凍します。
特徴抽出器としての利用 - 最終層のみ訓練する手法
特徴抽出 (Feature Extraction) は、事前訓練済みモデルの重みを完全に固定し、最終の分類層のみを新しいタスク用に訓練する手法です。ファインチューニングよりも計算コストが低く、データが極めて少ない場合 (50-200 枚程度) に特に有効です。
実装方法:
モデルの全パラメータを凍結し、最終層のみを訓練可能にします。for param in model.parameters(): param.requires_grad = False で全層を凍結した後、model.fc = nn.Linear(in_features, num_classes) で最終層を置き換えます。新しい層のパラメータのみが勾配計算の対象となります。
特徴ベクトルの抽出と SVM/kNN:
CNN の中間層の出力を特徴ベクトルとして抽出し、SVM や k-NN などの古典的な分類器で分類する方法もあります。最終プーリング層の出力 (例: ResNet-50 なら 2048 次元) を特徴量として使用します。scikit-learn の SVM と組み合わせることで、GPU なしでも高精度な分類が可能です。
どちらを選ぶべきか:
- データが 50-200 枚: 特徴抽出が安全。過学習リスクが低い
- データが 200-1000 枚: ファインチューニングが効果的。差分学習率を使用
- データが 1000 枚以上: フルファインチューニングで最高精度を追求
- ドメインが大きく異なる場合 (医療画像など): より多くの層を訓練する必要がある
モデルアーキテクチャの選択 - ResNet, EfficientNet, ViT
転移学習に使用するベースモデルの選択は、精度、推論速度、モデルサイズのトレードオフを考慮して決定します。2025 年時点での主要な選択肢を比較します。
ResNet (Residual Network):
2015 年に提案された残差接続を持つ CNN で、転移学習の定番モデルです。ResNet-50 (2560 万パラメータ) が最も広く使用されています。構造がシンプルで理解しやすく、多くのフレームワークで最適化されています。ImageNet Top-1 精度は 76-80% (モデルサイズによる) です。
EfficientNet:
2019 年に提案された、幅・深さ・解像度を統合的にスケーリングするモデルです。EfficientNet-B0 (540 万パラメータ) から B7 (6600 万パラメータ) まで、精度と計算コストのバランスが優れています。同じ精度を達成するのに ResNet の 1/5-1/10 の計算量で済みます。転移学習での性能も高く、少量データでの精度が特に優れています。
Vision Transformer (ViT):
2020 年に提案された、Transformer アーキテクチャを画像認識に適用したモデルです。画像をパッチに分割し、自己注意機構で処理します。大規模データ (ImageNet-21K) での事前訓練が特に効果的で、CNN を上回る精度を達成します。ViT-Base (8600 万パラメータ) が転移学習で広く使用されています。
ConvNeXt:
2022 年に提案された、Transformer の設計原則を CNN に取り入れたモデルです。ViT と同等の精度を CNN アーキテクチャで達成し、推論速度が ViT より高速です。転移学習での安定性も高く、最新の選択肢として注目されています。
ドメイン適応と実践的なテクニック
転移学習の効果は、事前訓練データと対象タスクのドメイン (領域) の類似度に依存します。ドメインが大きく異なる場合の対処法と、実践的なテクニックを解説します。
ドメインギャップの問題:
ImageNet (自然画像) で訓練されたモデルを医療画像や衛星画像に適用する場合、画像の特性が大きく異なるためそのままでは性能が低下します。医療画像はグレースケールが多く、テクスチャパターンが自然画像と異なります。この場合、より多くの層を訓練対象にするか、ドメイン固有のデータで事前訓練されたモデルを使用します。
ドメイン固有の事前訓練モデル:
- 医療画像: CheXNet (胸部 X 線)、BiomedCLIP (生物医学画像全般)
- 衛星画像: SatMAE、SSL4EO (リモートセンシング)
- 病理画像: PathDino、UNI (組織病理学)
学習率スケジューリング:
コサインアニーリング (Cosine Annealing) やウォームアップ付き学習率スケジュールが転移学習で効果的です。最初の数エポックは学習率を徐々に上げ (ウォームアップ)、その後コサイン関数に従って減衰させます。急激な学習率変化による事前訓練済み重みの破壊を防ぎます。
データ拡張との組み合わせ:
少量データでの転移学習では、データ拡張が特に重要です。RandAugment や CutMix を組み合わせることで、100 枚程度のデータでも実用的な精度を達成できます。ただし拡張が強すぎると事前訓練済みの特徴が活かせなくなるため、適度な強度設定が必要です。
実践プロジェクト - 100 枚のデータで画像分類器を構築
実際に 100 枚程度の少量データから画像分類器を構築する手順を、コード例とともに解説します。犬と猫の 2 クラス分類を例に、転移学習の全工程を実践します。
データ準備:
各クラス 50 枚、合計 100 枚の画像を用意します。訓練:検証 = 8:2 に分割し、訓練 80 枚、検証 20 枚とします。ディレクトリ構造は data/train/cat/, data/train/dog/, data/val/cat/, data/val/dog/ の形式にします。
モデル構築:
model = timm.create_model('efficientnet_b0', pretrained=True, num_classes=2) で EfficientNet-B0 をベースにした 2 クラス分類器を構築します。最終層は自動的に 2 出力に置き換わります。
訓練設定:
オプティマイザは AdamW、学習率は 1e-4 (事前訓練層) と 1e-3 (最終層)、エポック数は 20-30、バッチサイズは 16 が目安です。データ拡張は水平反転、回転 (±15 度)、色変換を適用します。学習率スケジューラはコサインアニーリングを使用します。
期待される結果:
100 枚のデータでも、転移学習により検証精度 90-95% を達成できることが多いです。ゼロから訓練した場合は 60-70% 程度にとどまるため、転移学習の効果は明確です。さらにデータ拡張を強化し、TTA を適用することで 95% 以上の精度も狙えます。
よくある問題と対処:
- 過学習: 訓練精度は高いが検証精度が低い場合、学習率を下げるか正則化を強化
- 学習が進まない: 学習率が低すぎる可能性。段階的に上げて確認
- 特定クラスの精度が低い: データの偏りを確認。少ないクラスのデータ拡張を強化