ファインチューニングによる画像分類の実験

2025年5月31日土曜日

Google Colab Keras TensorFlow 画像分類 転移学習

X f B! P L
ファインチューニングによる画像分類の実験 アイキャッチ画像

はじめに

転移学習の一種であるファインチューニングを行ってみました。限られたデータでも、事前学習済みモデルを活かすことで、精度よく画像分類が行えます。

転移学習とファインチューニングの違い

転移学習:

  • すでに学習済みのモデルの知識(重み)を活かして、新しいデータに対応させる手法全般
  • 学習済みモデルの重みを活用
  • 必ずしも全層を再学習するとは限らない

ファインチューニング:

  • 転移学習の一部で、学習済みモデルの一部または全部の層の重みを微調整(再学習)すること
  • 通常、学習済みのモデル(例:VGG16, ResNet等)を読み込み
  • 一部の層を凍結(trainable = False)、一部は再学習する

ポイント: 学習済みの重みを活かして一部層を再調整する。

学習の準備

Google Driveのマウント

学習用のデータを読み込むために、Google Driveをマウントします。

from google.colab import drive
drive.mount('/content/drive')

ベースモデルの作成(MNISTで事前学習)

まずはKerasのMNISTデータセットで、シンプルなベースモデルを作成・学習します。

import tensorflow as tf
from tensorflow import keras

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

# モデル構築
base_model = keras.Sequential([
    keras.layers.Input(shape=(28, 28, 1)),
    keras.layers.Conv2D(32, 3, activation='relu'),  # layer 0
    keras.layers.MaxPooling2D(),                    # layer 1
    keras.layers.Flatten(),                         # layer 2
    keras.layers.Dense(128, activation='relu'),     # layer 3
    keras.layers.Dropout(0.2),                      # layer 4
    keras.layers.Dense(10, activation='softmax')    # layer 5
])

base_model.compile(optimizer='adam',
                   loss='sparse_categorical_crossentropy',
                   metrics=['accuracy'])

# 事前学習
base_model.fit(x_train, y_train, epochs=5)

# モデル保存
base_model.save('my_mnist_model.keras')

ファインチューニング

from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# モデル読み込み
model = load_model('my_mnist_model.keras')

# 一部の層を凍結(例:畳み込み層)
for layer in model.layers[:-2]:
    layer.trainable = False

# 再コンパイル(凍結後は必要)
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# trainable 状態の確認
for i, layer in enumerate(model.layers):
    print(f"{i:2d}: {layer.name:30s} trainable = {layer.trainable}")

# データ準備(白黒反転など)
datagen = ImageDataGenerator(
    rescale=1./255,
    preprocessing_function=lambda x: 1.0 - x
)
train_generator = datagen.flow_from_directory(
    '/content/drive/MyDrive/Colab/digits',
    target_size=(28, 28),
    color_mode='grayscale',
    batch_size=32,
    class_mode='sparse'
)

# ファインチューニング(凍結していない層だけ訓練される)
model.fit(train_generator, epochs=5)

ポイント:

for layer in model.layers[:-2]:
    layer.trainable = False

最後の2層を除いた層すべてを選ぶスライスです。今回なら layer0 ~ layer3 が対象になります。

つまり「畳み込み層」「プーリング層」「Flatten」「中間のDense」などの層の重みが訓練中に更新されなくなります。

転移学習・ファインチューニングの目的:

  • すでに学習した「汎用的な特徴抽出器(Conv層など)」はそのまま使いたい
  • 新しいデータセットに合わせて、分類部分(出力層やその直前)だけを再学習したい

→ だから「特徴抽出部分は凍結し、出力層だけ trainable にする」。

実行時ログ(抜粋)

 0: conv2d_1                       trainable = False
 1: max_pooling2d_1                trainable = False
 2: flatten_1                      trainable = False
 3: dense_2                        trainable = False
 4: dropout_1                      trainable = True
 5: dense_3                        trainable = True

予測

from tensorflow.keras.preprocessing import image
import numpy as np

img_path = '/content/drive/MyDrive/Colab/handwritten_digit.png'
img = image.load_img(img_path, target_size=(28, 28), color_mode='grayscale')
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0) / 255.0
img_array = 1.0 - img_array  # ←★ 追加:白黒反転

prediction = model.predict(img_array)
print('予測ラベル:', np.argmax(prediction))

実行結果は以下です:

1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 82ms/step
予測ラベル: 4

予測の結果、「4」と書かれた画像が「4」と認識されました。

少ない学習で効率的にモデルを構築することができた。

まとめ

  • 転移学習は既存モデルを再利用できる強力な手法です
  • ファインチューニングにより新しいデータにも対応可能です
  • 層を凍結することで、汎用的な特徴を活かしながら効率的に学習できます

このブログを検索

自己紹介

はじめまして、機械学習を独学中のSHOU TAKEと申します。本ブログでは、Python・Keras・Google Colabを活用した画像分類やニューラルネットワークの実験記事を中心に発信しています。初学者の方にも分かりやすく、学んだことをそのまま実験形式でまとめるスタイルです。これまで取り組んだテーマには、学習率やOptimizerの比較、Batch Sizeの検証、事前学習の活用などがあります。ご質問やご感想は、お問い合わせフォームからお気軽にどうぞ。

お問い合わせフォーム

名前

メール *

メッセージ *

プライバシーポリシー

QooQ