STEP 19:データ拡張(Data Augmentation)

🔄 STEP 19: データ拡張(Data Augmentation)

限られたデータから多様な訓練データを生成して精度向上!

📋 このステップで学ぶこと

  • データ拡張とは何か?なぜ必要か?
  • 画像の拡張手法(回転、反転、ズームなど)
  • ImageDataGeneratorの使い方
  • tf.keras.layers での拡張(最新手法)
  • データ拡張によるCIFAR-10の精度向上
  • データ拡張の注意点

🔄 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}”)

⚠️ 5. データ拡張の注意点

5-1. 適切な拡張を選ぶ

⚠️ 不適切なデータ拡張の例
  • 数字認識で垂直反転:6と9が区別できなくなる
  • 顔認識で大きな回転:顔は通常上を向いている
  • 文字認識で水平反転:bとdが区別できなくなる

5-2. 適切な拡張の選び方

タスク 推奨する拡張 避けるべき拡張
一般物体認識 回転、反転、ズーム、シフト 特になし
数字認識 小さな回転、シフト、ズーム 垂直反転、大きな回転
医療画像 回転、反転、明るさ 過度な色変更
衛星画像 回転(360度)、反転 過度なズーム

📝 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で学習済みのモデルを活用して、少ないデータでも高精度を実現しましょう!

📝 練習問題

問題1 やさしい

データ拡張の目的

データ拡張の主な目的として、正しくないものを選んでください。

  • A. 過学習の防止
  • B. 訓練データの増加
  • C. テストデータの精度向上を直接操作する
  • D. モデルのロバスト性向上
正解:C

データ拡張はテストデータには適用しません。訓練データを拡張することで、結果的にテスト精度が向上しますが、直接テストデータを操作するわけではありません。

問題2 やさしい

horizontal_flipの意味

ImageDataGeneratorのhorizontal_flip=Trueは何を行いますか?

  • A. 上下反転
  • B. 左右反転
  • C. 90度回転
  • D. ランダムな角度で回転
正解:B

horizontal_flip(水平反転)は左右を入れ替えます。垂直反転(上下反転)はvertical_flipです。

問題3 ふつう

不適切なデータ拡張

手書き数字(0-9)の認識タスクで、避けるべきデータ拡張はどれですか?

  • A. 小さな回転(±15度)
  • B. 水平シフト
  • C. 垂直反転
  • D. 小さなズーム
正解:C

垂直反転すると、6と9が区別できなくなります。数字認識では垂直反転は避けるべきです。

問題4 むずかしい

データ拡張の適用タイミング

tf.keras.layersでデータ拡張を定義した場合、いつ拡張が適用されますか?

  • A. 訓練時のみ
  • B. 推論時のみ
  • C. 訓練時と推論時の両方
  • D. モデルのコンパイル時
正解:A

RandomFlip、RandomRotationなどのデータ拡張レイヤーは、訓練時(training=True)のみ適用され、推論時(model.predict())は何も変換しません。

📝

学習メモ

ディープラーニング基礎 - Step 19

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE