概要
Keras公式サイトの
をやってみる。
少ないサンプルからディープラーニングで優位なモデルを作る。
ステップとしては、
- スクラッチで作る。
- bottleneck featureで学習済みモデル使う
- Fine tuningを使う
- スクラッチで作る。
- bottleneck featureで学習済みモデル使う
- Fine tuningを使う
画像の用意
まず、クラス分けする画像の用意をする。今回は猫と犬のクラス分け。
kaggleからcats and dogsのデータをダウンロードする。このデータセットは25000枚あるが、今回は少ないデータセットでのモデル構築が目的なので、トレーニングデータとしてcats, dogs 1000枚ごと、テストデータとして400枚ごと取り出してフォルダに分ける。
- cats_and_dogs_1000
- train
- cats (1000枚)
- dogs (1000枚)
- validation
- cats (400枚)
- dogs (400枚)
切り分けたコマンド
<code>
ll dog* | head -1000 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/train/dogs/
ll cat* | head -1000 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/train/cats/
ll dog* | tail -400 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/validation/dogs/
ll cat* | tail -400 | awk '{print $9}' | xargs -i cp -p {} ../../cats_and_dogs_1000/validation/cats/
<code>
前処理とデータ増加
画像を少し加工しながらデータを増やす。これには過学習を防いでモデルを、一般化する効果があるらしい。
Kerasでは keras.preprocessing.image.ImageDataGenerator class を使ってこれを実現できる。
必要なライブラリのインポート
<code>
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
<code>
画像増やす。
<code>
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
<code>
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
スクラッチの畳み込み演算トレーニング
<code>
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
<code>
正解率は以下のようになった。
Epoch 50/50
125/125 [==============================] - 13s - loss: 0.4843 - acc: 0.7900 - val_loss: 0.4923 - val_acc: 0.7950
Bottleneck feature
学習済みモデルの最終層を削除して、そのモデルを特徴抽出として使うことをbottleneck featureと呼ぶらしい
ここはよく理解できなかったのでスキップ
<code>
正解率は以下のようになった。
Epoch 50/50 125/125 [==============================] - 13s - loss: 0.4843 - acc: 0.7900 - val_loss: 0.4923 - val_acc: 0.7950
Bottleneck feature
学習済みモデルの最終層を削除して、そのモデルを特徴抽出として使うことをbottleneck featureと呼ぶらしい
ここはよく理解できなかったのでスキップ
ここはよく理解できなかったのでスキップ
Fine Tuning
最後に、FineTuningで予測して見る。
ステップとして
- VGG16モデルを読み出して、パラメータをロードする。
- 前で作ったモデルをトップに積んで、パラメータをロードする。
- VGG16の層をfreezeする。
- モデルのコンパイル
- トレーニング
必要なKerasのクラスロード
<code>
from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Model
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
<code>
使用する変数の定義
<code>
# path to the model weights files.
weights_path = '../keras/examples/vgg16_weights.h5'
top_model_weights_path = 'bottleneck_fc_model.h5'
# dimensions of our images.
img_width, img_height = 150, 150
train_data_dir = 'images/cats_and_dogs_1000/train'
validation_data_dir = 'images/cats_and_dogs_1000/validation'
nb_train_samples = 2000
nb_validation_samples = 800
epochs = 50
batch_size = 16
<code>
VGG16モデルをロードして、bottleneck featureで作成したモデルをトップに積む。
<code>
# build the VGG16 network
base_model = applications.VGG16(weights='imagenet', include_top= False, input_shape=(150, 150, 3))
print('Model loaded.')
# build a classifier model to put on top of the convolutional model
top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(1, activation='sigmoid'))
# note that it is necessary to start with a fully-trained
# classifier, including the top classifier,
# in order to successfully do fine-tuning
top_model.load_weights(top_model_weights_path)
# add the model on top of the convolutional base
# model.add(top_model)
model = Model(input= base_model.input, output= top_model(base_model.output))
<code>
最初の25レイヤーはパラメータをアップデートしないようにする。
<code>
# set the first 25 layers (up to the last conv block)
# to non-trainable (weights will not be updated)
for layer in model.layers[:25]:
layer.trainable = False
<code>
モデルのコンパイル
<code>
# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='binary_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
<code>
画像データの用意
<code>
# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary')
<code>
モデルの学習
<code>
# fine-tune the model
model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
epochs=epochs,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)
<code>
結果は以下のようになり、精度が上がったことが確認できた。
Epoch 50/50 125/125 [==============================] - 151s - loss: 0.5791 - acc: 0.9250 - val_loss: 1.1987 - val_acc: 0.8813