Kerasで画像分類|ファインチューニングによる高精度モデルの作り方

2025年5月31日土曜日

Fine-tuning Google Colab Keras ファインチューニング 画像分類 転移学習

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

はじめに|ファインチューニングで高精度な画像分類を目指す

画像認識や機械学習の分野では、限られたデータセットで高精度な分類を実現するために「転移学習」や「ファインチューニング」といった手法が非常に効果的です。 本記事では、KerasGoogle Colabを用いて、事前学習済みモデルをファインチューニングする方法をステップバイステップで解説します。

手書き数字認識のような小規模な画像分類タスクでも、ファインチューニングを活用すれば短時間かつ高精度なモデル構築が可能です。

転移学習とファインチューニングの違いとは?|画像分類モデルの再利用戦略

転移学習(Transfer Learning)は、すでに学習済みのモデルを他のタスクに応用するための技術です。

  • 過去に大規模データセットで学習された重みを活用
  • 新しい問題に適応するために、モデルの一部または全部を再利用
  • 全層を再学習するとは限らない

ファインチューニング(Fine-tuning)は、転移学習の一手法であり、以下のような特徴があります。

  • 学習済みモデルの一部の層の重みを「再調整」
  • 一部の層は「凍結(学習させない)」し、一部は「再学習」させる
  • より高度で微細な調整が可能

要点:ファインチューニングでは、事前学習済みモデルの知識を活かしつつ、新しいデータに合わせた調整を行います。

Kerasでの学習準備|Google Driveのマウントとベースモデルの構築

Google Driveのマウント

学習用画像データはGoogle Drive上に保存しておくと便利です。以下のコードでColabからDriveにアクセスできるようになります。

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

MNISTを使って事前学習モデルを構築

まずは、KerasのMNISTデータセットを使って、畳み込みニューラルネットワーク(CNN)のベースモデルを作成・学習します。

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')

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'])

ポイント: `model.layers[:-2]` により、出力層以外を凍結しています。

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

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

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

画像データはImageDataGeneratorで読み込み、白黒反転などの前処理を追加しています。

# データ準備(白黒反転など)
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)

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

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

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

ファインチューニングの学習ログ|層のtrainable設定と結果

モデルの各層の学習可能(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」と書かれた画像を正しく分類できました。ファインチューニングの有効性が示されています。

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

まとめ|転移学習とファインチューニングで効率よく画像分類

  • 転移学習は、既存の学習済みモデルを活用できるため、少ないデータでも高い精度を出せる
  • ファインチューニングにより、新しいデータに最適化されたモデル構築が可能
  • 層の凍結を活用することで、学習時間と計算リソースを削減しながら高精度な分類を実現

この記事を参考に、あなたのプロジェクトでもファインチューニングを取り入れて、よりスマートな画像分類モデルを構築してみてください!

このブログを検索

このブログのまとめページ

自己紹介

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

お問い合わせフォーム

名前

メール *

メッセージ *

プライバシーポリシー

QooQ