🔄 1. データ拡張とは?
1-1. データ拡張の定義
データ拡張(Data Augmentation)は、既存の訓練データに変換を加えて、新しい訓練データを人工的に生成する技術です。
📸 写真の例え
1枚の猫の写真から、様々なバリエーションを作ります:
🐱 元の写真
🐱↔️ 左右反転した写真
🐱↩️ 少し回転した写真
🐱🔍 少しズームした写真
🐱☀️ 明るさを変えた写真
→ 1枚の写真が5枚以上の訓練データに!
1-2. なぜデータ拡張が必要?
✅ データ拡張のメリット
- 過学習の防止:多様なデータで汎化性能が向上
- データ不足の解消:少ないデータでも効果的な学習が可能
- ロバスト性の向上:様々な条件の画像に対応できる
- 位置不変性の強化:物体がどこにあっても認識できる
1-3. データ拡張の効果
【データ拡張の効果例】
CIFAR-10での実験結果:
データ拡張なし:
訓練精度: 95%
テスト精度: 78% ← 過学習している
データ拡張あり:
訓練精度: 88%
テスト精度: 85% ← 汎化性能が向上!
→ 訓練精度は下がるが、テスト精度が上がる
(これが理想的な状態)
🎨 2. 画像拡張の種類
2-1. 幾何学的変換
【幾何学的変換の種類】
■ 水平反転(Horizontal Flip)
┌─────────┐ ┌─────────┐
│ 🐱 │ → │ 🐱 │
│ → │ │ ← │
└─────────┘ └─────────┘
左右を入れ替える(最も一般的)
■ 回転(Rotation)
┌─────────┐ ┌─────────┐
│ 🐱 │ → │ 🐱 │
│ │ │ ↗ │
└─────────┘ └─────────┘
指定角度の範囲でランダムに回転
■ ズーム(Zoom)
┌─────────┐ ┌───────┐
│ 🐱 │ → │ 🐱 │
│ │ │ │
└─────────┘ └───────┘
拡大または縮小
■ シフト(Shift)
┌─────────┐ ┌─────────┐
│ 🐱 │ → │ │
│ │ │ 🐱 │
└─────────┘ └─────────┘
上下左右に移動
2-2. 色調変換
| 変換 |
説明 |
効果 |
| 明るさ変更 |
画像全体を明るく/暗くする |
照明条件の変化に対応 |
| コントラスト変更 |
明暗の差を強く/弱くする |
様々な撮影条件に対応 |
| 彩度変更 |
色の鮮やかさを変える |
色褪せた画像にも対応 |
| 色相変更 |
色味を変える |
ホワイトバランスの変化に対応 |
💻 3. ImageDataGeneratorの使い方
3-1. 基本的な使い方
📝 ImageDataGeneratorのパラメータ
- rotation_range:回転角度の範囲(度)
- width_shift_range:水平シフトの範囲(割合)
- height_shift_range:垂直シフトの範囲(割合)
- horizontal_flip:水平反転するかどうか
- zoom_range:ズームの範囲
- fill_mode:変換後の空白を埋める方法
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# データ拡張の設定
datagen = ImageDataGenerator(
rotation_range=15, # ±15度の回転
width_shift_range=0.1, # 横方向に10%シフト
height_shift_range=0.1, # 縦方向に10%シフト
horizontal_flip=True, # 左右反転
zoom_range=0.1, # 10%ズーム
fill_mode=’nearest’ # 空白は最近傍で埋める
)
# 訓練データに適用
datagen.fit(X_train)
3-2. モデル学習への適用
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout, BatchNormalization
# データ準備
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train.astype(‘float32’) / 255.0
X_test = X_test.astype(‘float32′) / 255.0
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# データ拡張の設定
datagen = ImageDataGenerator(
rotation_range=15,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True,
zoom_range=0.1
)
# モデル構築(前回と同じ)
model = Sequential([
Conv2D(32, (3, 3), padding=’same’, activation=’relu’, input_shape=(32, 32, 3)),
BatchNormalization(),
Conv2D(32, (3, 3), padding=’same’, activation=’relu’),
BatchNormalization(),
MaxPooling2D((2, 2)),
Dropout(0.25),
Conv2D(64, (3, 3), padding=’same’, activation=’relu’),
BatchNormalization(),
Conv2D(64, (3, 3), padding=’same’, activation=’relu’),
BatchNormalization(),
MaxPooling2D((2, 2)),
Dropout(0.25),
Flatten(),
Dense(512, activation=’relu’),
Dropout(0.5),
Dense(10, activation=’softmax’)
])
model.compile(optimizer=’adam’, loss=’categorical_crossentropy’, metrics=[‘accuracy’])
# データ拡張を使った学習(fit_generatorではなくfitを使用)
history = model.fit(
datagen.flow(X_train, y_train, batch_size=64), # ★ ここがポイント
epochs=50,
validation_data=(X_test, y_test),
steps_per_epoch=len(X_train) // 64
)
⚠️ 注意点
- テストデータには拡張しない:テストは元のデータで評価
- 学習時間が増える:毎回異なる画像を生成するため
- steps_per_epoch:1エポックあたりのステップ数を指定
🆕 4. tf.keras.layersでの拡張(推奨)
4-1. レイヤーとしてのデータ拡張
TensorFlow 2.2以降では、データ拡張をモデルの一部として組み込むことができます。
この方法はGPUで高速に処理でき、より効率的です。
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
# データ拡張レイヤー
data_augmentation = Sequential([
layers.RandomFlip(“horizontal”), # 水平反転
layers.RandomRotation(0.1), # ±10%回転
layers.RandomZoom(0.1), # ±10%ズーム
layers.RandomTranslation(0.1, 0.1), # ±10%シフト
])
# モデルにデータ拡張を組み込む
model = Sequential([
# データ拡張(訓練時のみ適用される)
data_augmentation,
# 正規化
layers.Rescaling(1./255),
# CNNレイヤー
layers.Conv2D(32, (3, 3), padding=’same’, activation=’relu’),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
# … 以下続く
])
4-2. 完成コード(推奨方式)
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
# データ準備(正規化はモデル内で行う)
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train.astype(‘float32’) # 正規化はモデル内で
X_test = X_test.astype(‘float32′) / 255.0 # テストは先に正規化
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# データ拡張レイヤー
data_augmentation = Sequential([
layers.RandomFlip(“horizontal”),
layers.RandomRotation(0.1),
layers.RandomZoom(0.1),
], name=’data_augmentation’)
# モデル構築
model = Sequential([
# 入力
layers.Input(shape=(32, 32, 3)),
# データ拡張(訓練時のみ)
data_augmentation,
# 正規化
layers.Rescaling(1./255),
# Block 1
layers.Conv2D(32, (3, 3), padding=’same’, activation=’relu’),
layers.BatchNormalization(),
layers.Conv2D(32, (3, 3), padding=’same’, activation=’relu’),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.25),
# Block 2
layers.Conv2D(64, (3, 3), padding=’same’, activation=’relu’),
layers.BatchNormalization(),
layers.Conv2D(64, (3, 3), padding=’same’, activation=’relu’),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.25),
# Classifier
layers.Flatten(),
layers.Dense(512, activation=’relu’),
layers.Dropout(0.5),
layers.Dense(10, activation=’softmax’)
])
model.compile(optimizer=’adam’, loss=’categorical_crossentropy’, metrics=[‘accuracy’])
# コールバック
callbacks = [
EarlyStopping(monitor=’val_loss’, patience=10, restore_best_weights=True),
ReduceLROnPlateau(monitor=’val_loss’, factor=0.5, patience=5)
]
# 学習
history = model.fit(
X_train, y_train,
epochs=50,
batch_size=64,
validation_data=(X_test * 255, y_test), # テストも元のスケールで
callbacks=callbacks
)
# 評価
test_loss, test_acc = model.evaluate(X_test * 255, y_test)
print(f”\nテスト精度: {test_acc:.4f}”)
📝 STEP 19 のまとめ
✅ このステップで学んだこと
- データ拡張:既存データを変換して訓練データを増やす技術
- 幾何学的変換:回転、反転、ズーム、シフト
- 色調変換:明るさ、コントラスト、彩度の変更
- ImageDataGenerator:従来の方法(まだ広く使われている)
- tf.keras.layers:モデルに組み込む新しい方法(推奨)
- 注意点:タスクに適した拡張を選ぶ
💡 覚えておくべきコード
# 推奨方式(レイヤーとして)
data_augmentation = Sequential([
layers.RandomFlip(“horizontal”),
layers.RandomRotation(0.1),
layers.RandomZoom(0.1),
])
# 従来方式(ImageDataGenerator)
datagen = ImageDataGenerator(
rotation_range=15,
horizontal_flip=True,
zoom_range=0.1
)
🚀 次のステップへ
データ拡張を習得したので、次のSTEP 20では転移学習(Transfer Learning)を学びます。
ImageNetで学習済みのモデルを活用して、少ないデータでも高精度を実現しましょう!