はじめに
転移学習の一種であるファインチューニングを行ってみました。限られたデータでも、事前学習済みモデルを活かすことで、精度よく画像分類が行えます。
転移学習とファインチューニングの違い
転移学習:
- すでに学習済みのモデルの知識(重み)を活かして、新しいデータに対応させる手法全般
- 学習済みモデルの重みを活用
- 必ずしも全層を再学習するとは限らない
ファインチューニング:
- 転移学習の一部で、学習済みモデルの一部または全部の層の重みを微調整(再学習)すること
- 通常、学習済みのモデル(例: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」と認識されました。
少ない学習で効率的にモデルを構築することができた。
まとめ
- 転移学習は既存モデルを再利用できる強力な手法です
- ファインチューニングにより新しいデータにも対応可能です
- 層を凍結することで、汎用的な特徴を活かしながら効率的に学習できます
0 件のコメント:
コメントを投稿