🐱🐶 STEP 27: ガイド付きプロジェクト
犬と猫の画像分類 – 転移学習とデータ拡張で高精度を目指す!
📋 プロジェクト概要
- 目標:犬と猫の画像を95%以上の精度で分類
- 使用技術:CNN、転移学習(MobileNetV2)、データ拡張
- データセット:Cats vs Dogs(Kaggle)
- 所要時間:約90分
- 環境:Google Colab(GPU推奨)
🎯 プロジェクト紹介
🏆 チャレンジ
犬と猫の画像を自動で分類するディープラーニングモデルを構築します。
このプロジェクトでは、これまで学んだ全ての技術を総動員します!
- ✅ CNN(畳み込みニューラルネットワーク)
- ✅ 転移学習(MobileNetV2)
- ✅ データ拡張
- ✅ コールバック(Early Stopping、ReduceLROnPlateau)
- ✅ モデル評価と可視化
プロジェクトの流れ
📌 5つのステップ
- 環境準備:データセットのダウンロードと前処理
- ベースラインモデル:シンプルなCNNで基準を作る
- データ拡張:訓練データを増強
- 転移学習:MobileNetV2で高精度を実現
- 評価と改善:結果の分析と改善
📦 STEP 1: 環境準備
1-1. Google Colabの設定
# GPUを有効化(ランタイム → ランタイムのタイプを変更 → GPU)
# GPUの確認
import tensorflow as tf
print(f”TensorFlow version: {tf.__version__}”)
print(f”GPU available: {tf.config.list_physical_devices(‘GPU’)}”)
1-2. データセットのダウンロード
import tensorflow as tf
from tensorflow.keras.utils import get_file
import os
import zipfile
# Cats vs Dogsデータセット(Microsoft提供のサブセット)
URL = “https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip”
path = get_file(“cats_and_dogs_filtered.zip”, origin=URL, extract=True)
PATH = os.path.join(os.path.dirname(path), “cats_and_dogs_filtered”)
# ディレクトリ構造の確認
train_dir = os.path.join(PATH, “train”)
validation_dir = os.path.join(PATH, “validation”)
train_cats = os.path.join(train_dir, “cats”)
train_dogs = os.path.join(train_dir, “dogs”)
val_cats = os.path.join(validation_dir, “cats”)
val_dogs = os.path.join(validation_dir, “dogs”)
print(f”訓練用 猫: {len(os.listdir(train_cats))}枚”)
print(f”訓練用 犬: {len(os.listdir(train_dogs))}枚”)
print(f”検証用 猫: {len(os.listdir(val_cats))}枚”)
print(f”検証用 犬: {len(os.listdir(val_dogs))}枚”)
実行結果:
訓練用 猫: 1000枚 訓練用 犬: 1000枚 検証用 猫: 500枚 検証用 犬: 500枚 合計: 訓練2000枚、検証1000枚
1-3. データの読み込み
from tensorflow.keras.preprocessing.image import ImageDataGenerator
IMG_SIZE = 150
BATCH_SIZE = 32
# データ読み込み(正規化のみ)
train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(IMG_SIZE, IMG_SIZE),
batch_size=BATCH_SIZE,
class_mode=’binary’
)
validation_generator = val_datagen.flow_from_directory(
validation_dir,
target_size=(IMG_SIZE, IMG_SIZE),
batch_size=BATCH_SIZE,
class_mode=’binary’
)
print(f”クラス: {train_generator.class_indices}”)
🏗️ STEP 2: ベースラインモデル
2-1. シンプルなCNN
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
# ベースラインモデル
baseline_model = Sequential([
Conv2D(32, (3, 3), activation=’relu’, input_shape=(IMG_SIZE, IMG_SIZE, 3)),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Flatten(),
Dense(512, activation=’relu’),
Dropout(0.5),
Dense(1, activation=’sigmoid’)
])
baseline_model.compile(
optimizer=’adam’,
loss=’binary_crossentropy’,
metrics=[‘accuracy’]
)
baseline_model.summary()
2-2. ベースラインの学習
from tensorflow.keras.callbacks import EarlyStopping
early_stop = EarlyStopping(monitor=’val_loss’, patience=5, restore_best_weights=True)
# 学習
baseline_history = baseline_model.fit(
train_generator,
epochs=30,
validation_data=validation_generator,
callbacks=[early_stop]
)
# 結果
val_loss, val_acc = baseline_model.evaluate(validation_generator)
print(f”\n📊 ベースライン検証精度: {val_acc:.4f}”)
実行結果:
Epoch 1/30 - accuracy: 0.5525 - val_accuracy: 0.6420 ... Epoch 15/30 - accuracy: 0.8950 - val_accuracy: 0.7240 📊 ベースライン検証精度: 0.7240 → 訓練は90%近いが、検証は72%...過学習している!
⚠️ 問題点
訓練精度と検証精度の差が大きい → 過学習
対策:データ拡張、転移学習を導入しよう!
🔄 STEP 3: データ拡張
3-1. データ拡張の設定
# データ拡張付きのImageDataGenerator
train_datagen_aug = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode=’nearest’
)
# 検証データは拡張しない
val_datagen = ImageDataGenerator(rescale=1./255)
train_generator_aug = train_datagen_aug.flow_from_directory(
train_dir,
target_size=(IMG_SIZE, IMG_SIZE),
batch_size=BATCH_SIZE,
class_mode=’binary’
)
3-2. 拡張データでの再学習
# 同じモデル構造で新規作成
aug_model = Sequential([
Conv2D(32, (3, 3), activation=’relu’, input_shape=(IMG_SIZE, IMG_SIZE, 3)),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation=’relu’),
MaxPooling2D((2, 2)),
Flatten(),
Dense(512, activation=’relu’),
Dropout(0.5),
Dense(1, activation=’sigmoid’)
])
aug_model.compile(optimizer=’adam’, loss=’binary_crossentropy’, metrics=[‘accuracy’])
# 学習
aug_history = aug_model.fit(
train_generator_aug,
epochs=50,
validation_data=validation_generator,
callbacks=[early_stop]
)
val_loss, val_acc = aug_model.evaluate(validation_generator)
print(f”\n📊 データ拡張後の検証精度: {val_acc:.4f}”)
実行結果:
📊 データ拡張後の検証精度: 0.7980 → 72% → 80%に改善!でもまだ物足りない...
🎓 STEP 4: 転移学習
4-1. MobileNetV2の読み込み
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.layers import GlobalAveragePooling2D
# 事前学習済みモデル
base_model = MobileNetV2(
weights=’imagenet’,
include_top=False,
input_shape=(IMG_SIZE, IMG_SIZE, 3)
)
# 重みを固定
base_model.trainable = False
# 転移学習モデル
transfer_model = Sequential([
base_model,
GlobalAveragePooling2D(),
Dense(256, activation=’relu’),
Dropout(0.5),
Dense(1, activation=’sigmoid’)
])
transfer_model.compile(
optimizer=’adam’,
loss=’binary_crossentropy’,
metrics=[‘accuracy’]
)
transfer_model.summary()
4-2. 特徴抽出(Phase 1)
# Phase 1: 分類層のみ学習
from tensorflow.keras.callbacks import ReduceLROnPlateau
callbacks = [
EarlyStopping(monitor=’val_loss’, patience=5, restore_best_weights=True),
ReduceLROnPlateau(monitor=’val_loss’, factor=0.5, patience=3)
]
transfer_history = transfer_model.fit(
train_generator_aug,
epochs=20,
validation_data=validation_generator,
callbacks=callbacks
)
val_loss, val_acc = transfer_model.evaluate(validation_generator)
print(f”\n📊 転移学習(Phase 1)検証精度: {val_acc:.4f}”)
実行結果:
📊 転移学習(Phase 1)検証精度: 0.9520 → 一気に95%超え!転移学習の威力!
4-3. ファインチューニング(Phase 2)
# Phase 2: ベースモデルの一部を解凍してファインチューニング
base_model.trainable = True
# 最後の50層だけ学習可能に
for layer in base_model.layers[:-50]:
layer.trainable = False
# 低い学習率で再コンパイル
from tensorflow.keras.optimizers import Adam
transfer_model.compile(
optimizer=Adam(learning_rate=1e-5),
loss=’binary_crossentropy’,
metrics=[‘accuracy’]
)
# ファインチューニング
finetune_history = transfer_model.fit(
train_generator_aug,
epochs=10,
validation_data=validation_generator,
callbacks=callbacks
)
val_loss, val_acc = transfer_model.evaluate(validation_generator)
print(f”\n📊 転移学習(Phase 2)検証精度: {val_acc:.4f}”)
実行結果:
📊 転移学習(Phase 2)検証精度: 0.9680 🎉 96.8%達成!目標の95%を大幅に超えました!
📊 STEP 5: 評価と可視化
5-1. 学習曲線の比較
import matplotlib.pyplot as plt
def plot_comparison(histories, labels):
“””複数の学習曲線を比較”””
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
for history, label in zip(histories, labels):
axes[0].plot(history.history[‘val_loss’], label=label)
axes[1].plot(history.history[‘val_accuracy’], label=label)
axes[0].set_title(‘検証損失の比較’)
axes[0].set_xlabel(‘エポック’)
axes[0].legend()
axes[1].set_title(‘検証精度の比較’)
axes[1].set_xlabel(‘エポック’)
axes[1].legend()
plt.tight_layout()
plt.show()
# 比較プロット
plot_comparison(
[baseline_history, aug_history, transfer_history],
[‘ベースライン’, ‘データ拡張’, ‘転移学習’]
)
5-2. 結果のまとめ
| モデル | 検証精度 | 改善率 |
|---|---|---|
| ベースラインCNN | 72.4% | – |
| +データ拡張 | 79.8% | +7.4% |
| +転移学習(Phase 1) | 95.2% | +15.4% |
| +ファインチューニング | 96.8% | +1.6% |
📝 プロジェクトまとめ
✅ 達成したこと
- 犬と猫の画像を96.8%の精度で分類
- ベースラインから24.4%の精度向上
- CNN、データ拡張、転移学習の実践的な活用
- 過学習への対処法の理解
💡 学んだポイント
- ベースライン重要:まずシンプルなモデルで基準を作る
- データ拡張の効果:少ないデータでも多様性を増やせる
- 転移学習の威力:事前学習済みモデルで大幅に精度向上
- 段階的なアプローチ:特徴抽出→ファインチューニング
🚀 次のステップへ
ガイド付きプロジェクトを完了しました!
次のSTEP 28では、独立プロジェクトとして自分でテーマを選んで取り組みます。
このプロジェクトで学んだテクニックを応用してみましょう!
✅ プロジェクトチェックリスト
- Google ColabでGPUを有効化した
- データセットをダウンロードして構造を確認した
- ベースラインCNNモデルを構築・学習した
- データ拡張を適用して再学習した
- MobileNetV2による転移学習を実装した
- ファインチューニングで精度を向上させた
- 学習曲線を可視化して比較した
- 目標精度(95%以上)を達成した
学習メモ
ディープラーニング基礎 - Step 27
📋 過去のメモ一覧
▼