はじめに
[Tensorflow 1.4.0 : Release note]
tf.keras is now part of the core TensorFlow API.
とあるように ver 1.4.0よりtf.keras.XXX
でkeras
に容易にアクセスできるようになりました.私も重い腰を上げ,素のtensorflow
からkeras(tf.keras)
への乗り換えをはじめています.特にモデルが大きくなる場合には記述の見通しがよく,keras
の威力を実感しています.
ただ,表題の通り1点よくわからない状況に出くわしたのでここにまとめてみます(正確な情報をご存知の方がおられればご教授いただけると嬉しいです).
環境
- Ubuntu 16.04
- Python 3.5
- tensorflow 1.4.0
状況
vgg16のfine-tuningを試したかったので,以下のような暫定コードを書きました.block1-4は固定,block5とfc層だけ再学習するという前提の構成です.入力はダミーにしています.
if __name__ == "__main__":
# vgg16
input_tensor = k.layers.Input(shape=(224, 224, 3))
vgg16_model = k.applications.VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
# my fc_layer
my_model = k.models.Sequential([
k.layers.InputLayer(input_shape=vgg16_model.output_shape[1:]),
k.layers.Flatten(),
k.layers.Dense(1, activation='sigmoid')
])
# freeze block1-4
for layer in vgg16_model.layers[:15]:
layer.trainable = False
# build model
model = k.models.Sequential([vgg16_model, my_model])
model.summary()
model.compile(loss='binary_crossentropy',
optimizer=k.optimizers.SGD(lr=1e-4),
metrics=['acc'])
# training
batch_size = 32
dummy_x = np.zeros(shape=(batch_size,224,224,3))
dummy_y = np.zeros(shape=(batch_size,1))
model.fit(x=dummy_x,
y=dummy_y,
batch_size=batch_size)
これを走らせるとモデル自体の構築は完了しますが学習が失敗します.tensorflow
のソースコードを少し見る限りk.applications.VGG16
が提供する情報が足らず,学習データとのバインドに失敗しているようにみえます(具体的にはvgg16_model._feed_input_names
の情報が空).
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
vgg16 (Model) (None, 7, 7, 512) 14714688
_________________________________________________________________
sequential_1 (Sequential) (None, 1) 25089
=================================================================
Total params: 14,739,777
Trainable params: 7,104,513
Non-trainable params: 7,635,264
_________________________________________________________________
Traceback (most recent call last):
File "__main__.py", line 72, in <module>
batch_size=batch_size)
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/_impl/keras/models.py", line 841, in fit
initial_epoch=initial_epoch)
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/_impl/keras/engine/training.py", line 1535, in fit
batch_size=batch_size)
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/_impl/keras/engine/training.py", line 1394, in _standardize_user_data
exception_prefix='input')
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/_impl/keras/engine/training.py", line 69, in _standardize_input_data
'expected no data, but got:', data)
ValueError: ('Error when checking model input: expected no data, but got:', array([[[[ 0., 0., 0.],
暫定対処
以下のようにダミーの入力レイヤーを足してやることでひとまず学習し始めるところまでは確認しました.
こういうものなのでしょうか?(それならそれで構わないのですが..)
if __name__ == "__main__":
# dummy input layer
dummy_input_layer = k.models.Sequential([
k.layers.InputLayer(input_shape=(224, 224, 3))
])
# vgg16
input_tensor = k.layers.Input(shape=(224, 224, 3))
vgg16_model = k.applications.VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
# my fc_layer
my_model = k.models.Sequential([
k.layers.InputLayer(input_shape=vgg16_model.output_shape[1:]),
k.layers.Flatten(),
k.layers.Dense(1, activation='sigmoid')
])
# freeze block1-4
for layer in vgg16_model.layers[:15]:
layer.trainable = False
# build model
model = k.models.Sequential([dummy_input_layer, vgg16_model, my_model])
model.summary()
model.compile(loss='binary_crossentropy',
optimizer=k.optimizers.SGD(lr=1e-4),
metrics=['acc'])
# training
batch_size = 32
dummy_x = np.zeros(shape=(batch_size,224,224,3))
dummy_y = np.zeros(shape=(batch_size,1))
model.fit(x=dummy_x,
y=dummy_y,
batch_size=batch_size)