tensorflowで学習済みモデルを使って転移学習をする実装をまとめておく。以下のようなコードになる。これはDenseNet121の学習済みモデルを使う場合。
from tensorflow.keras import datasets, layers, models, applications, optimizers
base_model = applications.DenseNet121(input_shape=(32, 32, 3),
include_top=False,
weights='imagenet')
(x_train, y_train), (x_test, y_test) = datasets.cifar10.load_data()
base_model.trainable = False
for layer in base_model.layers[-60:]:
layer.trainable = True
new_model = models.Sequential([
base_model,
layers.Flatten(),
layers.Dense(1024, activation='relu'),
layers.Dropout(0.1),
layers.Dense(512, activation='relu'),
layers.Dropout(0.2),
layers.Dense(512, activation='relu'),
layers.Dense(10, activation='softmax')
])
adam_low_rate = optimizers.Adam(learning_rate=0.001)
new_model.compile(optimizer = adam_low_rate,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
history_dense = new_model.fit(x_train, y_train, epochs=7, validation_data=(x_test, y_test), batch_size=128)
# Output
Epoch 1/7
391/391 [==============================] - 20s 33ms/step - loss: 1.5311 - accuracy: 0.4531 - val_loss: 1.3824 - val_accuracy: 0.5028
Epoch 2/7
391/391 [==============================] - 9s 24ms/step - loss: 1.3191 - accuracy: 0.5283 - val_loss: 1.3110 - val_accuracy: 0.5312
Epoch 3/7
391/391 [==============================] - 10s 25ms/step - loss: 1.2229 - accuracy: 0.5638 - val_loss: 1.2777 - val_accuracy: 0.5462
Epoch 4/7
391/391 [==============================] - 10s 26ms/step - loss: 1.1426 - accuracy: 0.5927 - val_loss: 1.2443 - val_accuracy: 0.5607
Epoch 5/7
391/391 [==============================] - 9s 23ms/step - loss: 1.0700 - accuracy: 0.6170 - val_loss: 1.2611 - val_accuracy: 0.5589
Epoch 6/7
391/391 [==============================] - 9s 24ms/step - loss: 1.0022 - accuracy: 0.6410 - val_loss: 1.2545 - val_accuracy: 0.5633
Epoch 7/7
391/391 [==============================] - 9s 24ms/step - loss: 0.9350 - accuracy: 0.6640 - val_loss: 1.2771 - val_accuracy: 0.5625
以下でベースとなる学習済みモデルを定義している。weights=’imagenet’でimagenetで事前学習したものという指定をしている。
base_model = applications.DenseNet121(input_shape=(32, 32, 3),
include_top=False,
weights='imagenet')
DenseNet121以外にもEfficientNetやVGGなどのモデルを以下のように書いて変えることができる。
# EfficientNetB0を使う場合
base_model = applications.EfficientNetB0(input_shape=(32, 32, 3),
include_top=False,
weights='imagenet')
# VGG16を使う場合
base_model = applications.VGG16(input_shape=(32, 32, 3),
include_top=False,
weights='imagenet')
次に、以下で学習用のデータを定義する。ここではCifar10を使う。Cifar100なども利用できる。
(x_train, y_train), (x_test, y_test) = datasets.cifar10.load_data()
以下でベースモデルのネットワークを再学習するかどうかを決める。Falseだと学習済みのままの重みが使われ、Trueにするとベースモデルのネットワークごと学習する。時間がかかるけどより精度が上がることも多いので比較するのも良い。
base_model.trainable = False
以下ではベースモデルの方で抽出した特徴量を分類するネットワークを定義している。1024などの値は64だったり別の値に変えることができる。Dropout層も入れることで精度が良くなる。最後のsoftmax層ではCifar10の場合だと10種類なので出力する次元数は10としてある。
new_model = models.Sequential([
base_model,
layers.Flatten(),
layers.Dense(1024, activation='relu'),
layers.Dropout(0.1),
layers.Dense(512, activation='relu'),
layers.Dropout(0.2),
layers.Dense(512, activation='relu'),
layers.Dense(10, activation='softmax')
])
最適化手法(optimizer)を以下で定義する。ここではAdamを定義している。学習率(learning_rate)は0.001。
adam_low_rate = optimizers.Adam(learning_rate=0.001)
以下で誤差関数を定義しており、ここでは’sparse_categorical_crossentropy’を選択。
new_model.compile(optimizer = adam_low_rate,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
最後に以下でモデルの学習を行う。epoch数は7、バッチサイズは128としている。
history_dense = new_model.fit(x_train, y_train, epochs=7, validation_data=(x_test, y_test), batch_size=128)